
# Ricerca AST indicizzata

La ricerca AST indicizzata è la versione con cache precaricata della [ricerca AST](https://greph.inline0.dev/it/docs/modes/ast). Alla prima chiamata estrae i fatti a livello di nodo (nomi delle chiamate, istanziazioni, dichiarazioni di classi e di metodi) e li salva in un archivio su disco; le chiamate successive usano l'archivio per saltare i file che chiaramente non possono contenere una corrispondenza strutturale. Il motore di ricerca verifica quindi di nuovo i candidati sul codice sorgente.

L'indice dei fatti è esposto nel sottocomando `greph-index ast-index` CLI e nei metodi della facciata `Greph::buildAstIndex()` / `Greph::searchAstIndexed()`. Partecipa inoltre ai flussi di lavoro precaricati con più indici e ai gruppi definiti da manifest.

## Creazione dell'indice

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

Per impostazione predefinita, l'indice dei fatti viene salvato in `<root>/.greph-ast-index/`.

Una creazione riuscita stampa un riepilogo su una riga:

```text
Built AST index for 2547 files in .greph-ast-index (84931 fact rows, +2547 ~0 -0 =0)
```

I quattro contatori indicano i file aggiunti, aggiornati, eliminati e invariati dall'ultima creazione.

## Aggiornamento dell'indice

```bash
./vendor/bin/greph-index ast-index refresh .
```

`refresh` ripercorre la radice indicizzata, analizza di nuovo i file modificati e riscrive solo le righe dei fatti che sono cambiate. L'output usa gli stessi quattro contatori dell'indice testuale.

I profili del ciclo di vita funzionano come per gli indici testuali precaricati:

- `static`: non verificare mai l'aggiornamento né modificare automaticamente
- `manual-refresh`: segnalare i dati obsoleti in `stats`, senza mai aggiornare durante la ricerca
- `opportunistic-refresh`: aggiornare durante la ricerca solo se l'insieme delle modifiche è ancora abbastanza ridotto
- `strict-stale-check`: rifiutare le ricerche con dati obsoleti invece di aggiornarli

## Interrogazione dell'indice

```bash
./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
```

La sintassi delle metavariabili è identica a quella della ricerca AST nativa. Consultate [Modalità / Ricerca AST](https://greph.inline0.dev/it/docs/modes/ast) per la grammatica completa.

### Opzioni

| Opzione | Significato |
|---|---|
| `--lang NAME` | Linguaggio AST. Predefinito: `php` |
| `-j N`, `--jobs N` | Numero di worker paralleli |
| `-l`, `--files-with-matches` | Elenca solo i file corrispondenti |
| `--glob GLOB` | Includi solo i file i cui percorsi corrispondono a GLOB |
| `--type NAME` / `--type-not NAME` | Filtro per tipo di file |
| `--json` | Genera output JSON |
| `--no-ignore` | Ignora `.gitignore` e `.grephignore` |
| `--hidden` | Includi file nascosti |
| `--strict-parse` | Interrompi in caso di errori di analisi invece di ignorarli |
| `--fallback MODE` | Comportamento in assenza dell'indice: `fail` (predefinito) oppure `scan` |
| `--index-dir DIR` | Usa una directory dell'indice non predefinita |
| `--trace-plan` | Genera la diagnostica del pianificatore AST precaricato in `stderr` |
| `--show-index-origin` | Anteponi all'output l'etichetta dell'indice corrispondente in modalità multi-indice o gruppo |

### Ripiego in assenza dell'indice

Per impostazione predefinita, `ast-index search` genera un errore se non esiste alcun indice nella posizione richiesta. Passate `--fallback scan` per ripiegare su una scansione AST nativa. È l'impostazione giusta per gli strumenti che preferiscono la ricerca indicizzata quando disponibile, ma devono comunque restituire risultati se l'indice non è ancora stato creato.

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

### Ricerca su più indici

Potete cercare in più indici AST precaricati con un solo comando ripetendo `--index-dir`. È utile per strutture come il core di WordPress insieme a un plugin o a un tema.

```bash
./vendor/bin/greph-index ast-index search \
  --index-dir ../wordpress/.greph-ast-index \
  --index-dir ./.greph-ast-index \
  --show-index-origin \
  'new $CLASS()' .
```

Quando `--show-index-origin` è abilitato, all'output viene anteposto il nome della voce dell'indice precaricato corrispondente, così potete vedere quale radice ha prodotto il risultato.

### Gruppi di indici definiti da manifest

Per configurazioni precaricate stabili, definite un manifest e fate operare `greph-index set` sugli indici raggruppati:

```bash
./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()' .
```

I sottocomandi dei gruppi condividono la stessa gestione del ciclo di vita, gli stessi controlli dei dati obsoleti e la stessa diagnostica del pianificatore dell'uso diretto di `ast-index`.

### Diagnostica del pianificatore

`--trace-plan` mostra come Greph ha ristretto la query prima dell'esecuzione del motore di ricerca completo. Per `ast-index` ciò include in genere:

- la firma approssimativa dei fatti estratta dal pattern
- quanti indici precaricati sono stati consultati
- quanti file sono stati esclusi dal filtro dei fatti
- quanti file candidati sono stati analizzati di nuovo per la verifica strutturale esatta

## Dati salvati nell'indice

Per ogni file indicizzato, l'estrattore dei fatti AST registra una riga per ogni nodo "interessante". I tipi di fatti comprendono i costrutti più spesso cercati dai pattern AST:

- Chiamate a funzioni e metodi (in base al nome chiamato)
- Istanze di classi (in base al nome della classe)
- Dichiarazioni di classi, interfacce, trait ed enum (in base al nome)
- Dichiarazioni di funzioni (in base al nome)
- Dichiarazioni di metodi (in base al nome e alla visibilità)
- Istruzioni use

Quando arriva una query, `Greph\Ast\AstFactQuery` traduce il pattern di ricerca in una firma approssimativa dei fatti (per esempio, "deve contenere un `new` di qualsiasi classe") e interseca l'archivio dei fatti. I file che superano l'intersezione vengono quindi analizzati di nuovo e confrontati con il pattern completo.

Ciò significa che l'indice dei fatti è un *prefiltro*, non un archivio di corrispondenze completo. La fase di corrispondenza analizza comunque il codice sorgente, quindi la correttezza strutturale è identica a quella della ricerca AST nativa; cambia solo l'insieme dei candidati, che è più piccolo.

## Quando usarlo

La modalità AST indicizzata è la scelta giusta quando:

- Eseguite ripetutamente le stesse query strutturali sulla stessa base di codice.
- I pattern cercano forme identificabili (nome della chiamata, nome della classe, tipo di dichiarazione) registrate dall'estrattore dei fatti.
- Volete una latenza inferiore rispetto alla nuova analisi di ogni file.

Per i pattern il cui tratto distintivo non è nell'insieme dei fatti (per esempio, espressioni annidate complesse senza un elemento iniziale riconoscibile), la [modalità AST memorizzata nella cache](https://greph.inline0.dev/it/docs/indexed/cache) è di solito più adatta, perché salta del tutto la fase di analisi senza basarsi su una firma approssimativa.

## Uso programmatico

```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` accetta lo stesso `AstSearchOptions` della ricerca AST nativa e restituisce dati con la stessa struttura `list<AstMatch>`. Per i flussi multi-indice o basati su manifest, usate `searchAstIndexedMany(...)` e `searchAstIndexedSet(...)`.
