解析发出TypeScript? -`const a = {foo:'bar'}`到`const a = {foo:'bar',可以:'haz'}`吗?

时间:2018-12-18 13:30:39

标签: typescript typescript-compiler-api

跟随the guide,了解其中的一些方法:

export function delint(sourceFile: ts.SourceFile) {
  delintNode(sourceFile);

  function delintNode(node: ts.Node) {
    if (node.kind === ts.SyntaxKind.VariableDeclaration) {
      // something
    }

    ts.forEachChild(node, delintNode);

如何获得其余的方法,即:向对象文字添加新的东西,然后输出具有相同属性顺序但末尾有新属性的编辑代码?

1 个答案:

答案 0 :(得分:0)

如果只想修改源文件文本以添加属性,则可以通过以下方式完成:

  1. 从AST获取对象文字表达式(使用concat demuxer有助于了解AST的外观)。
  2. 使用ts.updateObjectLiteral为具有新属性的旧节点获取新节点。
  3. 打印出新节点的文本,并使用打印的节点文本修改原始文本。
  4. 如有必要,请重新解析为新的AST,或仅使用修改后的文本。

请注意,打印对象文字会删除您以前使用的任何自定义格式,因为打印机以自己的方式打印节点。之后,您可能希望通过更漂亮的代码或其他格式化程序来运行代码。

示例:

import * as ts from "typescript";

// parse the AST
const sourceFile = ts.createSourceFile("file.ts", "const a = { foo: 'bar' };",
    ts.ScriptTarget.Latest, false);

// get the object literal expression
const objectLiteralExpression = sourceFile.statements.find(ts.isVariableStatement)!
    .declarationList.declarations[0].initializer as ts.ObjectLiteralExpression;

// get a transformed node with the new property and print it
const transformedOle = ts.updateObjectLiteral(objectLiteralExpression, [
    ...objectLiteralExpression.properties,
    ts.createPropertyAssignment("can", ts.createStringLiteral("haz"))
]);
const newNodeText = ts.createPrinter()
    .printNode(ts.EmitHint.Unspecified, transformedOle, sourceFile);

// get the new source file text and reparse it to a new AST
const oldText = sourceFile.text;
const newText = oldText.substring(0, objectLiteralExpression.getStart(sourceFile, true))
    + newNodeText + oldText.substring(objectLiteralExpression.end);
const newSourceFile = ts.createSourceFile("file.ts", newText, ts.ScriptTarget.Latest, false);

// outputs: `const a = { foo: "bar", can: "haz" };`
console.log(newText);

如果要在发射时执行此操作,请考虑为Program#emit(...)提供自定义转换器。