
# AST paieška podėlyje

AST paieška podėlyje papildo [faktų indeksą](https://greph.inline0.dev/lt/docs/indexed/ast) kaip šiltosios talpyklos režimas. Užuot saugojus išgautus faktus ir iš naujo analizavus atitinkančius failus, podėlyje diske saugomi serializuoti išanalizuoti sintaksės medžiai. Vėlesnių užklausų metu medžiai deserializuojami ir šablonų atitikimo mechanizmas paleidžiamas tiesiogiai, visiškai praleidžiant PHP-Parser konvejerį.

Podėlį galima pasiekti naudojant subkomandą `greph-index ast-cache` CLI ir fasadinius metodus `Greph::buildAstCache()` / `Greph::searchAstCached()`. Jis taip pat leidžia ieškoti keliuose indeksuose ir manifestais pagrįstuose rinkiniuose.

## Podėlio kūrimas

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

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

# Build a cache that may refresh automatically for small changes
./vendor/bin/greph-index ast-cache build . \
  --lifecycle opportunistic-refresh \
  --auto-refresh-max-files 32 \
  --auto-refresh-max-bytes 1048576
```

Pagal numatytuosius nustatymus podėlis saugomas `<root>/.greph-ast-cache/`. Podėlio kūrimas paprastai užtrunka ilgiausiai iš trijų indeksavimo režimų, nes kiekvieną failą reikia išanalizuoti vieną kartą.

Sėkmingai sukūrus indeksą, išvedama vienos eilutės suvestinė:

```text
Built AST cache for 2547 files in .greph-ast-cache (2541 cached trees, +2541 ~0 -0 =0)
```

Podėlyje saugomų medžių paprastai būna šiek tiek mažiau nei failų, nes nepavykus išanalizuoti failų (klaidos praleidžiamos tyliai), podėlio įrašai nesukuriami. Jei norite matyti analizės klaidas, paieškos komandai perduokite `--strict-parse`.

## Podėlio atnaujinimas

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

`refresh` iš naujo pereina indeksuojamą šakninį katalogą, iš naujo analizuoja pakeistus failus ir perrašo tik pasikeitusius podėlyje saugomus medžius.

Gyvavimo ciklo profiliai tokie patys kaip ir kituose įkeltuose režimuose:

- `static`: niekada automatiškai netikrina aktualumo ir nekeičia podėlio
- `manual-refresh`: praneša apie pasenusią būseną `stats`, tačiau paieškos metu podėlio neatnaujina
- `opportunistic-refresh`: paieškos metu atnaujina tik tada, kai pakeitimų rinkinys neviršija sukonfigūruotų ribų
- `strict-stale-check`: vietoj atnaujinimo atmeta paieškas su pasenusiu podėliu

## Užklausos podėliui

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

Vėliavėlių rinkinys toks pats kaip [`ast-index search`](https://greph.inline0.dev/lt/docs/indexed/ast#querying-the-index), įskaitant `--fallback scan`, skirtą trūkstamam podėliui.

### Paieška keliuose indeksų podėliuose

Pakartokite `--index-dir`, jei viena komanda norite ieškoti keliuose įkeltuose podėliuose:

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

### Manifestais pagrįsti podėlių rinkiniai

Jei jau turite pavadintus įkeltų indeksų rinkinius, AST paieškai podėlyje galite naudoti tą patį manifestą:

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

### Planavimo diagnostika

`--trace-plan` pateikia į AST podėlį nukreipto planavimo sprendimus `stderr`, įskaitant:

- kuriuose įkeltuose podėliuose atlikta paieška
- ar buvo vykdomas pasenusio podėlio atnaujinimas
- kiek kandidatų failų liko po susiaurinimo failų lygmeniu
- kiek podėlyje saugomų medžių deserializuota tikslios struktūrinės atitikties paieškai

## Podėlio ir faktų indekso palyginimas

Abu režimai paspartina AST paiešką, tačiau yra optimizuoti skirtingoms užduotims.

| Aspektas | Faktų indeksas (`ast-index`) | Talpykla (`ast-cache`) |
|---|---|---|
| Kas saugoma | Išgauti faktai (iškvietimų pavadinimai, klasių pavadinimai, deklaracijos) | Serializuoti išanalizuoti medžiai |
| Kūrimo sąnaudos | Mažesnės | Didesnės (analizuojama viskas) |
| Kūrimo dydis | Mažesnis | Didesnis |
| Užklausos eiga | Filtruojama pagal faktus, tada analizuojami ir tikrinami kandidatai | Deserializuojamas medis, tada atliekama atitikties paieška |
| Geriausiai tinka | Šablonams su atpažįstama pradžia (iškvietimo ar klasės pavadinimu) | Šablonams, kurių skiriamasis požymis yra struktūrinis, o ne vardinis |
| Blogiausiai tinka | Šablonams, kurių pradžia yra metavariantas | Šaltoms užklausoms medyje, kuris nebetelpa į OS puslapių talpyklą |

Praktikoje faktų indeksas užtikrina greičiausias šaltas užklausas, o talpykla – greičiausias šiltas užklausas. Naudokite tai, kas labiausiai tinka jūsų darbo krūviui, arba sukurkite abu ir leiskite įrankiams pasirinkti.

## Naudojimas programoje

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

Greph::buildAstCache('.', lifecycle: IndexLifecycleProfile::Static);

$matches = Greph::searchAstCached(
    'array($$$ITEMS)',
    'src',
    new AstSearchOptions(jobs: 4, tracePlan: true),
);
```

`searchAstCached` priima tuos pačius `AstSearchOptions` kaip ir AST paieška ir grąžina tokios pačios formos `list<AstMatch>`. Skiriasi tik tai, kad analizatoriaus eiga praleidžiama failams, kurie jau yra talpykloje. Kelių indeksų ar manifestu pagrįstoms eigoms naudokite `searchAstCachedMany(...)` ir `searchAstCachedSet(...)`.

## Kada naudoti

Talpykloje saugomas AST režimas tinkamas, kai:

- Vykdote pasikartojančias struktūrines užklausas tai pačiai kodų bazei.
- Ankstesnių vykdymų siauroji vieta buvo PHP-Parser (profiliuose matomas laikas, praleistas leksinėje analizėje ir analizatoriuje).
- Galite skirti disko vietos serializuotų medžių saugyklai.

Jei užklausos paprastai aprėpia nedidelę kodų bazės dalį, o atitikmenys telkiasi ties atpažįstamais iškvietimų ar klasių pavadinimais, [faktų indeksas](https://greph.inline0.dev/lt/docs/indexed/ast) paprastai tinka geriau. Jei užklausos plačiai aprėpia kodų bazę, bet galite skirti laiko vienkartinei analizei, laimi talpykla.
