apexskier / nova-typescript

Typescript support for Nova
https://extensions.panic.com/extensions/apexskier/apexskier.typescript/
MIT License
68 stars 18 forks source link

Able to summon suggestions at any time? #30

Closed sgwilym closed 3 years ago

sgwilym commented 4 years ago

In VSCode, it's possible to summon a list of the best suggestions TS can come up with by pressing Ctrl + Space.

This is useful in situations when you'd like to see the available exports on a package, or any situation where you don't know the first few characters of a token.

Is this possible in this extension, or in Nova?

apexskier commented 4 years ago

Ideally Nova would allow you to summon its completions at any time, instead of just when you are typing - I think that's a valid feature request for the Nova team and should be the ultimate resolution.


This made me curious about language server provided completions in general, so I tried adding a manual request to textDocument/completion. I expected Nova to intercept the response, since that's what it does for textDocument/publishDiagnostics which I think it uses internally. It doesn't intercept it though, so Nova might not be using the language server for completion. I know Nova doesn't use a bunch of the features from the Language Server Protocol, so I've implemented them manually in this plugin.

I started experimenting to see if the suggestions provided by the language server are better, and to see if I can register my own Nova completion assistant. I'd like to use a completion assistant, but I haven't gotten it working yet. With what's currently available from Nova's extension API I can't create a great UI for presenting suggestions outside of this (closest is choice picker, which only allows a single bit of text). You can play with it in my branch at https://github.com/apexskier/nova-typescript/pull/31.

Screen Shot 2020-08-10 at 21 23 53
sgwilym commented 4 years ago

Thanks for exploring this! I've filed a feature request at https://dev.panic.com/panic/nova-issues/-/issues/1464

Cykelero commented 4 years ago

I filed a related issue, specifically about summoning completions when typing a dot). In the comments, the dev team's conclusion is that the ball seems mostly in the extension's court; since it's where the language server is wrapped.

apexskier commented 4 years ago

@Cykelero

I think I see Logan's point there - what you're referring to is summoning completions on and given the context of a specific object you're "interacting" with, which Nova is decoupled from.

Nova, and the vast majority of the code driving this extension, operates on the Language Server Protocol. I'd expect the protocol would be able to provide that context, although I'm definitely not an expert and might be wrong. If it does, I'm curious how much is specific to TypeScript. I suspect there might be something that could be done generically that could be shared with any language server nova extension, but I'm not sure. (I suspect the actions this extension supplies, like Go to Definition and Rename Symbol could be built in to Nova)

Some more context to your comment:

AFAIK, Visual Studio Code entirely relies on the TypeScript language server for completion

That's true, but the TypeScript language server doesn't conform to the Language Server Protocol. It's similar but not the same, which is a little confusing. I'm hopeful that in future they'll converge, given that Microsoft is behind both projects.

apexskier commented 4 years ago

I've done some more playing around and have discovered some things

  1. Registering a completion assistant has no effect if a language server is running. (here's a test branch).
  2. The completion assistant interface is purely synchronous - this means I can't provide a custom one with a language server.

In 1.6.0 / #31 I'm adding an experimental feature that adds basic support for manual suggestion summoning through a best-effort UI. You can bind the command to a keyboard shortcut through nova's keybinding settings. Once it's out, let me know how it goes.

sgwilym commented 4 years ago

@apexskier I checked out the new feature this morning - it's actually pretty usable if it weren't for that last insert dialogue!

https://dev.panic.com/panic/nova-issues/-/issues/1518#note_7537

If there's anything we can do from Nova's side to make this simpler for them, we are happy to investigate!

Hope springs eternal.

apexskier commented 4 years ago

Can you clarify what insert dialog you're referring to? It might be one I've added myself.

sgwilym commented 4 years ago

@apexskier This one:

image
apexskier commented 4 years ago

I can get rid of that. I added it because the prior choice picker has pretty much nothing I can do to add more context that is provided by the language server.

Instead, I think it makes more sense to introduce a "show documentation" type of command that lets you see more information about a symbol (a lot provide documentation through doc comments). I was playing around with that in https://github.com/apexskier/nova-typescript/compare/signature-help.

apexskier commented 4 years ago

Somewhat related to this is a Nova bug I discovered that should be fixed in v1.3. Language server trigger character, such as "." aren't triggering auto complete like they should.

Some info from an email thread with Nova support:

On September 28, 2020 cameron@camlittle.com wrote:

...

Because I’m using a language server, I can't define a completion provider (https://github.com/apexskier/nova-typescript/compare/poc-completion-assistant#diff-8cfead41d88ad47d44509a8ab0a109adR105), and because of the synchronous nature of the current completion provider api I can’t hack around this issue to support it manually (since fetching completions manually from a language server is asynchronous).

I just did some more research and testing, and I’m fairly sure my main issue is a Nova bug in the language server protocol client implementation. In the language server protocol, the client is in charge of sending completion requests (https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion). Nova does this for identifiers, given that completions with my extension show up, but it doesn’t appear to respect the triggerCharacters defined in the server capabilities.

My underlying language server sends this within it’s capabilities:

   "capabilities": { 
      "completionProvider": {
        "triggerCharacters": [
          ".",
          "\"",
          "'",
          "/",
          "@",
          "<"
        ],
        "resolveProvider": true
      },

From the spec (emphasis mine):

Most tools trigger completion request automatically without explicitly requesting it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user starts to type an identifier. For example if the user types c in a JavaScript file code complete will automatically pop up present console besides others as a completion item. Characters that make up identifiers don't need to be listed here. If code complete should automatically be trigger on characters not being valid inside an identifier (for example . in JavaScript) list them in triggerCharacters.

The first emphases works, the second doesn’t.

On September 29, 2020 Thomas wrote:

...

Also, support for invoking LSP completions using the triggerCharacters property will come in 1.3, which should be out next week.

apexskier commented 4 years ago

Additionally, these are resolved

Nova 1.2 allows registering a completion assistant with an LSP client running

  • The completion assistant interface is purely synchronous - this means I can't provide a custom one with a language server.

In the same support thread they told me this does return a promise, and the docs have been updated to reflect that.

https://github.com/DefinitelyTyped/DefinitelyTyped/pull/48340 ⬅️ An approval on this would be helpful!

apexskier commented 3 years ago

Nova 2 has support for this natively - Editor > Show Completions, which is bound to ^ Space by default.