
# Búsqueda indexada de AST

La búsqueda indexada de AST es la versión con caché precargada de la [búsqueda de AST](https://greph.inline0.dev/es/docs/modes/ast). La primera llamada extrae datos de los nodos (nombres de llamadas, instanciaciones, declaraciones de clases y declaraciones de métodos) y los guarda en disco; las llamadas siguientes usan el almacén para omitir archivos que claramente no pueden contener una coincidencia estructural. A continuación, el comparador vuelve a verificar los candidatos con el código fuente.

El índice de datos está disponible mediante el subcomando `greph-index ast-index` CLI y los métodos de interfaz `Greph::buildAstIndex()` / `Greph::searchAstIndexed()`. También se usa en los flujos de trabajo con varios índices precargados y conjuntos respaldados por manifiestos.

## Creación del índice

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

De forma predeterminada, el índice de datos se guarda en `<root>/.greph-ast-index/`.

Si la creación finaliza correctamente, se muestra un resumen de una línea:

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

Los cuatro contadores muestran los archivos añadidos, actualizados, eliminados y sin cambios desde la última creación del índice.

## Actualización del índice

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

`refresh` vuelve a recorrer la raíz indexada, analiza de nuevo los archivos modificados y reescribe solo las filas de datos que han cambiado. La salida usa los mismos cuatro contadores que el índice de texto.

Los perfiles de ciclo de vida funcionan igual que en los índices de texto precargados:

- `static`: nunca comprueba la vigencia ni modifica el índice automáticamente
- `manual-refresh`: informa si el índice está desactualizado en `stats`, pero nunca lo actualiza durante la búsqueda
- `opportunistic-refresh`: actualiza el índice durante la búsqueda solo si el conjunto de cambios sigue siendo lo bastante pequeño
- `strict-stale-check`: rechaza las búsquedas con datos desactualizados en lugar de actualizar el índice

## Consulta del índice

```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 sintaxis de las metavariables es idéntica a la de la búsqueda de AST nativa. Consulte [Modos / Búsqueda de AST](https://greph.inline0.dev/es/docs/modes/ast) para ver la gramática completa.

### Opciones

| Opción | Significado |
|---|---|
| `--lang NAME` | Lenguaje del AST. Valor predeterminado: `php` |
| `-j N`, `--jobs N` | Número de procesos de trabajo paralelos |
| `-l`, `--files-with-matches` | Mostrar solo los archivos que coinciden |
| `--glob GLOB` | Incluir solo los archivos cuyas rutas coincidan con GLOB |
| `--type NAME` / `--type-not NAME` | Filtro por tipo de archivo |
| `--json` | Emitir salida JSON |
| `--no-ignore` | Ignorar `.gitignore` y `.grephignore` |
| `--hidden` | Incluir archivos ocultos |
| `--strict-parse` | Fallar ante errores de análisis en vez de omitirlos |
| `--fallback MODE` | Comportamiento si falta el índice: `fail` (predeterminado) o `scan` |
| `--index-dir DIR` | Usar un directorio de índice no predeterminado |
| `--trace-plan` | Emitir diagnósticos del planificador de AST precargado a `stderr` |
| `--show-index-origin` | Anteponer a la salida la etiqueta del índice coincidente en el modo de varios índices o conjuntos |

### Alternativa si falta el índice

De forma predeterminada, `ast-index search` genera un error si no hay ningún índice en la ubicación solicitada. Pase `--fallback scan` para recurrir a un análisis de AST nativo. Esta opción es adecuada para herramientas que buscan con un índice cuando está disponible, pero que también deben mostrar resultados cuando aún no se ha creado.

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

### Búsqueda en varios índices

Puede buscar en varios índices de AST precargados con un solo comando si repite `--index-dir`. Resulta útil para estructuras como un núcleo WordPress junto con un complemento o 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()' .
```

Si se habilita `--show-index-origin`, la salida incluye como prefijo el nombre de la entrada del índice precargado coincidente, para que pueda ver qué raíz produjo el resultado.

### Conjuntos de índices respaldados por manifiestos

Para configuraciones precargadas estables, defina un manifiesto y deje que `greph-index set` opere con los índices agrupados:

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

Los subcomandos de conjuntos comparten la misma gestión del ciclo de vida, las comprobaciones de datos desactualizados y los diagnósticos del planificador que el uso directo de `ast-index`.

### Diagnósticos del planificador

`--trace-plan` muestra cómo Greph redujo el conjunto de consultas antes de ejecutar el comparador completo. Para `ast-index`, suele incluir:

- la firma general de datos extraída del patrón
- cuántos índices precargados se buscaron
- cuántos archivos se descartaron con el filtro de datos
- cuántos archivos candidatos se volvieron a analizar para verificar la estructura exacta

## Datos que almacena el índice

Para cada archivo indexado, el extractor de datos del AST registra una fila por cada nodo «interesante». El conjunto de tipos de datos abarca las construcciones a las que suelen dirigirse los patrones de AST:

- Llamadas a funciones y métodos (por nombre de llamada)
- Instanciaciones de clases (por nombre de clase)
- Declaraciones de clases, interfaces, traits y enumeraciones (por nombre)
- Declaraciones de funciones (por nombre)
- Declaraciones de métodos (por nombre y visibilidad)
- Instrucciones de uso

Cuando llega una consulta, `Greph\Ast\AstFactQuery` traduce el patrón de búsqueda a una firma general de datos (por ejemplo, «debe contener un `new` de cualquier clase») y consulta el almacén de datos. Luego, vuelve a analizar los archivos que superan esa intersección y los compara con el patrón completo.

Esto significa que el índice de datos es un *prefiltro*, no un almacén de coincidencias exhaustivo. El paso de comparación sigue analizando el código fuente, por lo que la precisión estructural es idéntica a la de la búsqueda de AST nativa; solo se reduce el conjunto de candidatos.

## Cuándo usarlo

El modo de AST indexado es adecuado cuando:

- Ejecuta repetidamente las mismas consultas estructurales en la misma base de código.
- Los patrones buscan formas identificables (nombre de llamada, nombre de clase o tipo de declaración) que guarda el extractor de datos.
- Quiere reducir la latencia frente a analizar todos los archivos de nuevo.

Para patrones cuyo rasgo distintivo no forma parte del conjunto de datos (por ejemplo, expresiones anidadas complejas sin una cabecera reconocible), el [modo de AST en caché](https://greph.inline0.dev/es/docs/indexed/cache) suele ser más adecuado, porque omite por completo el análisis sin depender de una firma general.

## Uso programático

```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` acepta el mismo `AstSearchOptions` que la búsqueda de AST nativa y devuelve la misma estructura de `list<AstMatch>`. Para flujos con varios índices o respaldados por manifiestos, use `searchAstIndexedMany(...)` y `searchAstIndexedSet(...)`.
