[![npm version][npm-version-src]][npm-version-href] [![npm downloads][npm-downloads-src]][npm-downloads-href] [![Github Actions][github-actions-src]][github-actions-href] [![Codecov][codecov-src]][codecov-href]
npm install oxc-walker[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![Github Actions][github-actions-src]][github-actions-href]
[![Codecov][codecov-src]][codecov-href]
A strongly-typed ESTree AST walker built on top of oxc-parser.
Install package:
``shnpm
npm install oxc-walker
$3
`ts
import { parseSync } from "oxc-parser";
import { walk } from "oxc-walker";const ast = parseSync("example.js", "const x = 1");
walk(ast.program, {
enter(node, parent, ctx) {
// ...
},
});
`$3
`js
import { parseAndWalk } from "oxc-walker";parseAndWalk("const x = 1", "example.js", (node, parent, ctx) => {
// ...
});
`⚙️ API
$3
Walk an AST.
`ts
// options
interface WalkOptions {
/**
* The function to be called when entering a node.
*/
enter?: (node: Node, parent: Node | null, ctx: CallbackContext) => void;
/**
* The function to be called when leaving a node.
*/
leave?: (node: Node, parent: Node | null, ctx: CallbackContext) => void;
/**
* The instance of ScopeTracker to use for tracking declarations and references.
*/
scopeTracker?: ScopeTracker;
}interface CallbackContext {
/**
* The key of the current node within its parent node object, if applicable.
*/
key: string | number | symbol | null | undefined;
/**
* The zero-based index of the current node within its parent's children array, if applicable.
*/
index: number | null;
/**
* The full Abstract Syntax Tree (AST) that is being walked, starting from the root node.
*/
ast: Program | Node;
}
`####
this.skip()When called inside an
enter callback, prevents the node's children from being walked.
It is not available in leave.####
this.replace(newNode)Replaces the current node with
newNode. When called inside enter, the new node's children will be walked.
The leave callback will still be called with the original node.> ⚠️ When a
ScopeTracker is provided, calling this.replace() will not update its declarations.####
this.remove()Removes the current node from its parent. When called inside
enter, the removed node's children
will not be walked._This has a higher precedence than
this.replace(), so if both are called, the node will be removed._> ⚠️ When a
ScopeTracker is provided, calling this.remove() will not update its declarations.$3
Parse the source code using
oxc-parser, walk the resulting AST and return the ParseResult.Overloads:
-
parseAndWalk(code, filename, enter)
- parseAndWalk(code, filename, options)`ts
interface ParseAndWalkOptions {
/**
* The function to be called when entering a node.
*/
enter?: (node: Node, parent: Node | null, ctx: CallbackContext) => void;
/**
* The function to be called when leaving a node.
*/
leave?: (node: Node, parent: Node | null, ctx: CallbackContext) => void;
/**
* The instance of ScopeTracker to use for tracking declarations and references.
*/
scopeTracker?: ScopeTracker;
/**
* The options for oxc-parser to use when parsing the code.
*/
parseOptions?: ParserOptions;
}
`$3
A utility to track scopes and declarations while walking an AST. It is designed to be used with the
walk
function from this library.`ts
interface ScopeTrackerOptions {
/**
* If true, the scope tracker will preserve exited scopes in memory.
* @default false
*/
preserveExitedScopes?: boolean;
}
`#### Example usage:
`ts
import { parseAndWalk, ScopeTracker } from "oxc-walker";const scopeTracker = new ScopeTracker();
parseAndWalk("const x = 1; function foo() { console.log(x) }", "example.js", {
scopeTracker,
enter(node, parent) {
if (node.type === "Identifier" && node.name === "x" && parent?.type === "CallExpression") {
const declaration = scopeTracker.getDeclaration(node.name);
console.log(declaration); // ScopeTrackerVariable
}
},
});
``ts
import { parseAndWalk, ScopeTracker, walk } from "oxc-walker";const code =
const a = 1;
const scopeTracker = new ScopeTracker({
preserveExitedScopes: true,
});
// pre-pass to collect hoisted declarations
const { program } = parseAndWalk(code, "example.js", {
scopeTracker,
});
// freeze the scope tracker to prevent further modifications
// and prepare it for second pass
scopeTracker.freeze();
// main pass to analyze references
walk(program, {
scopeTracker,
enter(node) {
if (node.type === "CallExpression" && node.callee.type === "MemberExpression" / ... /) {
const declaration = scopeTracker.getDeclaration("a");
console.log(declaration); // ScopeTrackerVariable; would be null without the pre-pass`
}
},
});
#### Helpers:
- scopeTracker.isDeclared(name: string): boolean - check if an identifier is declared in reference to the current scopescopeTracker.getDeclaration(name: string): ScopeTrackerNode | null
- - get the scope tracker node with metadata for a given identifier name in reference to the current scopescopeTracker.freeze()
- - freeze the scope tracker to prevent further modifications and prepare for second pass (useful for multi-pass analysis)scopeTracker.getCurrentScope(): string
- - get the key of the current scope (a unique identifier for the scope, do not rely on its format)scopeTracker.isCurrentScopeUnder(scopeKey: string): boolean
- - check if the current scope is a child of the given scope key
- Clone this repository
- Enable Corepack using corepack enablepnpm install
- Install dependencies using pnpm dev`
- Run interactive tests using
Made with ❤️
Published under MIT License.
[npm-version-src]: https://img.shields.io/npm/v/oxc-walker?style=flat-square
[npm-version-href]: https://npmjs.com/package/oxc-walker
[npm-downloads-src]: https://img.shields.io/npm/dm/oxc-walker?style=flat-square
[npm-downloads-href]: https://npm.chart.dev/oxc-walker
[github-actions-src]: https://img.shields.io/github/actions/workflow/status/danielroe/oxc-walker/ci.yml?branch=main&style=flat-square
[github-actions-href]: https://github.com/danielroe/oxc-walker/actions?query=workflow%3Aci
[codecov-src]: https://img.shields.io/codecov/c/gh/danielroe/oxc-walker/main?style=flat-square
[codecov-href]: https://codecov.io/gh/danielroe/oxc-walker