How to generate code from AST typescript parser?
Asked Answered
L

2

20

After I read the Using the Compiler API article, I could get the AST from string-code.

But when I try to generate the code (by escodegen) from AST (not transpile it) to code I got an error:

Unknown node type: undefined

Is there a way to generate the ast to the code?

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

Lemon answered 9/12, 2020 at 9:23 Comment(0)
B
17

You can do it by createPrinter and pass node to printNode.

Here working example:

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

British answered 9/12, 2020 at 11:51 Comment(0)
B
7

I think it might help you:

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);

OUTPUT:

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:  

UPDATE

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;

Generate AST back to code

Please take a look here I know, this is not full answer, but it might help other people to answer this question.

Unfortunately, I have no time do dig deeper(

P.S. Code taken from here

Bonsai answered 9/12, 2020 at 9:50 Comment(3)
In fact, I need the string-code. in my case I expect function foo() ..... so is there a way to generate back from ast to string?Lemon
In your update, it transpile. I want to regenerate (not transpile I said it in the question please)Lemon
@JonSud sorry, just don't have enough time to go deeperBonsai

© 2022 - 2024 — McMap. All rights reserved.