yuku-ast 0.1.2 → 0.1.4

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
@@ -6,6 +6,7 @@ node builders, type guards, a walker, and identifier validators. No runtime depe
6
6
  | Import | Provides |
7
7
  | --------------------- | ------------------------------------------------------------ |
8
8
  | `yuku-ast` | `walk`, `walkAsync`, `b` (node builders), `is` (type guards) |
9
+ | `yuku-ast/utils` | node utilities such as `nameOf` |
9
10
  | `yuku-ast/identifier` | identifier and reserved-word validators |
10
11
 
11
12
  ```ts
@@ -112,7 +113,9 @@ is.CallExpression(node); // every concrete type
112
113
  is.Expression(node); // families
113
114
  is.StringLiteral(node); // Literal variants
114
115
  is.StaticMemberExpression(node); // MemberExpression variants
115
- is.BindingIdentifier(node); // Identifier roles, via `kind`
116
+
117
+ is.Identifier(node, "this"); // an Identifier with that exact name
118
+ is.oneOf(node, ["CallExpression", "NewExpression"]); // any of these types
116
119
 
117
120
  walk(program, {
118
121
  Literal(node, path) {
@@ -123,6 +126,32 @@ walk(program, {
123
126
  });
124
127
  ```
125
128
 
129
+ `is.oneOf(node, types)` narrows to the union of the listed types, and
130
+ `is.Identifier(node, name?)` narrows to `Identifier`. Both accept `null` or
131
+ `undefined`.
132
+
133
+ ## Reading names (`nameOf`)
134
+
135
+ `nameOf(node)` returns the static name a node denotes, an `Identifier`'s `name`
136
+ or a string `Literal`'s `value`, and `null` for anything else (including `null`
137
+ or `undefined`). It reads the common `Identifier | StringLiteral` slots, such as
138
+ a `ModuleExportName` or a static property or member key, in one call.
139
+
140
+ ```ts
141
+ import { walk } from "yuku-ast";
142
+ import { nameOf } from "yuku-ast/utils";
143
+
144
+ walk(program, {
145
+ ExportSpecifier(node) {
146
+ // `export { x as y }` and `export { x as "z" }` both resolve.
147
+ nameOf(node.exported); // "y", "z"
148
+ },
149
+ Property(node) {
150
+ if (!node.computed) nameOf(node.key); // static key name, else null
151
+ },
152
+ });
153
+ ```
154
+
126
155
  ## Builders (`b`)
127
156
 
128
157
  A builder for every node type. Required fields are positional, the rest go in a
@@ -19,10 +19,7 @@ declare function isIdentifierStart(cp: number): boolean;
19
19
  declare function isIdentifierChar(cp: number): boolean;
20
20
  /**
21
21
  * Returns `true` if `name` is a valid ECMAScript `IdentifierName`: the grammar
22
- * an identifier token must satisfy.
23
- *
24
- * Unlike the `is.IdentifierName` node guard, this validates a raw string rather
25
- * than an AST node.
22
+ * an identifier token must satisfy. Validates a raw string, not an AST node.
26
23
  *
27
24
  * @example
28
25
  * isIdentifierName("foo"); // true
@@ -29,10 +29,7 @@ function isIdentifierChar(cp) {
29
29
  }
30
30
  /**
31
31
  * Returns `true` if `name` is a valid ECMAScript `IdentifierName`: the grammar
32
- * an identifier token must satisfy.
33
- *
34
- * Unlike the `is.IdentifierName` node guard, this validates a raw string rather
35
- * than an AST node.
32
+ * an identifier token must satisfy. Validates a raw string, not an AST node.
36
33
  *
37
34
  * @example
38
35
  * isIdentifierName("foo"); // true
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as t from "yuku-parser";
2
- import { BigIntLiteral, BindingIdentifier, BooleanLiteral, ComputedMemberExpression, Directive, IdentifierName, IdentifierReference, LabelIdentifier, Node, NullLiteral, NumericLiteral, PrivateFieldExpression, RegExpLiteral, StaticMemberExpression, StringLiteral } from "yuku-parser";
2
+ import { BigIntLiteral, BooleanLiteral, ComputedMemberExpression, Directive, Identifier, Node, NullLiteral, NumericLiteral, PrivateFieldExpression, RegExpLiteral, StaticMemberExpression, StringLiteral } from "yuku-parser";
3
3
 
4
4
  //#region src/types.d.ts
5
5
  /** Discriminant `type` string of every AST node. */
