【问题标题】:Parse emit TypeScript? - `const a = {foo: 'bar'}` to `const a = {foo: 'bar', can: 'haz'}`?解析发出 TypeScript? - `const a = {foo: 'bar'}` 到 `const a = {foo: 'bar', can: 'haz'}`?
【发布时间】:2018-12-18 22:51:37
【问题描述】:

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

我如何获得其余的方法,即:向对象字面量添加一个新事物,然后输出具有相同属性顺序但最后是一个新属性的编辑代码?

【问题讨论】:

    标签: typescript typescript-compiler-api


    【解决方案1】:

    如果你只是想修改源文件文本添加属性,那么可以这样:

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

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

    例子:

    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(...) 提供自定义转换器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-04
      • 2022-01-12
      • 2015-01-13
      • 1970-01-01
      • 1970-01-01
      • 2014-03-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多