Skip to content

Specification to open a second completion after apply a completion item #565

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

Open
angelozerr opened this issue Sep 7, 2018 · 24 comments
Open
Labels
completion feature-request Request for new features or functionality
Milestone

Comments

@angelozerr
Copy link
Contributor

One feature that I love when I write code is the completion apply which opens a second completion popup which suggests the values that you can insert after completion apply.

Here a Java demo which defines 2 int variables (i and j). When substring method completion is applied, it suggest completion popup for the substring parameters which are int.

applycompletiondemo

There are other usecases like HTML/XML (when completion for attribute is applied, it suggest values for attribute values, etc).

It should be cool if LSP could specify a new protocol to manage that (by extending completionItem/resolve?)

@mickaelistria
Copy link

I think this can be covered by using placeholder and choices which are already specified for completion.
But these placeholders don't get rich information like what completion gives. So there is indeed room for improvements.
Maybe the Completion response could add a new type of placeholders that could be "completablePlaceholders" with one default value for insertion, tab stops and so on, and just giving the hint that on edition of this placeholder, a new completion request should be sent?

@dbaeumer dbaeumer added discussion feature-request Request for new features or functionality labels Sep 7, 2018
@dbaeumer dbaeumer added this to the Backlog milestone Sep 7, 2018
@mickaelistria
Copy link

Actually, as I'm thinking about it, I don't think we need the protocol to state something about it: if there is a placeholder, it's most likely that user will probably want to edit it, and if user wants to edit it, why wouldn't the client ask for another completion?
FWIW, automatically asking for completion on placeholders would be a welcome addition to LSP4E for instance.

@DanTup
Copy link
Contributor

DanTup commented Nov 26, 2018

There is a command on CompletionItem which we use in the (not currently LSP) Dart plugin to do just this:

https://github.com/Dart-Code/Dart-Code/blob/7df6509870d51cc99a90cf220715f4f97c681bbf/src/providers/dart_completion_item_provider.ts#L197-202

However, it's not clear how this could work with LSP since that command is VS Code-specific. I guess if you're implementing both the LSP server and the plugin the wraps it for an editor, you could send a custom command and then map it on to the appropriate thing for each editor, but it's messy.

@angelozerr
Copy link
Contributor Author

@tsmaeder told me that it exists a specification for snippet choice https://github.com/Microsoft/language-server-protocol/blob/master/snippetSyntax.md#choice

@mickaelistria I'm not sure that LSP4e implement that ?

I think it's a good idea for values which not require complex computing. For other case like Java completion apply, I think it should be better to call a command. We could have a syntax snippet like this:

${1(myCompletionCommand)}

@DanTup
Copy link
Contributor

DanTup commented Dec 3, 2018

I think it should be better to call a command. We could have a syntax snippet like this:

There's already a command property on CompletionItem (see my previous comment above) - isn't this the same as what you're requesting?

@mickaelistria
Copy link

Eclipse LSP4E implements snippet choice IIRC. But anyway, I still stand with my former command #565 (comment) : there is nothing preventing the client from invoking content assist at the location of placeholders and I don't think we need addition in LSP spec to do that.

@angelozerr
Copy link
Contributor Author

Eclipse LSP4E implements snippet choice IIRC.

That's strange, I have tested with lsp4xml, but it doesn't work? Where is the supposed code which manages the open of the second completion popup with choice values?

@mickaelistria
Copy link

I have tested with lsp4xml, but it doesn't work?

Sorry you're right. Eclipse LSP4E has support for linked regions but not yet for snippet proposals. Feel free to open a new bug to LSP4E for that (and even for re-triggering completion when on another region and no snippet proposal is found); but still I don't think the spec needs anything more.

@dbaeumer dbaeumer added the info-needed Issue requires more information from poster label Dec 11, 2018
@dbaeumer
Copy link
Member

Looks like this doesn't need any addition in the spec. Any objection to close the issue?

@DanTup
Copy link
Contributor

DanTup commented Dec 11, 2018

@dbaeumer Actually, I think my comment above may be incorrect. Thinking again, it's not clear whether the command on a completionItem is a command that the LSP client sends back to the server (via executeCommand) or a command for the client to execute (eg. like calling editor.action.triggerSuggest).

