Przejdź do treści

Wyszukiwanie AST z indeksem

Wyszukiwanie AST z indeksem to wariant wyszukiwania AST z rozgrzaną pamięcią podręczną. Pierwsze wywołanie wyodrębnia fakty na poziomie węzłów (nazwy wywołań, utworzone instancje, deklaracje klas i metod) i zapisuje je na dysku. Kolejne wywołania korzystają z tego magazynu, aby pominąć pliki, które ewidentnie nie zawierają dopasowania strukturalnego. Następnie mechanizm dopasowujący ponownie weryfikuje kandydatów na podstawie kodu źródłowego.

Indeks faktów jest dostępny w podpoleceniu greph-index ast-index CLI oraz metodach fasady Greph::buildAstIndex() / Greph::searchAstIndexed(). Obsługuje też wyszukiwanie obejmujące wiele indeksów z rozgrzaną pamięcią i zestawy oparte na manifeście.

Tworzenie indeksu

Powłoka
# 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

Domyślnie indeks faktów jest przechowywany w <root>/.greph-ast-index/.

Po pomyślnym utworzeniu indeksu wyświetlane jest jednowierszowe podsumowanie:

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

Cztery liczniki pokazują liczbę dodanych, zaktualizowanych, usuniętych i niezmienionych plików od czasu ostatniego tworzenia indeksu.

Odświeżanie indeksu

Powłoka
./vendor/bin/greph-index ast-index refresh .

refresh ponownie przegląda indeksowany katalog główny, analizuje zmienione pliki i przepisuje tylko zmienione wiersze faktów. Dane wyjściowe zawierają te same cztery liczniki co indeks tekstowy.

Profile cyklu życia działają tak samo jak w przypadku rozgrzanych indeksów tekstowych:

  • static: nigdy automatycznie nie sprawdzaj aktualności ani nie modyfikuj
  • manual-refresh: zgłaszaj nieaktualny stan w stats, ale nigdy nie odświeżaj podczas wyszukiwania
  • opportunistic-refresh: odświeżaj podczas wyszukiwania tylko wtedy, gdy zbiór zmian jest wystarczająco mały
  • strict-stale-check: odrzucaj nieaktualne wyszukiwania zamiast odświeżać indeks

Wyszukiwanie w indeksie

Powłoka
./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

Składnia metazmiennych jest identyczna jak w natywnym wyszukiwaniu AST. Pełną gramatykę znajdziesz w sekcji Tryby / wyszukiwanie AST.

Opcje

Flaga Znaczenie
--lang NAME Język AST. Domyślnie: php
-j N, --jobs N Liczba procesów roboczych działających równolegle
-l, --files-with-matches Wyświetlaj tylko pasujące pliki
--glob GLOB Uwzględniaj tylko pliki, których ścieżki pasują do GLOB
--type NAME / --type-not NAME Filtr typu pliku
--json Generuj dane wyjściowe JSON
--no-ignore Ignoruj .gitignore i .grephignore
--hidden Uwzględniaj ukryte pliki
--strict-parse Zgłaszaj błędy analizy zamiast je pomijać
--fallback MODE Zachowanie w przypadku braku indeksu: fail (domyślnie) lub scan
--index-dir DIR Używaj niestandardowego katalogu indeksu
--trace-plan Zapisuj diagnostykę planera rozgrzanego AST do stderr
--show-index-origin Poprzedzaj dane wyjściowe etykietą pasującego indeksu w trybie wielu indeksów lub zestawu

Zapasowe wyszukiwanie bez indeksu

Domyślnie ast-index search zgłasza błąd, gdy w żądanej lokalizacji nie ma indeksu. Przekaż --fallback scan, aby zamiast tego przeprowadzić natywne skanowanie AST. To właściwe ustawienie dla narzędzi, które mają korzystać z wyszukiwania indeksowanego, gdy jest dostępne, ale powinny zwracać wyniki również wtedy, gdy indeks nie został jeszcze utworzony.

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

Możesz przeszukać kilka rozgrzanych indeksów AST jednym poleceniem, powtarzając --index-dir. Przydaje się to w układach takich jak WordPress wraz z wtyczką lub motywem.

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

Gdy włączono --show-index-origin, przed danymi wyjściowymi pojawia się nazwa pasującej pozycji rozgrzanego indeksu, dzięki czemu widać, który katalog główny zawiera wynik.

Zestawy indeksów oparte na manifeście

W przypadku stabilnych konfiguracji rozgrzanych indeksów zdefiniuj manifest i pozwól greph-index set działać na zgrupowanych indeksach:

Powłoka
./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()' .

Podpolecenia zestawu obsługują cykl życia, sprawdzanie nieaktualności i diagnostykę planera tak samo jak bezpośrednie użycie ast-index.

Diagnostyka planera

--trace-plan pokazuje, jak Greph zawęził zapytanie przed uruchomieniem pełnego mechanizmu dopasowującego. W przypadku ast-index obejmuje to zazwyczaj:

  • przybliżony podpis faktów wyodrębniony ze wzorca
  • liczbę przeszukanych rozgrzanych indeksów
  • liczbę plików odrzuconych przez filtr faktów
  • liczbę plików kandydujących, które ponownie przeanalizowano w celu dokładnej weryfikacji strukturalnej

Co przechowuje indeks

Dla każdego indeksowanego pliku moduł wyodrębniania faktów AST zapisuje wiersz dla każdego „interesującego” węzła. Zestaw rodzajów faktów obejmuje konstrukcje, których najczęściej dotyczą wzorce AST:

  • Wywołania funkcji i metod (według wywoływanej nazwy)
  • Tworzenie instancji klas (według nazwy klasy)
  • Deklaracje klas, interfejsów, cech i wyliczeń (według nazwy)
  • Deklaracje funkcji (według nazwy)
  • Deklaracje metod (według nazwy i widoczności)
  • Instrukcje use

Po nadejściu zapytania Greph\Ast\AstFactQuery przekształca wzorzec wyszukiwania w przybliżony podpis faktów (na przykład „musi zawierać new dowolnej klasy”) i przecina zbiory w magazynie faktów. Pliki, które przejdą to przecięcie, są następnie ponownie analizowane i dopasowywane do pełnego wzorca.

Oznacza to, że indeks faktów jest filtrem wstępnym, a nie pełnym magazynem dopasowań. Etap dopasowywania nadal analizuje kod źródłowy, więc poprawność strukturalna jest taka sama jak w natywnym wyszukiwaniu AST; zmniejsza się tylko zbiór kandydatów.

Kiedy używać

Tryb AST z indeksem sprawdza się, gdy:

  • Wielokrotnie wykonujesz te same zapytania strukturalne w tej samej bazie kodu.
  • Wzorce dotyczą rozpoznawalnych kształtów (nazwy wywołania, nazwy klasy, rodzaju deklaracji), które zapisuje moduł wyodrębniania faktów.
  • Chcesz zmniejszyć opóźnienie w porównaniu z ponowną analizą każdego pliku.

W przypadku wzorców, których cechy wyróżniającej nie ma w zbiorze faktów (na przykład złożonych zagnieżdżonych wyrażeń bez rozpoznawalnego początku), lepiej sprawdza się zwykle tryb buforowanego AST, ponieważ całkowicie pomija etap analizy bez polegania na przybliżonym podpisie.

Użycie programowe

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 przyjmuje ten sam AstSearchOptions co natywne wyszukiwanie AST i zwraca dane o tym samym kształcie list<AstMatch>. W przypadku przepływów obejmujących wiele indeksów lub opartych na manifeście użyj searchAstIndexedMany(...) i searchAstIndexedSet(...).