
# PHP API

## `Greph\Greph`

`Greph\Greph` 클래스는 정적 진입점입니다. 모든 검색, 재작성 및 인덱스 작업을 제공합니다. 모든 메서드는 단일 경로나 경로 목록을 받습니다.

```php
use Greph\Greph;
```

### `walk`

```php
public static function walk(string|array $paths, ?WalkOptions $options = null): FileList
```

`$paths`을 절대 파일 경로로 구성된 평면 `FileList`로 해석합니다. gitignore, `.grephignore`, 파일 유형 필터, glob 패턴, 숨김 파일 포함, 심볼릭 링크 추적, 바이너리 감지 및 최대 파일 크기 제한을 적용합니다.

```php
use Greph\Walker\WalkOptions;
use Greph\Walker\FileTypeFilter;

$files = Greph::walk('src', new WalkOptions(
    fileTypeFilter: new FileTypeFilter(['php']),
));

foreach ($files->paths() as $path) {
    echo "$path\n";
}
```

---

### `searchText`

```php
public static function searchText(
    string $pattern,
    string|array $paths,
    ?TextSearchOptions $options = null,
): array
```

텍스트 검색을 실행하고 `list<TextFileResult>`을 반환합니다. 각 `TextFileResult`에는 파일 경로와 `TextMatch` 객체 목록(줄, 열, 내용, 캡처, 선택적 컨텍스트)이 포함됩니다.

```php
use Greph\Greph;
use Greph\Text\TextSearchOptions;

$results = Greph::searchText(
    'function',
    'src',
    new TextSearchOptions(
        fixedString: true,
        caseInsensitive: true,
        beforeContext: 1,
        afterContext: 1,
        jobs: 4,
    ),
);

foreach ($results as $file) {
    foreach ($file->matches as $match) {
        echo "{$file->file}:{$match->line}:{$match->content}\n";
    }
}
```

`jobs > 1`이 설정되어 있고 파일 수가 작업자 임계값을 넘으면 `searchText`이 자동으로 스캔을 `WorkerPool`에 전달합니다. 그렇지 않으면 프로세스 내에서 실행됩니다.

---

### `searchAst`

```php
public static function searchAst(
    string $pattern,
    string|array $paths,
    ?AstSearchOptions $options = null,
): array
```

구조적 AST 검색을 실행하고 `list<AstMatch>`을 반환합니다. 패턴은 PHP 소스로 작성하며 `$VAR` 및 `$$$VARIADIC` 메타변수를 사용합니다. 각 `AstMatch`에는 파일, 캡처된 `PhpParser\Node`, 캡처 정보, 시작 및 종료 줄과 바이트 오프셋, 일치한 소스 부분이 포함됩니다.

```php
use Greph\Greph;
use Greph\Ast\AstSearchOptions;

$matches = Greph::searchAst(
    'new $CLASS()',
    'src',
    new AstSearchOptions(),
);

foreach ($matches as $match) {
    echo "{$match->file}:{$match->startLine}:{$match->code}\n";
}
```

---

### `rewriteAst`

```php
public static function rewriteAst(
    string $searchPattern,
    string $rewritePattern,
    string|array $paths,
    ?AstSearchOptions $options = null,
): array
```

구조적 재작성을 실행하고 `list<RewriteResult>`을 반환합니다. 각 `RewriteResult`에는 파일 경로, 원본 콘텐츠, 재작성된 콘텐츠 및 대체 횟수가 포함됩니다. 재작성은 형식을 보존합니다. 일치한 노드 범위만 교체하고 나머지 파일은 그대로 둡니다.

```php
$rewrites = Greph::rewriteAst(
    'array($$$ITEMS)',
    '[$$$ITEMS]',
    'src',
);

foreach ($rewrites as $result) {
    if ($result->changed()) {
        file_put_contents($result->file, $result->rewrittenContents);
    }
}
```

파사드는 디스크에 쓰지 않으며 변경 사항을 적용할지는 호출자가 결정합니다. CLI은 `--dry-run` 또는 `--interactive`가 설정되지 않은 경우 변경 사항을 적용합니다.

---

### 인덱싱된 텍스트 검색

#### `buildTextIndex`

```php
public static function buildTextIndex(
    string $rootPath = '.',
    ?string $indexPath = null,
    IndexLifecycle|IndexLifecycleProfile|string|null $lifecycle = null,
): IndexBuildResult
```

`$rootPath`용 새 트라이그램 및 식별자 포스팅 인덱스를 빌드합니다. 인덱스는 `$indexPath`에 저장되며 기본값은 `$rootPath/.greph-index`입니다. `$lifecycle`은 `static`, `manual-refresh`, `opportunistic-refresh` 또는 `strict-stale-check`일 수 있습니다. 파일 수, 트라이그램 수 및 추가/업데이트/삭제/변경 없음 항목 수가 포함된 `IndexBuildResult`을 반환합니다.

#### `refreshTextIndex`

```php
public static function refreshTextIndex(
    string $rootPath = '.',
    ?string $indexPath = null,
    IndexLifecycle|IndexLifecycleProfile|string|null $lifecycle = null,
): IndexBuildResult
```

기존 텍스트 인덱스를 점진적으로 새로 고칩니다. 파일을 다시 해시하고 변경된 항목만 다시 씁니다.

#### `searchTextIndexed`

```php
public static function searchTextIndexed(
    string $pattern,
    string|array $paths,
    ?TextSearchOptions $options = null,
    ?string $indexPath = null,
): array
```

준비된 인덱스에서 텍스트 검색을 실행합니다. 인덱스가 없으면 런타임 오류를 반환합니다(먼저 `buildTextIndex`을 호출하세요). `searchText`와 정확히 같은 형식의 `list<TextFileResult>`을 반환합니다.

```php
Greph::buildTextIndex('.');
$results = Greph::searchTextIndexed('function', 'src');
```

#### `searchTextIndexedMany`

```php
public static function searchTextIndexedMany(
    string $pattern,
    string|array $paths,
    array $indexPaths,
    ?TextSearchOptions $options = null,
): array
```

여러 텍스트 인덱스 디렉터리에서 준비된 텍스트 검색을 실행합니다. Greph은 적용 가능한 각 인덱스를 검색하고, 절대 파일 경로를 기준으로 중복을 제거하며, 제공된 모든 인덱스 루트 밖의 경로에 대해서만 기본 스캔으로 대체합니다.

#### `loadIndexSet`

```php
public static function loadIndexSet(?string $manifestPath = null): IndexSet
```

현재 작업 디렉터리의 `.greph-index-set.json`을 기본값으로 사용해 인덱스 세트 매니페스트를 불러옵니다.

#### `searchTextIndexedSet`

```php
public static function searchTextIndexedSet(
    string $pattern,
    string|array $paths,
    ?TextSearchOptions $options = null,
    ?string $manifestPath = null,
    array $entryNames = [],
): array
```

인덱스 세트 매니페스트에서 선택한 `text` 항목을 해석하고 `searchTextIndexedMany`과 동등한 작업을 실행합니다.

---

### 인덱싱된 AST 검색

#### `buildAstIndex` / `refreshAstIndex`

```php
public static function buildAstIndex(
    string $rootPath = '.',
    ?string $indexPath = null,
    IndexLifecycle|IndexLifecycleProfile|string|null $lifecycle = null,
): AstIndexBuildResult
public static function refreshAstIndex(
    string $rootPath = '.',
    ?string $indexPath = null,
    IndexLifecycle|IndexLifecycleProfile|string|null $lifecycle = null,
): AstIndexBuildResult
```

AST 사실 인덱스를 빌드하거나 점진적으로 새로 고칩니다. 추출한 사실은 기본적으로 `$rootPath/.greph-ast-index`에 저장합니다.

#### `searchAstIndexed`

```php
public static function searchAstIndexed(
    string $pattern,
    string|array $paths,
    ?AstSearchOptions $options = null,
    ?string $indexPath = null,
): array
```

사실 인덱스를 사용해 후보를 좁힌 후 소스와 대조해 일치 여부를 다시 확인합니다. `searchAst`과 동일한 `list<AstMatch>` 형식으로 반환합니다.

#### `searchAstIndexedMany`

```php
public static function searchAstIndexedMany(
    string $pattern,
    string|array $paths,
    array $indexPaths,
    ?AstSearchOptions $options = null,
): array
```

여러 AST 인덱스 디렉터리에서 준비된 AST 사실 검색을 실행합니다.

#### `searchAstIndexedSet`

```php
public static function searchAstIndexedSet(
    string $pattern,
    string|array $paths,
    ?AstSearchOptions $options = null,
    ?string $manifestPath = null,
    array $entryNames = [],
): array
```

인덱스 세트 매니페스트에서 선택한 `ast-index` 항목을 해석하고 `searchAstIndexedMany`과 동등한 작업을 실행합니다.

#### `buildAstCache` / `refreshAstCache`

```php
public static function buildAstCache(
    string $rootPath = '.',
    ?string $indexPath = null,
    IndexLifecycle|IndexLifecycleProfile|string|null $lifecycle = null,
): AstCacheBuildResult
public static function refreshAstCache(
    string $rootPath = '.',
    ?string $indexPath = null,
    IndexLifecycle|IndexLifecycleProfile|string|null $lifecycle = null,
): AstCacheBuildResult
```

캐시된 파스 트리 저장소를 빌드하거나 점진적으로 새로 고칩니다. 직렬화된 트리는 기본적으로 `$rootPath/.greph-ast-cache`에 저장합니다.

#### `searchAstCached`

```php
public static function searchAstCached(
    string $pattern,
    string|array $paths,
    ?AstSearchOptions $options = null,
    ?string $indexPath = null,
): array
```

캐시된 파스 트리에서 AST 검색을 실행해 파서를 완전히 건너뜁니다. `searchAst`과 동일한 `list<AstMatch>` 형식으로 반환합니다.

#### `searchAstCachedMany`

```php
public static function searchAstCachedMany(
    string $pattern,
    string|array $paths,
    array $indexPaths,
    ?AstSearchOptions $options = null,
): array
```

여러 캐시 디렉터리에서 준비된 캐시 AST 검색을 실행합니다.

#### `searchAstCachedSet`

```php
public static function searchAstCachedSet(
    string $pattern,
    string|array $paths,
    ?AstSearchOptions $options = null,
    ?string $manifestPath = null,
    array $entryNames = [],
): array
```

인덱스 세트 매니페스트에서 선택한 `ast-cache` 항목을 해석하고 `searchAstCachedMany`과 동등한 작업을 실행합니다.

---

## `Greph\Text\TextSearchOptions`

텍스트 검색용 읽기 전용 옵션 객체입니다.

```php
new TextSearchOptions(
    bool $fixedString = false,
    bool $caseInsensitive = false,
    bool $wholeWord = false,
    bool $invertMatch = false,
    ?int $maxCount = null,
    int $beforeContext = 0,
    int $afterContext = 0,
    bool $countOnly = false,
    bool $filesWithMatches = false,
    bool $filesWithoutMatches = false,
    bool $jsonOutput = false,
    bool $tracePlan = false,
    int $jobs = 1,
    bool $respectIgnore = true,
    bool $includeHidden = false,
    bool $followSymlinks = false,
    bool $skipBinaryFiles = true,
    bool $includeGitDirectory = false,
    ?FileTypeFilter $fileTypeFilter = null,
    int $maxFileSizeBytes = 10485760,
    array $globPatterns = [],
    bool $showLineNumbers = true,
    bool $showFileNames = true,
)
```

검증:

- `jobs >= 1`
- `beforeContext, afterContext >= 0`
- `maxCount === null || maxCount >= 1`

파일 트리를 별도로 탐색하려면 `walkOptions()`을 사용해 일치하는 `WalkOptions`을 가져오세요.

`tracePlan`은 준비된 인덱스 검색기가 사용하며, `greph-index` CLI 흐름에서는 플래너 진단을 `stderr`으로 출력하는 데 사용됩니다. 기본 `searchText` 자체에서는 사용하지 않습니다.

---

## `Greph\Ast\AstSearchOptions`

AST 검색 및 재작성용 읽기 전용 옵션 객체입니다.

```php
new AstSearchOptions(
    string $language = 'php',
    int $jobs = 1,
    bool $respectIgnore = true,
    bool $includeHidden = false,
    bool $followSymlinks = false,
    bool $skipBinaryFiles = true,
    bool $includeGitDirectory = false,
    ?FileTypeFilter $fileTypeFilter = null,
    int $maxFileSizeBytes = 10485760,
    array $globPatterns = [],
    bool $skipParseErrors = true,
    bool $dryRun = false,
    bool $interactive = false,
    bool $jsonOutput = false,
    bool $tracePlan = false,
)
```

