TypeScript API Factory.updatesourcefile,如何设置“ pos”并“结束”新声明(及其子节点)的成员?

发布于 2025-01-20 13:34:32 字数 2408 浏览 3 评论 0原文

I'm updating a sourceFile in a transform -

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

It looks very much like the 2017 suggestion by Typescript's @weswigham

在调试器中查看我可以在Start sf3上看到新节点,所有节点都具有pos结束成员等于-1代码>。

我想这不一定是一个问题,但是稍后,在之后的转换在同一文件上工作,调用node.getText()导致例外情况深处打字稿。调试异常,我可以看到pos结束成员仍然是-1,并且在此类语句中,异常发生。

在没有前转换的情况下运行后转换时,也不例外。

我有一个预感,应该有一种方法来更新posend成员,但我不知道。这些都没有做到:

  • ctx.factory.createnodearray
  • ts.setsourcemaprange(希望有副作用)
  • 普通的访问者步行呼叫ts.foreachchild递归也没有(侧)效应。

如何更新pos结束成员?

(与此同时,避免在变换之后的后期中崩溃的解决方法是访问node.text,而不是node.getText() ,因为node.text具有正确的本地值,而node.getText()似乎依赖于posend 代码>要访问源文件全文,该文件不超出同步。)


更新:

我通过更新源文件尝试了另一种方法 使用其他函数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;

调试器显示posend end已正确设置。 但是,在“成功”之后,Typescript继续执行自己的 在结果源文件上转换之前,但是当尝试访问符号数据时,它崩溃了。也许这是因为新源文件尚未被类型检查,因此没有符号数据。

I'm updating a sourceFile in a transform -

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

It looks very much like the 2017 suggestion by Typescript's @weswigham here.

Looking in the debugger I can see the new nodes at the start sf3 all have pos and end members equal to -1.

I guess that shouldn't necessarily be a problem, but later, in an after transform working on the same file, a call to node.getText() results in an exception deep in Typescript. Debugging the exception I can see the pos and end members are still -1, and on such a statement the exception occurs.

When running the after-transform without the before-transform, there is no exception.

I have a hunch there should be a way to update the pos and end member but I don't know it. None of these threee did it:

  • ctx.factory.createNodeArray
  • ts.setSourceMapRange (hoping for side effect)
  • a plain visitor walk calling ts.forEachChild recursively also had no (side) effect.

How can the pos and end members be updated?

(In the meantime, a workaround to avoid a crash in the later after transform is to access node.text instead of node.getText(), because node.text has the correct local value, while node.getText()appears to rely on pos and end to access the source files full text, which is out of sync.)


UPDATE:

I tried a different approach by updating the source file
using a different function ts.updateSourceFile, instead of
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;

The debugger showed that pos and end were correctly set.
However, following that "success", typescript continued to perform it's own before transforms on the resulting source file, but it crashed when trying to access symbol data. Perhaps this is because the new source file has not been type-checked, so there is no symbol data.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文