Skip to content
An abstract, 8-bit style image featuring several bold, geometric code block shapes overlapping within a 128x128 pixel space, each shape in one of five distinct colors. Select blocks contain minimal, branching line patterns evoking nodes of an abstract syntax tree. Thin connectors link some blocks, suggesting searching and transformation between nodes. Small, crisp programming icons—such as a curly bracket, a 'py' for Python, and a diamond for SQL—are embedded within some shapes. The scene is entirely flat, 2D, with sharp, clean edges, no background, and no human figures.

ast-grep

ast-grep is a fast and polyglot tool for code structural search, lint, rewriting at large scale.

GenAIScript provides a wrapper around ast-grep to search for patterns in the AST of a script, and transform the AST! This is a very efficient way to create scripts that modify source code as one is able to surgically target specific parts of the code.

  • load the ast-grep module
const sg = await host.astGrep()

The search method allows you to search for patterns in the AST of a script. The first argument is the language, the second argument is the file globs, and the third argument is the pattern to search for.

  • find all TypeScript console.log statements. This example uses the ‘pattern’ syntax.
// matches is an array of AST (immutable) nodes
const { matches } = await sg.search("ts", "src/*.ts", "console.log($META)")
  • find all TypeScript functions without comments. This example uses the rule syntax.
const { matches } = await sg.search("ts", "src/fib.ts", {
rule: {
kind: "function_declaration",
not: {
precedes: {
kind: "comment",
stopBy: "neighbor",
},
},
},
})

or if you copy the rules from the ast-grep playground using YAML,

const { matches } = await sg.search(
"ts",
"src/fib.ts",
YAML`
rule:
kind: function_declaration
not:
precedes:
kind: comment
stopBy: neighbor
`
)

A common use case is to restrict the pattern to code impacted by a code diff. You can pass a diff string to the search method and it will filter out matches that do not intersect with the to files of the diff.

const diff = await git.diff({ base: "main" })
const { matches } = await sg.search("ts", "src/fib.ts", {...}, { diff })

A common use case is to search for a pattern and replace it with another pattern. The transformation phase can leverage inline prompts to perform LLM transformations. This can be done with the replace method.

const edits = sg.changeset()

The replace method creates an edit that replaces the content of a node with new text. The edit is stored internally but not applied until commit is called.

edits.replace(matches[0], "console.log('replaced')")

Of course, things get more interesting when you use inline prompts to generate the replacement text.

for(const match of matches) {
const updated = await prompt`... ${match.text()} ...`
edits.replace(
match.node,
`console.log
('${updated.text}')`)
}

Next, you can commit the edits to create a set of in-memory files. The changes are not applied to the file system yet.

const newFiles = edits.commit()

If you wish to apply the changes to the file system, you can use the writeFiles function.

await workspace.writeFiles(newFiles)

This version of ast-grep supports the following built-in languages:

  • Html
  • JavaScript
  • TypeScript
  • Tsx
  • Css
  • C
  • C++
  • Python
  • C#

The following languages require installing an additional package (full list):

  • SQL, @ast-grep/lang-sql
  • Angular, @ast-grep/lang-angular
Terminal window
npm install -D @ast-grep/lang-sql

The following file extensions are mapped to the corresponding languages:

  • HTML: html, htm
  • JavaScript: cjs, mjs, js
  • TypeScript: cts, mts, ts
  • TSX: tsx
  • CSS: css
  • c: c
  • cpp: cpp, cxx, h, hpp, hxx
  • python: py
  • C#: cs
  • sql: sql

GenAIScript has default mappings from well-known file extensions to languages. However, you can override this by passing the lang option to the search method.

const { matches } = await sg.search("ts", "src/fib.ts", {...}, { lang: "ts" })

There is a learning curve to grasp the query language of ast-grep.

You can enable the genaiscript:astgrep namespace to see the queries and results in the logs.

Terminal window
DEBUG=genaiscript:astgrep ...