Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extension API Request: Send Custom Requests To TypeScript Language Service Plugins #43893

Closed
hediet opened this issue Apr 29, 2021 · 4 comments
Closed
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript

Comments

@hediet
Copy link
Member

hediet commented Apr 29, 2021

Context

Some advanced VS Code extensions need access to the TypeScript AST or type/symbol information.
This includes advanced code actions that require parameters (e.g. reorder parameters), inline type information rendering or code map extensions.

Technically, such extensions could parse/typecheck TypeScript on their own. However, this is not only redundant work and very slow, but also has issues if the TypeScript version does not match the version the user uses.

Problem

To avoid these problems, the already running TS language service can be made use of by implementing a TS language service plugin.
However, language service plugins can only extend specific functionality, like completion, hover information or diagnostics.
They do not have access to webviews or cursor positions of VS Code.

Vice versa, VS Code extensions have access to webviews and much more, but they can only send completion/hover/diagnostics requests to the TS language service and not interact with wustom TS language service plugins.

It would be very helpful if third party VS Code extension <-> TS language service plugin communication is officially supported.

Workaround

Currently, you can hijack the command executeCompletionItemProvider for a magic position (for example 10^10), JSON serialize your request and use it as triggerCharacter and override the corresponding handler in the typescript language service plugin to handle that custom request (given the magic position matches).
You can send a response back by encoding it as a CompletionList entry.
It works, but is a very hacky approach.

Proposed Solution

Extend the API returned by the TypeScript language features extension (or alternatively provide a new command typescript.invokeCustomCommand with corresponding parameters):

class ApiV0 {
  // ...
  invokeCustomCommand(customCommandId: string, uris: Uri[], payload: /* JSON serializable */ unknown): Promise<unknown> { ... }
}

Extend the LanguageService interface of the TypeScript project:

export interface LanguageService {
  // ...
  handleCustomCommand(customCommandId: string, fileNames: string[], payload: /* JSON serializable */ unknown): Promise<unknown>;
}

Uris are automatically translated to file names.

The default implementation just throws an error. Language service plugins can override this method and handle receiving requests.

@paulshen
Copy link

This feature would unlock a lot of my personal extension ideas (eg semantic code visualization)! I'd love to query the TS service like typescript-language-features does. I've spent a lot of time looking at typescript-language-features and I was going down the rabbit hole of replicating its behavior (spawning another TS server). Didn't think of @hediet's clever hack but it'd be great to have a blessed way of accomplishing this!

@mjbvz mjbvz transferred this issue from microsoft/vscode Apr 29, 2021
@swissmanu
Copy link

My work-in-progress extension for RxJS debugging would benefit from this a lot. If I would have actual type information at hand without an additional compile, recommending debugging actions to my users for a specific code fragment would become much more reliable.

@mjbvz mjbvz removed their assignment May 5, 2021
@RyanCavanaugh RyanCavanaugh added In Discussion Not yet reached consensus Suggestion An idea for TypeScript labels May 6, 2021
@mjbvz
Copy link
Contributor

mjbvz commented May 12, 2021

For the TS side, @sheetalkamat mentioned there may already be a way for a plugin to register for a new command if the plugin has access to the session: #43449 (comment)

@andrewbranch
Copy link
Member

Fixed by #44291

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
In Discussion Not yet reached consensus Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

6 participants