@nudojs/parser 0.5.1 → 1.1.0-beta.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
@@ -4,15 +4,15 @@ Babel-based parser and directive extraction for [Nudo](https://github.com/nudojs
4
4
 
5
5
  ## What is Nudo?
6
6
 
7
- Nudo is a type inference engine for JavaScript. Instead of a separate type system, it runs your code with symbolic type values via abstract interpretation — no TypeScript, no build step.
7
+ Nudo is a type inference engine for JavaScript. The type system is Abs (`shape × term × pred × conf`); analysis runs Abs-native via abstract interpretation — no TypeScript, no build step.
8
8
 
9
9
  ## This package
10
10
 
11
11
  `@nudojs/parser` handles source code parsing and Nudo directive extraction:
12
12
 
13
13
  - **Parsing** — wraps Babel parser for JavaScript/TypeScript source files
14
- - **Directives** — extracts `@nudo:case`, `@nudo:mock`, `@nudo:pure`, `@nudo:skip`, `@nudo:sample`, `@nudo:env`, `@nudo:mock-module`, `@nudo:as`, and `@nudo:replace` from comments. `@nudo:refine` / `@nudo:import` are parsed in `@nudojs/core` (`algebra/refine.ts`).
15
- - **Type expressions** — parses inline type value expressions used in directives
14
+ - **Directives** — extracts `@nudo:case`, `@nudo:mock`, `@nudo:pure`, `@nudo:skip`, `@nudo:sample`, `@nudo:env`, `@nudo:mock-module`, `@nudo:as`, and `@nudo:replace` from comments. `@nudo:contract` / `@nudo:import` are parsed in `@nudojs/core` (`algebra/refine.ts`).
15
+ - **Case arg expressions** — parses constraint builders and concrete literals used in directives
16
16
 
17
17
  ## Install
18
18
 
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { File, Node } from '@babel/types';
1
+ import { File, Node, AssignmentExpression, Expression, Identifier, MemberExpression, Program, ClassBody, VariableDeclarator, ExportSpecifier, ExportDefaultSpecifier, ExportNamespaceSpecifier, Statement } from '@babel/types';
2
2
  import { Abs, MockHelper } from '@nudojs/core';
3
3
  export { stripTypes } from '@nudojs/core';
4
4
 
@@ -15,10 +15,95 @@ declare function parse(source: string, opts?: {
15
15
  errorRecovery?: boolean;
16
16
  }): File;
17
17
 
18
+ /** File → its Program; Program → itself. Replaces `(ast as File).program ?? ast`. */
19
+ declare function asProgram(ast: Node | File | Program | null | undefined): Program | undefined;
20
+ /** Top-level statements of a File/Program (empty when neither). */
21
+ declare function programBody(ast: Node | File | Program | null | undefined): Statement[];
22
+ declare function asIdentifier(node: Node | null | undefined): Identifier | undefined;
23
+ declare function asExpression(node: Node | null | undefined): Expression | undefined;
24
+ declare function asAssignmentExpression(node: Node | null | undefined): AssignmentExpression | undefined;
25
+ /** Identifier.name, else StringLiteral.value (module string export names). */
26
+ declare function nameOrStringValue(node: Node | null | undefined): string | undefined;
27
+ /** Identifier.name only (undefined for string export names). */
28
+ declare function identifierName(node: Node | null | undefined): string | undefined;
29
+ /** VariableDeclaration.declarations; empty for other nodes. */
30
+ declare function getDeclarations(node: Node | null | undefined): VariableDeclarator[];
31
+ /** First declarator's init (fn-binding extraction). */
32
+ declare function getDeclaratorInit(node: Node | null | undefined): Expression | undefined;
33
+ /** First declarator of a VariableDeclaration, narrowed to Identifier id. */
34
+ declare function getFirstDeclaratorId(node: Node | null | undefined): Identifier | undefined;
35
+ /** VariableDeclarator id narrowed to Identifier. */
36
+ declare function getDeclaratorId(node: Node | null | undefined): Identifier | undefined;
37
+ /** Inner declaration of `export default` / `export …` (undefined for other nodes). */
38
+ declare function getExportDeclaration(node: Node | null | undefined): Node | undefined;
39
+ /**
40
+ * Unwrap an export form: named/default exports yield their inner declaration
41
+ * with `exported: true`; any other statement is returned as-is with `exported: false`.
42
+ */
43
+ declare function unwrapExport(node: Node | null | undefined): {
44
+ declaration: Node;
45
+ exported: boolean;
46
+ };
47
+ /** ExportNamedDeclaration.specifiers (empty for other nodes). */
48
+ declare function getExportSpecifiers(node: Node | null | undefined): (ExportSpecifier | ExportDefaultSpecifier | ExportNamespaceSpecifier)[];
49
+ /** ExportSpecifier local name — Identifier only (matches `local.name`). */
50
+ declare function exportSpecifierLocalName(spec: Node | null | undefined): string | undefined;
51
+ /** ExportSpecifier exported name (`exported.name ?? exported.value`). */
52
+ declare function exportSpecifierExportedName(spec: Node | null | undefined): string | number | undefined;
53
+ /** ExpressionStatement.expression. */
54
+ declare function getExpressionStatementExpression(node: Node | null | undefined): Expression | undefined;
55
+ /** Function/Class declaration or expression `id?.name`. */
56
+ declare function fnOrClassIdName(node: Node | null | undefined): string | undefined;
57
+ /** ClassDeclaration/ClassExpression `id?.name`. */
58
+ declare function classIdName(node: Node | null | undefined): string | undefined;
59
+ /** `id.loc` of a named function/class (undefined when anonymous or unlocated). */
60
+ declare function fnOrClassIdLoc(node: Node | null | undefined): Node["loc"];
61
+ /** Non-computed member property key text (Identifier.name or StringLiteral.value). */
62
+ declare function memberPropertyKey(member: Node | null | undefined): string | null;
63
+ /** Identifier name of a non-computed member's object (e.g. `module` in `module.exports`). */
64
+ declare function memberObjectName(member: Node | null | undefined): string | undefined;
65
+ /** Identifier name of a non-computed member's property (e.g. `exports`). */
66
+ declare function memberPropertyName(member: Node | null | undefined): string | undefined;
67
+ /** `module.exports` / `module["exports"]` is rejected here: computed keys return false. */
68
+ declare function isModuleExportsMember(member: Node | null | undefined): boolean;
69
+ declare function asMemberExpression(node: Node | null | undefined): MemberExpression | undefined;
70
+ /** Class body members; empty when node is not a class. */
71
+ declare function getClassMembers(node: Node | null | undefined): ClassBody["body"];
72
+ /**
73
+ * `key.name ?? key.value` on a class/object member key.
74
+ * Handles Identifier / StringLiteral / NumericLiteral and ESTree-shaped keys.
75
+ */
76
+ declare function classMemberKeyName(member: Node | null | undefined): string | number | undefined;
77
+ /** Key node of a class member (for range selection). */
78
+ declare function classMemberKey(member: Node | null | undefined): Node | undefined;
79
+ type InstanceMethod = {
80
+ name: string;
81
+ node: Node;
82
+ };
83
+ /**
84
+ * Instance methods of a class-like node. Accepts Babel `ClassMethod` /
85
+ * `TSDeclareMethod` and ESTree `MethodDefinition` (whose function lives in `value`).
86
+ * Skips getters/setters/constructors and static members.
87
+ */
88
+ declare function classInstanceMethods(node: Node | null | undefined): InstanceMethod[];
89
+ /** Class/TSDeclare method function node (ESTree MethodDefinition → its `value`). */
90
+ declare function methodFunctionNode(member: Node | null | undefined): Node | undefined;
91
+ /**
92
+ * Parameter display label: `name`, `...rest`, or `_`.
93
+ * Non-identifier rest arguments keep the historical `...undefined` string form.
94
+ */
95
+ declare function paramDisplayName(param: Node | null | undefined): string;
96
+ /** RestElement argument name, else plain Identifier name. */
97
+ declare function paramName(param: Node | null | undefined): string | undefined;
98
+ /** CJS/ESM default interop: callable module or `{ default }` wrapper. */
99
+ declare function unwrapDefaultExport<T>(mod: T | {
100
+ default: T;
101
+ }): T;
102
+
18
103
  type CaseDirective = {
19
104
  kind: "case";
20
105
  name: string;
21
- /** 无损参数 Abs(case 文法唯一真理源;约束表达式与 T.* 均产出) */
106
+ /** 无损参数 Abs(case 文法唯一真理源:约束构建器 / 具体字面量) */
22
107
  argsAbs: Abs[];
23
108
  /** `=> expected` 断言 Abs */
24
109
  expected?: Abs;
@@ -82,14 +167,12 @@ type FunctionWithDirectives = {
82
167
  directives: Directive[];
83
168
  };
84
169
  /**
85
- * case 实参主路径:始终产出 Abs;约束表达式优先。
86
- * `T.*` 文法 **已弃用**,仅为旧 fixture 兼容保留——新代码用 `number()`/`lit()`。
170
+ * case 实参 / 指令类型表达式唯一文法:约束构建器优先,其余为具体字面量、
171
+ * 结构字面量与箭头函数。`T.*` 文法已物理删除。
87
172
  */
88
173
  declare function parseCaseArgExpr(expr: string): Abs;
89
- /** @deprecated 旧名兼容;等价 parseCaseArgExpr */
90
- declare function parseTypeValueExpr(expr: string): Abs;
91
174
  declare function extractDirectives(ast: Node): FunctionWithDirectives[];
92
175
  declare function extractInlineDirectives(node: Node): InlineDirective[];
93
176
  declare function extractFileDirectives(ast: Node): FileDirective[];
94
177
 
95
- export { type AsDirective, type CaseDirective, type Directive, type EnvDirective, type FileDirective, type FunctionWithDirectives, type InlineDirective, type MockDirective, type MockModuleDirective, type PureDirective, type ReplaceDirective, type SampleDirective, type SinonExpression, type SkipDirective, extractDirectives, extractFileDirectives, extractInlineDirectives, parse, parseCaseArgExpr, parseTypeValueExpr };
178
+ export { type AsDirective, type CaseDirective, type Directive, type EnvDirective, type FileDirective, type FunctionWithDirectives, type InlineDirective, type InstanceMethod, type MockDirective, type MockModuleDirective, type PureDirective, type ReplaceDirective, type SampleDirective, type SinonExpression, type SkipDirective, asAssignmentExpression, asExpression, asIdentifier, asMemberExpression, asProgram, classIdName, classInstanceMethods, classMemberKey, classMemberKeyName, exportSpecifierExportedName, exportSpecifierLocalName, extractDirectives, extractFileDirectives, extractInlineDirectives, fnOrClassIdLoc, fnOrClassIdName, getClassMembers, getDeclarations, getDeclaratorId, getDeclaratorInit, getExportDeclaration, getExportSpecifiers, getExpressionStatementExpression, getFirstDeclaratorId, identifierName, isModuleExportsMember, memberObjectName, memberPropertyKey, memberPropertyName, methodFunctionNode, nameOrStringValue, paramDisplayName, paramName, parse, parseCaseArgExpr, programBody, unwrapDefaultExport, unwrapExport };
package/dist/index.js CHANGED
@@ -7,6 +7,173 @@ function parse(source, opts) {
7
7
  // src/index.ts
8
8
  import { stripTypes } from "@nudojs/core";
9
9
 
10
+ // src/ast-guards.ts
11
+ import { isExpression } from "@babel/types";
12
+ function asProgram(ast) {
13
+ if (!ast) return void 0;
14
+ if (ast.type === "File") return ast.program;
15
+ if (ast.type === "Program") return ast;
16
+ return void 0;
17
+ }
18
+ function programBody(ast) {
19
+ return asProgram(ast)?.body ?? [];
20
+ }
21
+ function asIdentifier(node) {
22
+ return node?.type === "Identifier" ? node : void 0;
23
+ }
24
+ function asExpression(node) {
25
+ return node && isExpression(node) ? node : void 0;
26
+ }
27
+ function asAssignmentExpression(node) {
28
+ return node?.type === "AssignmentExpression" ? node : void 0;
29
+ }
30
+ function nameOrStringValue(node) {
31
+ if (!node) return void 0;
32
+ if (node.type === "Identifier") return node.name;
33
+ if (node.type === "StringLiteral") return node.value;
34
+ return void 0;
35
+ }
36
+ function identifierName(node) {
37
+ return node?.type === "Identifier" ? node.name : void 0;
38
+ }
39
+ function getDeclarations(node) {
40
+ return node?.type === "VariableDeclaration" ? node.declarations : [];
41
+ }
42
+ function getDeclaratorInit(node) {
43
+ const decl = node?.type === "VariableDeclarator" ? node : void 0;
44
+ return decl?.init ?? void 0;
45
+ }
46
+ function getFirstDeclaratorId(node) {
47
+ const decl = getDeclarations(node)[0];
48
+ return decl?.id.type === "Identifier" ? decl.id : void 0;
49
+ }
50
+ function getDeclaratorId(node) {
51
+ const decl = node?.type === "VariableDeclarator" ? node : void 0;
52
+ return decl?.id.type === "Identifier" ? decl.id : void 0;
53
+ }
54
+ function getExportDeclaration(node) {
55
+ if (!node) return void 0;
56
+ if (node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration") {
57
+ return node.declaration ?? void 0;
58
+ }
59
+ return void 0;
60
+ }
61
+ function unwrapExport(node) {
62
+ if (node?.type === "ExportNamedDeclaration" && node.declaration) {
63
+ return { declaration: node.declaration, exported: true };
64
+ }
65
+ if (node?.type === "ExportDefaultDeclaration") {
66
+ return { declaration: node.declaration, exported: true };
67
+ }
68
+ return { declaration: node, exported: false };
69
+ }
70
+ function getExportSpecifiers(node) {
71
+ return node?.type === "ExportNamedDeclaration" ? node.specifiers : [];
72
+ }
73
+ function exportSpecifierLocalName(spec) {
74
+ return spec?.type === "ExportSpecifier" ? identifierName(spec.local) : void 0;
75
+ }
76
+ function exportSpecifierExportedName(spec) {
77
+ if (spec?.type !== "ExportSpecifier") return void 0;
78
+ const exported = spec.exported;
79
+ return exported.type === "Identifier" ? exported.name : exported.value;
80
+ }
81
+ function getExpressionStatementExpression(node) {
82
+ return node?.type === "ExpressionStatement" ? node.expression : void 0;
83
+ }
84
+ function fnOrClassIdName(node) {
85
+ if (!node) return void 0;
86
+ if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ClassDeclaration" || node.type === "ClassExpression" || node.type === "TSDeclareFunction") {
87
+ return node.id?.name;
88
+ }
89
+ return void 0;
90
+ }
91
+ function classIdName(node) {
92
+ if (!node) return void 0;
93
+ if (node.type === "ClassDeclaration" || node.type === "ClassExpression") {
94
+ return node.id?.name;
95
+ }
96
+ return void 0;
97
+ }
98
+ function fnOrClassIdLoc(node) {
99
+ if (!node) return void 0;
100
+ if (node.type === "FunctionDeclaration" || node.type === "FunctionExpression" || node.type === "ClassDeclaration" || node.type === "ClassExpression" || node.type === "TSDeclareFunction") {
101
+ return node.id?.loc ?? void 0;
102
+ }
103
+ return void 0;
104
+ }
105
+ function memberPropertyKey(member) {
106
+ if (member?.type !== "MemberExpression" || member.computed) return null;
107
+ return nameOrStringValue(member.property) ?? null;
108
+ }
109
+ function memberObjectName(member) {
110
+ if (member?.type !== "MemberExpression") return void 0;
111
+ return identifierName(member.object);
112
+ }
113
+ function memberPropertyName(member) {
114
+ if (member?.type !== "MemberExpression" || member.computed) return void 0;
115
+ return identifierName(member.property);
116
+ }
117
+ function isModuleExportsMember(member) {
118
+ return memberObjectName(member) === "module" && memberPropertyName(member) === "exports";
119
+ }
120
+ function asMemberExpression(node) {
121
+ return node?.type === "MemberExpression" ? node : void 0;
122
+ }
123
+ function getClassMembers(node) {
124
+ if (node?.type === "ClassDeclaration" || node?.type === "ClassExpression") {
125
+ return node.body.body;
126
+ }
127
+ return [];
128
+ }
129
+ function classMemberKeyName(member) {
130
+ const key = member?.key;
131
+ return key?.name ?? key?.value;
132
+ }
133
+ function classMemberKey(member) {
134
+ return member?.key ?? void 0;
135
+ }
136
+ function classInstanceMethods(node) {
137
+ const out = [];
138
+ for (const raw of getClassMembers(node)) {
139
+ const m = raw;
140
+ const isMethod = m.type === "MethodDefinition" || m.type === "ClassMethod" || m.type === "TSDeclareMethod";
141
+ if (!isMethod) continue;
142
+ if (m.kind && m.kind !== "method") continue;
143
+ if (m.static) continue;
144
+ const keyName = m.key?.type === "Identifier" ? m.key.name : void 0;
145
+ if (!keyName) continue;
146
+ const methodNode = m.type === "MethodDefinition" ? m.value ?? void 0 : raw;
147
+ if (!methodNode) continue;
148
+ out.push({ name: keyName, node: methodNode });
149
+ }
150
+ return out;
151
+ }
152
+ function methodFunctionNode(member) {
153
+ const m = member;
154
+ if (!m) return void 0;
155
+ return m.type === "MethodDefinition" ? m.value ?? void 0 : member;
156
+ }
157
+ function paramDisplayName(param) {
158
+ if (!param) return "_";
159
+ if (param.type === "Identifier") return param.name;
160
+ if (param.type === "RestElement") {
161
+ const arg = param.argument;
162
+ return `...${arg.name}`;
163
+ }
164
+ return "_";
165
+ }
166
+ function paramName(param) {
167
+ if (!param) return void 0;
168
+ if (param.type === "Identifier") return param.name;
169
+ if (param.type === "RestElement") return identifierName(param.argument);
170
+ return void 0;
171
+ }
172
+ function unwrapDefaultExport(mod) {
173
+ if (typeof mod === "function") return mod;
174
+ return mod.default;
175
+ }
176
+
10
177
  // src/directives.ts
11
178
  import {
12
179
  stub,
@@ -14,9 +181,6 @@ import {
14
181
  mock,
15
182
  abs as makeAbs,
16
183
  lit as termLit,
17
- num,
18
- str,
19
- bool,
20
184
  numLit,
21
185
  strLit,
22
186
  boolLit,
@@ -46,17 +210,13 @@ function absLit(v) {
46
210
  if (v === null) return absNullLit();
47
211
  return absUndefLit();
48
212
  }
49
- function absUnion(members) {
50
- if (members.length === 0) return absExact({ k: "never" });
51
- return members.reduce((acc, m) => joinAbs(acc, m));
52
- }
53
213
  var CASE_NAME_REGEX = /@nudo:case\s+"([^"]+)"\s*\(/g;
54
214
  var MOCK_INLINE_REGEX = /@nudo:mock\s+(\w+)\s*=\s*(.+)/g;
55
215
  var MOCK_FROM_REGEX = /@nudo:mock\s+(\w+)\s+from\s+"([^"]+)"/g;
