-
Notifications
You must be signed in to change notification settings - Fork 135
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
Fix Code Action Resolution #680
Conversation
10eabe1
to
d2c4f8b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fix itself LGTM, do you mind adding a test to cover this?
Thanks!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've looked at the code below this change and it looks to me that if the user provides multiple only
items like source.fixAll
and source.formatAll.terraform-ls
then the server will perform the formatting multiple times, once for each. If so then that seems non-ideal. The formatting is already very slow and that wouldn't help in running the code action within the allotted time budget.
@rchl James mentioned that to me yesterday himself and I initially said that I would expect such a behaviour, but I see your point about the performance too and forgot that ST doesn't allow code actions to be filtered by language. We have two options here I think:
|
I do think that the formatting doesn't quite fit within the Also, producing multiple code actions with formatting changes doesn't quite make sense because those have to be run sequentially so if the first one formats the document then the second one will likely fail in mysterious way since it will be applying the changes to an already formatted document. |
Side note: Using the versioned workspace edits (new in 3.16 LSP spec) would be preferred since that would guard against applying changes to already changed document. |
I don't disagree but I would hope we can address the problem without rearchitecting it completely.
I don't disagree here either, but I struggle to find any documentation or established convention to support this opinion, as is unfortunately common with many features in LSP. |
Sure. It's not a must have but good to have in general wherever text edits are created.
I tend to think of "fix" addressing an existing diagnostics while "format" formatting the code with no relation to any existing diagnostics. |
49a0e4a
to
0163b81
Compare
Thanks @rchl for the help in working out this implementation! I've read through your conversation here and the content of https://code.visualstudio.com/api/references/vscode-api#CodeActionKind and come to similar conclusions. I've removed I still have to deal with what should happen if multiple format-type actions are requested. |
0163b81
to
d0b884b
Compare
I tried several approaches to test what would happen if multiple code actions are received, but could not reproduce this case. In each attempt, only one code action was received by the LS from VS Code. I tried using the all languages "editor.codeActionsOnSave": {
"source.formatAll": true,
"source.formatAll.terraform-ls": true
},
"[terraform]": {
"editor.defaultFormatter": "hashicorp.terraform"
}, I also tried variations of the language specific "[terraform]": {
"editor.codeActionsOnSave": {
"source.formatAll": true,
"source.formatAll.terraform-ls": true
},
"editor.defaultFormatter": "hashicorp.terraform"
}, Each time, no matter the order, the LS would only receive one code action to process. |
d0b884b
to
e4a5ba0
Compare
Possibly VSCode has some special filtering logic. Request{
"context": {
"diagnostics": [],
"only": [
"source.formatAll",
"source.formatAll.terraform-ls"
]
},
"range": {
"end": {
"character": 0,
"line": 150
},
"start": {
"character": 0,
"line": 0
}
},
"textDocument": {
"uri": "file:///Users/xxx/app.tf"
}
} Response[
{
"edit": {
"changes": {
"file:///Users/xxx/app.tf": [
{
"newText": " min = 1,\n",
"range": {
"end": {
"character": 0,
"line": 21
},
"start": {
"character": 0,
"line": 20
}
}
}
]
}
},
"kind": "source.formatAll",
"title": "Format Document"
},
{
"edit": {
"changes": {
"file:///Users/xxx/app.tf": [
{
"newText": " min = 1,\n",
"range": {
"end": {
"character": 0,
"line": 21
},
"start": {
"character": 0,
"line": 20
}
}
}
]
}
},
"kind": "source.formatAll.terraform-ls",
"title": "Format Document"
}
] Note that the ST implementation was initially based on VSCode's since it's not really specified anywhere how "code-action-on-save" should work. So I would be fine with changing the ST implementation rather than doing anything about it here. But regardless, returning two formatting code actions is pretty bad since, if applied, will likely result in the document's code being broken. |
Also, on unrelated note, formatting typically takes so much time that it most of the time exceeds the time budget allocated for formatting (2s) and ends up being ignored. I will likely create a separate issue for that although I guess that it might be hard to address if formatting relies on running |
I've looked closer at VSCode's implementation and it does indeed filters/deduplicates code actions in this case. Given that, I'll update the ST LSP implementation to do the same. But I've also realized that "editor.codeActionsOnSave": {
"source.formatAll": true,
"source.formatAll.terraform-ls": false,
}, Where the general formatting code action is enabled but it's disabled specifically for terraform. Everything should still work as expected when only announcing support for |
@rchl I would be curious if you are able to reproduce this by running |
From the terminal it's reasonably fast: cat app.tf | time terraform fmt
terraform fmt 0.28s user 0.30s system 90% cpu 0.641 total From the code action it's considerably slower:
There are no precise timestamps here but I've manually checked it and this code action request took 1209 ms. EDIT: Actually there is a precise time from the server also which confirms my measurement. |
Actually yes, I'm using tfenv:
But formatting from the terminal also uses it:
|
e4a5ba0
to
0570a8b
Compare
This fixes several parts of the code action handler workflow. - Remove `source` as it is a base type and not a specific action we can use. - Remove `source.fixAll` because the action implies fixing errors, but terraform fmt only formats code style. - Remove `source.formatAll` to allow fine grained selection of actions. - Rename `source.formatAll.terraform-ls` to `source.formatAll.terraform` to follow existing Code Action conventions. - Correctly set the code action value in the returned `lsp.CodeAction` response to the one chosen by the user. - Exit early so as to not format a document without an explicit request. When additional code actions are added, we can modify this to return a merged list of actions to apply.
0570a8b
to
346a329
Compare
Ok, after much research, I've landed on an implementation I think everyone can use. I wrote up alot of my notes inside code-actions.md in the developer section, I still have some more links to add. We may move the documentation around at a later date, but this is a good place for it right now. I've removed all code action registrations except I also renamed I also have set it to return early if no actions are provided. We don't have any user invokable actions yet, so we shouldn't perform work if there are no requested actions. Invokable actions are explained more in developer docs section. When we start to add actions like refactor or quick fixes, this can be modified. Clients will have to mimic VS Code's client behavior of |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy with the fix itself 👍🏻 , but I proposed some changes to the docs which seemed a bit too VS Code specific without explicitly noting that fact.
Also thank you for doing all that research in this area!
Co-authored-by: Radek Simko <[email protected]>
Co-authored-by: Radek Simko <[email protected]>
Co-authored-by: Radek Simko <[email protected]>
Co-authored-by: Radek Simko <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🚀
(Just make sure to use the squash option when pushing the merge button)
@rchl We've merged this now just to get the fix out there. If there are points you'd like to work on, let us know in an issue and we'll work through it so Sublime works just as well as VS Code does |
It looks good to me, thanks. |
Enable the CodeAction tests that were commented out until the changes in hashicorp/terraform-ls#680 was released.
Enable the CodeAction tests that were commented out until the changes in hashicorp/terraform-ls#680 was released.
I'm going to lock this pull request because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. |
This fixes several parts of the code action handler workflow.
source
as it is a base type and not a specific action we can use.source.fixAll
because the action implies fixing errors, but terraform fmt only formats code style.source.formatAll
to allow fine grained selection of actions.source.formatAll.terraform-ls
tosource.formatAll.terraform
to follow existing Code Action conventions.lsp.CodeAction
response to the one chosen by the user.To confirm this works as intended, the following should be tested:
Configure your client with the following settings or follow the usage section of code-actions.md:
closes #679