yuku-ast 0.13.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 CHANGED
@@ -1,8 +1,16 @@
1
1
  # yuku-ast
2
2
 
3
- A typed, mutating AST walker and syntactic utilities for JavaScript and TypeScript ESTree trees, powered by [Yuku](https://github.com/yuku-toolchain/yuku).
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
- Works with any ESTree / TypeScript-ESTree AST. Traversal order is driven by tables generated from the [yuku-parser](https://www.npmjs.com/package/yuku-parser) AST definition, so it can never drift from the parser, and there is no runtime key discovery.
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
- // fires for function declarations, expressions, and arrows
38
+ // function declarations, expressions, and arrows
33
39
  },
34
40
  enter(node) {},
35
41
  });
36
42
  ```
37
43
 
38
- Aliases: `Expression`, `Statement`, `Declaration`, `ModuleDeclaration`, `Function`, `Class`, `Method`, `Loop`, `Pattern`, `JSX`, `TSType`. Per node the order is universal `enter`, alias enters, the typed enter, children, then the mirror for leave.
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
- The context exposes the position (`ctx.parent`, `ctx.key`, `ctx.index`, `ctx.ancestors()`), flow control (`ctx.skip()`, `ctx.stop()`), and in-place mutation: `ctx.replace(node)` continues into the replacement, `ctx.remove()` skips the removed subtree, `ctx.insertBefore(node)` inserts a sibling without visiting it, `ctx.insertAfter(node)` inserts one the walk visits. An optional third argument threads state to every handler as `ctx.state`.
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
- `walkAsync` is the async counterpart: identical traversal and mutation semantics, every handler awaited before the walk moves on.
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
- One constructor per node type, its fields derived from the node type itself, so a builder can never drift from the AST. Spans default to 0, which `ctx.replace` fills from the replaced node.
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
- One guard per concrete node type, per alias group, and for the common shapes ESTree folds into one type: literal kinds, member expression kinds, and directives. Every guard accepts `null` and `undefined` and narrows.
122
+ ## Imports and exports
70
123
 
71
- ## Modules
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 { collectImports, collectExports } from "yuku-ast";
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
- Declaration forms expand to one record per bound name, destructuring included. The per-declaration forms `collectImportDeclaration` and `collectExportDeclaration` return the records of a single statement, composing with a walk:
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
- findAll, // findAll(program, "CallExpression")
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
- ## Identifiers
168
+ ## Identifier names
117
169
 
118
170
  ```ts
119
- import { isValidIdentifier, isIdentifierName, isKeyword } from "yuku-ast";
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 and adds full semantics: scopes, symbols, resolved references, closure analysis, and cross-file module linking, computed natively. Its `module.walk` carries the semantic model in context (`ctx.scope`, `ctx.symbol`, `ctx.reference`).
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
@@ -18,5 +18,4 @@ type GroupType<A extends AliasName> = (typeof ALIAS_GROUPS)[A][number];
18
18
  export type AliasMap = {
19
19
  [A in AliasName]: NodeOfType<GroupType<A>>;
20
20
  };
21
- export declare const ALIAS_NAMES: readonly AliasName[];
22
21
  export {};
package/dist/aliases.js CHANGED
@@ -154,4 +154,3 @@ export const ALIAS_GROUPS = {
154
154
  "TSMappedType",
155
155
  ],
156
156
  };
157
- export const ALIAS_NAMES = Object.keys(ALIAS_GROUPS);
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export { ALIAS_GROUPS, ALIAS_NAMES, type AliasMap, type AliasName } from "./aliases.js";
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, NODE_TYPES } from "./generated.js";
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, NODE_TYPES } from "./generated.js";
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.13.0",
4
- "description": "Typed AST toolkit for JavaScript and TypeScript ESTree trees: walker, builders, guards, and syntactic utilities",
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.13.0"
27
+ "@yuku-toolchain/types": "^0.14.0"
25
28
  },
26
29
  "keywords": [
27
30
  "ast",