如何从 AST 打字稿解析器生成代码?
How to generate code from AST typescript parser?
读完 Using the Compiler API 文章后,我可以从字符串代码中获取 AST。
但是当我尝试生成代码(通过 escodegen)从 AST(不转译它)到代码 我得到了一个错误:
Unknown node type: undefined
有没有办法生成代码的ast?
import * as fs from "fs";
import escodegen from "escodegen";
import * as ts from "typescript";
const code = `
function foo() { }
`;
const node = ts.createSourceFile("x.ts", code, ts.ScriptTarget.Latest);
console.log({ node });
const x = escodegen.generate(node);
console.log({ x });
我认为这可能对你有帮助:
import * as ts from "typescript";
const filename = "test.ts";
const code = `const test: number = 1 + 2;`;
const sourceFile = ts.createSourceFile(
filename, code, ts.ScriptTarget.Latest
);
function printRecursiveFrom(
node: ts.Node, indentLevel: number, sourceFile: ts.SourceFile
) {
const indentation = "-".repeat(indentLevel);
const syntaxKind = ts.SyntaxKind[node.kind];
const nodeText = node.getText(sourceFile);
console.log(`${indentation}${syntaxKind}: ${nodeText}`);
node.forEachChild(child =>
printRecursiveFrom(child, indentLevel + 1, sourceFile)
);
}
printRecursiveFrom(sourceFile, 0, sourceFile);
输出:
SourceFile:
-EndOfFileToken:
SourceFile:
-EndOfFileToken:
SourceFile: const test: number = 1 + 2;
-FirstStatement: const test: number = 1 + 2;
--VariableDeclarationList: const test: number = 1 + 2
---VariableDeclaration: test: number = 1 + 2
----Identifier: test
----NumberKeyword: number
----BinaryExpression: 1 + 2
-----FirstLiteralToken: 1
-----PlusToken: +
-----FirstLiteralToken: 2
-EndOfFileToken:
更新
import * as ts from "typescript";
const code = `const test: number = 1 + 2;`;
const transpiledCode = ts.transpileModule(code, {}).outputText;
console.log(transpiledCode); // var test = 1 + 2;
将 AST 生成回代码
请看here
我知道,这不是完整的答案,但它可能会帮助其他人回答这个问题。
不幸的是,我没有时间深入挖掘(
P.S。代码取自 here
您可以通过 createPrinter
完成并将 node
传递给 printNode
。
这里的工作示例:
const code = `
function foo() { }
`;
const node = ts.createSourceFile("x.ts", code, ts.ScriptTarget.Latest);
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const result = printer.printNode(ts.EmitHint.Unspecified, node, node);
console.log(result); // function foo() { }
读完 Using the Compiler API 文章后,我可以从字符串代码中获取 AST。
但是当我尝试生成代码(通过 escodegen)从 AST(不转译它)到代码 我得到了一个错误:
Unknown node type: undefined
有没有办法生成代码的ast?
import * as fs from "fs";
import escodegen from "escodegen";
import * as ts from "typescript";
const code = `
function foo() { }
`;
const node = ts.createSourceFile("x.ts", code, ts.ScriptTarget.Latest);
console.log({ node });
const x = escodegen.generate(node);
console.log({ x });
我认为这可能对你有帮助:
import * as ts from "typescript";
const filename = "test.ts";
const code = `const test: number = 1 + 2;`;
const sourceFile = ts.createSourceFile(
filename, code, ts.ScriptTarget.Latest
);
function printRecursiveFrom(
node: ts.Node, indentLevel: number, sourceFile: ts.SourceFile
) {
const indentation = "-".repeat(indentLevel);
const syntaxKind = ts.SyntaxKind[node.kind];
const nodeText = node.getText(sourceFile);
console.log(`${indentation}${syntaxKind}: ${nodeText}`);
node.forEachChild(child =>
printRecursiveFrom(child, indentLevel + 1, sourceFile)
);
}
printRecursiveFrom(sourceFile, 0, sourceFile);
输出:
SourceFile:
-EndOfFileToken:
SourceFile:
-EndOfFileToken:
SourceFile: const test: number = 1 + 2;
-FirstStatement: const test: number = 1 + 2;
--VariableDeclarationList: const test: number = 1 + 2
---VariableDeclaration: test: number = 1 + 2
----Identifier: test
----NumberKeyword: number
----BinaryExpression: 1 + 2
-----FirstLiteralToken: 1
-----PlusToken: +
-----FirstLiteralToken: 2
-EndOfFileToken:
更新
import * as ts from "typescript";
const code = `const test: number = 1 + 2;`;
const transpiledCode = ts.transpileModule(code, {}).outputText;
console.log(transpiledCode); // var test = 1 + 2;
将 AST 生成回代码
请看here 我知道,这不是完整的答案,但它可能会帮助其他人回答这个问题。
不幸的是,我没有时间深入挖掘(
P.S。代码取自 here
您可以通过 createPrinter
完成并将 node
传递给 printNode
。
这里的工作示例:
const code = `
function foo() { }
`;
const node = ts.createSourceFile("x.ts", code, ts.ScriptTarget.Latest);
const printer = ts.createPrinter({ newLine: ts.NewLineKind.LineFeed });
const result = printer.printNode(ts.EmitHint.Unspecified, node, node);
console.log(result); // function foo() { }