
# Indekseeritud AST-otsing

Indekseeritud AST-otsing on [AST-otsingu](https://greph.inline0.dev/et/docs/modes/ast) soojendatud vahemäluga variant. Esimene käivitus eraldab sõlmetaseme faktid (kutsete nimed, eksemplaride loomised, klassideklaratsioonid ja meetodideklaratsioonid) kettal asuvasse hoidlasse; järgnevad käivitused kasutavad seda hoidlat, et jätta vahele failid, mis ilmselgelt ei saa sisaldada struktuurset vastet. Seejärel kontrollib vastemootor kandidaadid lähtekoodiga uuesti üle.

Faktiregistrile pääseb ligi alamkäsuga `greph-index ast-index` CLI ning fassaadi meetoditega `Greph::buildAstIndex()` / `Greph::searchAstIndexed()`. See osaleb ka soojendatud mitme registri ja manifestipõhistes komplektitöövoogudes.

## Registri loomine

```bash
# Full build at the current directory
./vendor/bin/greph-index ast-index build .

# Full build at an explicit root
./vendor/bin/greph-index ast-index build path/to/repo

# Use a non-default index directory
./vendor/bin/greph-index ast-index build . --index-dir /tmp/greph-ast-index

# Build a mutable overlay that can refresh cheaply on demand
./vendor/bin/greph-index ast-index build . \
  --lifecycle opportunistic-refresh \
  --auto-refresh-max-files 32 \
  --auto-refresh-max-bytes 1048576
```

Vaikimisi salvestatakse faktiregister asukohta `<root>/.greph-ast-index/`.

Eduka loomise korral kuvatakse üherealine kokkuvõte:

```text
Built AST index for 2547 files in .greph-ast-index (84931 fact rows, +2547 ~0 -0 =0)
```

Neli loendurit näitavad pärast eelmist loomist lisatud, uuendatud, kustutatud ja muutumatuna püsinud failide arvu.

## Registri värskendamine

```bash
./vendor/bin/greph-index ast-index refresh .
```

`refresh` käib indekseeritud juurkausta uuesti läbi, parsib muudetud failid uuesti ja kirjutab ümber ainult muutunud faktiread. Väljundis kasutatakse samu nelja loendurit nagu tekstiindeksi puhul.

Elutsükli profiilid toimivad samamoodi nagu soojendatud tekstiindeksite puhul:

- `static`: ära kontrolli automaatselt ajakohasust ega muuda andmeid
- `manual-refresh`: teavita aegunud olekust käsus `stats`, kuid ära värskenda otsingu ajal kunagi
- `opportunistic-refresh`: värskenda otsingu ajal ainult siis, kui muudetud failide kogumi töötlemine on endiselt piisavalt kiire
- `strict-stale-check`: lükka aegunud otsingud tagasi, selle asemel et neid värskendada

## Registrist päringute tegemine

```bash
./vendor/bin/greph-index ast-index search 'new $CLASS()' src
./vendor/bin/greph-index ast-index search '$obj->$method($$$ARGS)' src
./vendor/bin/greph-index ast-index search --json 'array($$$ITEMS)' src
./vendor/bin/greph-index ast-index search -l 'array($$$ITEMS)' src
./vendor/bin/greph-index ast-index search --trace-plan 'new $CLASS()' src
```

Metamuutujate süntaks on sama mis algupärases AST-otsingus. Täieliku grammatika leiate jaotisest [Režiimid / AST-otsing](https://greph.inline0.dev/et/docs/modes/ast).

### Suvandid

| Lipp | Tähendus |
|---|---|
| `--lang NAME` | AST keel. Vaikimisi: `php` |
| `-j N`, `--jobs N` | Paralleeltöötajate arv |
| `-l`, `--files-with-matches` | Loetle ainult vastavad failid |
| `--glob GLOB` | Kaasa ainult failid, mille teed vastavad GLOB-ile |
| `--type NAME` / `--type-not NAME` | Failitüübi filter |
| `--json` | Väljasta JSON-vormingus väljund |
| `--no-ignore` | Eira `.gitignore` ja `.grephignore` |
| `--hidden` | Kaasa peidetud failid |
| `--strict-parse` | Tõrku parsimisvigade korral, selle asemel et need vahele jätta |
| `--fallback MODE` | Käitumine puuduva registri korral: `fail` (vaikimisi) või `scan` |
| `--index-dir DIR` | Kasuta vaikeasukohast erinevat registrikataloogi |
| `--trace-plan` | Väljasta soojendatud AST plaanuri diagnostika asukohta `stderr` |
| `--show-index-origin` | Lisa väljundi ette vastava registrikirje silt mitme registri või komplekti režiimis |

### Varuvariant puuduva registri korral

Vaikimisi annab `ast-index search` vea, kui soovitud asukohas registrit pole. Natiivse AST-skanni kasutamiseks varuvariandina edastage `--fallback scan`. See sobib tööriistadele, mis eelistavad võimaluse korral indekseeritud otsingut, kuid peavad tulemused tagastama ka siis, kui registrit pole veel loodud.

```bash
./vendor/bin/greph-index ast-index search --fallback scan 'new $CLASS()' src
```

### Otsing mitmest registrist

Ühe käsuga saab otsida mitmest soojendatud AST registrist, korrates valikut `--index-dir`. See on kasulik näiteks paigutuse korral, kus WordPress põhikoodile lisandub pistikprogramm või teema.

```bash
./vendor/bin/greph-index ast-index search \
  --index-dir ../wordpress/.greph-ast-index \
  --index-dir ./.greph-ast-index \
  --show-index-origin \
  'new $CLASS()' .
```

Kui `--show-index-origin` on lubatud, lisatakse väljundi ette vastava soojendatud registrikirje nimi, et näeksite, millise juurkausta vaste pärineb.

### Manifestipõhised registrikomplektid

Stabiilse soojendatud seadistuse jaoks määrake manifest ja laske `greph-index set`-il kasutada rühmitatud registreid:

```bash
./vendor/bin/greph-index set build
./vendor/bin/greph-index set stats --mode ast-index --dry-refresh
./vendor/bin/greph-index set search --mode ast-index --show-index-origin 'new $CLASS()' .
```

Komplekti alamkäsud kasutavad sama elutsükli haldust, aegumise kontrolle ja plaanuri diagnostikat nagu otsekäsu `ast-index` puhul.

### Plaanuri diagnostika

`--trace-plan` näitab, kuidas Greph kitsendas päringut enne täieliku vastemootori käivitamist. Tavaliselt hõlmab see `ast-index` puhul järgmist:

- mustrist eraldatud üldine fakti signatuur
- otsitud soojendatud registrite arv
- faktifiltri poolt kõrvale jäetud failide arv
- kandidaatfailide arv, mis parsiti täpseks struktuuri kontrollimiseks uuesti

## Registri sisu

Iga indekseeritud faili kohta salvestab AST faktide eraldaja rea iga „huvipakkuva“ sõlme kohta. Faktitüüpide hulka kuuluvad konstruktsioonid, mida AST-mustrid kõige sagedamini sihivad:

- Funktsiooni- ja meetodikutseid (kutse nime järgi)
- Klassieksemplaride loomisi (klassi nime järgi)
- Klasside, liideste, trait’ide ja enum’ide deklaratsioone (nime järgi)
- Funktsioonideklaratsioone (nime järgi)
- Meetodideklaratsioone (nime ja nähtavuse järgi)
- Use-lauseid

Päringu saabumisel teisendab `Greph\Ast\AstFactQuery` otsingumustri üldiseks faktisignatuuriks (näiteks „peab sisaldama mis tahes klassi `new`-i“) ja võrdleb seda faktide hoidlaga. Allesjäänud failid parsitakse seejärel uuesti ja leitakse vasted kogu mustri järgi.

See tähendab, et faktiregister on *eelfilter*, mitte täielik vastete hoidla. Vastendamise etapis parsitakse lähtekood ikka veel, seega on struktuurne korrektsus sama mis algupärases AST-otsingus; väiksem on ainult kandidaatide kogum.

## Millal seda kasutada

Indekseeritud AST-režiim sobib, kui:

- Käivitate samu struktuuripäringuid sama koodibaasi vastu korduvalt.
- Mustrite sihtmärgiks on tuvastatavad kujundid (kutse nimi, klassi nimi, deklaratsiooni liik), mida faktide eraldaja salvestab.
- Soovite väiksemat viivitust kui kõigi failide uuesti parsimisel.

Mustrite puhul, mille eristav tunnus faktikogumis puudub (näiteks keerukad pesastatud avaldised ilma äratuntava algusosata), sobib tavaliselt paremini [vahemällu salvestatud AST-režiim](https://greph.inline0.dev/et/docs/indexed/cache), sest see jätab parsimisetapi täielikult vahele ega tugine üldisele signatuurile.

## Programmipõhine kasutus

```php
use Greph\Greph;
use Greph\Ast\AstSearchOptions;
use Greph\Index\IndexLifecycleProfile;

Greph::buildAstIndex('.', lifecycle: IndexLifecycleProfile::OpportunisticRefresh);

$matches = Greph::searchAstIndexed(
    'new $CLASS()',
    'src',
    new AstSearchOptions(jobs: 4, tracePlan: true),
);
```

`searchAstIndexed` aktsepteerib samu `AstSearchOptions` väärtusi mis algupärane AST-otsing ja tagastab sama kujuga `list<AstMatch>` tulemuse. Mitme registri või manifestipõhiste töövoogude jaoks kasutage `searchAstIndexedMany(...)` ja `searchAstIndexedSet(...)`.
