gpt4 book ai didi

typescript - 如何使用 TS Compiler API 查找变量在另一个文件中的定义位置

转载 作者:行者123 更新时间:2023-12-01 03:03:04 27 4
gpt4 key购买 nike

给定:

// foo.ts
import { bar } from "./bar"

// bar.ts
export const bar = 3;

如果我有 ts.Symbol对于 bar在“foo.ts”中,我怎样才能到达 bar在“bar.ts”中?

理想情况下,TS 编译器 API 会公开一个定义使用链,我可以遍历该链来查找定义。不过,我认为不会。

所以现在我正在尝试:
  • 使用模块说明符“./bar.ts”和当前 ts.SourceFile获取 ts.ResolvedModule表示“bar.ts”的对象,其中包含完整的文件路径。
  • ts.SourceFile(fullFilePath)获取 ts.SourceFile对于“bar.ts”
  • checker.getExportsOfModule(symbolForBarDotTs)从“bar.ts”获取导出并找到具有匹配名称的导出。

  • 棘手的部分似乎是从模块说明符中解析模块。我不想从头开始编写模块解析的逻辑,因为算法很复杂,并且依赖于至少六个编译器选项的交互。 TS Compiler API 的两个部分看起来很有希望:
  • host.resolveModuleNames ,不幸的是,只有在宿主实现了它时才可用,并且默认编译器宿主没有实现它。
  • 使用 (program.getSourceFile(pathToFoo) as any).resolvedModules . resolvedModules属性似乎正是我正在寻找的东西,但不是公共(public) API 的一部分。

  • 有没有更好的办法?我希望:
  • 停止使用非私有(private) API
  • 停止做太多编译器已经知道该怎么做的工作

    "bar.ts"

  • 在这种情况下,很容易看到“./bar”指的是文件系统上具有匹配名称的相邻源文件,但是当有人使用“paths”或“node_modules”或“@types”等时,那么模块分辨率很重要。

    更新

    对于以下一般问题:

    If I have a ts.Symbol for the bar in "foo.ts", how can I get to the bar in "bar.ts"?



    @DavidSherret's answer大部分时间都会工作。

    但是,在以下情况下,它不能满足我的要求:
    // foo.ts
    import { bar } from "./bar"

    // bar.ts
    export { bar } from "./baz"

    // baz.ts
    export const bar = 3;


    TypeChecker#getAliasedSymbol 说 baz在 "foo.ts"中指向 bar在“baz.ts”中,完全跳过“bar.ts”。这对我的目的不起作用,因为我试图找出一组入口点,不再需要 .d.ts 文件的哪些部分,并删除不需要的部分。在这种情况下,删除“bar.ts”是个坏主意。

    最佳答案

    命名导入的符号将有一个关联的“别名符号”,它代表声明。因此,要获得变量声明的符号,您可以使用 TypeChecker#getAliasedSymbol方法,然后从中获取声明。

    例如:

    const barNamedImportSymbol = typeChecker.getSymbolAtLocation(barNamedImport.name)!;
    const barSymbol = typeChecker.getAliasedSymbol(barNamedImportSymbol);
    const barDeclaration = barSymbol.declarations[0] as ts.VariableDeclaration;

    console.log(barDeclaration.getText(barFile)); // outputs `bar = 3`

    导入声明的命名导入有一个单独的符号,因为这是特定于“foo.ts”文件的符号。

    更新:获取模块说明符中引用的文件符号

    要获取导入或导出声明模块说明符中引用的文件的符号,您可以获取模块说明符节点的符号:
    const otherFileSymbol = typeChecker.getSymbolAtLocation(importDeclaration.moduleSpecifier)!;

    从那里,您可以检查其导出的某个名称:
    const barSymbol = otherFileSymbol.exports!.get(ts.escapeLeadingUnderscores("bar"))!;
    // outputs: export { bar } from "./baz"; in second example above
    console.log(barSymbol.declarations[0].parent.parent.getText());

    关于typescript - 如何使用 TS Compiler API 查找变量在另一个文件中的定义位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59838013/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com