typescript APIfactory.updateSourceFile,如何设置new statements(及其子节点)的“pos”和“end”成员?

问题描述 投票:0回答:1

我正在更新转换中的源文件 -

export function transformBefore(
  absTsconfigPath: string
): ts.TransformerFactory<ts.SourceFile> | ts.CustomTransformerFactory {
  return (ctx) => (sf) => {
    const add:ts.Statement[]=[];
    if (...){
      add.push(...createSomeSyntheticStatements(ctx.factory))
    }
    if (!add.length) return sf;
    const flags:ts.NodeFlags = sf.flags;
    const sf1 = ctx.factory.updateSourceFile(
      sf,ctx.factory.createNodeArray([...add,...sf.statements]));
    ts.setSourceMapRange(sf1, 
      ts.getSourceMapRange(sf)); // no effect on pos,end of added nodes
    const sf3 = visitorWalk(sf1,ctx); // no effect on pos,end of added nodes
    return sf3;
  }

它看起来非常像 Typescript 的 @weswigham here 2017 年的建议。

在调试器中查看,我可以看到开头的新节点

sf3
都具有
pos
end
成员等于
-1

我想这不一定是问题,但后来,在处理同一文件的 after 转换中,对

node.getText()
的调用会导致 Typescript 中出现异常。调试异常我可以看到
pos
end
成员仍然是
-1
,并且在这样的语句上会发生异常。

在没有前变换的情况下运行后变换时,没有异常。

我有预感应该有一种方法可以更新

pos
end
成员,但我不知道。这三个人都没有做到:

  • ctx.factory.createNodeArray
  • ts.setSourceMapRange
    (希望有副作用)
  • 普通访客步行递归调用
    ts.forEachChild
    也没有(副作用)。

pos
end
成员如何更新?

(同时,避免在稍后的 after 转换中崩溃的解决方法是访问

node.text
而不是
node.getText()
,因为
node.text
具有正确的本地值,而
node.getText()
似乎依赖于
 pos
end
访问源文件全文,这是不同步的。)


更新:

我通过更新源文件尝试了不同的方法 使用不同的函数

ts.updateSourceFile
,而不是
ctx.factory.updateSourceFile
-

    const oldText = sf.getFullText();
    const newText = addedText + oldText;
    // The function checkChangeRange in typescript.js code-documents the specs for TextChangeRange and newText 
    const textChangeRange:ts.TextChangeRange = {newLength:addedText.length,span:{start:0,length:0}};
    const updatedSf = ts.updateSourceFile(sf,newText,textChangeRange,true);
    return updatedSf;

调试器显示

pos
end
已正确设置。 然而,在“成功”之后,打字稿继续对生成的源文件执行它的 own before 转换,但在尝试访问符号数据时崩溃了。也许这是因为新的源文件没有经过类型检查,所以没有符号数据。

typescript api transform abstract-syntax-tree
1个回答
0
投票

我在向源文件添加新节点时遇到类似的问题:如果新语句包含对类的引用(在原始源文件中导入,但仅用作类型),则转换后的源文件将返回与转换前相同的文本字符串。并且打字稿看不到导入上的引用并将其标记为未使用(因为它仅在源文件文本字符串中搜索https://github.com/microsoft/TypeScript/blob/main/src/services/findAllReferences.ts #L1799):

源文件:

import { Foo } from './foo;

class Bar {
  constructor(foo: Foo) {}
}

如果我尝试添加:

console.log(Foo)

转换后,导入未使用 -> 任何树摇晃都会将其删除 ->

console.log(Foo)
破坏程序(即使我在 Foo 上使用了标识符符号)

© www.soinside.com 2019 - 2024. All rights reserved.