56
216
  var PURE_REGEX = /@nudo:pure\b/g;
57
217
  var SKIP_REGEX = /@nudo:skip(?:\s+(.+))?/g;
58
218
  var SAMPLE_REGEX = /@nudo:sample\s+(\d+)/g;
59
- var CONSTRAINT_EXPR_RE = /^(number|string|boolean|array|shape|lit|union|fn|partial|pick|omit|record|required|readonly|nonNullable|and)\s*\(/;
219
+ var CONSTRAINT_EXPR_RE = /^(number|string|boolean|any|array|shape|lit|union|fn|partial|pick|omit|record|required|readonly|nonNullable|and)\s*\(/;
60
220
  function tryParseConstraint(expr) {
61
221
  const s = expr.trim();
62
222
  if (!CONSTRAINT_EXPR_RE.test(s)) return void 0;
@@ -85,15 +245,15 @@ function flattenPreds(preds) {
85
245
  function constraintSelfEqLit(c, selfIds) {
86
246
  const leaves = flattenPreds(c.preds);
87
247
  const eqs = leaves.filter((p2) => p2.op === "eq");
88
- if (eqs.length !== 1) return void 0;
248
+ if (eqs.length !== 1) return { found: false };
89
249
  const p = eqs[0];
90
- if (p.op !== "eq") return void 0;
250
+ if (p.op !== "eq") return { found: false };
91
251
  const isSelf = (t) => t.op === "var" && typeof t.id === "string" && selfIds.includes(t.id);
92
252
  const a = p.a;
93
253
  const b = p.b;
94
- if (isSelf(a) && b.op === "lit") return b.value;
95
- if (isSelf(b) && a.op === "lit") return a.value;
96
- return void 0;
254
+ if (isSelf(a) && b.op === "lit") return { found: true, value: b.value };
255
+ if (isSelf(b) && a.op === "lit") return { found: true, value: a.value };
256
+ return { found: false };
97
257
  }
98
258
  function constraintToCaseArgAbs(c) {
99
259
  if (c.members && c.members.length > 0) {
@@ -102,10 +262,32 @@ function constraintToCaseArgAbs(c) {
102
262
  return { shape: { k: "sum", members: parts }, conf: "path" };
103
263
  }
104
264
  const selfIds = [SELF, "__arg", "__nudo_self__"];
105
- const lv = constraintSelfEqLit(c, selfIds);
106
- if (typeof lv === "number" && !Number.isNaN(lv)) return numLit(lv);
107
- if (typeof lv === "string") return strLit(lv);
108
- if (typeof lv === "boolean") return boolLit(lv);
265
+ const litRes = constraintSelfEqLit(c, selfIds);
266
+ if (litRes.found) {
267
+ const lv = litRes.value;
268
+ if (typeof lv === "number" && !Number.isNaN(lv)) return numLit(lv);
269
+ if (typeof lv === "string") return strLit(lv);
270
+ if (typeof lv === "boolean") return boolLit(lv);
271
+ if (lv === null) return absNullLit();
272
+ return absUndefLit();
273
+ }
274
+ if (c.element) {
275
+ return absExact({ k: "arr", element: constraintToCaseArgAbs(c.element) });
276
+ }
277
+ if (c.fields) {
278
+ const slots = {};
279
+ for (const [key, field] of Object.entries(c.fields)) {
280
+ slots[key] = { value: constraintToCaseArgAbs(field.constraint) };
281
+ }
282
+ return absExact({ k: "obj", slots });
283
+ }
284
+ const bareScalar = !c.fields && !c.element && !c.members && !c.fn && c.int !== true && c.preds.length === 0;
285
+ if (bareScalar) {
286
+ if (c.prim === "number" || c.prim === "string" || c.prim === "boolean") {
287
+ return absExact({ k: "prim", type: c.prim });
288
+ }
289
+ if (!c.prim) return absUnknown();
290
+ }
109
291
  return constraintToEntryAbs(c, "__arg");
110
292
  }
111
293
  function parseCaseArgExpr(expr) {
@@ -117,52 +299,16 @@ function parseCaseArgExpr(expr) {
117
299
  return absUnknown();
118
300
  }
119
301
  }
120
- return parseLegacyTypeExpr(expr);
121
- }
122
- function parseTypeValueExpr(expr) {
123
- return parseCaseArgExpr(expr);
302
+ return parseLiteralOrStructure(expr);
124
303
  }
125
- function parseLegacyTypeExpr(expr) {
304
+ function parseLiteralOrStructure(expr) {
126
305
  const s = expr.trim();
127
- if (s === "T.number") return num();
128
- if (s === "T.string") return str();
129
- if (s === "T.boolean") return bool();
130
- if (s === "T.unknown") return absUnknown();
131
- if (s === "T.never") return absExact({ k: "never" });
132
- if (s === "T.null") return absNullLit();
133
- if (s === "T.undefined") return absUndefLit();
134
306
  if (s === "true") return absLit(true);
135
307
  if (s === "false") return absLit(false);
136
308
  if (s === "null") return absLit(null);
137
309
  if (s === "undefined") return absLit(void 0);
138
- const literalMatch = s.match(/^T\.literal\((.+)\)$/);
139
- if (literalMatch) {
140
- return absLit(parsePrimitiveValue(literalMatch[1].trim()));
141
- }
142
- if (s.startsWith("T.union(") && s.endsWith(")")) {
143
- const inner = s.slice("T.union(".length, -1);
144
- const args = splitTopLevelArgs(inner);
145
- return absUnion(args.map(parseLegacyTypeExpr));
146
- }
147
- if (s.startsWith("T.array(") && s.endsWith(")")) {
148
- const inner = s.slice("T.array(".length, -1);
149
- return absExact({ k: "arr", element: parseLegacyTypeExpr(inner) });
150
- }
151
- if (s.startsWith("T.tuple(") && s.endsWith(")")) {
152
- const inner = s.slice("T.tuple(".length, -1).trim();
153
- if (inner.startsWith("[") && inner.endsWith("]")) {
154
- const elements = splitTopLevelArgs(inner.slice(1, -1));
155
- return absExact({ k: "tuple", elements: elements.map(parseLegacyTypeExpr) });
156
- }
157
- return absExact({ k: "tuple", elements: [] });
158
- }
159
- if (s.startsWith("T.object(") && s.endsWith(")")) {
160
- const inner = s.slice("T.object(".length, -1).trim();
161
- if (inner.startsWith("{") && inner.endsWith("}")) {
162
- return parseObjectLiteral(inner.slice(1, -1).trim());
163
- }
164
- return absExact({ k: "obj", slots: {} });
165
- }
310
+ if (s === "unknown" || s === "any") return absUnknown();
311
+ if (s === "never") return absExact({ k: "never" });
166
312
  if (findTopLevelArrow(s) !== -1 || /^function\s*[\w$]*\s*\(/.test(s)) {
167
313
  const fnExpr = parseArrowFunctionExpr(s);
168
314
  if (fnExpr) {
@@ -180,7 +326,7 @@ function parseLegacyTypeExpr(expr) {
180
326
  const content = s.slice(1, -1).trim();
181
327
  if (!content) return absExact({ k: "tuple", elements: [] });
182
328
  const elements = splitTopLevelArgs(content);
183
- return absExact({ k: "tuple", elements: elements.map(parseLegacyTypeExpr) });
329
+ return absExact({ k: "tuple", elements: elements.map((e) => parseCaseArgExpr(e)) });
184
330
  }
185
331
  return absUnknown();
186
332
  }
@@ -193,21 +339,10 @@ function parseObjectLiteral(content) {
193
339
  if (colonIdx === -1) continue;
194
340
  const key = entry.slice(0, colonIdx).trim().replace(/^["']|["']$/g, "");
195
341
  const val = entry.slice(colonIdx + 1).trim();
196
- slots[key] = { value: parseLegacyTypeExpr(val) };
342
+ slots[key] = { value: parseCaseArgExpr(val) };
197
343
  }
198
344
  return absExact({ k: "obj", slots });
199
345
  }
200
- function parsePrimitiveValue(s) {
201
- if (s === "true") return true;
202
- if (s === "false") return false;
203
- if (s === "null") return null;
204
- if (s === "undefined") return void 0;
205
- if (/^-?\d+(\.\d+)?$/.test(s)) return Number(s);
206
- if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
207
- return s.slice(1, -1);
208
- }
209
- return s;
210
- }
211
346
  function splitTopLevelArgs(s) {
212
347
  const result = [];
213
348
  let depth = 0;
@@ -622,7 +757,7 @@ function findReplaceSeparator(raw) {
622
757
  }
623
758
  if (ch === " " && depth === 0) {
624
759
  const rest = raw.slice(i + 1).trimStart();
625
- if (rest.startsWith("T.") || rest.startsWith("{") || rest.startsWith("[") || rest.startsWith('"') || rest.startsWith("'") || /^-?\d/.test(rest) || rest === "true" || rest === "false" || rest === "null" || rest === "undefined") {
760
+ if (CONSTRAINT_EXPR_RE.test(rest) || rest.startsWith("{") || rest.startsWith("[") || rest.startsWith('"') || rest.startsWith("'") || rest === "true" || rest === "false" || rest === "null" || rest === "undefined" || rest === "unknown" || rest === "any" || rest === "never" || /^-?\d+(\.\d+)?$/.test(rest) || rest.includes("=>") || /^function\s*[\w$]*\s*\(/.test(rest)) {
626
761
  return i;
627
762
  }
628
763
  }
@@ -668,11 +803,43 @@ function extractFileDirectives(ast) {
668
803
  return results;
669
804
  }
670
805
  export {
806
+ asAssignmentExpression,
807
+ asExpression,
808
+ asIdentifier,
809
+ asMemberExpression,
810
+ asProgram,
811
+ classIdName,
812
+ classInstanceMethods,
813
+ classMemberKey,
814
+ classMemberKeyName,
815
+ exportSpecifierExportedName,
816
+ exportSpecifierLocalName,
671
817
  extractDirectives,
672
818
  extractFileDirectives,
673
819
  extractInlineDirectives,
820
+ fnOrClassIdLoc,
821
+ fnOrClassIdName,
822
+ getClassMembers,
823
+ getDeclarations,
824
+ getDeclaratorId,
825
+ getDeclaratorInit,
826
+ getExportDeclaration,
827
+ getExportSpecifiers,
828
+ getExpressionStatementExpression,
829
+ getFirstDeclaratorId,
830
+ identifierName,
831
+ isModuleExportsMember,
832
+ memberObjectName,
833
+ memberPropertyKey,
834
+ memberPropertyName,
835
+ methodFunctionNode,
836
+ nameOrStringValue,
837
+ paramDisplayName,
838
+ paramName,
674
839
  parse,
675
840
  parseCaseArgExpr,
676
- parseTypeValueExpr,
677
- stripTypes
841
+ programBody,
842
+ stripTypes,
843
+ unwrapDefaultExport,
844
+ unwrapExport
678
845
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nudojs/parser",
3
- "version": "0.5.1",
3
+ "version": "1.1.0-beta.0",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },
@@ -39,7 +39,8 @@
39
39
  "registry": "https://registry.npmjs.org"
40
40
  },
41
41
  "dependencies": {
42
- "@nudojs/core": "2.0.1"
42
+ "@babel/types": "^8.0.6",
43
+ "@nudojs/core": "3.0.0-beta.0"
43
44
  },
44
45
  "scripts": {
45
46
  "build": "tsup src/index.ts --format esm --dts"