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

Provide more structured type information to editors via tsserver #46701

Closed
DuncanWalter opened this issue Nov 5, 2021 · 4 comments
Closed

Provide more structured type information to editors via tsserver #46701

DuncanWalter opened this issue Nov 5, 2021 · 4 comments
Labels
API Relates to the public API for TypeScript Question An issue which isn't directly actionable in code

Comments

@DuncanWalter
Copy link

This is somewhere between a suggestion and a question (and a blog post based on word count) that also touches on VS Code / LSP, so I didn't know where to put it. Feel free to point me elsewhere.

There are a few type related editor features I'm interested in attempting to implement, but they feel like relatively "core" or tightly integrated features. The most closely related projects I'm aware of have a few shared limitations that I'd also like to sidestep if possible. What I'm hoping to get out of this wall of text is a sense of whether these feel like "core" features I shouldn't be attempting without input from maintainers, whether there's a definitive "best approach" for tackling these types of features, and confirmation that these aren't already existing concepts. I think at least some of the changes would land in TypeScript and VS Code, which is why I'm dropping this here first. If this is the right spot for this conversation, I imagine we'll also want to tag @mjbvz into the conversation. I've done a fair amount of reading around the TypeScript repo over time if that makes it easier to explain anything.

A few things I'm interested in playing with:

  • when I select an identifier in the editor, the editor already provides a sort of "type hint" that shows what its type is. I'd like to be able to "click into" aliases and interfaces in the type hint so I can drill down into specifics. Today AFAIK the best way to get equivalent information is to "goto definition" until you hit the bottom of the type's structure, then pop back up the tree while building up the type definition in your head. Visually I'm imagining something similar to VS Code's code-folding behavior or the ast-explorer web page. This sounds like a huge can of worms and is probably the most ambitious idea here.
  • provide a visual indicator when an identifier or expression evaluates to any in the editor. Similar to the concept of code coverage and technically possible today by abusing @typescript/eslint and making a custom rule to forbid the any type. Ideally I was hoping to make something visually more subtle that talks to the tsserver instance that's already driving TS support in the editor instead of having a parallel TS process. I'm less interested in code coverage as a build time check, and more interested in making it obvious when any is unintentionally bleeding somewhere. In my experience new TS devs don't have good intuition for when a single explicit any will infect other types, and experienced TS devs still occasionally gloss over a type problem on accident by creating references to any in non-obvious ways. I suppose this is also closely related to semantic highlighting.
  • allow me to see the diagnostics suppressed by directives like @ts-ignore-error or @ts-expect-error by hovering/selecting them in the editor. This might be super easy or super difficult depending on how that suppression is implemented. I haven't dug around in that part of the code much.

Shared limitations:

  • I don't think there's a way in a non-@Builtin VS Code extension to access the editor's canonical tsserver instance. I also see how allowing other extensions to toss requests at the tsserver instance might be a red flag- maybe there's a middle ground? I've never worked with a tsserver plugin directly, so maybe that's a good place to start. My understanding is that tools like @typescript-eslint have to run their own tsc instances via the node api in watch mode to get the type information they use. Maybe it makes sense for them (eslint needs to run when tsserver isn't running) but for all these editor-only features I'd love to hit the already running server.
  • There doesn't appear to be a way to ask tsserver or tsc for a structural representation of a type (probably some sort of tree resembling an AST- there must be an existing representation somewhere in TS already). AFAIK the type hints shown in the editor are sent as strings to the editor. This is probably far more performant, so I'd be looking for a separate, dedicated source of information for the new request. I'd also want this representation to be powerful enough to tell when two types have the same name but are actually from separate places.

very vaguely related issue about code coverage: #36802

@andrewbranch
Copy link
Member

It sounds like you’re interested in building a language service plugin. I believe you can even bundle this into a VS Code extension, have that insert the TS plugin, and then communicate between the VS Code extension (the client) and the TS plugin (run by TS Server). I think this is how https://github.com/denoland/vscode_deno works. Does that answer your question?

@andrewbranch andrewbranch added API Relates to the public API for TypeScript Question An issue which isn't directly actionable in code labels Nov 11, 2021
@DuncanWalter
Copy link
Author

Thank you! I expect to hit a couple specific issues later based on that readme you linked, but this definitely sounds like the concept I'm looking for. I think this issue can probably be closed and I can open more specific issues that are easier to triage later if needed. I'm going to jot down a few bullets about how language server plugins interact with this issue- could you give this a quick scan and see if I've got an accurate mental picture?

  • Language service plugins are bits of code that execute in the tsserver process (not a separate child process) and typically augment/alter tsserver's default behavior.
  • To use a language service plugin, a project needs to configure it in its tsconfig(s?) and the programmer may also need to have a corresponding editor extension installed/configured depending on what the language service plugin is doing. For example, it's not enough to install a VS Code extension and open any open source project- the project is likely missing configuration.
  • Language service plugins aren't meant for adding new "api endpoints" to the TS language server, but language service plugins have essentially free access to everything in the tsserver process and can alter any existing behavior up-to-but-not-including changing input and output types of requests.
  • There are quite a few ~popular tools already using language server plugins. From what I can tell from peeking at their source code, most of these tools are enabling/disabling tsserver behaviors or essentially forbidding certain identifiers from being used.

@andrewbranch
Copy link
Member

Language service plugins are bits of code that execute in the tsserver process (not a separate child process) and typically augment/alter tsserver's default behavior.

Yes.

To use a language service plugin, a project needs to configure it in its tsconfig(s?) and the programmer may also need to have a corresponding editor extension installed/configured depending on what the language service plugin is doing. For example, it's not enough to install a VS Code extension and open any open source project- the project is likely missing configuration.

I believe language server plugins can be added without tsconfig listing it by sending a command to TS Server. I think this is how the Deno VS Code extension works.

Language service plugins aren't meant for adding new "api endpoints" to the TS language server, but language service plugins have essentially free access to everything in the tsserver process and can alter any existing behavior up-to-but-not-including changing input and output types of requests.

Historically true, but this is now possible via #44291

There are quite a few ~popular tools already using language server plugins. From what I can tell from peeking at their source code, most of these tools are enabling/disabling tsserver behaviors or essentially forbidding certain identifiers from being used.

🤷 I’m not super familiar with existing uses in the wild.

@Kingwl
Copy link
Contributor

Kingwl commented Apr 6, 2022

Historically true, but this is now possible via #44291

Sadly it's not true yet.
The only one person who can communicate with tsserver is vscode builtin typescript extension. But If with microsoft/vscode#146879. It's will come true.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
API Relates to the public API for TypeScript Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

3 participants