@@ -95,6 +95,8 @@ type AliasMap = { [K in AliasName]: NodeOfType<(typeof ALIAS_GROUPS)[K][number]>
95
95
  //#region src/predicates.d.ts
96
96
  type MaybeNode = Node | null | undefined;
97
97
  declare const is: {
98
+ /** True when `node`'s `type` is one of `types`, narrowing to that union. */oneOf: <const K extends NodeType>(node: MaybeNode, types: readonly K[]) => node is NodeOfType<K>; /** An `Identifier`, optionally with the exact `name` (e.g. `is.Identifier(node, "this")`). */
99
+ Identifier: (node: MaybeNode, name?: string) => node is Identifier;
98
100
  Expression: (node: MaybeNode) => node is NodeOfType<"Identifier" | "Literal" | "ThisExpression" | "Super" | "ArrayExpression" | "ObjectExpression" | "FunctionExpression" | "ArrowFunctionExpression" | "ClassExpression" | "TaggedTemplateExpression" | "TemplateLiteral" | "MemberExpression" | "CallExpression" | "NewExpression" | "ChainExpression" | "SequenceExpression" | "ParenthesizedExpression" | "BinaryExpression" | "LogicalExpression" | "ConditionalExpression" | "UnaryExpression" | "UpdateExpression" | "AssignmentExpression" | "YieldExpression" | "AwaitExpression" | "ImportExpression" | "MetaProperty" | "TSAsExpression" | "TSSatisfiesExpression" | "TSTypeAssertion" | "TSNonNullExpression" | "TSInstantiationExpression" | "JSXElement" | "JSXFragment">;
99
101
  Statement: (node: MaybeNode) => node is AliasMap["Statement"];
100
102
  Declaration: (node: MaybeNode) => node is AliasMap["Declaration"];
@@ -106,10 +108,6 @@ declare const is: {
106
108
  Pattern: (node: MaybeNode) => node is AliasMap["Pattern"];
107
109
  JSX: (node: MaybeNode) => node is AliasMap["JSX"];
108
110
  TSType: (node: MaybeNode) => node is AliasMap["TSType"];
109
- IdentifierReference: (node: MaybeNode) => node is IdentifierReference;
110
- BindingIdentifier: (node: MaybeNode) => node is BindingIdentifier;
111
- LabelIdentifier: (node: MaybeNode) => node is LabelIdentifier;
112
- IdentifierName: (node: MaybeNode) => node is IdentifierName;
113
111
  StringLiteral: (node: MaybeNode) => node is StringLiteral;
114
112
  NumericLiteral: (node: MaybeNode) => node is NumericLiteral;
115
113
  BooleanLiteral: (node: MaybeNode) => node is BooleanLiteral;
@@ -149,7 +147,6 @@ declare const is: {
149
147
  TSEnumDeclaration: (node: MaybeNode) => node is import("yuku-parser").TSEnumDeclaration;
150
148
  TSModuleDeclaration: (node: MaybeNode) => node is import("yuku-parser").TSModuleDeclaration;
151
149
  TSImportEqualsDeclaration: (node: MaybeNode) => node is import("yuku-parser").TSImportEqualsDeclaration;
152
- Identifier: (node: MaybeNode) => node is import("yuku-parser").Identifier;
153
150
  Literal: (node: MaybeNode) => node is NodeOfType<"Literal">;
154
151
  ThisExpression: (node: MaybeNode) => node is import("yuku-parser").ThisExpression;
155
152
  Super: (node: MaybeNode) => node is import("yuku-parser").Super;
@@ -289,7 +286,7 @@ declare const is: {
289
286
  //#endregion
290
287
  //#region src/builders.d.ts
291
288
  declare const b: {
292
- identifier(name: string, kind?: t.IdentifierKind, opts?: {
289
+ identifier(name: string, opts?: {
293
290
  typeAnnotation?: t.TSTypeAnnotation | null;
294
291
  optional?: boolean;
295
292
  decorators?: t.Decorator[];
package/dist/index.mjs CHANGED
@@ -548,6 +548,10 @@ function aliasGuard(name) {
548
548
  }
549
549
  const is = {
550
550
  ...Object.fromEntries(Object.keys(VISITOR_KEYS).map((type) => [type, (node) => node != null && node.type === type])),
551
+ /** True when `node`'s `type` is one of `types`, narrowing to that union. */
552
+ oneOf: (node, types) => node != null && types.includes(node.type),
553
+ /** An `Identifier`, optionally with the exact `name` (e.g. `is.Identifier(node, "this")`). */
554
+ Identifier: (node, name) => node?.type === "Identifier" && (name === void 0 || node.name === name),
551
555
  Expression: aliasGuard("Expression"),
552
556
  Statement: aliasGuard("Statement"),
553
557
  Declaration: aliasGuard("Declaration"),
@@ -559,10 +563,6 @@ const is = {
559
563
  Pattern: aliasGuard("Pattern"),
560
564
  JSX: aliasGuard("JSX"),
561
565
  TSType: aliasGuard("TSType"),
562
- IdentifierReference: (node) => node?.type === "Identifier" && node.kind === "reference",
563
- BindingIdentifier: (node) => node?.type === "Identifier" && node.kind === "binding",
564
- LabelIdentifier: (node) => node?.type === "Identifier" && node.kind === "label",
565
- IdentifierName: (node) => node?.type === "Identifier" && node.kind === "name",
566
566
  StringLiteral: (node) => node?.type === "Literal" && typeof node.value === "string",
567
567
  NumericLiteral: (node) => node?.type === "Literal" && typeof node.value === "number",
568
568
  BooleanLiteral: (node) => node?.type === "Literal" && typeof node.value === "boolean",
@@ -582,11 +582,10 @@ const span = {
582
582
  };
583
583
  const isComputedKey = (key) => key.type !== "Identifier" && key.type !== "PrivateIdentifier";
584
584
  const b = {
585
- identifier(name, kind = "reference", opts = {}) {
585
+ identifier(name, opts = {}) {
586
586
  return {
587
587
  type: "Identifier",
588
588
  name,
589
- kind,
590
589
  ...opts,
591
590
  ...span
592
591
  };
@@ -893,8 +892,8 @@ const b = {
893
892
  metaProperty(meta, property) {
894
893
  return {
895
894
  type: "MetaProperty",
896
- meta: b.identifier(meta, "name"),
897
- property: b.identifier(property, "name"),
895
+ meta: b.identifier(meta),
896
+ property: b.identifier(property),
898
897
  ...span
899
898
  };
900
899
  },
@@ -0,0 +1,18 @@
1
+ import { Node } from "yuku-parser";
2
+
3
+ //#region src/utils/index.d.ts
4
+ type MaybeNode = Node | null | undefined;
5
+ /**
6
+ * The static name a node denotes: an `Identifier`'s `name`, or a string
7
+ * `Literal`'s `value`. Returns `null` for anything else, and for `null` or
8
+ * `undefined`, so the common `Identifier | StringLiteral` name slots (a
9
+ * `ModuleExportName`, or a static property or member key) read in one call.
10
+ *
11
+ * @example
12
+ * nameOf(b.identifier("x")) // "x"
13
+ * nameOf(b.stringLiteral("y")) // "y"
14
+ * nameOf(b.numericLiteral(1)) // null
15
+ */
16
+ declare function nameOf(node: MaybeNode): string | null;
17
+ //#endregion
18
+ export { nameOf };
package/dist/utils.mjs ADDED
@@ -0,0 +1,20 @@
1
+ //#region src/utils/index.ts
2
+ /**
3
+ * The static name a node denotes: an `Identifier`'s `name`, or a string
4
+ * `Literal`'s `value`. Returns `null` for anything else, and for `null` or
5
+ * `undefined`, so the common `Identifier | StringLiteral` name slots (a
6
+ * `ModuleExportName`, or a static property or member key) read in one call.
7
+ *
8
+ * @example
9
+ * nameOf(b.identifier("x")) // "x"
10
+ * nameOf(b.stringLiteral("y")) // "y"
11
+ * nameOf(b.numericLiteral(1)) // null
12
+ */
13
+ function nameOf(node) {
14
+ if (node == null) return null;
15
+ if (node.type === "Identifier") return node.name;
16
+ if (node.type === "Literal" && typeof node.value === "string") return node.value;
17
+ return null;
18
+ }
19
+ //#endregion
20
+ export { nameOf };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yuku-ast",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "A fast, typed AST toolkit for yuku-parser's ESTree / TypeScript-ESTree AST: node builders, type guards, a walker, and identifier validators.",
5
5
  "keywords": [
6
6
  "ast",
@@ -30,6 +30,7 @@
30
30
  "exports": {
31
31
  ".": "./dist/index.mjs",
32
32
  "./identifier": "./dist/identifier.mjs",
33
+ "./utils": "./dist/utils.mjs",
33
34
  "./package.json": "./package.json"
34
35
  },
35
36
  "scripts": {
@@ -48,9 +49,9 @@
48
49
  "tsdown": "^0.22.0",
49
50
  "typescript": "^6.0.3",
50
51
  "yuku-codegen": "^0.5.18",
51
- "yuku-parser": "^0.5.18"
52
+ "yuku-parser": "^0.5.20"
52
53
  },
53
54
  "peerDependencies": {
54
- "yuku-parser": ">=0.5.18"
55
+ "yuku-parser": ">=0.5.20"
55
56
  }
56
57
  }