Repository: TypeScript
Issue: When Invoking "Go To Implementation" For Parameters, Go To Arguments
Labels: Suggestion,Awaiting More Feedback

# Suggestion

## 🔍 Search Terms

Go To Implementation, Parameter, Go To Arguments

## ✅ Viability Checklist

My suggestion meets these guidelines:

* [x] This wouldn't be a breaking change in existing TypeScript/JavaScript code
* [x] This wouldn't change the runtime behavior of existing JavaScript code
* [x] This could be implemented without emitting different JS based on the types of the expressions
* [x] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, new syntax sugar for JS, etc.)
* [x] This feature would agree with the rest of [TypeScript's Design Goals](https://github.com/Microsoft/TypeScript/wiki/TypeScript-Design-Goals).



## Context

The TypeScript language server allows to go to implementation for properties. This is super useful, as it allows to quickly jump to possible property values:

![Code_-_Insiders_f7EoFPs8cb](https://github.com/microsoft/TypeScript/assets/2931520/8f0cdc40-cb03-4800-8279-28ceace5a58c)

```
function foobar(myArg: { myProperty: number }) {}
foobar({ myProperty: 4 });
```

## ⭐ Suggestion

It would be very useful if "Go To Implementation" would be supported for parameters as well, jumping to the corresponding argument: (ignore the comments in the code, they are just there to make the demo work)

![Code_-_Insiders_LGZpHeaJJF](https://github.com/microsoft/TypeScript/assets/2931520/0bde7a0f-6de0-4a2d-98a9-b5ad6df1163a)

Ideally, this would also work for named tuples:

![Code_-_Insiders_3WPPBeW6Lh](https://github.com/microsoft/TypeScript/assets/2931520/868e730f-7849-4799-882c-324ab410e7ae)

```ts
function foobar(myArg1: number) { }
type GetParams<T extends (arg: any) => void> = T extends (...arg: infer P) => void ? P : never;

function f(...args: GetParams<typeof foobar>): void { }

f(/*def:myArg1*/ 1);

```

## 📃 Motivation

In VS Code, we use dependency injection and often delegate instantiation of a class to an instantiation service.
This can look like this:

```ts
export class TextMateWorkerHost implements IDisposable {
	// ...
	constructor(
		private readonly _reportTokenizationTime: (timeMs: number, languageId: string, sourceExtensionId: string | undefined, lineLength: number, isRandomSample: boolean) => void,
		@IExtensionResourceLoaderService private readonly _extensionResourceLoaderService: IExtensionResourceLoaderService,
		@IModelService private readonly _modelService: IModelService,
		@ILanguageConfigurationService private readonly _languageConfigurationService: ILanguageConfigurationService,
		// ...
	) {
	}
}
```

This class can be instantiated like this:
```ts
class TextMateTokenizationFeature {
	private readonly _workerHost = this._instantiationService.createInstance(
		TextMateWorkerHost,
		(timeMs, languageId, sourceExtensionId, lineLength, isRandomSample) => this.reportTokenizationTime(timeMs, languageId, sourceExtensionId, lineLength, true, isRandomSample)
	);
}
```

I often want to jump from the `_reportTokenizationTime` field in `TextMateWorkerHost` to the arrow expression in `TextMateTokenizationFeature`.
Currently, this is not so easy, as I would need to list all references of `TextMateWorkerHost` to find `this._instantiationService.createInstance(TextMateWorkerHost, ...`. Then I have to check all arguments and find the right callback.

This feature request would make this very easy, by just jumping to implementation of the parameter `_reportTokenizationTime`.

[(here is a another example of this use-case)](https://www.typescriptlang.org/play/?#code/PTAEDsHsBcEsGMCmAuUBJcAbW5EGFIBbAB00TknAGcBZSAE0U1AAsBDK0AdlACdEAZon7gkVAISgAFAEZQ0AJ7FEfQcMSjEAGlAA2UADc2mAK4r+QkWICUAKHiYOnDNlwESZCtTqNmiAB7QGvScACKwVMSQVGwARmSgAN62oKmgxCbxCKBU0Gxw8KoA5hFBvAAKvJAGsIy8UsRVNXWoJuAA1lAA7uDWqAaQtUkAvrYpaRlZhfxs9JSYCjl5BeihoAC8oADkLjj4RKTksJS0DExbANxjaaAgEDAIKKDwJ9C8JvDQkLysHKAADKpLBoxOJxqk7vB2JgyOAik8AGI4ejyFgqUhsJCgLpo-jySCgWYoti8IomQgaaCcHEaQnpElsCllUARQn0Rgo3GIMEASBe1DeHy+9VsPJ5k2w00Qs3miyCgR8TFQaAAKgFoIrMFpReLeLAjEFVDKsIsAPpUJiIT6IegAZRMRXhuTQQUIyoA8rELbwjPFEAAee2OxDO10YAQEgA+oDajAEe3oAD5tWKJdkZnMTaBTfKNWdMAA1YRUY7gND0D1e4S+sj+8Dk2LCUDR+swnRoTUEcBBbt4dhwm0AUQMlObMfAcYTyZ1jX1+XM0szC2zURLXiole9NYDGdloHK0VgXgA2gBdaepvUGhfG5emxixSBtJAF4xmZUI6XQEz8UKIR-Pog4bfIQ+Slimupzoau5ZqaGhxGQFboJ6W4IQGj6QGQbDgBekHXkaS5mjaR7fMqBCMIO9AkbwEEAAJoBguTYXAYGULa1aPOkV7zgRe6mjgTHdrArHgOxPqPMqjF5EJIliTUSB0Wg7igROcmcbO+EwXeLyECpdocUgZFEHpakKTq9EADLYWSbDwl28ZkrwskGei3HQYufGOHCJi2fs4AOT+zniYZ6BWd5vn2bAjlBfJ2iitYSTgqAoyjLYdwqmioCUrAeIvA+HAqOwnBGKYKhSNhKKKMoCUWOomicF8oAAAa7G4ByeKWpy+E1yC2K1+weEcJyagAdPwJS5MIlTVLUwhSIktwAFSgCNq2gItYDDNYVz9e4hzrqN42lFNTSzfUC3AMtq0jetm3bWMDhOKAXZvJhZA-MkNwaTxWlmoQ+bKlgex7R1w35lcNxJfyuTvJ83xSElNz0VJzHCV4pmuVBN6EdmAnSSx6MuZJAqozFjzajcNx3NdSUJZ9lMQmAGWsqy0CZRiWJoDGVA+TCiy4Da+IQGwNRFDxjUCFUhDNbt7VDd4+YjdDgpw7wTVggzqRsxEI2mv9vgbKiOv8STMmE8FiBKzMQQo5oCOa5TsuDQd+YUw7aS5pqbvu0bVC6zzwa5AA6rU8LQAAgvQbDEGUI0WmQ1r0C6iCEN77va37cFUcKKEjSOvAlpQ5Zpw7Ge66uR6dSXmtl-e-5Ppor6ldXDO1-Bfr0C3lNl8Rwpd-diNpNDmGW5gkBFFITV4NbgsACSJE7+2daNaChMMTX3TcKVjHcdB4iVZhAnVYjXSNfVA21zvL4rR2TRUp11PNS0rWtG3Jfdi+gwrvhjYgE1lNNZoc0LpXVfndK4QA)

## Implementation

I don't know how reference search works in typescript, but using the typescript compiler API, one could traverse all *CallExpression*s, ask the checker for their signature, query `checker.getResolvedSignature(s)` and check the returned symbols.
Unfortunately it seems like the symbol with name `myArg1` returned for the first parameter of `f` is not linked to the parameter symbol with name `myArg1` of `foobar`.