Esta herramienta te permite realizar cambios mágicos en el código, sin IA

En el mundo de la programación, el texto es el rey, por lo que herramientas como grep, sed y awk son fantásticos compañeros para su compilador o intérprete. La caja de herramientas de todo programador también puede beneficiarse de un sistema de control de versiones basado en texto, como Git.

Pero todas estas herramientas funcionan a nivel de texto genérico. Si bien las expresiones regulares pueden ser increíblemente poderosas, todavía no se adaptan perfectamente a la gramática de un lenguaje de programación. Para una búsqueda semántica y significativa, necesita un tipo diferente de herramienta. Ingrese ast-grep.

¿Qué es ast-grep y por qué lo necesitarías?

Búsqueda superpoderosa que comprende su código

Digamos que desea una lista de todos los nombres de funciones en su código base. Un primer intento podría verse así:

grep -r 'function' ...

Y luego puede que te des cuenta de que estás haciendo coincidir demasiadas ocurrencias irrelevantes, por lo que refinas tu expresión regular:

egrep -r '^function\W' ...

Continúas de esta manera hasta que, eventualmente, te das cuenta de que, no importa lo que hagas, tu búsqueda coincidirá con algo como:

/*
The following should be:
function foo(a, b, c)
but that’s not going to work because...
*/

Herramientas como grep simplemente no entienden el contexto de algo que parece una declaración de función dentro de un comentario. Funcionan simplemente haciendo coincidir caracteres individuales, sin considerar ningún significado más amplio que puedan encarnar las combinaciones de esos caracteres.

ast-grep es diferente. En lugar de leer el texto carácter por carácter, línea por línea, analiza el texto (como un compilador) y construye un árbol de sintaxis abstracta (AST) que representa el significado real de su código. Al usarlo, puede realizar búsquedas semánticas de elementos como declaraciones de variables, llamadas a funciones, etc.

En su interior, ast-grep utiliza la popular biblioteca Tree-sitter, que le permite admitir una amplia gama de lenguajes tan diversos como Python, Java y Go. ast-grep está escrito en Rust, por lo que funciona bien, incluso buscando en bases de código grandes. Esto es importante porque, dado que tiene que analizar completamente los archivos antes de buscarlos, hay mucho más trabajo que hacer que una búsqueda estándar basada en texto.

Cómo buscar casi cualquier cosa usando ast-grep

Usar la línea de comandos o una aplicación web perfecta para principiantes

El uso más simple de ast-grep utiliza la opción -p para especificar un único patrón simple.

ast-grep -p 'console.log'

Sin ningún argumento de ruta, ast-grep buscará archivos en el directorio actual de forma recursiva. A menos que especifique un idioma, ast-grep lo inferirá en función de la extensión del archivo. El programa agrupará los resultados por archivo, imprimiendo los detalles de cada partido, destacando las partes relevantes:

Tenga en cuenta que esta búsqueda devuelve llamadas a funciones sin argumentos y una referencia a la propiedad del método que ni siquiera es una llamada. Sin embargo, busca específicamente un objeto llamado consola, por lo que no encontrará lo siguiente:

with (console) {
    log("Hello, world.");
}

Pero, correctamente, ignorará «‘console.log'» como cadena y «/* console.log */» como comentario. En este punto, le aconsejo que explore el área de juegos de ast-grep, una aplicación web que ejecuta ast-grep en segundo plano y presenta sus resultados:

Como puede ver, el patio de juegos indica claramente qué coincidió y qué no. Esto contrasta con el programa de línea de comandos, que filtra la entrada y solo devuelve coincidencias. El patio de juegos me resultó muy útil cuando aprendí por primera vez sobre ast-grep y traté de construir mis propios patrones.

Puede utilizar metavariables para hacer coincidir contenido más dinámico. Una metavariable comienza con $ y usa solo letras mayúsculas, junto con guiones bajos y dígitos. Para encontrar todas las llamadas a console.log con un solo argumento, use este patrón:

console.log($SINGLE_ARG)

Observe que el patrón coincide con llamadas con un solo argumento, no con aquellas que no tienen ninguno o que tienen más de uno:

Si desea hacer coincidir varios argumentos, puede utilizar una variable meta múltiple, que comienza con tres signos de dólar:

console.log($$$MULTIPLE_ARGS)

Este patrón coincidirá con todas las llamadas a console.log, incluidas aquellas con cero o varios argumentos:

Para búsquedas más complejas, ast-grep admite una sintaxis de reglas en YAML. Puede utilizar esto para definir búsquedas altamente contextuales, aprovechando al máximo la estructura AST.

Por ejemplo, aquí hay una regla que coincide con todas las llamadas a console.log, console.debug y console.warn, además de las llamadas a console.error si no están dentro de una cláusula catch:

id: no-console-except-error
language: typescript
rule:
  any:
    - pattern: console.error($$$)
      not:
        inside:
          kind: catch_clause
          stopBy: end
    - pattern: console.$METHOD($$$)
constraints:
  METHOD:
    regex: 'log|debug|warn'

Cambia tu código sin editarlo manualmente

Con una preparación y pruebas cuidadosas, ast-grep puede ser un potente editor automatizado

ast-grep ya es una herramienta poderosa, pero va más allá de la búsqueda. Con su función de reemplazo, ast-grep también te permite modificar tu código. Esto significa que puede realizar cambios que requieren mucho tiempo en segundos, ya sea de forma automática o interactiva.

Considere el ejemplo anterior de console.log. Imagine una de sus bases de código plagada de código de depuración que llama a console.log. Decides que quieres algo un poco más sofisticado, entonces comienzas con una función personalizada, my_logger:

function my_logger() {
    if (GLOBAL_DEBUG) {
        console.log.apply(null, arguments)
    }
}

Es solo un simple contenedor para console.log, con una bandera global, por ahora. Pero el punto es que necesitarás convertir cada llamada a console.log() en una llamada my_logger. Usando ast-grep, este es un proceso simple. Comience con un archivo de reglas, por ejemplo, fix-logging.yml:

rule:
  pattern: console.log($$$MULTIPLE_ARGS)
fix: my_logger($$$MULTIPLE_ARGS)

Luego ejecútelo así para ver los cambios que se realizarían:

ast-grep scan --rule fix-logging.yml

Si está satisfecho con los resultados, puede hacer que ast-grep realice estos cambios por usted, actualizando los archivos en el lugar con la opción –update-all:

ast-grep scan --rule fix-logging.yml --update-all

Hay varios modos que puedes usar para realizar cambios, incluido uno interactivo, que es probablemente la forma más segura de ejecutar ast-grep mientras te familiarizas con él.


A pesar de la pronunciada curva de aprendizaje, dominar ast-grep será recompensado

No hay duda: ast-grep es un programa complicado. Los ejemplos que he incluido aquí se encuentran en el extremo más fácil de la escala y, si profundiza más en la documentación, verá que esta herramienta tiene mucho más que ofrecer.

Si bien puede resultar abrumador, el área de juegos ayuda mucho y usar el modo interactivo para limpiar su código base es una excelente manera de comenzar a aprender ast-grep.

We use cookies in order to give you the best possible experience on our website. By continuing to use this site, you agree to our use of cookies.
Accept