跳到主要内容

@nudojs/parser

parser 包负责源代码解析和指令提取。产出 Babel 兼容的 AST 以及供求值器使用的结构化指令数据。

parse​

parse(source: string, opts?: { errorRecovery?: boolean }): File

将 JavaScript/TypeScript 源码解析为 Babel File AST,再对其执行 stripTypes——返回的 AST 不含任何 TS 专有节点,因此 .ts 输入在所有下游消费方(求值器、analyzer、LSP)零接线即可工作。

固定 Babel 选项:sourceType: "module"、plugins: ["typescript", "jsx"]、attachComment: true(指令提取需要)。

opts.errorRecovery 启用 Babel 错误恢复模式,供尽力而为的解析使用(例如对老 CJS 使用现场文件的 collectCallRecords);默认 false,语法错误快速失败。

返回: Babel File 节点(根 AST),TS 专有语法已原地剥除。


stripTypes​

stripTypes<T extends Node>(ast: T): T

从 Babel AST 中原地剥除 TS 专有语法并返回同一棵树——不重写任何 loc/start/end,兄弟节点顺序保持不变(@nudo:case 注释按 comment loc 对齐)。parse() 已无条件执行此 pass,只有当你自己用 @babel/parser 解析时才需要直接调用。

剥除/解包内容:类型断言(as、satisfies、<T>x、x!)解包为内层表达式;interface、类型别名、declare 语句、TS enum、type-only import/export 删除;参数/返回类型注解与类型参数列表丢弃。enum 成员引用会退化为 unknown-global 诊断——求值器没有 enum 求值语义。非 declare 的 namespace 和 import x = require(...) 保留原样,求值为 unknown。


指令类型​

指令从注释中提取,使用 @nudo: 命名空间。函数级指令来自顶层语句的前导块注释;文件级与行内指令来自行注释(见 extractFileDirectives / extractInlineDirectives)。

Directive 联合类型涵盖五种函数级指令:

type Directive =
| CaseDirective
| MockDirective
| PureDirective
| SkipDirective
| SampleDirective;

CaseDirective​

type CaseDirective = {
kind: "case";
name: string;
argsAbs: Abs[];
expected?: Abs;
commentLine?: number;
}

调试见证用例,带输入参数(约束构建器 + 具体字面量)。可选 expected 用于 nudo test 返回类型断言。

MockDirective​

type MockDirective = {
kind: "mock";
name: string;
expression?: string; // 行内表达式(原始文本)
fromPath?: string; // mock 模块路径
arrowFn?: { params: string[]; body: Node; paramPatterns: Node[] }; // 解析后的行内箭头函数
sinonExpr?: SinonExpression; // stub()/spy()/mock() 表达式
nudoMock?: MockHelper; // 解析后的 mock-helper 形态(来自 @nudojs/core)
}

将某绑定替换为感知 Abs 的 mock 实现。行内箭头函数(@nudo:mock fetch = (url) => ({ ok: true }))解析进 arrowFn;sinon 风格与 stub() 风格表达式统一归一化为 nudoMock(@nudojs/core 的 MockHelper)。

SinonExpression​

type SinonExpression = {
type: "stub" | "spy" | "mock";
returnValue?: Abs;
resolvedValue?: Abs;
rejectedValue?: Abs;
}

@nudo:mock 的 sinon 风格形态(@nudo:mock fetch = sinon.stub().resolves({...})),从 stub()/spy()/mock() 前缀归一化而来。

PureDirective​

type PureDirective = { kind: "pure" }

标记函数为纯函数,启用记忆化。

SkipDirective​

type SkipDirective = {
kind: "skip";
returns?: Abs;
}

跳过求值;使用 returns 或已有类型注解。

SampleDirective​

type SampleDirective = {
kind: "sample";
count: number;
}

请求的循环迭代次数。仅为源码兼容而解析,analyzer 不消费——循环求值走有界展开,此指令对输出无效果。

FileDirective​

文件顶部(任何语句之前)的行注释,对文件内所有函数生效:

type FileDirective = EnvDirective | MockModuleDirective;

type EnvDirective = {
kind: "env";
envs: string[]; // 具名或基于路径的 env,逗号分隔
}

type MockModuleDirective = {
kind: "mock-module";
source: string; // 要替换的 import 说明符
fromPath: string; // 提供 mock 模块的文件
names?: string[]; // 部分形态:只 mock 这些导出
}

InlineDirective​

附着在内部语句或表达式上的行注释:

type InlineDirective = AsDirective | ReplaceDirective;

type AsDirective = {
kind: "as";
typeAbs: Abs; // 假设类型:// @nudo:as string
}

type ReplaceDirective = {
kind: "replace";
targetSource: string; // 要覆盖的表达式文本
typeAbs: Abs; // 替换类型
}

FunctionWithDirectives​

type FunctionWithDirectives = {
node: Node; // Babel AST node (function declaration/expression)
name: string; // function name
directives: Directive[];
}

顶层函数及其关联指令。


extractDirectives​

extractDirectives(ast: Node): FunctionWithDirectives[]

从顶层语句的前导块注释中提取 @nudo:* 指令。仅包含至少有一条指令的语句。支持:

  • FunctionDeclaration
  • ExportDefaultDeclaration(内含 FunctionDeclaration)
  • VariableDeclaration(第一个声明)

返回: 函数及其指令的数组,每个带标注的语句对应一项。


extractFileDirectives​

extractFileDirectives(ast: Node): FileDirective[]

从 AST 的顶层行注释提取文件级指令:/// @nudo:env(一个或多个逗号分隔的 env)与 /// @nudo:mock-module "source" from "path"(部分 mock 可带 { a, b } 名单)。非 File 节点返回空数组。

示例:

/// @nudo:env node, ./nudo-harvest-node.ts

extractInlineDirectives​

extractInlineDirectives(node: Node): InlineDirective[]

从附着在单个节点上的行注释提取 @nudo:as 与 @nudo:replace 指令——agent 侧类型假设(nudo.whatIf 注入 // @nudo:as <type> 行)背后的机制。注释必须独占一行、位于语句上方(同一行的行尾注释不算该节点的前导注释);其余注释类型被忽略。

示例:

// @nudo:as string()
const y = f(x);

parseCaseArgExpr​

parseCaseArgExpr(expr: string): Abs

把指令类型表达式解析为 Abs——产品文法是约束构建器 + 具体字面量 + 结构字面量。用于 @nudo:case 实参、@nudo:as/@nudo:replace、mock 返回值与 @nudo:skip 返回表达式。

支持形式(按优先级):

  • 约束表达式(主文法):number()、number().gt(0)、lit(...)、union(…)、shape({…})、array(…)、fn({…}, …)、and、partial/pick/omit/record/required/readonly/nonNullable
  • 裸字面量:true、false、null、undefined、数字、带引号字符串
  • 函数:箭头表达式((x) => x + 1)与 function(x) { ... }——解析为真实的函数 Abs
  • JSON 风格:{ "key": value }、[a, b, c]

返回: 解析得到的 Abs,无法识别的表达式返回 unknown。