yuku-parser 0.6.5 → 0.6.6
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 +4 -28
- package/decode.js +1 -185
- package/index.d.ts +0 -6
- package/index.js +0 -2
- package/package.json +14 -15
- package/walk.js +0 -184
package/README.md
CHANGED
|
@@ -60,45 +60,21 @@ sourceTypeFromPath("foo.mjs"); // "module"
|
|
|
60
60
|
|
|
61
61
|
## Walking the AST
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
The AST is standard ESTree, and [`yuku-ast`](https://www.npmjs.com/package/yuku-ast) walks it with typed visitors, alias groups, in-place mutation, and syntactic utilities:
|
|
64
64
|
|
|
65
65
|
```ts
|
|
66
|
-
import { parse
|
|
66
|
+
import { parse } from "yuku-parser";
|
|
67
|
+
import { walk } from "yuku-ast";
|
|
67
68
|
|
|
68
|
-
const { program } = parse(`
|
|
69
|
-
const message = "hello";
|
|
70
|
-
console.log(message);
|
|
71
|
-
`);
|
|
69
|
+
const { program } = parse(`console.log("hello");`);
|
|
72
70
|
|
|
73
71
|
walk(program, {
|
|
74
72
|
Identifier(node) {
|
|
75
73
|
console.log(node.name);
|
|
76
74
|
},
|
|
77
|
-
CallExpression: {
|
|
78
|
-
enter(node, ctx) { /* before children */ },
|
|
79
|
-
leave(node, ctx) { /* after children */ },
|
|
80
|
-
},
|
|
81
|
-
enter(node) { /* every node */ },
|
|
82
|
-
});
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
The context exposes the position (`ctx.parent`, `ctx.key`, `ctx.index`, `ctx.ancestors()`), flow control (`ctx.skip()`, `ctx.stop()`), and in-place mutation:
|
|
86
|
-
|
|
87
|
-
```ts
|
|
88
|
-
walk(program, {
|
|
89
|
-
DebuggerStatement(node, ctx) {
|
|
90
|
-
ctx.remove();
|
|
91
|
-
},
|
|
92
|
-
Literal(node, ctx) {
|
|
93
|
-
if (node.value === 1) ctx.replace({ type: "Identifier", start: 0, end: 0, name: "ONE" });
|
|
94
|
-
},
|
|
95
75
|
});
|
|
96
76
|
```
|
|
97
77
|
|
|
98
|
-
`ctx.replace(node)` continues the walk into the replacement, `ctx.remove()` skips the removed subtree, `ctx.insertBefore(node)` inserts a sibling without visiting it, and `ctx.insertAfter(node)` inserts one the walk will visit. An optional third argument threads state to every handler as `ctx.state`.
|
|
99
|
-
|
|
100
|
-
The AST is also standard ESTree, so any ESTree-compatible walker works as well.
|
|
101
|
-
|
|
102
78
|
## Semantic analysis
|
|
103
79
|
|
|
104
80
|
[`yuku-analyzer`](https://www.npmjs.com/package/yuku-analyzer) builds on this parser and adds full semantics: scopes, symbols, resolved references, closure analysis, and cross-file module linking, computed natively in the same pass. Its walk carries the semantic model in context (`ctx.scope`, `ctx.symbol`, `ctx.reference`). See the [analyzer documentation](https://yuku.fyi/analyzer).
|
package/decode.js
CHANGED
|
@@ -19,190 +19,6 @@ const TS_METHOD_SIGNATURE_KINDS = ["method", "get", "set"];
|
|
|
19
19
|
const TS_MODULE_KINDS = ["namespace", "module"];
|
|
20
20
|
const TS_MAPPED_OPTIONAL = [false, true, "+", "-"];
|
|
21
21
|
const TS_MAPPED_READONLY = [null, true, "+", "-"];
|
|
22
|
-
const CHILD_KEYS = Object.create(null);
|
|
23
|
-
function _ck(type, keys) {
|
|
24
|
-
const prev = CHILD_KEYS[type];
|
|
25
|
-
if (prev === undefined) CHILD_KEYS[type] = keys;
|
|
26
|
-
else for (const k of keys) if (!prev.includes(k)) prev.push(k);
|
|
27
|
-
}
|
|
28
|
-
_ck("SequenceExpression", ["expressions"]);
|
|
29
|
-
_ck("ParenthesizedExpression", ["expression"]);
|
|
30
|
-
_ck("ArrowFunctionExpression", ["typeParameters", "params", "returnType", "body"]);
|
|
31
|
-
_ck("FunctionDeclaration", ["id", "typeParameters", "params", "returnType", "body"]);
|
|
32
|
-
_ck("FunctionExpression", ["id", "typeParameters", "params", "returnType", "body"]);
|
|
33
|
-
_ck("TSDeclareFunction", ["id", "typeParameters", "params", "returnType", "body"]);
|
|
34
|
-
_ck("TSEmptyBodyFunctionExpression", ["id", "typeParameters", "params", "returnType", "body"]);
|
|
35
|
-
_ck("BlockStatement", ["body"]);
|
|
36
|
-
_ck("BlockStatement", ["body"]);
|
|
37
|
-
_ck("BinaryExpression", ["left", "right"]);
|
|
38
|
-
_ck("LogicalExpression", ["left", "right"]);
|
|
39
|
-
_ck("ConditionalExpression", ["test", "consequent", "alternate"]);
|
|
40
|
-
_ck("UnaryExpression", ["argument"]);
|
|
41
|
-
_ck("UpdateExpression", ["argument"]);
|
|
42
|
-
_ck("AssignmentExpression", ["left", "right"]);
|
|
43
|
-
_ck("ArrayExpression", ["elements"]);
|
|
44
|
-
_ck("ObjectExpression", ["properties"]);
|
|
45
|
-
_ck("SpreadElement", ["argument"]);
|
|
46
|
-
_ck("Property", ["key", "value"]);
|
|
47
|
-
_ck("MemberExpression", ["object", "property"]);
|
|
48
|
-
_ck("CallExpression", ["callee", "typeArguments", "arguments"]);
|
|
49
|
-
_ck("ChainExpression", ["expression"]);
|
|
50
|
-
_ck("TaggedTemplateExpression", ["tag", "typeArguments", "quasi"]);
|
|
51
|
-
_ck("NewExpression", ["callee", "typeArguments", "arguments"]);
|
|
52
|
-
_ck("AwaitExpression", ["argument"]);
|
|
53
|
-
_ck("YieldExpression", ["argument"]);
|
|
54
|
-
_ck("MetaProperty", ["meta", "property"]);
|
|
55
|
-
_ck("Decorator", ["expression"]);
|
|
56
|
-
_ck("ClassDeclaration", ["decorators", "id", "typeParameters", "superClass", "superTypeArguments", "implements", "body"]);
|
|
57
|
-
_ck("ClassExpression", ["decorators", "id", "typeParameters", "superClass", "superTypeArguments", "implements", "body"]);
|
|
58
|
-
_ck("ClassBody", ["body"]);
|
|
59
|
-
_ck("MethodDefinition", ["decorators", "key", "value"]);
|
|
60
|
-
_ck("TSAbstractMethodDefinition", ["decorators", "key", "value"]);
|
|
61
|
-
_ck("PropertyDefinition", ["decorators", "key", "typeAnnotation", "value"]);
|
|
62
|
-
_ck("AccessorProperty", ["decorators", "key", "typeAnnotation", "value"]);
|
|
63
|
-
_ck("TSAbstractPropertyDefinition", ["decorators", "key", "typeAnnotation", "value"]);
|
|
64
|
-
_ck("TSAbstractAccessorProperty", ["decorators", "key", "typeAnnotation", "value"]);
|
|
65
|
-
_ck("StaticBlock", ["body"]);
|
|
66
|
-
_ck("Super", []);
|
|
67
|
-
_ck("Literal", []);
|
|
68
|
-
_ck("Literal", []);
|
|
69
|
-
_ck("Literal", []);
|
|
70
|
-
_ck("Literal", []);
|
|
71
|
-
_ck("Literal", []);
|
|
72
|
-
_ck("ThisExpression", []);
|
|
73
|
-
_ck("Literal", []);
|
|
74
|
-
_ck("TemplateLiteral", ["quasis", "expressions"]);
|
|
75
|
-
_ck("TemplateElement", []);
|
|
76
|
-
_ck("Identifier", []);
|
|
77
|
-
_ck("PrivateIdentifier", []);
|
|
78
|
-
_ck("Identifier", ["decorators", "typeAnnotation"]);
|
|
79
|
-
_ck("Identifier", []);
|
|
80
|
-
_ck("Identifier", []);
|
|
81
|
-
_ck("ExpressionStatement", ["expression"]);
|
|
82
|
-
_ck("IfStatement", ["test", "consequent", "alternate"]);
|
|
83
|
-
_ck("SwitchStatement", ["discriminant", "cases"]);
|
|
84
|
-
_ck("SwitchCase", ["test", "consequent"]);
|
|
85
|
-
_ck("ForStatement", ["init", "test", "update", "body"]);
|
|
86
|
-
_ck("ForInStatement", ["left", "right", "body"]);
|
|
87
|
-
_ck("ForOfStatement", ["left", "right", "body"]);
|
|
88
|
-
_ck("WhileStatement", ["test", "body"]);
|
|
89
|
-
_ck("DoWhileStatement", ["body", "test"]);
|
|
90
|
-
_ck("BreakStatement", ["label"]);
|
|
91
|
-
_ck("ContinueStatement", ["label"]);
|
|
92
|
-
_ck("LabeledStatement", ["label", "body"]);
|
|
93
|
-
_ck("WithStatement", ["object", "body"]);
|
|
94
|
-
_ck("ReturnStatement", ["argument"]);
|
|
95
|
-
_ck("ThrowStatement", ["argument"]);
|
|
96
|
-
_ck("TryStatement", ["block", "handler", "finalizer"]);
|
|
97
|
-
_ck("CatchClause", ["param", "body"]);
|
|
98
|
-
_ck("DebuggerStatement", []);
|
|
99
|
-
_ck("EmptyStatement", []);
|
|
100
|
-
_ck("VariableDeclaration", ["declarations"]);
|
|
101
|
-
_ck("VariableDeclarator", ["id", "init"]);
|
|
102
|
-
_ck("ExpressionStatement", ["expression"]);
|
|
103
|
-
_ck("AssignmentPattern", ["decorators", "left", "typeAnnotation", "right"]);
|
|
104
|
-
_ck("RestElement", ["decorators", "argument", "typeAnnotation"]);
|
|
105
|
-
_ck("ArrayPattern", ["decorators", "elements", "typeAnnotation"]);
|
|
106
|
-
_ck("ObjectPattern", ["decorators", "properties", "typeAnnotation"]);
|
|
107
|
-
_ck("Property", ["key", "value"]);
|
|
108
|
-
_ck("Program", ["hashbang", "body"]);
|
|
109
|
-
_ck("ImportExpression", ["source", "options"]);
|
|
110
|
-
_ck("ImportDeclaration", ["specifiers", "source", "attributes"]);
|
|
111
|
-
_ck("ImportSpecifier", ["imported", "local"]);
|
|
112
|
-
_ck("ImportDefaultSpecifier", ["local"]);
|
|
113
|
-
_ck("ImportNamespaceSpecifier", ["local"]);
|
|
114
|
-
_ck("ImportAttribute", ["key", "value"]);
|
|
115
|
-
_ck("ExportNamedDeclaration", ["declaration", "specifiers", "source", "attributes"]);
|
|
116
|
-
_ck("ExportDefaultDeclaration", ["declaration"]);
|
|
117
|
-
_ck("ExportAllDeclaration", ["exported", "source", "attributes"]);
|
|
118
|
-
_ck("ExportSpecifier", ["local", "exported"]);
|
|
119
|
-
_ck("TSTypeAnnotation", ["typeAnnotation"]);
|
|
120
|
-
_ck("TSAnyKeyword", []);
|
|
121
|
-
_ck("TSUnknownKeyword", []);
|
|
122
|
-
_ck("TSNeverKeyword", []);
|
|
123
|
-
_ck("TSVoidKeyword", []);
|
|
124
|
-
_ck("TSNullKeyword", []);
|
|
125
|
-
_ck("TSUndefinedKeyword", []);
|
|
126
|
-
_ck("TSStringKeyword", []);
|
|
127
|
-
_ck("TSNumberKeyword", []);
|
|
128
|
-
_ck("TSBigIntKeyword", []);
|
|
129
|
-
_ck("TSBooleanKeyword", []);
|
|
130
|
-
_ck("TSSymbolKeyword", []);
|
|
131
|
-
_ck("TSObjectKeyword", []);
|
|
132
|
-
_ck("TSIntrinsicKeyword", []);
|
|
133
|
-
_ck("TSThisType", []);
|
|
134
|
-
_ck("TSTypeReference", ["typeName", "typeArguments"]);
|
|
135
|
-
_ck("TSQualifiedName", ["left", "right"]);
|
|
136
|
-
_ck("TSTypeQuery", ["exprName", "typeArguments"]);
|
|
137
|
-
_ck("TSImportType", ["source", "options", "qualifier", "typeArguments"]);
|
|
138
|
-
_ck("TSTypeParameter", ["name", "constraint", "default"]);
|
|
139
|
-
_ck("TSTypeParameterDeclaration", ["params"]);
|
|
140
|
-
_ck("TSTypeParameterInstantiation", ["params"]);
|
|
141
|
-
_ck("TSLiteralType", ["literal"]);
|
|
142
|
-
_ck("TSTemplateLiteralType", ["quasis", "types"]);
|
|
143
|
-
_ck("TSArrayType", ["elementType"]);
|
|
144
|
-
_ck("TSIndexedAccessType", ["objectType", "indexType"]);
|
|
145
|
-
_ck("TSTupleType", ["elementTypes"]);
|
|
146
|
-
_ck("TSNamedTupleMember", ["label", "elementType"]);
|
|
147
|
-
_ck("TSOptionalType", ["typeAnnotation"]);
|
|
148
|
-
_ck("TSRestType", ["typeAnnotation"]);
|
|
149
|
-
_ck("TSJSDocNullableType", ["typeAnnotation"]);
|
|
150
|
-
_ck("TSJSDocNonNullableType", ["typeAnnotation"]);
|
|
151
|
-
_ck("TSJSDocUnknownType", []);
|
|
152
|
-
_ck("TSUnionType", ["types"]);
|
|
153
|
-
_ck("TSIntersectionType", ["types"]);
|
|
154
|
-
_ck("TSConditionalType", ["checkType", "extendsType", "trueType", "falseType"]);
|
|
155
|
-
_ck("TSInferType", ["typeParameter"]);
|
|
156
|
-
_ck("TSTypeOperator", ["typeAnnotation"]);
|
|
157
|
-
_ck("TSParenthesizedType", ["typeAnnotation"]);
|
|
158
|
-
_ck("TSFunctionType", ["typeParameters", "params", "returnType"]);
|
|
159
|
-
_ck("TSConstructorType", ["typeParameters", "params", "returnType"]);
|
|
160
|
-
_ck("TSTypePredicate", ["parameterName", "typeAnnotation"]);
|
|
161
|
-
_ck("TSTypeLiteral", ["members"]);
|
|
162
|
-
_ck("TSMappedType", ["key", "constraint", "nameType", "typeAnnotation"]);
|
|
163
|
-
_ck("TSPropertySignature", ["key", "typeAnnotation"]);
|
|
164
|
-
_ck("TSMethodSignature", ["key", "typeParameters", "params", "returnType"]);
|
|
165
|
-
_ck("TSCallSignatureDeclaration", ["typeParameters", "params", "returnType"]);
|
|
166
|
-
_ck("TSConstructSignatureDeclaration", ["typeParameters", "params", "returnType"]);
|
|
167
|
-
_ck("TSIndexSignature", ["parameters", "typeAnnotation"]);
|
|
168
|
-
_ck("TSTypeAliasDeclaration", ["id", "typeParameters", "typeAnnotation"]);
|
|
169
|
-
_ck("TSInterfaceDeclaration", ["id", "typeParameters", "extends", "body"]);
|
|
170
|
-
_ck("TSInterfaceBody", ["body"]);
|
|
171
|
-
_ck("TSInterfaceHeritage", ["expression", "typeArguments"]);
|
|
172
|
-
_ck("TSClassImplements", ["expression", "typeArguments"]);
|
|
173
|
-
_ck("TSEnumDeclaration", ["id", "body"]);
|
|
174
|
-
_ck("TSEnumBody", ["members"]);
|
|
175
|
-
_ck("TSEnumMember", ["id", "initializer"]);
|
|
176
|
-
_ck("TSModuleDeclaration", ["id", "body"]);
|
|
177
|
-
_ck("TSModuleBlock", ["body"]);
|
|
178
|
-
_ck("TSModuleDeclaration", ["id", "body"]);
|
|
179
|
-
_ck("TSParameterProperty", ["decorators", "parameter"]);
|
|
180
|
-
_ck("Identifier", ["typeAnnotation"]);
|
|
181
|
-
_ck("TSAsExpression", ["expression", "typeAnnotation"]);
|
|
182
|
-
_ck("TSSatisfiesExpression", ["expression", "typeAnnotation"]);
|
|
183
|
-
_ck("TSTypeAssertion", ["typeAnnotation", "expression"]);
|
|
184
|
-
_ck("TSNonNullExpression", ["expression"]);
|
|
185
|
-
_ck("TSInstantiationExpression", ["expression", "typeArguments"]);
|
|
186
|
-
_ck("TSExportAssignment", ["expression"]);
|
|
187
|
-
_ck("TSNamespaceExportDeclaration", ["id"]);
|
|
188
|
-
_ck("TSImportEqualsDeclaration", ["id", "moduleReference"]);
|
|
189
|
-
_ck("TSExternalModuleReference", ["expression"]);
|
|
190
|
-
_ck("JSXElement", ["openingElement", "children", "closingElement"]);
|
|
191
|
-
_ck("JSXOpeningElement", ["name", "typeArguments", "attributes"]);
|
|
192
|
-
_ck("JSXClosingElement", ["name"]);
|
|
193
|
-
_ck("JSXFragment", ["openingFragment", "children", "closingFragment"]);
|
|
194
|
-
_ck("JSXOpeningFragment", []);
|
|
195
|
-
_ck("JSXClosingFragment", []);
|
|
196
|
-
_ck("JSXIdentifier", []);
|
|
197
|
-
_ck("JSXNamespacedName", ["namespace", "name"]);
|
|
198
|
-
_ck("JSXMemberExpression", ["object", "property"]);
|
|
199
|
-
_ck("JSXAttribute", ["name", "value"]);
|
|
200
|
-
_ck("JSXSpreadAttribute", ["argument"]);
|
|
201
|
-
_ck("JSXExpressionContainer", ["expression"]);
|
|
202
|
-
_ck("JSXEmptyExpression", []);
|
|
203
|
-
_ck("JSXText", []);
|
|
204
|
-
_ck("JSXSpreadChild", ["expression"]);
|
|
205
|
-
_ck("Hashbang", []);
|
|
206
22
|
function buildPosMap(src, byteLen, startByte) {
|
|
207
23
|
const m = new Uint32Array(byteLen - startByte + 1);
|
|
208
24
|
const len = src.length;
|
|
@@ -845,4 +661,4 @@ function decode(buffer, source) {
|
|
|
845
661
|
},
|
|
846
662
|
};
|
|
847
663
|
}
|
|
848
|
-
export { decode
|
|
664
|
+
export { decode };
|
package/index.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
// yuku-parser's public type surface. The AST, diagnostic, and traversal type
|
|
2
|
-
// model lives in @yuku-toolchain/types and is re-exported here for backward
|
|
3
|
-
// compatibility; this file adds only the parser's own parse/walk API.
|
|
4
|
-
|
|
5
1
|
import type {
|
|
6
2
|
Comment,
|
|
7
3
|
Diagnostic,
|
|
@@ -16,8 +12,6 @@ import type {
|
|
|
16
12
|
|
|
17
13
|
export * from "@yuku-toolchain/types";
|
|
18
14
|
|
|
19
|
-
// Parsing
|
|
20
|
-
|
|
21
15
|
/** Options for configuring the parser. */
|
|
22
16
|
interface ParseOptions {
|
|
23
17
|
/**
|
package/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yuku-parser",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.6",
|
|
4
4
|
"description": "High-performance JavaScript/TypeScript parser",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -14,24 +14,23 @@
|
|
|
14
14
|
"index.js",
|
|
15
15
|
"index.d.ts",
|
|
16
16
|
"binding.js",
|
|
17
|
-
"decode.js"
|
|
18
|
-
"walk.js"
|
|
17
|
+
"decode.js"
|
|
19
18
|
],
|
|
20
19
|
"optionalDependencies": {
|
|
21
|
-
"@yuku-parser/binding-linux-x64-gnu": "0.6.
|
|
22
|
-
"@yuku-parser/binding-linux-arm64-gnu": "0.6.
|
|
23
|
-
"@yuku-parser/binding-linux-arm-gnu": "0.6.
|
|
24
|
-
"@yuku-parser/binding-linux-x64-musl": "0.6.
|
|
25
|
-
"@yuku-parser/binding-linux-arm64-musl": "0.6.
|
|
26
|
-
"@yuku-parser/binding-linux-arm-musl": "0.6.
|
|
27
|
-
"@yuku-parser/binding-darwin-x64": "0.6.
|
|
28
|
-
"@yuku-parser/binding-darwin-arm64": "0.6.
|
|
29
|
-
"@yuku-parser/binding-win32-x64": "0.6.
|
|
30
|
-
"@yuku-parser/binding-win32-arm64": "0.6.
|
|
31
|
-
"@yuku-parser/binding-freebsd-x64": "0.6.
|
|
20
|
+
"@yuku-parser/binding-linux-x64-gnu": "0.6.6",
|
|
21
|
+
"@yuku-parser/binding-linux-arm64-gnu": "0.6.6",
|
|
22
|
+
"@yuku-parser/binding-linux-arm-gnu": "0.6.6",
|
|
23
|
+
"@yuku-parser/binding-linux-x64-musl": "0.6.6",
|
|
24
|
+
"@yuku-parser/binding-linux-arm64-musl": "0.6.6",
|
|
25
|
+
"@yuku-parser/binding-linux-arm-musl": "0.6.6",
|
|
26
|
+
"@yuku-parser/binding-darwin-x64": "0.6.6",
|
|
27
|
+
"@yuku-parser/binding-darwin-arm64": "0.6.6",
|
|
28
|
+
"@yuku-parser/binding-win32-x64": "0.6.6",
|
|
29
|
+
"@yuku-parser/binding-win32-arm64": "0.6.6",
|
|
30
|
+
"@yuku-parser/binding-freebsd-x64": "0.6.6"
|
|
32
31
|
},
|
|
33
32
|
"dependencies": {
|
|
34
|
-
"@yuku-toolchain/types": "0.5
|
|
33
|
+
"@yuku-toolchain/types": "0.6.5"
|
|
35
34
|
},
|
|
36
35
|
"keywords": [
|
|
37
36
|
"acorn",
|
package/walk.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
import { CHILD_KEYS } from "./decode.js";
|
|
2
|
-
|
|
3
|
-
export class WalkContext {
|
|
4
|
-
_ancestors = [];
|
|
5
|
-
_node = null;
|
|
6
|
-
_key = null;
|
|
7
|
-
_list = null;
|
|
8
|
-
_frame = null;
|
|
9
|
-
_skip = false;
|
|
10
|
-
_stopped = false;
|
|
11
|
-
_removed = false;
|
|
12
|
-
_replacement = null;
|
|
13
|
-
state;
|
|
14
|
-
|
|
15
|
-
get node() {
|
|
16
|
-
return this._node;
|
|
17
|
-
}
|
|
18
|
-
get parent() {
|
|
19
|
-
const a = this._ancestors;
|
|
20
|
-
return a.length === 0 ? null : a[a.length - 1];
|
|
21
|
-
}
|
|
22
|
-
get key() {
|
|
23
|
-
return this._key;
|
|
24
|
-
}
|
|
25
|
-
get index() {
|
|
26
|
-
return this._list === null ? null : this._frame.i;
|
|
27
|
-
}
|
|
28
|
-
ancestors() {
|
|
29
|
-
return [...this._ancestors];
|
|
30
|
-
}
|
|
31
|
-
skip() {
|
|
32
|
-
this._skip = true;
|
|
33
|
-
}
|
|
34
|
-
stop() {
|
|
35
|
-
this._stopped = true;
|
|
36
|
-
}
|
|
37
|
-
replace(node) {
|
|
38
|
-
if (node === null || typeof node !== "object" || typeof node.type !== "string") {
|
|
39
|
-
throw new TypeError("replace: expected an AST node");
|
|
40
|
-
}
|
|
41
|
-
if (this.parent === null) {
|
|
42
|
-
throw new TypeError("replace: cannot replace the walk root");
|
|
43
|
-
}
|
|
44
|
-
// synthetic nodes inherit the original span, for source maps
|
|
45
|
-
if (node.start === 0 && node.end === 0) {
|
|
46
|
-
node.start = this._node.start;
|
|
47
|
-
node.end = this._node.end;
|
|
48
|
-
}
|
|
49
|
-
this._replacement = node;
|
|
50
|
-
}
|
|
51
|
-
remove() {
|
|
52
|
-
if (this.parent === null) {
|
|
53
|
-
throw new TypeError("remove: cannot remove the walk root");
|
|
54
|
-
}
|
|
55
|
-
this._removed = true;
|
|
56
|
-
}
|
|
57
|
-
insertBefore(node) {
|
|
58
|
-
// advance past the insert so the current node keeps its turn
|
|
59
|
-
this.#insert(node, 0);
|
|
60
|
-
this._frame.i++;
|
|
61
|
-
}
|
|
62
|
-
insertAfter(node) {
|
|
63
|
-
// lands at the next slot, so the walk visits it
|
|
64
|
-
this.#insert(node, 1);
|
|
65
|
-
}
|
|
66
|
-
#insert(node, offset) {
|
|
67
|
-
if (this._list === null) {
|
|
68
|
-
throw new TypeError("insertBefore/insertAfter require a node in an array field");
|
|
69
|
-
}
|
|
70
|
-
this._list.splice(this._frame.i + offset, 0, node);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function createDispatch(visitors) {
|
|
75
|
-
let enter = null;
|
|
76
|
-
let leave = null;
|
|
77
|
-
const concrete = new Map();
|
|
78
|
-
for (const [name, value] of Object.entries(visitors)) {
|
|
79
|
-
if (value == null) continue;
|
|
80
|
-
if (name === "enter") enter = value;
|
|
81
|
-
else if (name === "leave") leave = value;
|
|
82
|
-
else if (typeof value === "function") concrete.set(name, { enter: value, leave: null });
|
|
83
|
-
else concrete.set(name, { enter: value.enter ?? null, leave: value.leave ?? null });
|
|
84
|
-
}
|
|
85
|
-
return { enter, leave, typed: (type) => concrete.get(type) };
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export function walk(root, visitors, state) {
|
|
89
|
-
_walk(root, visitors, state, new WalkContext());
|
|
90
|
-
return root;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function _walk(root, visitors, state, ctx) {
|
|
94
|
-
const d = createDispatch(visitors);
|
|
95
|
-
ctx.state = state;
|
|
96
|
-
const ancestors = ctx._ancestors;
|
|
97
|
-
|
|
98
|
-
function position(node, key, list, frame) {
|
|
99
|
-
ctx._node = node;
|
|
100
|
-
ctx._key = key;
|
|
101
|
-
ctx._list = list;
|
|
102
|
-
ctx._frame = frame;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function applyReplace(parent, key, list, frame) {
|
|
106
|
-
const next = ctx._replacement;
|
|
107
|
-
ctx._replacement = null;
|
|
108
|
-
if (list !== null) list[frame.i] = next;
|
|
109
|
-
else parent[key] = next;
|
|
110
|
-
return next;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function applyRemove(parent, key, list, frame) {
|
|
114
|
-
ctx._removed = false;
|
|
115
|
-
if (list !== null) {
|
|
116
|
-
list.splice(frame.i, 1);
|
|
117
|
-
frame.i--;
|
|
118
|
-
} else {
|
|
119
|
-
parent[key] = null;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
(function visit(node, key, list, frame) {
|
|
124
|
-
let typed = d.typed(node.type);
|
|
125
|
-
const parent = ctx.parent;
|
|
126
|
-
|
|
127
|
-
position(node, key, list, frame);
|
|
128
|
-
if (d.enter !== null) {
|
|
129
|
-
d.enter(node, ctx);
|
|
130
|
-
if (ctx._stopped) return false;
|
|
131
|
-
}
|
|
132
|
-
if (typed !== undefined && typed.enter !== null) {
|
|
133
|
-
typed.enter(node, ctx);
|
|
134
|
-
if (ctx._stopped) return false;
|
|
135
|
-
}
|
|
136
|
-
if (ctx._removed) {
|
|
137
|
-
applyRemove(parent, key, list, frame);
|
|
138
|
-
return true;
|
|
139
|
-
}
|
|
140
|
-
if (ctx._replacement !== null) {
|
|
141
|
-
node = applyReplace(parent, key, list, frame);
|
|
142
|
-
typed = d.typed(node.type);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
const skipped = ctx._skip;
|
|
146
|
-
ctx._skip = false;
|
|
147
|
-
if (!skipped) {
|
|
148
|
-
const keys = CHILD_KEYS[node.type];
|
|
149
|
-
if (keys !== undefined && keys.length > 0) {
|
|
150
|
-
ancestors.push(node);
|
|
151
|
-
for (let k = 0; k < keys.length; k++) {
|
|
152
|
-
const key2 = keys[k];
|
|
153
|
-
const value = node[key2];
|
|
154
|
-
if (value === null || value === undefined || typeof value !== "object") continue;
|
|
155
|
-
if (Array.isArray(value)) {
|
|
156
|
-
const childFrame = { i: 0 };
|
|
157
|
-
for (; childFrame.i < value.length; childFrame.i++) {
|
|
158
|
-
const item = value[childFrame.i];
|
|
159
|
-
// pattern element holes are null
|
|
160
|
-
if (item !== null && !visit(item, key2, value, childFrame)) return false;
|
|
161
|
-
}
|
|
162
|
-
} else if (!visit(value, key2, null, null)) {
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
ancestors.pop();
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
position(node, key, list, frame);
|
|
171
|
-
if (typed !== undefined && typed.leave !== null) {
|
|
172
|
-
typed.leave(node, ctx);
|
|
173
|
-
if (ctx._stopped) return false;
|
|
174
|
-
}
|
|
175
|
-
if (d.leave !== null) {
|
|
176
|
-
d.leave(node, ctx);
|
|
177
|
-
if (ctx._stopped) return false;
|
|
178
|
-
}
|
|
179
|
-
if (ctx._removed) applyRemove(parent, key, list, frame);
|
|
180
|
-
else if (ctx._replacement !== null) applyReplace(parent, key, list, frame);
|
|
181
|
-
|
|
182
|
-
return true;
|
|
183
|
-
})(root, null, null, null);
|
|
184
|
-
}
|