feat: init
This commit is contained in:
236
node_modules/oxc-walker/README.md
generated
vendored
Normal file
236
node_modules/oxc-walker/README.md
generated
vendored
Normal file
@@ -0,0 +1,236 @@
|
||||
# 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](https://github.com/oxc-project/oxc).
|
||||
|
||||
## Usage
|
||||
|
||||
Install package:
|
||||
|
||||
```sh
|
||||
# npm
|
||||
npm install oxc-walker
|
||||
|
||||
# pnpm
|
||||
pnpm install oxc-walker
|
||||
```
|
||||
|
||||
### Walk a parsed AST
|
||||
|
||||
```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) {
|
||||
// ...
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Parse and walk directly
|
||||
|
||||
```js
|
||||
import { parseAndWalk } from "oxc-walker";
|
||||
|
||||
parseAndWalk("const x = 1", "example.js", (node, parent, ctx) => {
|
||||
// ...
|
||||
});
|
||||
```
|
||||
|
||||
## ⚙️ API
|
||||
|
||||
### `walk(ast, options)`
|
||||
|
||||
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.
|
||||
|
||||
### `parseAndWalk(source, filename, callback, options?)`
|
||||
|
||||
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;
|
||||
}
|
||||
```
|
||||
|
||||
### `ScopeTracker`
|
||||
|
||||
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 = `
|
||||
function foo() {
|
||||
console.log(a)
|
||||
}
|
||||
|
||||
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 scope
|
||||
- `scopeTracker.getDeclaration(name: string): ScopeTrackerNode | null` - get the scope tracker node with metadata for a given identifier name in reference to the current scope
|
||||
- `scopeTracker.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
|
||||
|
||||
## 💻 Development
|
||||
|
||||
- Clone this repository
|
||||
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
|
||||
- Install dependencies using `pnpm install`
|
||||
- Run interactive tests using `pnpm dev`
|
||||
|
||||
## License
|
||||
|
||||
Made with ❤️
|
||||
|
||||
Published under [MIT License](./LICENCE).
|
||||
|
||||
<!-- Badges -->
|
||||
|
||||
[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
|
||||
Reference in New Issue
Block a user