I assumed you could put editor.action.triggerSuggest in it (since that's what I do in the equiv field in the VS Code API), however now I'm thinking this is unlikely, since an LSP server probably shouldn't be relying on internal command identifiers that may of may not be available on the client.

Can you clarify which it is - is CompletionItem.command the ID of a command the LSP server handles (via executeCommand) - in which case I think this requres is not currently possible - or executed by the client (in which case, should LSP define well-known commands that the server can call on the client)?

@DanTup
Copy link
Contributor

DanTup commented Dec 11, 2018

Actually, the spec does say this!

The protocol currently doesn’t specify a set of well-known commands. So executing a command requires some tool extension code

And the thing that decides which commands should be sent to the server versus executing in the client plugin is ExecuteCommandOptions.

TL;DR - putting editor.action.triggerSuggest in the command on a CompletionItem probably works, but since it might not be consistent across editors, may be better as a custom command.

@dbaeumer
Copy link
Member

The server in some respect relies on capabilities on the client side. These are commands which are not handled by the server itself and settings (getConfiguration call send from the server to the client). The current advice is that a server specs these and that the client plugin needs to do these transformations (for example map the settings to their settings store).

I am not a big fan of starting to spec editor commands since this can be very specific to a tool / UI.

@DanTup
Copy link
Contributor

DanTup commented Dec 11, 2018

Yeah, I think what is there is fine now I understand it better.

That said, I think there's still something ambiguous. The description of ExecuteCommandOptions sounds like any commands that are listed in there will be sent to the server (via workspace/executeCommand) and anything not listed in it will be handled locally (eg. the client expects the local extension can handle it).

However, for CodeAction the text says:

When the command is selected the server should be contacted again (via the workspace/executeCommand) request to execute the command

It's not clear whether the client should send the command from the CodeAction to the server always, or whether it should handle it locally if it's not listed in ExecuteCommandOptions. I think the latter would be better (because if desired, it allows the code action commands to be run through a local handler), however I suspect based on the text that it currently always goes to the server in VS Code?

@dbaeumer
Copy link
Member

@DanTup actually no. The idea of this sentence was to avoid to execute local editor commands. I will clarify this.

@DanTup
Copy link
Contributor

DanTup commented Dec 20, 2018

@dbaeumer I'm not sure I follow - does this mean it's not allowed to execute local commands in code fixes? (If not, that somewhat throws a spanner in the works for the discussion on the "ask for user input" issue 😕)

@dbaeumer
Copy link
Member

@DanTup if you expect the server to run in different clients then executing the command will very likely fails unless we standardize commands which I am actually not a fan of. Or do I misunderstand something?

@DanTup
Copy link
Contributor

DanTup commented Dec 20, 2018

@dbaeumer No, that's right - but the spec already explicitly mentions this:

Command

Represents a reference to a command. Provides a title which will be used to represent a command in the UI. Commands are identified by a string identifier. The protocol currently doesn’t specify a set of well-known commands. So executing a command requires some tool extension code.

This is what #642 is about (ignoring the misleading title) - I think the client capabilities should include the command IDs the client extension supports, so the server can act appropriately. There's no need for LSP to standardise them, they should be documented by as LSP server as extra functionality that can be provided if the client provides the required local functionality.

@dbaeumer
Copy link
Member

As commented on the other item this sentence was added when a server had no way to handle commands. I will change this to indicate that the best way is to execute a command on the server.

@DanTup
Copy link
Contributor

DanTup commented Dec 20, 2018

I think I somewhat derailed this thread. I don't think the original request is resolved anymore, since the server shouldn't rely on being able to using editor.action.triggerSuggest as a command.

@dbaeumer dbaeumer removed info-needed Issue requires more information from poster discussion labels Oct 31, 2019
@vrama628
Copy link

I want to use something like this to implement "multi-stage autocompletion", for example:

two-step

To record this gif I used the hack @DanTup suggested. It'd be nice to have a client-agnostic solution for this.

@muirdm
Copy link

muirdm commented Feb 14, 2020

To revive the discussion, I propose we add a new LSP snippet variable COMPLETE that instructs the client to trigger a completion and insert the result. Since it is a variable that can be repeated inside the snippet, completion can be triggered at each tab stop, or a subset of tab stops.

For example, say you have

function foo(int a, string b) {}

Completing to foo could yield either of the following:

  1. A snippet foo(${1:$COMPLETE}, ${2:$COMPLETE}) which would automatically trigger completion for the first argument, then after the user presses TAB it would trigger completion at the second argument.
  2. A snippet foo(${1:$COMPLETE}) which similarly triggers completion. However, the inner completion could return another snippet: best_int, ${1:$COMPLETE}, allowing you to complete each argument one at a time. I believe it would also allow for the "multi-stage autocomplete" @vrama628 is talking about.

A problem arises if the user needs multiple completions to fill in a single argument. For example, they want to enter user.age() for a. If they press TAB after completing user, it will take them to the next parameter instead of letting them continue user. In this case the user could use a different trigger character such as . to select user and avoid TABbing to the next tab stop.

To be backwards compatible with clients that don't support COMPLETE, you can pass the existing placeholder value as the default value for the $COMPLETE variable. For example: foo(${1:${COMPLETE:a}}) would show "a" as the placeholder if the client doesn't support $COMPLETE.

@dbaeumer
Copy link
Member

Interesting idea. The only problem I see is that this makes the snippets deviate from TextMate snippets which we tried to avoid so far.

I would suggest that we open a separate issue for the snippet idea since I see this independent from this request. I don't want to ask users to generate snippets if they want to trigger a second code completion call after inserting a completion item.

@muirdm
Copy link

muirdm commented Mar 9, 2020

I don't want to ask users to generate snippets if they want to trigger a second code completion call after inserting a completion item.

When would the user need to generate a snippet? In my proposal the LSP server generates the snippets with $COMPLETE, not the user.

I would suggest that we open a separate issue for the snippet idea since I see this independent from this request.

I was trying to propose a concrete way to implement the desired behavior. It seems natural to use snippets since otherwise it would be very clunky for a single completion item to control multiple completion triggers.

@dbaeumer
Copy link
Member

dbaeumer commented Mar 9, 2020

When would the user need to generate a snippet?

I meant users of the library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
completion feature-request Request for new features or functionality
Projects
None yet
Development

No branches or pull requests

6 participants