
# PHP API

## `Greph\Greph`

La classe `Greph\Greph` est le point d’entrée statique. Elle expose toutes les opérations de recherche, de réécriture et d’indexation. Toutes les méthodes acceptent un chemin unique ou une liste de chemins.

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

### `walk`

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

Résout `$paths` en une liste plate de chemins de fichiers absolus `FileList`. Respecte gitignore, `.grephignore`, les filtres par type de fichier, les motifs glob, l’inclusion des fichiers masqués, le suivi des liens symboliques, la détection des fichiers binaires et la limite de taille des fichiers.

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

Effectue une recherche textuelle et renvoie un `list<TextFileResult>`. Chaque `TextFileResult` expose le chemin du fichier et une liste d’objets `TextMatch` (ligne, colonne, contenu, captures, contexte facultatif).

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

Lorsque `jobs > 1` et que le nombre de fichiers dépasse le seuil de travailleurs, `searchText` répartit automatiquement l’analyse entre un `WorkerPool`. Sinon, elle s’exécute dans le processus courant.

---

### `searchAst`

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

Effectue une recherche structurelle dans l’AST et renvoie un `list<AstMatch>`. Les motifs sont écrits en source PHP avec des métavariables `$VAR` et `$$$VARIADIC`. Chaque `AstMatch` comprend le fichier, le `PhpParser\Node` capturé, les captures, les décalages de début et de fin en lignes et en octets, ainsi que l’extrait de code source correspondant.

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

Effectue une réécriture structurelle et renvoie un `list<RewriteResult>`. Chaque `RewriteResult` expose le chemin du fichier, le contenu d’origine, le contenu réécrit et le nombre de remplacements. Les réécritures préservent le format : seules les plages des nœuds correspondants sont remplacées ; le reste du fichier reste intact.

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

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

La façade n’écrit pas sur le disque ; l’appelant décide s’il souhaite appliquer les modifications. CLI les applique, sauf si `--dry-run` ou `--interactive` est défini.

---

### Recherche textuelle indexée

#### `buildTextIndex`

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

Crée un index trigramme et identifiants pour `$rootPath`. L’index est enregistré dans `$indexPath` (`$rootPath/.greph-index` par défaut). `$lifecycle` peut être `static`, `manual-refresh`, `opportunistic-refresh` ou `strict-stale-check`. Renvoie un `IndexBuildResult` indiquant le nombre de fichiers, le nombre de trigrammes et les nombres d’éléments ajoutés, mis à jour, supprimés ou inchangés.

#### `refreshTextIndex`

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

Actualise progressivement un index textuel existant. Les fichiers sont hachés à nouveau et seules les entrées modifiées sont réécrites.

#### `searchTextIndexed`

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

Effectue une recherche textuelle dans l’index préchauffé. Renvoie une erreur d’exécution si l’index n’existe pas (appelez d’abord `buildTextIndex`). Renvoie un `list<TextFileResult>` de même structure que `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
```

Effectue une recherche textuelle dans plusieurs répertoires d’index préchauffés. Greph interroge chaque index applicable, élimine les doublons selon le chemin absolu du fichier et n’effectue une analyse native que pour les chemins situés en dehors de toutes les racines d’index fournies.

#### `loadIndexSet`

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

Charge un manifeste d’ensemble d’index ; la valeur par défaut est `.greph-index-set.json` dans le répertoire de travail actuel.

#### `searchTextIndexedSet`

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

Résout les entrées `text` sélectionnées dans un manifeste d’ensemble d’index et exécute l’équivalent de `searchTextIndexedMany`.

---

### Recherche AST indexée

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

Crée ou actualise progressivement l’index des faits AST. Enregistre les faits extraits dans `$rootPath/.greph-ast-index` par défaut.

#### `searchAstIndexed`

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

Utilise l’index des faits pour réduire le nombre de candidats avant de vérifier à nouveau les correspondances dans le code source. Renvoie un `list<AstMatch>` de même structure que `searchAst`.

#### `searchAstIndexedMany`

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

Effectue une recherche préchauffée de faits AST dans plusieurs répertoires d’index AST.

#### `searchAstIndexedSet`

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

Résout les entrées `ast-index` sélectionnées dans un manifeste d’ensemble d’index et exécute l’équivalent de `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
```

Crée ou actualise progressivement le stockage des arbres syntaxiques analysés en cache. Enregistre les arbres sérialisés dans `$rootPath/.greph-ast-cache` par défaut.

#### `searchAstCached`

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

Effectue une recherche AST dans les arbres syntaxiques analysés en cache, sans lancer l’analyseur. Renvoie un `list<AstMatch>` de même structure que `searchAst`.

#### `searchAstCachedMany`

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

Effectue une recherche AST préchauffée dans plusieurs répertoires de cache.

#### `searchAstCachedSet`

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

Résout les entrées `ast-cache` sélectionnées dans un manifeste d’ensemble d’index et exécute l’équivalent de `searchAstCachedMany`.

---

## `Greph\Text\TextSearchOptions`

Objet d’options en lecture seule pour la recherche textuelle.

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

Validation :

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

Utilisez `walkOptions()` pour calculer le `WalkOptions` correspondant si vous souhaitez parcourir séparément l’arborescence de fichiers.

`tracePlan` est utilisé par les moteurs de recherche indexée préchauffés, et les flux `greph-index` CLI émettent des diagnostics du planificateur vers `stderr`. La recherche native `searchText` ne l’utilise pas.

---

## `Greph\Ast\AstSearchOptions`

Objet d’options en lecture seule pour la recherche et la réécriture 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,
)
```

Le filtre par défaut des types de fichiers en mode AST est `php`. Lorsque `skipParseErrors` vaut `true` (valeur par défaut), les fichiers qui ne peuvent pas être analysés sont ignorés sans message ; définissez cette option sur `false` pour déclencher des exceptions en cas d’erreur d’analyse. `tracePlan` est utilisé par les moteurs de recherche AST préchauffés, et `greph-index ast-index|ast-cache search` émet des diagnostics d’élagage des candidats.

---

## `Greph\Walker\WalkOptions`

Objet d’options en lecture seule pour le parcours de fichiers.

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

Résout les types de fichiers nommés en listes d’extensions. Alias intégrés :

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

---

## Objets de résultat

### `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` et `AstCacheBuildResult` suivent la même structure, avec `factCount` et `cachedTreeCount` substitués respectivement.

---

## Exceptions

Greph lève trois exceptions typées, toutes dans `Greph\Exceptions` :

| Exception | Quand elle est levée |
|---|---|
| `WalkerException` | Erreurs du système de fichiers pendant le parcours (chemin manquant, répertoire illisible) |
| `PatternException` | Expression régulière ou motif AST non valide |
| `ParseException` | Impossible d’analyser la source PHP (uniquement lorsque `skipParseErrors: false`) |

Les méthodes de recherche indexée lèvent `\RuntimeException` lorsqu’aucun index n’existe à l’emplacement demandé. `greph-index` CLI propose une option `--fallback scan` qui intercepte ces exceptions et lance à la place une analyse sans index.
