yuku-ast 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -25
- package/dist/aliases.d.ts +0 -1
- package/dist/aliases.js +0 -1
- package/dist/context.d.ts +1 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -2
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
# yuku-ast
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Walk, build, and check any ESTree / TypeScript-ESTree AST, with typed visitors, in-place mutation, builders, guards, and syntactic utilities, part of [Yuku](https://yuku.fyi).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
It is plain JavaScript and works on any ESTree AST, whichever parser produced it. Traversal order comes from tables generated from Yuku's AST definition, so it never drifts from the parser, and there is no runtime key discovery.
|
|
6
|
+
|
|
7
|
+
- [Install](#install)
|
|
8
|
+
- [Walking](#walking)
|
|
9
|
+
- [Builders](#builders)
|
|
10
|
+
- [Guards](#guards)
|
|
11
|
+
- [Imports and exports](#imports-and-exports)
|
|
12
|
+
- [Utilities](#utilities)
|
|
13
|
+
- [Identifier names](#identifier-names)
|
|
6
14
|
|
|
7
15
|
## Install
|
|
8
16
|
|
|
@@ -12,8 +20,6 @@ npm install yuku-ast
|
|
|
12
20
|
|
|
13
21
|
## Walking
|
|
14
22
|
|
|
15
|
-
Handlers are keyed by node `type`, by alias group, or the universal `enter` / `leave`. Every handler receives the exact node type.
|
|
16
|
-
|
|
17
23
|
```ts
|
|
18
24
|
import { parse } from "yuku-parser";
|
|
19
25
|
import { walk } from "yuku-ast";
|
|
@@ -29,31 +35,78 @@ walk(program, {
|
|
|
29
35
|
leave(node, ctx) {},
|
|
30
36
|
},
|
|
31
37
|
Function(node) {
|
|
32
|
-
//
|
|
38
|
+
// function declarations, expressions, and arrows
|
|
33
39
|
},
|
|
34
40
|
enter(node) {},
|
|
35
41
|
});
|
|
36
42
|
```
|
|
37
43
|
|
|
38
|
-
|
|
44
|
+
Handlers are keyed by node `type`, by alias group, or by the universal `enter` / `leave`, and receive the exact node type. The alias groups are `Expression`, `Statement`, `Declaration`, `ModuleDeclaration`, `Function`, `Class`, `Method`, `Loop`, `Pattern`, `JSX`, and `TSType`. Per node, the order is the universal `enter`, alias enters, the typed enter, the children, then the same in reverse for leave.
|
|
45
|
+
|
|
46
|
+
An optional third argument threads state to every handler as `ctx.state`. `walkAsync` is the async counterpart, with the same traversal order and mutation semantics and every handler awaited before the walk moves on.
|
|
47
|
+
|
|
48
|
+
### The context
|
|
49
|
+
|
|
50
|
+
One context object is reused across the whole walk, so do not store it.
|
|
51
|
+
|
|
52
|
+
```js
|
|
53
|
+
ctx.node; // the current node
|
|
54
|
+
ctx.parent; // its parent, or null at the walk root
|
|
55
|
+
ctx.key; // the field on the parent holding this node
|
|
56
|
+
ctx.index; // position in an array field, or null
|
|
57
|
+
ctx.ancestors(); // a copy of the ancestor chain, root first
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Mutation
|
|
61
|
+
|
|
62
|
+
Handlers can mutate the AST in place.
|
|
39
63
|
|
|
40
|
-
|
|
64
|
+
| Operation | Effect |
|
|
65
|
+
| ------------------------ | -------------------------------------------------------------------------------------------------------------- |
|
|
66
|
+
| `ctx.skip()` | Do not descend into this node's children. `leave` still fires. |
|
|
67
|
+
| `ctx.stop()` | End the walk immediately. |
|
|
68
|
+
| `ctx.replace(node)` | Swap the current node. The walk continues into the replacement's children and `leave` fires for its new type. |
|
|
69
|
+
| `ctx.remove()` | Splice the node out of an array field, or null a plain field. Children are not walked, `leave` does not fire. |
|
|
70
|
+
| `ctx.insertBefore(node)` | Insert a sibling before the current node. The inserted node is not visited. |
|
|
71
|
+
| `ctx.insertAfter(node)` | Insert a sibling after the current node. The walk visits it. |
|
|
41
72
|
|
|
42
|
-
|
|
73
|
+
A replacement created with `start: 0, end: 0`, such as a [builder](#builders) node, inherits the original node's span, which keeps source maps meaningful through [`yuku-codegen`](https://www.npmjs.com/package/yuku-codegen).
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
walk(program, {
|
|
77
|
+
DebuggerStatement(node, ctx) {
|
|
78
|
+
ctx.remove();
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### findAll
|
|
84
|
+
|
|
85
|
+
`findAll` collects every node of the given types, in source order.
|
|
86
|
+
|
|
87
|
+
```js
|
|
88
|
+
import { findAll } from "yuku-ast";
|
|
89
|
+
|
|
90
|
+
findAll(program, "CallExpression");
|
|
91
|
+
findAll(program, ["ClassDeclaration", "TSInterfaceDeclaration"]);
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
`CHILD_KEYS` maps each node type to its child fields in traversal order, for walkers of your own.
|
|
43
95
|
|
|
44
96
|
## Builders
|
|
45
97
|
|
|
46
|
-
|
|
98
|
+
`b` has one typed constructor per node type, its fields derived from the node type itself, so a builder never drifts from the AST. Spans default to 0, which `ctx.replace` fills from the replaced node.
|
|
47
99
|
|
|
48
100
|
```ts
|
|
49
101
|
import { b } from "yuku-ast";
|
|
50
102
|
|
|
51
|
-
b.Identifier({ name: "x" });
|
|
52
103
|
b.CallExpression({ callee: b.Identifier({ name: "f" }), arguments: [], optional: false });
|
|
53
104
|
```
|
|
54
105
|
|
|
55
106
|
## Guards
|
|
56
107
|
|
|
108
|
+
`is` has one guard per node type, per alias group, and for the shapes ESTree folds into one type: literal kinds, member expression kinds, and directives. Every guard accepts `null` and `undefined` and narrows.
|
|
109
|
+
|
|
57
110
|
```ts
|
|
58
111
|
import { is } from "yuku-ast";
|
|
59
112
|
|
|
@@ -66,12 +119,12 @@ is.StaticMemberExpression(node);
|
|
|
66
119
|
is.Directive(node);
|
|
67
120
|
```
|
|
68
121
|
|
|
69
|
-
|
|
122
|
+
## Imports and exports
|
|
70
123
|
|
|
71
|
-
|
|
124
|
+
`collectImports` and `collectExports` read a module's import and export declarations, one record per bound name, destructuring included.
|
|
72
125
|
|
|
73
126
|
```ts
|
|
74
|
-
import {
|
|
127
|
+
import { collectExports, collectImports } from "yuku-ast";
|
|
75
128
|
|
|
76
129
|
for (const record of collectImports(program)) {
|
|
77
130
|
record.source; // "./m"
|
|
@@ -82,14 +135,14 @@ for (const record of collectImports(program)) {
|
|
|
82
135
|
}
|
|
83
136
|
|
|
84
137
|
for (const record of collectExports(program)) {
|
|
85
|
-
record.exported; // the exported name, null for bare export *
|
|
138
|
+
record.exported; // the exported name, null for a bare export *
|
|
86
139
|
record.local; // the backing local name, when there is one
|
|
87
140
|
record.source; // the re-export specifier, when there is one
|
|
88
141
|
record.typeOnly;
|
|
89
142
|
}
|
|
90
143
|
```
|
|
91
144
|
|
|
92
|
-
|
|
145
|
+
`collectImportDeclaration` and `collectExportDeclaration` return the records of a single statement, for use inside a walk.
|
|
93
146
|
|
|
94
147
|
```ts
|
|
95
148
|
walk(program, {
|
|
@@ -103,28 +156,31 @@ walk(program, {
|
|
|
103
156
|
|
|
104
157
|
```ts
|
|
105
158
|
import {
|
|
106
|
-
nameOf, // Identifier name or string Literal value
|
|
107
|
-
literalValue, // string | number | boolean | bigint | RegExp | null
|
|
108
|
-
unwrap, // strips parens and erased TS assertion wrappers
|
|
109
|
-
isWrapper, // true for the wrappers unwrap strips
|
|
110
|
-
isCallOf, // isCallOf(node, "require")
|
|
111
159
|
bindingIdentifiers, // every binding Identifier a pattern introduces
|
|
112
|
-
|
|
160
|
+
isCallOf, // isCallOf(node, "require")
|
|
161
|
+
isWrapper, // true for the wrappers unwrap strips
|
|
162
|
+
literalValue, // string | number | boolean | bigint | RegExp | null
|
|
163
|
+
nameOf, // Identifier name or string Literal value
|
|
164
|
+
unwrap, // strips parens and erased TypeScript assertion wrappers
|
|
113
165
|
} from "yuku-ast";
|
|
114
166
|
```
|
|
115
167
|
|
|
116
|
-
##
|
|
168
|
+
## Identifier names
|
|
117
169
|
|
|
118
170
|
```ts
|
|
119
|
-
import {
|
|
171
|
+
import { isIdentifierName, isValidIdentifier } from "yuku-ast";
|
|
120
172
|
|
|
121
173
|
isValidIdentifier("foo"); // true
|
|
122
174
|
isValidIdentifier("class"); // false, reserved
|
|
123
175
|
isIdentifierName("class"); // true, syntactically an IdentifierName
|
|
124
176
|
```
|
|
125
177
|
|
|
126
|
-
Plus `isIdentifierStart`, `isIdentifierChar`, `isReservedWord`, `isStrictReservedWord`, `isStrictBindReservedWord`, `isStrictBindOnlyReservedWord`.
|
|
178
|
+
Plus `isIdentifierStart`, `isIdentifierChar`, `isKeyword`, `isReservedWord`, `isStrictReservedWord`, `isStrictBindReservedWord`, and `isStrictBindOnlyReservedWord`.
|
|
127
179
|
|
|
128
180
|
## Semantic analysis
|
|
129
181
|
|
|
130
|
-
[`yuku-analyzer`](https://www.npmjs.com/package/yuku-analyzer) builds on this walker
|
|
182
|
+
[`yuku-analyzer`](https://www.npmjs.com/package/yuku-analyzer) builds on this walker. Its `module.walk` carries the semantic model in the context, as `ctx.scope`, `ctx.symbol`, and `ctx.reference`.
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
package/dist/aliases.d.ts
CHANGED
package/dist/aliases.js
CHANGED
package/dist/context.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Node } from "@yuku-toolchain/types";
|
|
2
|
-
interface Frame {
|
|
2
|
+
export interface Frame {
|
|
3
3
|
i: number;
|
|
4
4
|
}
|
|
5
5
|
/**
|
|
@@ -52,4 +52,3 @@ export declare class WalkContext<T extends Node = Node, S = unknown> {
|
|
|
52
52
|
/** Insert a sibling after the current node, visited by the walk. Array fields only. */
|
|
53
53
|
insertAfter(node: Node): void;
|
|
54
54
|
}
|
|
55
|
-
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export type { AliasMap, AliasName } from "./aliases.js";
|
|
2
2
|
export { b } from "./builders.js";
|
|
3
3
|
export { WalkContext } from "./context.js";
|
|
4
|
-
export { CHILD_KEYS
|
|
4
|
+
export { CHILD_KEYS } from "./generated.js";
|
|
5
5
|
export { isIdentifierChar, isIdentifierName, isIdentifierStart, isKeyword, isReservedWord, isStrictBindOnlyReservedWord, isStrictBindReservedWord, isStrictReservedWord, isValidIdentifier, } from "./identifier.js";
|
|
6
6
|
export { is } from "./is.js";
|
|
7
7
|
export { collectExportDeclaration, collectExports, collectImportDeclaration, collectImports, type CollectedExport, type CollectedImport, } from "./modules.js";
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export { ALIAS_GROUPS, ALIAS_NAMES } from "./aliases.js";
|
|
2
1
|
export { b } from "./builders.js";
|
|
3
2
|
export { WalkContext } from "./context.js";
|
|
4
|
-
export { CHILD_KEYS
|
|
3
|
+
export { CHILD_KEYS } from "./generated.js";
|
|
5
4
|
export { isIdentifierChar, isIdentifierName, isIdentifierStart, isKeyword, isReservedWord, isStrictBindOnlyReservedWord, isStrictBindReservedWord, isStrictReservedWord, isValidIdentifier, } from "./identifier.js";
|
|
6
5
|
export { is } from "./is.js";
|
|
7
6
|
export { collectExportDeclaration, collectExports, collectImportDeclaration, collectImports, } from "./modules.js";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yuku-ast",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.14.0",
|
|
4
|
+
"description": "Walk, build, and check any ESTree / TypeScript-ESTree AST, with typed visitors, builders, and guards",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
"type": "module",
|
|
11
11
|
"main": "./dist/index.js",
|
|
12
12
|
"types": "./dist/index.d.ts",
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=14.18.0"
|
|
15
|
+
},
|
|
13
16
|
"exports": {
|
|
14
17
|
".": "./dist/index.js",
|
|
15
18
|
"./package.json": "./package.json"
|
|
@@ -21,7 +24,7 @@
|
|
|
21
24
|
"build": "tsc -p tsconfig.json"
|
|
22
25
|
},
|
|
23
26
|
"dependencies": {
|
|
24
|
-
"@yuku-toolchain/types": "^0.
|
|
27
|
+
"@yuku-toolchain/types": "^0.14.0"
|
|
25
28
|
},
|
|
26
29
|
"keywords": [
|
|
27
30
|
"ast",
|