
# Indeksuota AST paieška

Indeksuota AST paieška – tai [AST paieškos](https://greph.inline0.dev/lt/docs/modes/ast) versija su įkeltu podėliu. Pirmo iškvietimo metu mazgų lygmens faktai (iškvietimų pavadinimai, egzempliorių kūrimas, klasių ir metodų deklaracijos) įrašomi į diske saugomą saugyklą; vėliau ši saugykla naudojama praleisti failus, kuriuose akivaizdžiai negali būti struktūrinės atitikties. Tada kandidatai iš naujo tikrinami su šaltinio kodu.

Faktų indeksą galima pasiekti naudojant subkomandą `greph-index ast-index` CLI ir fasadinius metodus `Greph::buildAstIndex()` / `Greph::searchAstIndexed()`. Jis taip pat naudojamas įkeltų indeksų paieškoje keliuose indeksuose ir manifestais pagrįstuose rinkiniuose.

## Indekso kūrimas

```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
```

Pagal numatytuosius nustatymus faktų indeksas saugomas `<root>/.greph-ast-index/`.

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

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

Keturi skaitikliai rodo nuo paskutinio kūrimo pridėtų, atnaujintų, ištrintų ir nepakitusių failų skaičių.

## Indekso atnaujinimas

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

`refresh` iš naujo pereina indeksuojamą šakninį katalogą, iš naujo analizuoja pakeistus failus ir perrašo tik pasikeitusius faktų įrašus. Išvedami tie patys keturi skaitikliai kaip ir teksto indekso atveju.

Gyvavimo ciklo profiliai veikia taip pat kaip ir įkelti teksto indeksai:

- `static`: niekada automatiškai netikrina aktualumo ir nekeičia indekso
- `manual-refresh`: praneša apie pasenusią būseną `stats`, tačiau paieškos metu indekso neatnaujina
- `opportunistic-refresh`: paieškos metu atnaujina tik tada, kai pakeitimų rinkinys dar pakankamai mažas
- `strict-stale-check`: vietoj atnaujinimo atmeta paieškas su pasenusiu indeksu

## Užklausos indeksui

```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
```

Metakintamųjų sintaksė tokia pati kaip įprastoje AST paieškoje. Visą gramatiką rasite skiltyje [Režimai / AST paieška](https://greph.inline0.dev/lt/docs/modes/ast).

### Parinktys

| Vėliavėlė | Reikšmė |
|---|---|
| `--lang NAME` | AST kalba. Numatytoji: `php` |
| `-j N`, `--jobs N` | Lygiagrečių procesų skaičius |
| `-l`, `--files-with-matches` | Rodyti tik atitinkančius failus |
| `--glob GLOB` | Įtraukti tik failus, kurių keliai atitinka GLOB |
| `--type NAME` / `--type-not NAME` | Failo tipo filtras |
| `--json` | Išvesti JSON formatą |
| `--no-ignore` | Nepaisyti `.gitignore` ir `.grephignore` |
| `--hidden` | Įtraukti paslėptus failus |
| `--strict-parse` | Aptikus analizės klaidų, nutraukti darbą, o ne jas praleisti |
| `--fallback MODE` | Trūkstamo indekso veiksena: `fail` (numatytoji) arba `scan` |
| `--index-dir DIR` | Naudoti nenumatytąjį indekso katalogą |
| `--trace-plan` | Į `stderr` išvesti įkelto AST planavimo diagnostiką |
| `--show-index-origin` | Naudojant kelis indeksus arba rinkinį, prieš išvestį nurodyti atitinkančio indekso žymą |

### Atsarginė veiksena, kai indekso nėra

Pagal numatytuosius nustatymus `ast-index search` pateikia klaidą, jei nurodytoje vietoje indekso nėra. Perduokite `--fallback scan`, kad vietoj to būtų vykdoma įprasta AST paieška. Ši parinktis tinka įrankiams, kurie, kai įmanoma, naudoja indeksuotą paiešką, bet turi pateikti rezultatus ir tada, kai indeksas dar nesukurtas.

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

### Paieška keliuose indeksuose

Galite ieškoti keliuose įkeltuose AST indeksuose viena komanda, pakartodami `--index-dir`. Tai naudinga tokiems išdėstymams kaip WordPress branduolys su papildiniu ar tema.

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

Kai įjungta `--show-index-origin`, prieš išvestį nurodomas atitinkančio įkelto indekso įrašo pavadinimas, kad matytumėte, iš kurio šakninio katalogo gautas rezultatas.

### Manifestais pagrįsti indeksų rinkiniai

Jei norite sukurti stabilią įkeltų indeksų konfigūraciją, aprašykite manifestą ir leiskite `greph-index set` veikti su sugrupuotais indeksais:

```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()' .
```

Rinkinių subkomandose naudojamas tas pats gyvavimo ciklo valdymas, pasenusių indeksų tikrinimas ir planavimo diagnostika kaip ir tiesiogiai naudojant `ast-index`.

### Planavimo diagnostika

`--trace-plan` parodo, kaip Greph susiaurino užklausą prieš pradedant veikti visam šablonų atitikimo mechanizmui. Naudojant `ast-index` paprastai rodoma:

- iš šablono išgautas apytikslis faktų parašas
- kiek įkeltų indeksų buvo peržiūrėta
- kiek failų atmetė faktų filtras
- kiek failų kandidatų iš naujo analizuota, kad būtų tiksliai patvirtinta struktūrinė atitiktis

## Kas saugoma indekse

Kiekvienam indeksuojamam failui AST faktų ištraukiklis įrašo po eilutę kiekvienam „įdomiam“ mazgui. Faktų tipai apima konstrukcijas, į kurias dažniausiai taikomi AST šablonai:

- Funkcijų ir metodų iškvietimai (pagal iškviečiamo elemento pavadinimą)
- Klasių egzempliorių kūrimas (pagal klasės pavadinimą)
- Klasių, sąsajų, trait ir enum tipų deklaracijos (pagal pavadinimą)
- Funkcijų deklaracijos (pagal pavadinimą)
- Metodų deklaracijos (pagal pavadinimą ir matomumą)
- Use sakiniai

Gavęs užklausą, `Greph\Ast\AstFactQuery` paverčia paieškos šabloną apytiksliu faktų parašu (pavyzdžiui, „turi būti bet kurios klasės `new`“) ir ieško faktų saugykloje. Tada iš naujo analizuojami failai, likę po šio filtro, ir tikrinama, ar jie atitinka visą šabloną.

Tai reiškia, kad faktų indeksas yra *išankstinis filtras*, o ne visą atitiktį sauganti saugykla. Atitikties tikrinimo žingsnyje šaltinis vis tiek analizuojamas, todėl struktūrinis tikslumas toks pat kaip įprastoje AST paieškoje; skiriasi tik mažesnis kandidatų rinkinys.

## Kada naudoti

Indeksuotas AST režimas tinka, kai:

- pakartotinai vykdote tas pačias struktūrines užklausas tai pačiai kodų bazei;
- šablonai taikomi atpažįstamoms formoms (iškvietimo pavadinimui, klasės pavadinimui ar deklaracijos tipui), kurias saugo faktų ištraukiklis;
- norite mažesnio delsos laiko nei iš naujo analizuojant kiekvieną failą.

Šablonams, kurių skiriamasis požymis nepatenka į faktų rinkinį (pavyzdžiui, sudėtingoms įdėtinėms išraiškoms be atpažįstamos pradžios), paprastai labiau tinka [AST režimas su podėliu](https://greph.inline0.dev/lt/docs/indexed/cache), nes jis visiškai praleidžia analizės etapą ir nesiremia apytiksliu parašu.

## Naudojimas programoje

```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` priima tą patį `AstSearchOptions` kaip ir įprasta AST paieška ir grąžina tokios pačios struktūros `list<AstMatch>`. Jei naudojate kelis indeksus ar manifestais pagrįstus rinkinius, naudokite `searchAstIndexedMany(...)` ir `searchAstIndexedSet(...)`.
