-
Notifications
You must be signed in to change notification settings - Fork 798
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
CodeActions to return Command[]|WorkspaceEdit
#178
Comments
@mickaelistria yes and no. The reason why we have commands is that at a specific position (problem) there can be more than one possible code action (e..g quick fix, ....). So you can provide command and postpone the actual computation of the edit until later. However I think there is also value to return a WorkspaceEdit. But that would need a UI piece as well. |
Ok, so it would be more something like |
Exactly, plus a way to name the WorkspaceEdit to present a label in the user interface. |
Like completion, the WorkspaceEdit from CodeActions should allow some placeholders for variable substitutions/linked edit when applied. |
This is #243 |
FWIW, at the moment, I believe this is the biggest limitation for the protocol, which prevents some of the common refactorings to be easily provided by language servers without tool-specific effort. I'd be delighted to know this gets considered for v4. |
There is actually an easy workaround for this with the applyEdit request that can be send form the server to the client. The only downside is one more server roundtrip. So I don't think that this 'blocks' something. I am even tending towards closing this unless we figure out the applyEdit is not sufficient. |
Agreed that this isn't necessary. I think this is because the workflow for using applyEdit to implement a code action is a bit tricky, and could be solved with a bit of documentation or some sugar in LSP libraries. For others coming to this bug, here's how to apply a workspace edit in response to a code action. I can confirm that this is working with both vscode and atom-languageclient with no tool-specific code. The conversation between server and client looks as follows:
And here are links within the commit that landed this into our server. Declare executeCommand capabilities: Return a Command with the method name (myApp/applyEdits) that you registered the capability to execute, and your WorkspaceEdit as a parameter: Polymer/polymer-editor-service@a2f77a5#diff-bd6d4fe0d7e96ac0e708e87e1617eab6R245 Execute that command by doing an ApplyWorkspaceEditRequest: |
The workflow with applyEdit seems overkill to me in most use-cases. I agree
there are workarounds, but I think we'd all prefer the LSP to be as simple
and powerful as possible. My proosal IMO matches those 2 goals better than
chaining several operations.
…--
Mickael Istria
Eclipse IDE <https://www.eclipse.org/downloads/eclipse-packages/>
developer, at Red Hat Developers <https://developers.redhat.com/> community
Elected Committer Representative at the Eclipse Foundation
<https://www.eclipse.org/org/> board of directors
|
ApplyEdit as a server to client notification is horrible because it is so stateful and asynchronous. Just send the edit on the command reply and editors can just apply it synchronously. I agree with @mickaelistria , returning a workspace edit which is he 99% case makes these commands much easier to implement in LSP clients. |
I agree that applying edits should be simple but the API shouldn't foster wrong coding patterns. Computing these edits (for example for refactorings) is very expensive and if a code action request returns 3 possible refactorings then it would be wrong to compute the edits upfront. They should be computed as late as possible not as early as possible. Adding another roundtrip to this doesn't make it more async. So instead of returning the edit the server could instruct the command if the client should auto register for the command execution so that the flow gets easier to be implemented. This kind of flow is even used in IDEs where the refactoring are not provided using a server. Usually the ide populates a menu (commands received via code actions). If a menu item is selected to calls into the language API to compute a workspace operation (execute command) and then applies theses workspace operations. |
As I understand it there is no limit to the number of unsolicited things the server can do in response to the execute command request. Is that correct? If it were a request/reply to execute command and it returned a workspace edit, then ok sure, but as it is an announced set of a sync notifications the editor has to know hat it is in the state of waiting for that to happen |
Announced should say ‘unbounded’ |
I think this should rather say "can be very expensive" as many actions can return very small edits that can easily be computed quickly at the same time as the parser/analyzer detects an issue. For example, an extra closing parenthesis, when detected by the parser, can immediately return the right text edit to remove it. It's not always an expensive operation.
Note that this change is backward compatible. I could make a PR for that. If so, should it include a client capability such as |
@mickaelistria I agree that these can be cheap to compute. A PR is very welcome here. In VS Code we added a type And yes we would need to add a client capability since clients might not support this. Something like |
The initial request seems well covered by #389 . Closing. |
In the vast majority of the use-cases of CodeActions, the action will be an edition. That would work for quick fix, code hints, generate related tests... Forcing the Command[] pattern here kinds of break the goal of being client-independent: the command are client-specific and it's the goal of the protocol to avoid such client-specific features.
So I would suggest that rather than returning a
Command[]
, the code actions should be allowed to also return a WorkspaceEdit. That would cover much more nicely a lot of use-cases in a client-independent way.The text was updated successfully, but these errors were encountered: