
# PHP API

## `Greph\Greph`

Kelas `Greph\Greph` adalah titik masuk statis. Kelas ini menyediakan semua operasi pencarian, penulisan ulang, dan pengindeksan. Semua metode menerima satu jalur atau daftar jalur.

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

### `walk`

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

Uraikan `$paths` menjadi `FileList` datar berisi jalur file absolut. Mengikuti gitignore, `.grephignore`, filter tipe file, pola glob, penyertaan file tersembunyi, penelusuran symlink, deteksi biner, dan batas ukuran file maksimum.

```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
```

Jalankan pencarian teks dan kembalikan `list<TextFileResult>`. Setiap `TextFileResult` menyediakan jalur file dan daftar objek `TextMatch` (baris, kolom, konten, tangkapan, konteks opsional).

```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";
    }
}
```

Saat `jobs > 1` dan jumlah file melampaui ambang pekerja, `searchText` otomatis mengirim pemindaian ke `WorkerPool`. Jika tidak, pemindaian berjalan dalam proses yang sama.

---

### `searchAst`

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

Jalankan pencarian AST struktural dan kembalikan `list<AstMatch>`. Pola ditulis sebagai sumber PHP dengan metavariabel `$VAR` dan `$$$VARIADIC`. Setiap `AstMatch` mencakup file, `PhpParser\Node` yang ditangkap, tangkapan, baris awal/akhir dan offset byte, serta irisan sumber yang cocok.

```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
```

Jalankan penulisan ulang struktural dan kembalikan `list<RewriteResult>`. Setiap `RewriteResult` menyediakan jalur file, konten asli, konten hasil penulisan ulang, dan jumlah penggantian. Penulisan ulang mempertahankan format: hanya rentang node yang cocok yang disisipkan; bagian file lainnya tidak disentuh.

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

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

Facade tidak menulis ke disk; pemanggil menentukan apakah perubahan diterapkan. CLI menerapkannya kecuali jika `--dry-run` atau `--interactive` ditetapkan.

---

### Pencarian teks terindeks

#### `buildTextIndex`

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

Buat indeks trigram dan postings pengenal baru untuk `$rootPath`. Indeks disimpan di `$indexPath` (default `$rootPath/.greph-index`). `$lifecycle` dapat berupa `static`, `manual-refresh`, `opportunistic-refresh`, atau `strict-stale-check`. Mengembalikan `IndexBuildResult` yang berisi jumlah file, jumlah trigram, serta jumlah yang ditambahkan/diperbarui/dihapus/tidak berubah.

#### `refreshTextIndex`

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

Perbarui indeks teks yang ada secara bertahap. File di-hash ulang dan hanya entri yang berubah yang ditulis ulang.

#### `searchTextIndexed`

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

Jalankan pencarian teks pada indeks yang sudah dipanaskan. Menghasilkan error runtime jika indeks tidak ada (panggil `buildTextIndex` terlebih dahulu). Mengembalikan `list<TextFileResult>` dengan bentuk yang persis sama seperti `searchText`.

```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
```

Jalankan pencarian teks pada beberapa direktori indeks teks yang sudah dipanaskan. Greph mencari di setiap indeks yang sesuai, menghapus duplikat berdasarkan jalur file absolut, dan menggunakan pemindaian native hanya untuk jalur di luar semua root indeks yang diberikan.

#### `loadIndexSet`

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

Muat manifes kumpulan indeks, dengan default `.greph-index-set.json` di direktori kerja saat ini.

#### `searchTextIndexedSet`

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

Uraikan entri `text` yang dipilih dari manifes kumpulan indeks, lalu jalankan proses yang setara dengan `searchTextIndexedMany`.

---

### Pencarian AST terindeks

#### `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
```

Buat atau perbarui indeks fakta AST secara bertahap. Secara default, fakta yang diekstrak disimpan di `$rootPath/.greph-ast-index`.

#### `searchAstIndexed`

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

Gunakan indeks fakta untuk mempersempit kandidat sebelum memverifikasi ulang kecocokan terhadap sumber. Mengembalikan bentuk `list<AstMatch>` yang sama seperti `searchAst`.

#### `searchAstIndexedMany`

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

Jalankan pencarian fakta AST pada beberapa direktori indeks AST yang sudah dipanaskan.

#### `searchAstIndexedSet`

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

Uraikan entri `ast-index` yang dipilih dari manifes kumpulan indeks, lalu jalankan proses yang setara dengan `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
```

Buat atau perbarui penyimpanan pohon hasil parsing yang di-cache secara bertahap. Secara default, pohon berserialisasi disimpan di `$rootPath/.greph-ast-cache`.

#### `searchAstCached`

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

Jalankan pencarian AST pada pohon hasil parsing yang di-cache, tanpa menjalankan parser sama sekali. Mengembalikan bentuk `list<AstMatch>` yang sama seperti `searchAst`.

#### `searchAstCachedMany`

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

Jalankan pencarian AST dalam cache pada beberapa direktori cache.

#### `searchAstCachedSet`

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

Uraikan entri `ast-cache` yang dipilih dari manifes kumpulan indeks, lalu jalankan proses yang setara dengan `searchAstCachedMany`.

---

## `Greph\Text\TextSearchOptions`

Objek opsi readonly untuk pencarian teks.

```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,
)
```

Validasi:

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

Gunakan `walkOptions()` untuk mendapatkan `WalkOptions` yang cocok jika Anda ingin menelusuri pohon file secara terpisah.

`tracePlan` digunakan oleh pencari terindeks yang sudah dipanaskan dan alur `greph-index` CLI untuk mengeluarkan diagnostik perencana ke `stderr`. `searchText` native sendiri tidak menggunakannya.

---

## `Greph\Ast\AstSearchOptions`

Objek opsi readonly untuk pencarian dan penulisan ulang 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,
)
```

Filter tipe file default untuk mode AST adalah `php`. Saat `skipParseErrors` bernilai `true` (default), file yang gagal diparse akan dilewati tanpa pemberitahuan; ubah ke `false` untuk menampilkan kesalahan parse sebagai exception. `tracePlan` digunakan oleh pencari AST yang telah dipanaskan dan `greph-index ast-index|ast-cache search` untuk menghasilkan diagnostik pemangkasan kandidat.

---

## `Greph\Walker\WalkOptions`

Objek opsi readonly untuk penelusur file.

```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`

Ubah tipe file bernama menjadi daftar ekstensi. Alias bawaan:

| Alias | Ekstensi |
|---|---|
| `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']);
```

---

## Objek hasil

### `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` dan `AstCacheBuildResult` memiliki bentuk yang sama, masing-masing dengan `factCount` dan `cachedTreeCount` sebagai pengganti.

---

## Exception

Greph melempar tiga exception bertipe, semuanya di `Greph\Exceptions`:

| Exception | Saat terjadi |
|---|---|
| `WalkerException` | Kesalahan sistem file saat penelusuran (jalur tidak ditemukan, direktori tidak dapat dibaca) |
| `PatternException` | Regex atau pola AST tidak valid |
| `ParseException` | Sumber PHP tidak dapat diparse (hanya saat `skipParseErrors: false`) |

Metode pencarian terindeks memunculkan `\RuntimeException` jika tidak ada indeks di lokasi yang diminta. `greph-index` CLI menyediakan opsi `--fallback scan` yang menangkap exception ini lalu beralih ke pemindaian tanpa indeks.
