
# PHP API

## `Greph\Greph`

La classe `Greph\Greph` è il punto di accesso statico. Espone tutte le operazioni di ricerca, riscrittura e indicizzazione. Tutti i metodi accettano un singolo percorso o un elenco di percorsi.

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

### `walk`

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

Risolve `$paths` in un `FileList` piatto di percorsi assoluti dei file. Rispetta gitignore, `.grephignore`, i filtri per tipo di file, i pattern glob, l’inclusione dei file nascosti, il seguito dei link simbolici, il rilevamento dei file binari e il limite massimo di dimensione.

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

Esegue una ricerca testuale e restituisce un `list<TextFileResult>`. Ogni `TextFileResult` espone il percorso del file e un elenco di oggetti `TextMatch` (riga, colonna, contenuto, acquisizioni e contesto facoltativo).

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

Quando `jobs > 1` e il numero di file superano la soglia dei worker, `searchText` distribuisce automaticamente la scansione a un `WorkerPool`. Altrimenti, viene eseguita nel processo corrente.

---

### `searchAst`

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

Esegue una ricerca strutturale AST e restituisce un `list<AstMatch>`. I pattern sono scritti come codice sorgente PHP con metavariabili `$VAR` e `$$$VARIADIC`. Ogni `AstMatch` include il file, il `PhpParser\Node` acquisito, le acquisizioni, le righe e gli offset in byte di inizio e fine, oltre alla porzione di codice sorgente corrispondente.

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

Esegue una riscrittura strutturale e restituisce un `list<RewriteResult>`. Ogni `RewriteResult` espone il percorso del file, il contenuto originale, quello riscritto e il numero di sostituzioni. Le riscritture preservano la formattazione: vengono sostituiti solo gli intervalli dei nodi corrispondenti, lasciando invariato il resto del file.

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

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

La facade non scrive su disco; spetta al chiamante decidere se applicare le modifiche. CLI le applica, a meno che non sia impostato `--dry-run` o `--interactive`.

---

### Ricerca testuale indicizzata

#### `buildTextIndex`

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

Crea un nuovo indice di posting per trigrammi e identificatori per `$rootPath`. L’indice viene salvato in `$indexPath` (il valore predefinito è `$rootPath/.greph-index`). `$lifecycle` può essere `static`, `manual-refresh`, `opportunistic-refresh` o `strict-stale-check`. Restituisce un `IndexBuildResult` con il numero di file, di trigrammi e di elementi aggiunti, aggiornati, eliminati o invariati.

#### `refreshTextIndex`

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

Aggiorna in modo incrementale un indice testuale esistente. I file vengono sottoposti nuovamente a hash e vengono riscritte solo le voci modificate.

#### `searchTextIndexed`

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

Esegue una ricerca testuale sull’indice caricato. Se l’indice non esiste, restituisce un errore runtime (chiamate prima `buildTextIndex`). Restituisce un `list<TextFileResult>` con la stessa struttura di `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
```

Esegue una ricerca testuale con indice caricato in più directory di indici testuali. Greph cerca in ciascun indice applicabile, elimina i duplicati in base al percorso assoluto del file e ricorre alla scansione nativa solo per i percorsi esterni a tutte le directory radice degli indici forniti.

#### `loadIndexSet`

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

Carica un manifest di insieme di indici, per impostazione predefinita `.greph-index-set.json` nella directory di lavoro corrente.

#### `searchTextIndexedSet`

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

Risolve le voci `text` selezionate dal manifest dell’insieme di indici ed esegue l’equivalente di `searchTextIndexedMany`.

---

### Ricerca AST indicizzata

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

Crea o aggiorna in modo incrementale l’indice dei fatti AST. Per impostazione predefinita, salva i fatti estratti in `$rootPath/.greph-ast-index`.

#### `searchAstIndexed`

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

Usa l’indice dei fatti per restringere i candidati prima di verificare nuovamente le corrispondenze nel codice sorgente. Restituisce un `list<AstMatch>` con la stessa struttura di `searchAst`.

#### `searchAstIndexedMany`

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

Esegue una ricerca dei fatti AST con indice caricato in più directory di indici AST.

#### `searchAstIndexedSet`

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

Risolve le voci `ast-index` selezionate dal manifest dell’insieme di indici ed esegue l’equivalente di `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
```

Crea o aggiorna in modo incrementale l’archivio degli alberi sintattici analizzati in cache. Per impostazione predefinita, salva gli alberi serializzati in `$rootPath/.greph-ast-cache`.

#### `searchAstCached`

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

Esegue una ricerca AST sugli alberi sintattici analizzati in cache, saltando interamente il parser. Restituisce un `list<AstMatch>` con la stessa struttura di `searchAst`.

#### `searchAstCachedMany`

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

Esegue una ricerca AST con cache caricata in più directory di cache.

#### `searchAstCachedSet`

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

Risolve le voci `ast-cache` selezionate dal manifest dell’insieme di indici ed esegue l’equivalente di `searchAstCachedMany`.

---

## `Greph\Text\TextSearchOptions`

Oggetto di opzioni di sola lettura per la ricerca testuale.

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

Convalida:

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

Usate `walkOptions()` per ricavare il `WalkOptions` corrispondente se volete esplorare separatamente l’albero dei file.

`tracePlan` viene usato dai motori di ricerca con indice caricato, mentre il flusso `greph-index` CLI invia le diagnostiche del planner a `stderr`. La ricerca nativa `searchText` non lo usa.

---

## `Greph\Ast\AstSearchOptions`

Oggetto di opzioni di sola lettura per la ricerca e la riscrittura 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,
)
```

Il filtro predefinito per tipo di file in modalità AST è `php`. Quando `skipParseErrors` è impostato su `true` (predefinito), i file che non vengono analizzati correttamente vengono ignorati senza avvisi; impostalo su `false` per visualizzare gli errori di analisi come eccezioni. `tracePlan` viene utilizzato dai motori di ricerca AST già riscaldati e `greph-index ast-index|ast-cache search` per generare diagnostica sull'eliminazione dei candidati.

---

## `Greph\Walker\WalkOptions`

Oggetto delle opzioni di sola lettura per il file walker.

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

Risolve i tipi di file nominati in elenchi di estensioni. Alias integrati:

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

---

## Oggetti risultato

### `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` e `AstCacheBuildResult` seguono la stessa struttura, rispettivamente con `factCount` e `cachedTreeCount` al loro posto.

---

## Eccezioni

Greph genera tre eccezioni tipizzate, tutte in `Greph\Exceptions`:

| Eccezione | Quando viene generata |
|---|---|
| `WalkerException` | Errori del filesystem durante la scansione (percorso mancante, directory non leggibile) |
| `PatternException` | Espressione regolare o pattern AST non valido |
| `ParseException` | Impossibile analizzare il codice sorgente PHP (solo quando `skipParseErrors: false`) |

I metodi di ricerca indicizzata generano `\RuntimeException` quando non è presente alcun indice nella posizione richiesta. Il `greph-index` CLI espone un'opzione `--fallback scan` che intercetta questi errori e ripiega su una scansione non indicizzata.
