TypeScript 当调用"转到实现"参数时,转到参数,

t2a7ltrp  于 7个月前  发布在  TypeScript
关注(0)|答案(5)|浏览(133)

建议

🔍 搜索词

转到实现,参数,转到参数

✅ 可实现性检查清单

我的建议符合以下准则:

  • 这不会对现有的TypeScript/JavaScript代码造成破坏性的更改
  • 这不会改变现有JavaScript代码的运行时行为
  • 这可以在不根据表达式的类型发出不同的JS的情况下实现
  • 这不是一个运行时特性(例如库功能、具有JavaScript输出的非ECMAScript语法、新的JS语法糖等)
  • 这个特性将与TypeScript's Design Goals的其他部分一致。

上下文

TypeScript语言服务器允许对属性进行转到实现。这非常有用,因为它可以快速跳转到可能的属性值:

  1. function foobar(myArg: { myProperty: number }) {}
  2. foobar({ myProperty: 4 });

⭐ 建议

如果“转到实现”也支持参数,跳转到相应的参数,那将会非常有用(忽略代码中的注解,它们只是为了让演示工作):

理想情况下,这也适用于命名元组:

  1. function foobar(myArg1: number) { }
  2. type GetParams<T extends (arg: any) => void> = T extends (...arg: infer P) => void ? P : never;
  3. function f(...args: GetParams<typeof foobar>): void { }
  4. f(/*def:myArg1*/ 1);

📃 动机

在VS Code中,我们使用依赖注入,经常将类的示例化委托给示例化服务。
这可以是这样的:

  1. export class TextMateWorkerHost implements IDisposable {
  2. // ...
  3. constructor(
  4. private readonly _reportTokenizationTime: (timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number, isRandomSample: boolean) => void,
  5. @IExtensionResourceLoaderService private readonly _extensionResourceLoaderService: IExtensionResourceLoaderService,
  6. @IModelService private readonly _modelService: IModelService,
  7. @ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
  8. // ...
  9. ) {
  10. }
  11. }

这个类可以这样示例化:

  1. class TextMateTokenizationFeature {
  2. private readonly _workerHost = this._instantiationService.createInstance(
  3. TextMateWorkerHost,
  4. (timeMs, languageId, sourceExtensionId, lineLength, isRandomSample) => this.reportTokenizationTime(timeMs, languageId, sourceExtensionId, lineLength, true, isRandomSample)
  5. );
  6. }

我经常想从 _reportTokenizationTime 字段跳转到 TextMateTokenizationFeature 中的箭头表达式。
目前,这并不容易,因为我需要列出所有 TextMateWorkerHost 的引用以找到 this._instantiationService.createInstance(TextMateWorkerHost, ... 。然后我必须检查所有参数并找到正确的回调。
这个功能请求将使这变得非常容易,只需跳转到参数 _reportTokenizationTime 的实现即可。

实现

我不知道TypeScript中的引用搜索是如何工作的,但是使用TypeScript编译器API,可以通过遍历所有的 CallExpressions,询问检查器它们的签名,查询 checker.getResolvedSignature(s) 并检查返回的符号来实现。
不幸的是,对于 f 的第一个参数的名称为 myArg1 的符号似乎没有链接到 myArg1 的参数符号。

unftdfkk

unftdfkk1#

为什么不直接在函数上"查找所有引用"呢?只有一个调用站点的情况似乎非常罕见。

tuwxkamq

tuwxkamq2#

为什么不直接在函数上“查找所有引用”?
当函数没有被直接调用时,这个功能是不起作用的,就像上面的例子中,this._instantiationService.createInstance - TextMateWorkerHost 的构造函数有0个引用。尽管类TextMateWorkerHost本身可能有数百个方法,但要找到构造函数的间接调用者是非常困难的。
如果函数被传递:

  1. const f = (x: number) => console.log(x);
  2. const x = f;
  3. x(10);

只有一个调用站点的情况似乎非常罕见
至少在我看来,对于VS Code代码库来说,这种情况并不算很罕见。但是,在函数有多个调用站点的情况下,这个功能也会很有帮助。

yquaqz18

yquaqz183#

当函数没有直接调用时,这个功能是无法工作的。如果函数被传递给其他地方,它也无法正常工作。假设Find All References无法找到给定函数的调用站点,那么这个功能如何能够找到参数?

ki1q1bka

ki1q1bka4#

这个特性如何能够找到参数?
TypeScript已经弄清楚了参数名称:

即使在更复杂的情况下:

如果 g 的签名类型中的参数符号指向 f 中的原始参数符号,那么应该很容易实现。因为参数名称已经被传递过来,我相信保持声明符号引用也应该很容易(如果这还不是情况的话)。
这甚至可以用于查找特定重载的调用者!

knsnq2tg

knsnq2tg5#

这也可能潜在地解决#32989问题。

相关问题