microsoft / language-server-protocol

Defines a common protocol for language servers.
https://microsoft.github.io/language-server-protocol/
Creative Commons Attribution 4.0 International
11.28k stars 798 forks source link

completionItem snippets conflict with signatureHelp #274

Open georgewfraser opened 7 years ago

georgewfraser commented 7 years ago

When implementing a java language server, it would be nice to be able to activate signatureHelp immediately, without a trigger character. Suppose for example the user has typed:

someValue.someMeth

We would like to autocomplete someValue.someMethod() and place the users cursor between parentheses. This is possible using snippets:

CompletionItem { label: someMethod, insertText: someMethod($0), insertTextFormat: 2 }

The problem is that signatureHelp relies on the trigger character (, and it doesn't get activated when the ( is inserted as part of the snippet.

This problem does not come up in languages like Typescript, because the expression someValue.someMethod is well-defined as a reference to someMethod. But in Java, method references have a different syntax someValue::someMethod. So we know the user will always type (, but we don't autocomplete it.

There are two possible solutions to this, one at the VSCode level and one at the language-server-protocol level:

  1. VSCode solution: if the character before $0 in a snippet is a signatureHelp trigger character, activate signatureHelp.
  2. LSP solution: add a property CompletionItem { ... activateSignatureHelp: boolean } that activates signature-help immediately following completion.
georgewfraser commented 7 years ago

As @jrieken explained to me on the other thread, solution 2 can be accomplished now simply by setting the command editor.action.triggerParameterHints in the CompletionItem. It wasn't apparent to me from the docs that you can issue built-in commands via the CompletionItem.command parameter; did I just miss something or is there room for improvement in the docs?

kdvolder commented 7 years ago

I.m.o. using a 'built-in' command in this way isn't a equivalent to your 'solution 2'. There is no list of built-in commands that can be relied upon across language server client implementations. So, this means, the 'solution 2' is then limited to language server clients that implement that particular command.

My objections would, of course, be resolved if LSP dictated a set of built-in commands that every language-server client should implement.

dbaeumer commented 5 years ago

See latest comment in https://github.com/microsoft/vscode/issues/78806#issuecomment-520327994

sam-mccall commented 2 years ago

It would be nice to have a solution to this problem (and I've been looking at implementing a workaround), but the idea proposed in microsoft/vscode#78806 doesn't work well so I wouldn't be happy to see it added to LSP.

If the completion item has foo(${1:arg1}, ${2:arg2}), you want signature help triggered when the cursor is placed at $1 and when it is placed in arg2. Attaching the command to code-complete acceptance only triggers signature help for the first arg (and only the first time, if you tab around the placeholders a bit).

I think editors already have enough info to infer the right behavior, namely that preceding non-whitespace characters ( and , are signature-help trigger characters. An example of an editor handling this well is Neovim + https://github.com/hrsh7th/nvim-cmp + https://github.com/ray-x/lsp_signature.nvim.