Přejít k obsahu

Indexované vyhledávání AST

Indexované vyhledávání AST je verze vyhledávání AST s připravenou mezipamětí. Při prvním volání se do úložiště na disku uloží fakta o uzlech (názvy volání, vytváření instancí, deklarace tříd a deklarace metod); následná volání pomocí tohoto úložiště přeskočí soubory, které zjevně nemohou obsahovat strukturální shodu. Poté se shody znovu ověří porovnáním se zdrojovým kódem.

Index faktů je dostupný v dílčím příkazu greph-index ast-index CLI a metodách fasády Greph::buildAstIndex() / Greph::searchAstIndexed(). Podporuje také připravené postupy s více indexy a sady založené na manifestu.

Vytvoření indexu

Shell
# 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

Index faktů se ve výchozím nastavení ukládá do <root>/.greph-ast-index/.

Úspěšné vytvoření vypíše jednořádkové shrnutí:

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

Čtyři počítadla udávají počet přidaných, aktualizovaných, smazaných a nezměněných souborů od posledního vytvoření indexu.

Obnovení indexu

Shell
./vendor/bin/greph-index ast-index refresh .

refresh znovu projde indexovaný kořen, znovu zpracuje změněné soubory a přepíše pouze změněné řádky faktů. Výstup používá stejná čtyři počítadla jako textový index.

Profily životního cyklu fungují stejně jako u připravených textových indexů:

  • static: nikdy automaticky nekontroluje aktuálnost ani nemění index
  • manual-refresh: hlásí zastaralý stav v stats, ale během vyhledávání index nikdy neobnovuje
  • opportunistic-refresh: obnovuje index při vyhledávání, pouze pokud je změněná sada stále dostatečně malá
  • strict-stale-check: místo obnovy odmítne zastaralé vyhledávání

Dotazování indexu

Shell
./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

Syntaxe metavariabel je stejná jako u nativního vyhledávání AST. Úplnou gramatiku najdete v části Režimy / vyhledávání AST.

Možnosti

Příznak Význam
--lang NAME Jazyk AST. Výchozí: php
-j N, --jobs N Počet paralelních pracovních procesů
-l, --files-with-matches Zobrazit pouze soubory se shodou
--glob GLOB Zahrnout pouze soubory, jejichž cesty odpovídají GLOB
--type NAME / --type-not NAME Filtr typů souborů
--json Vygenerovat výstup JSON
--no-ignore Ignorovat .gitignore a .grephignore
--hidden Zahrnout skryté soubory
--strict-parse Při chybách parsování skončit chybou místo jejich přeskočení
--fallback MODE Chování při chybějícím indexu: fail (výchozí) nebo scan
--index-dir DIR Použít jiný než výchozí adresář indexu
--trace-plan Vypisovat diagnostiku připraveného plánovače AST do stderr
--show-index-origin V režimu více indexů nebo sad předřadit výstupu štítek odpovídajícího indexu

Náhradní režim při chybějícím indexu

Ve výchozím nastavení ast-index search zobrazí chybu, pokud na požadovaném místě není žádný index. Zadáním --fallback scan místo toho přejde na nativní skenování AST. Toto nastavení se hodí pro nástroje, které mají používat indexované vyhledávání, když je dostupné, ale přesto mají vracet výsledky, pokud index ještě nebyl vytvořen.

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

V jednom příkazu můžete prohledávat několik připravených indexů AST opakováním --index-dir. Hodí se to pro rozložení, jako je jádro WordPress doplněné o zásuvný modul nebo šablonu.

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

Je-li povoleno --show-index-origin, výstup se opatří názvem odpovídající položky připraveného indexu, abyste viděli, který kořen obsahuje výsledek.

Sady indexů založené na manifestu

Pro stabilní připravená prostředí definujte manifest a nechte greph-index set pracovat se skupinou indexů:

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

Dílčí příkazy pro sady sdílejí stejné zpracování životního cyklu, kontroly zastaralosti a diagnostiku plánovače jako přímé použití ast-index.

Diagnostika plánovače

--trace-plan ukazuje, jak Greph zúžil dotaz před spuštěním úplného porovnávání. U ast-index to obvykle zahrnuje:

  • hrubý podpis faktů získaný ze vzoru
  • počet prohledaných připravených indexů
  • počet souborů vyřazených filtrem faktů
  • počet souborů kandidátů znovu zpracovaných pro přesné strukturální ověření

Co index ukládá

Extraktor faktů AST zaznamená pro každý indexovaný soubor jeden řádek pro každý „zajímavý“ uzel. Sada typů faktů pokrývá konstrukce, na které se vzory AST zaměřují nejčastěji:

  • Volání funkcí a metod (podle názvu volání)
  • Vytváření instancí tříd (podle názvu třídy)
  • Deklarace tříd, rozhraní, traitů a výčtů (podle názvu)
  • Deklarace funkcí (podle názvu)
  • Deklarace metod (podle názvu a viditelnosti)
  • Příkazy use

Když přijde dotaz, Greph\Ast\AstFactQuery převede vzor vyhledávání na hrubý podpis faktů (například „musí obsahovat new libovolné třídy“) a provede průnik s úložištěm faktů. Soubory, které průnikem projdou, se znovu zpracují a porovnají s úplným vzorem.

Index faktů je tedy předfiltr, nikoli úložiště úplných shod. Při porovnávání se zdrojový kód stále parsuje, takže strukturální správnost je stejná jako u nativního vyhledávání AST; zmenší se pouze množina kandidátů.

Kdy jej použít

Režim indexovaného AST je vhodný, když:

  • Opakovaně spouštíte stejné strukturální dotazy nad stejnou kódovou základnou.
  • Vzory se zaměřují na rozpoznatelné tvary (název volání, název třídy, druh deklarace), které ukládá extraktor faktů.
  • Chcete nižší latenci než při opakovaném parsování každého souboru.

U vzorů, jejichž rozlišovací znak není v sadě faktů (například u složitých vnořených výrazů bez rozpoznatelné hlavičky), se obvykle lépe hodí režim AST v mezipaměti, protože zcela přeskočí parsování a nespoléhá na hrubý podpis.

Programové použití

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 přijímá stejný AstSearchOptions jako nativní vyhledávání AST a vrací výsledek ve stejném tvaru list<AstMatch>. Pro postupy s více indexy nebo manifestem použijte searchAstIndexedMany(...) a searchAstIndexedSet(...).