본문으로 건너뛰기

인덱스 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는 오류를 발생시킵니다. 대신 네이티브 AST 스캔을 실행하려면 --fallback scan를 전달하세요. 인덱스가 있으면 인덱스 검색을 사용하되, 아직 빌드되지 않은 경우에도 결과를 내야 하는 도구에 적합한 설정입니다.

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

--index-dir를 반복하면 한 명령으로 여러 개의 사전 준비 AST 인덱스를 검색할 수 있습니다. 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는 네이티브 AST 검색과 동일한 AstSearchOptions를 받고 같은 형태의 list<AstMatch>를 반환합니다. 다중 인덱스 또는 매니페스트 기반 흐름에는 searchAstIndexedMany(...) 및 searchAstIndexedSet(...)를 사용하세요.