如何从 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 });

codesandbox.io

我认为这可能对你有帮助:

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() { }

codesandbox