AST 모드의 기본 파일 유형 필터는 `php`입니다. `skipParseErrors`이 `true`(기본값)이면 파싱에 실패한 파일은 조용히 건너뜁니다. 파싱 오류를 예외로 표시하려면 `false`으로 변경하세요. `tracePlan`는 준비된 AST 검색기가 사용하며, `greph-index ast-index|ast-cache search`는 후보 제거 진단을 출력하는 데 사용됩니다.

---

## `Greph\Walker\WalkOptions`

파일 워커용 읽기 전용 옵션 객체입니다.

```php
new WalkOptions(
    bool $respectIgnore = true,
    bool $includeHidden = false,
    bool $followSymlinks = false,
    bool $skipBinaryFiles = false,
    bool $includeGitDirectory = false,
    ?FileTypeFilter $fileTypeFilter = null,
    int $maxFileSizeBytes = 10485760,
    array $globPatterns = [],
)
```

---

## `Greph\Walker\FileTypeFilter`

이름이 지정된 파일 유형을 확장자 목록으로 해석합니다. 기본 제공 별칭:

| 별칭 | 확장자 |
|---|---|
| `css` | `css`, `sass`, `scss` |
| `html` | `htm`, `html`, `phtml` |
| `js` | `cjs`, `js`, `mjs` |
| `json` | `json` |
| `md` | `markdown`, `md` |
| `php` | `inc`, `php`, `php3`, `php4`, `php5`, `php7`, `php8`, `phpt`, `phtml` |
| `txt` | `txt` |
| `ts` | `ts`, `tsx` |
| `xml` | `xml` |
| `yaml` | `yaml`, `yml` |

```php
new FileTypeFilter(includeTypes: ['php'], excludeTypes: ['md']);
```

---

## 결과 객체

### `Greph\Text\TextFileResult`

```php
final readonly class TextFileResult
{
    public string $file;
    /** @var list<TextMatch> */
    public array $matches;

    public function matchCount(): int;
    public function hasMatches(): bool;
}
```

### `Greph\Text\TextMatch`

```php
final readonly class TextMatch
{
    public string $file;
    public int $line;
    public int $column;
    public string $content;
    public string $matchedText;
    /** @var array<int|string, string> */
    public array $captures;
    /** @var list<array{line: int, content: string}> */
    public array $beforeContext;
    /** @var list<array{line: int, content: string}> */
    public array $afterContext;
}
```

### `Greph\Ast\AstMatch`

```php
final readonly class AstMatch
{
    public string $file;
    public PhpParser\Node $node;
    /** @var array<string, mixed> */
    public array $captures;
    public int $startLine;
    public int $endLine;
    public int $startFilePos;
    public int $endFilePos;
    public string $code;
}
```

### `Greph\Ast\RewriteResult`

```php
final readonly class RewriteResult
{
    public string $file;
    public string $originalContents;
    public string $rewrittenContents;
    public int $replacementCount;

    public function changed(): bool;
}
```

### `Greph\Index\IndexBuildResult`

```php
final readonly class IndexBuildResult
{
    public string $rootPath;
    public string $indexPath;
    public int $fileCount;
    public int $trigramCount;
    public int $addedFiles;
    public int $updatedFiles;
    public int $deletedFiles;
    public int $unchangedFiles;
}
```

`AstIndexBuildResult`와 `AstCacheBuildResult`은 각각 `factCount`와 `cachedTreeCount`로 대체된 동일한 형식을 따릅니다.

---

## 예외

Greph은 모두 `Greph\Exceptions`에 속하는 세 가지 유형의 예외를 발생시킵니다.

| 예외 | 발생하는 경우 |
|---|---|
| `WalkerException` | 순회 중 파일 시스템 오류(경로 누락, 디렉터리를 읽을 수 없음) |
| `PatternException` | 잘못된 정규식 또는 AST 패턴 |
| `ParseException` | PHP 소스를 파싱할 수 없음(`skipParseErrors: false`인 경우에만) |

요청한 위치에 인덱스가 없으면 인덱스 검색 메서드는 `\RuntimeException`을 발생시킵니다. `greph-index` CLI에는 이를 포착하고 대신 비인덱스 검색으로 대체하는 `--fallback scan` 옵션이 있습니다.
