Към съдържанието

Индексирано търсене в AST

Индексираното търсене в AST е вариантът с предварително зареден кеш на търсенето в AST. При първото извикване се извличат факти на ниво възел (имена на извиквания, инстанции, декларации на класове и декларации на методи) и се записват на диска; при следващите извиквания хранилището се използва за пропускане на файлове, които очевидно не могат да съдържат структурно съвпадение. След това съпоставителят проверява отново кандидатите спрямо изходния код.

Индексът на факти е достъпен чрез подкомандата greph-index ast-index CLI и методите на фасада Greph::buildAstIndex() / Greph::searchAstIndexed(). Той участва и в работните процеси с предварително заредени индекси в няколко набора, както и в тези, чиито набори се описват с манифест.

Създаване на индекса

Обвивка
# 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

По подразбиране индексът на факти се съхранява в <root>/.greph-ast-index/.

При успешно създаване се извежда едноредово обобщение:

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

Четирите брояча показват добавените, обновените, изтритите и непроменените файлове след последното създаване.

Обновяване на индекса

Обвивка
./vendor/bin/greph-index ast-index refresh .

refresh обхожда отново индексирания корен, анализира отново променените файлове и пренаписва само променените редове с факти. Изходът използва същите четири брояча като текстовия индекс.

Профилите за жизнения цикъл работят по същия начин като при предварително заредените текстови индекси:

  • static: никога не проверява актуалността и не променя автоматично
  • manual-refresh: отчита остаряло състояние в stats, но никога не обновява при търсене
  • opportunistic-refresh: обновява при търсене само ако наборът от промени е достатъчно малък
  • strict-stale-check: отхвърля търсенията с остарели данни, вместо да обновява

Заявки към индекса

Обвивка
./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

Синтаксисът на метапроменливите е идентичен с този при нативното търсене в AST. Вижте Режими / Търсене в AST за пълната граматика.

Опции

Флаг Значение
--lang NAME Език на AST. По подразбиране: php
-j N, --jobs N Брой паралелни работници
-l, --files-with-matches Изброява само съвпадащите файлове
--glob GLOB Включва само файлове, чиито пътища съвпадат с GLOB
--type NAME / --type-not NAME Филтър по тип файл
--json Извежда изход във формат JSON
--no-ignore Игнорира .gitignore и .grephignore
--hidden Включва скритите файлове
--strict-parse Прекратява при грешки при анализиране, вместо да ги пропуска
--fallback MODE Поведение при липсващ индекс: fail (по подразбиране) или scan
--index-dir DIR Използва директория за индекс, различна от тази по подразбиране
--trace-plan Извежда диагностиката на планировчика за предварително зареден AST в stderr
--show-index-origin Добавя към изхода етикета на съвпадащия индекс в режим с няколко индекса или набори

Резервен режим при липсващ индекс

По подразбиране ast-index search извежда грешка, когато на посоченото място няма индекс. Подайте --fallback scan, за да преминете към нативно сканиране на AST. Това е подходящата настройка за инструменти, които използват индексирано търсене, когато има индекс, но трябва да извеждат резултати и преди създаването му.

Обвивка
./vendor/bin/greph-index ast-index search --fallback scan 'new $CLASS()' src

Можете да търсите в няколко предварително заредени индекса на AST с една команда, като повторите --index-dir. Това е полезно за оформления като ядро на WordPress плюс плъгин или тема.

Обвивка
./vendor/bin/greph-index ast-index search \
  --index-dir ../wordpress/.greph-ast-index \
  --index-dir ./.greph-ast-index \
  --show-index-origin \
  'new $CLASS()' .

Когато --show-index-origin е активиран, към изхода се добавя името на съвпадналия запис в предварително заредения индекс, за да виждате кой корен е дал резултата.

Набори от индекси с манифест

За стабилни конфигурации с предварително заредени индекси задайте манифест и позволете на greph-index set да работи с групираните индекси:

Обвивка
./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()' .

Подкомандите за набори споделят същата обработка на жизнения цикъл, проверки за остарели данни и диагностика на планировчика като прякото използване на ast-index.

Диагностика на планировчика

--trace-plan показва как Greph е стеснил заявката, преди да стартира пълният съпоставител. За ast-index това обикновено включва:

  • грубия подпис на факти, извлечен от шаблона
  • броя на претърсените предварително заредени индекси
  • броя на файловете, отхвърлени от филтъра за факти
  • броя на файловете кандидати, анализирани повторно за точна структурна проверка

Какво съхранява индексът

За всеки индексиран файл извличателят на факти от AST записва по един ред за всеки „интересен“ възел. Видовете факти обхващат конструкциите, към които най-често са насочени шаблоните за AST:

  • Извиквания на функции и методи (по име на извиканото)
  • Инстанции на класове (по име на класа)
  • Декларации на класове, интерфейси, трейтове и enum-и (по име)
  • Декларации на функции (по име)
  • Декларации на методи (по име и видимост)
  • Инструкции use

Когато постъпи заявка, Greph\Ast\AstFactQuery преобразува шаблона за търсене в груб подпис на факти (например „трябва да съдържа new от произволен клас“) и търси пресечението в хранилището с факти. След това оцелелите при тази проверка файлове се анализират отново и се съпоставят с пълния шаблон.

Това означава, че индексът на факти е предварителен филтър, а не хранилище за пълноценни съвпадения. Стъпката на съпоставяне все пак анализира изходния код, така че структурната коректност е същата като при нативното търсене в AST; по-малък е само наборът от кандидати.

Кога да го използвате

Индексираният режим на AST е подходящият инструмент, когато:

  • Повтаряте едни и същи структурни заявки върху една и съща кодова база.
  • Шаблоните търсят разпознаваеми форми (име на извикване, име на клас, вид декларация), които извличателят на факти съхранява.
  • Искате по-ниска латентност от тази при повторно анализиране на всеки файл.

За шаблони, чиято отличителна черта не присъства в набора от факти (например сложни вложени изрази без разпознаваема начална част), кешираният режим на AST обикновено е по-подходящ, защото изцяло пропуска стъпката на анализиране, без да разчита на груб подпис.

Програмно използване

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 приема същия AstSearchOptions като нативното търсене в AST и връща същата структура на list<AstMatch>. За работни процеси с няколко индекса или с набори, описани чрез манифест, използвайте searchAstIndexedMany(...) и searchAstIndexedSet(...).