使用TypeScript Compiler API在函数之前添加注释

时间:2018-04-24 18:36:18

标签: typescript typescript-compiler-api

我有一个TypeScript文件,我想将其转换为JavaScript。作为此翻译的一部分,我想在每个函数之前添加注释,我希望使用TypeScript编译器API来完成此操作。

我尝试了两种不同的方法。其中一个是抓住SourceFile并更改其statements,如下所示:

const program = ts.createProgram([args.input], {});
const srcFile = find(program.getSourceFiles(), (sourceFile) => !sourceFile.isDeclarationFile);
srcFile.statements = ts.createNodeArray(srcFile.statements.map((statement) => {
    if (!ts.isFunctionDeclaration(statement)) {
        return statement;
    }
    return ts.addSyntheticLeadingComment(
        statement,
        ts.SyntaxKind.MultiLineCommentTrivia,
        "My long desired comment",
        true,
    );
}));

这给了我以下错误:

TypeError: Cannot read property 'emitNode' of undefined
at getOrCreateEmitNode (/Users/.../node_modules/typescript/lib/typescript.js:52792:19)
at getOrCreateEmitNode (/Users/.../node_modules/typescript/lib/typescript.js:52801:17)
at setSyntheticLeadingComments (/Users/.../node_modules/typescript/lib/typescript.js:52918:9)
at Object.addSyntheticLeadingComment (/Users/.../node_modules/typescript/lib/typescript.js:52923:16)
at /Users/.../dist/index.js:26:15
at Array.map (<anonymous>)
at Object.<anonymous> (/Users/.../dist/index.js:21:60)
at Module._compile (internal/modules/cjs/loader.js:654:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:665:10)
at Module.load (internal/modules/cjs/loader.js:566:32)

我尝试在statement之前打ts.addSyntheticLeadingCommentstatementFunctionDeclaration,正如预期的那样,虽然错过了emitNode字段,我期望由getOrCreateEmitNode函数创建。

我尝试的第二种方法是类似的,但它遇到了同样的问题;而不是覆盖原始的srcFile.statement,我正在使用打印机,如下所示:

const printer = ts.createPrinter(undefined, {
    substituteNode: (hint, node) => {
        if (ts.isFunctionDeclaration(node)) {
            return ts.addSyntheticLeadingComment(
                node,
                ts.SyntaxKind.MultiLineCommentTrivia,
                "My long desired comment",
                true,
           );
        }
    },
});

console.log(printer.printFile(srcFile));

,它提供与前一代码相同的错误。

我想要更改的TypeScript文件非常简单:

function myFunc(a: number, b: number): number {
    return a + b;
}

我真的很感激这方面的一些帮助。

祝你好运, 拉杜

2 个答案:

答案 0 :(得分:1)

不需要替换节点。请记住,注释不是AST的一部分,因此请不要将其添加到语句数组中,而不要使用现有函数声明。相反,只需在节点上调用addSyntheticLeadingComment,而不使用返回值。

例如,以下代码可以正常工作:

import * as ts from "typescript";

const file = ts.createSourceFile("test.ts", `function myFunc(a: number, b: number): number {
    return a + b;
}`, ts.ScriptTarget.Latest, true);
const functionDec = file.statements.find(ts.isFunctionDeclaration)!;

ts.addSyntheticLeadingComment(functionDec, ts.SyntaxKind.MultiLineCommentTrivia,
    "My long desired comment", true);

const printer = ts.createPrinter({ removeComments: false });
console.log(printer.printFile(file));

输出:

/*My long desired comment*/
function myFunc(a: number, b: number): number {
    return a + b;
}

答案 1 :(得分:0)

David Sherret's 答案是正确的,但无论我尝试什么,我总是遇到 Cannot read property 'emitNode' of undefined at getOrCreateEmitNode 错误。

事实证明我遗漏了 ts.createSourceFile 中名为 setParentNodes 的第四个参数。通过将此参数设置为 true,我可以使用 addSyntheticLeadingComment

基本上这个参数 (setParentNodes) 设置每个 Nodeparent 属性。

getOrCreateEmitNode 需要向上遍历树,没有父引用就不能这样做。有关 setParentNodes 的更多详细信息,请查看 this Github issue