API Reference
ast-grep currently has an experimental API for Node.js.
You can see API usage guide for more details.
NAPI
Please see the link for up-to-date type declaration.
https://github.com/ast-grep/ast-grep/blob/main/crates/napi/index.d.ts
Supported Languages
@ast-grep/napi supports JS ecosystem languages by default. More custom languages can be loaded via registerDynamicLanguage.
Type
export const enum Lang {
Html = 'Html',
JavaScript = 'JavaScript',
Tsx = 'Tsx',
Css = 'Css',
TypeScript = 'TypeScript',
}
// More custom languages can be loaded
// see https://github.com/ast-grep/langs
type CustomLang = string & {}CustomLang is not widely used now. If you have use case and needs support, please file an issue in the @ast-grep/langs repository.
Main functions
You can use parse to transform a string to ast-grep's main object SgRoot. ast-grep also provides other utility for parse kind string and construct pattern.
/** Parse a string to an ast-grep instance */
export function parse(lang: Lang, src: string): SgRoot
/** Get the `kind` number from its string name. */
export function kind(lang: Lang, kindName: string): number
/** Compile a string to ast-grep Pattern. */
export function pattern(lang: Lang, pattern: string): NapiConfigExample
import { parse, Lang } from '@ast-grep/napi'
const ast = parse(Lang.JavaScript, source)
const root = ast.root()
root.find("console.log")SgRoot
You will get an SgRoot instance when you parse(lang, string).
SgRoot can also be accessed in lang.findInFiles's callback by calling node.getRoot().
In the latter case, sgRoot.filename() will return the path of the matched file.
Type
/** Represents the parsed tree of code. */
class SgRoot {
/** Returns the root SgNode of the ast-grep instance. */
root(): SgNode
/**
* Returns the path of the file if it is discovered by ast-grep's `findInFiles`.
* Returns `"anonymous"` if the instance is created by `parse(lang, source)`.
*/
filename(): string
}Example
import { parse, Lang } from '@ast-grep/napi'
const ast = parse(Lang.JavaScript, source)
const root = ast.root()
root.find("console.log")SgNode
The main interface to traverse the AST.
Type
Most methods are self-explanatory. Please submit a new issue if you find something confusing.
class SgNode {
// Read node's information
range(): Range
isLeaf(): boolean
isNamed(): boolean
isNamedLeaf(): boolean
kind(): string
// check if node has kind
is(kind: string): boolean
// for TypeScript type narrow
kindToRefine: string
text(): string
// Check if node meets certain patterns
matches(m: string): boolean
inside(m: string): boolean
has(m: string): boolean
precedes(m: string): boolean
follows(m: string): boolean
// Get nodes' matched meta variables
getMatch(m: string): SgNode | null
getMultipleMatches(m: string): Array<SgNode>
// Get node's SgRoot
getRoot(): SgRoot
// Traverse node tree
children(): Array<SgNode>
find(matcher: string | number | NapiConfig): SgNode | null
findAll(matcher: string | number | NapiConfig): Array<SgNode>
field(name: string): SgNode | null
parent(): SgNode | null
child(nth: number): SgNode | null
ancestors(): Array<SgNode>
next(): SgNode | null
nextAll(): Array<SgNode>
prev(): SgNode | null
prevAll(): Array<SgNode>
// Edit
replace(text: string): Edit
commitEdits(edits: Edit[]): string
}Some methods have more sophisticated type signatures for the ease of use. See the source code and our tech blog
NapiConfig
NapiConfig is used in find or findAll.
Type
NapiConfig has similar fields as the rule config.
interface NapiConfig {
rule: object
constraints?: object
language?: FrontEndLanguage
transform?: object
utils?: object
}FindConfig
FindConfig is used in findInFiles.
Type
interface FindConfig {
// You can search multiple paths
// ast-grep will recursively find all files under the paths.
paths: Array<string>
// Specify what nodes will be matched
matcher: NapiConfig
}Edit
Edit is used in replace and commitEdits.
interface Edit {
startPos: number
endPos: number
insertedText: string
}Useful Examples
- Test Case Source for
@ast-grep/napi - ast-grep usage in vue-vine
Language Object (deprecated) Deprecated
language objects are deprecated
ast-grep/napi also has special language objects for html, js and css. They are deprecated and will be removed in the next version.
A language object has following methods.
/**
* @deprecated language specific objects are deprecated
* use the equivalent functions like `parse` in @ast-grep/napi
*/
export declare namespace js {
/** @deprecated use `parse(Lang.JavaScript, src)` instead */
export function parse(src: string): SgRoot
/** @deprecated use `parseAsync(Lang.JavaScript, src)` instead */
export function parseAsync(src: string): Promise<SgRoot>
/** @deprecated use `kind(Lang.JavaScript, kindName)` instead */
export function kind(kindName: string): number
/** @deprecated use `pattern(Lang.JavaScript, p)` instead */
export function pattern(pattern: string): NapiConfig
/** @deprecated use `findInFiles(Lang.JavaScript, config, callback)` instead */
export function findInFiles(
config: FindConfig,
callback: (err: null | Error, result: SgNode[]) => void
): Promise<number>
}Example
import { js } from '@ast-grep/napi'
const source = `console.log("hello world")`
const ast = js.parse(source)Python API
SgRoot
The entry point object of ast-grep. You can use SgRoot to parse a string into a syntax tree.
class SgRoot:
def __init__(self, src: str, language: str) -> None: ...
def root(self) -> SgNode: ...SgNode
Most methods are self-explanatory. Please submit a new issue if you find something confusing.
class SgNode:
# Node Inspection
def range(self) -> Range: ...
def is_leaf(self) -> bool: ...
def is_named(self) -> bool: ...
def is_named_leaf(self) -> bool: ...
def kind(self) -> str: ...
def text(self) -> str: ...
# Refinement
def matches(self, **rule: Unpack[Rule]) -> bool: ...
def inside(self, **rule: Unpack[Rule]) -> bool: ...
def has(self, **rule: Unpack[Rule]) -> bool: ...
def precedes(self, **rule: Unpack[Rule]) -> bool: ...
def follows(self, **rule: Unpack[Rule]) -> bool: ...
def get_match(self, meta_var: str) -> Optional[SgNode]: ...
def get_multiple_matches(self, meta_var: str) -> List[SgNode]: ...
def get_transformed(self, meta_var: str) -> Optional[str]: ...
def __getitem__(self, meta_var: str) -> SgNode: ...
# Search
@overload
def find(self, config: Config) -> Optional[SgNode]: ...
@overload
def find(self, **kwargs: Unpack[Rule]) -> Optional[SgNode]: ...
@overload
def find_all(self, config: Config) -> List[SgNode]: ...
@overload
def find_all(self, **kwargs: Unpack[Rule]) -> List[SgNode]: ...
# Tree Traversal
def get_root(self) -> SgRoot: ...
def field(self, name: str) -> Optional[SgNode]: ...
def parent(self) -> Optional[SgNode]: ...
def child(self, nth: int) -> Optional[SgNode]: ...
def children(self) -> List[SgNode]: ...
def ancestors(self) -> List[SgNode]: ...
def next(self) -> Optional[SgNode]: ...
def next_all(self) -> List[SgNode]: ...
def prev(self) -> Optional[SgNode]: ...
def prev_all(self) -> List[SgNode]: ...
# Edit
def replace(self, new_text: str) -> Edit: ...
def commit_edits(self, edits: List[Edit]) -> str: ...Rule
The Rule object is a Python representation of the YAML rule object in the CLI. See the reference.
class Pattern(TypedDict):
selector: str
context: str
class Rule(TypedDict, total=False):
# atomic rule
pattern: str | Pattern
kind: str
regex: str
# relational rule
inside: Relation
has: Relation
precedes: Relation
follows: Relation
# composite rule
all: List[Rule]
any: List[Rule]
# pseudo code below for demo.
"not": Rule # Python does not allow "not" keyword as attribute
matches: str
# Relational Rule Related
StopBy = Union[Literal["neighbor"], Literal["end"], Rule]
class Relation(Rule, total=False):
stopBy: StopBy
field: strConfig
The Config object is similar to the YAML rule config in the CLI. See the reference.
class Config(TypedDict, total=False):
rule: Rule
constraints: Dict[str, Mapping]
utils: Dict[str, Rule]
transform: Dict[str, Mapping]Edit
Edit is used in replace and commitEdits.
class Edit:
# The start position of the edit
start_pos: int
# The end position of the edit
end_pos: int
# The text to be inserted
inserted_text: strRust API
Rust API is not stable yet. The following link is only for those who are interested in modifying ast-grep's source.