Skip to content
Go back

deepkit中的type compiler调试

Updated:

launch.json直接配置一个测试调试


        {
            "type": "node",
            "request": "launch",
            "name": "Debug Infer Test",
            "program": "${workspaceFolder}/node_modules/jest/bin/jest",
            "args": [
                "${workspaceFolder}/packages/type-compiler/tests/transpile.spec.ts",
                "--runInBand",
                "--no-cache"
            ],
            "console": "integratedTerminal",
            "internalConsoleOptions": "neverOpen",
            "sourceMaps": true,
            "windows": {
                "program": "${workspaceFolder}/node_modules/jest/bin/jest.js"
            }
        },

直接修改test里要transpile的代码,type-compiler里的createProgram/transformSourceFile里加断点,就可以了

    const res = transpile({
        'app': `
            type Text222<T> = T extends boolean ? 'y' : 'n';
            type test1 = Text222<boolean | string>;
        `
    },

具体例子

对于代码:

            type Text222<T> = T extends boolean ? 'y' : 'n';
            type test1 = Text222<boolean | string>;

首先从 transformSourceFile 开始:

transformSourceFile(sourceFile: SourceFile): SourceFile {
    // 初始化转换过程
    this.sourceFile = sourceFile;
    const visitor = (node: Node): any => {
        node = visitEachChild(node, visitor, this.context);
        // 处理类型别名声明
        if (isTypeAliasDeclaration(node)) {
            this.compileDeclarations.set(node, {
                name: node.name,
                sourceFile: this.sourceFile,
            });
        }
        return node;
    };
    this.sourceFile = visitNode(this.sourceFile, visitor);
}

当遇到 Text222<T> 定义时,会调用 createProgramVarFromNode

protected createProgramVarFromNode(node: Node, name: EntityName, sourceFile?: SourceFile): Statement[] {
    const typeProgram = new CompilerProgram(node, sourceFile);

    // 处理类型参数
    if (node.typeParameters) {
        for (const param of node.typeParameters) {
            typeProgram.pushTemplateParameter(getIdentifierName(param.name));
        }
    }

    // 提取类型结构
    this.extractPackStructOfType(node, typeProgram);
}

然后进入 extractPackStructOfType 处理条件类型:

case SyntaxKind.ConditionalType: {
    const narrowed = node as ConditionalTypeNode;

    // 处理条件类型
    program.pushConditionalFrame();
    this.extractPackStructOfType(narrowed.checkType, program);  // T
    this.extractPackStructOfType(narrowed.extendsType, program); // boolean
    program.pushOp(ReflectionOp.extends);

    // 处理 true 分支
    program.pushCoRoutine();
    this.extractPackStructOfType(narrowed.trueType, program); // 'y'
    const trueProgram = program.popCoRoutine();

    // 处理 false 分支
    program.pushCoRoutine();
    this.extractPackStructOfType(narrowed.falseType, program); // 'n'
    const falseProgram = program.popCoRoutine();

    program.pushOp(ReflectionOp.jumpCondition, trueProgram, falseProgram);
}

当处理 test1 = Text222<boolean | string> 时,会进入 extractPackStructOfTypeReference

protected extractPackStructOfTypeReference(type: TypeReferenceNode, program: CompilerProgram): void {
    // 处理类型参数
    if (type.typeArguments) {
        for (const argument of type.typeArguments) {
            this.extractPackStructOfType(argument, program);
        }
    }

    // 处理联合类型
    if (isUnionTypeNode(type.typeArguments[0])) {
        program.pushFrame();
        for (const subType of type.typeArguments[0].types) {
            this.extractPackStructOfType(subType, program);
        }
        program.pushOp(ReflectionOp.union);
    }
}

最终会生成一个包含以下操作码的程序:

// 对于 Text222<T>
[
    ReflectionOp.typeParameter,  // T
    ReflectionOp.boolean,        // boolean
    ReflectionOp.extends,        // extends
    ReflectionOp.jumpCondition,  // ?
    ReflectionOp.literal,        // 'y'
    ReflectionOp.literal,        // 'n'
]

// 对于 test1
[
    ReflectionOp.boolean,        // boolean
    ReflectionOp.string,         // string
    ReflectionOp.union,          // |
    ReflectionOp.inlineCall      // 应用 Text222
]

Suggest Changes

Previous Post
deepkit协程学习
Next Post
deepkit学习