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
# 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:
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
./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 modyfikujmanual-refresh: zgłaszaj nieaktualny stan wstats, ale nigdy nie odświeżaj podczas wyszukiwaniaopportunistic-refresh: odświeżaj podczas wyszukiwania tylko wtedy, gdy zbiór zmian jest wystarczająco małystrict-stale-check: odrzucaj nieaktualne wyszukiwania zamiast odświeżać indeks
Wyszukiwanie w indeksie
./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.
./vendor/bin/greph-index ast-index search --fallback scan 'new $CLASS()' src
Wyszukiwanie w wielu indeksach
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.
./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:
./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
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(...).