Skip to content
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

Refactor plugin: Prefer code action #3167

Conversation

andys8
Copy link
Collaborator

@andys8 andys8 commented Sep 15, 2022

_isPreferred can influence the client side order of code actions. The idea is that an unused import is likely to be removed and less likely the warning will be disabled. Therefore actions to remove a single or all redundant imports should be preferred, so that the client can prioritize them higher.

Followup of #3018

Demo

Here is an example in Vim/CoC. There is an import that isn't necessary. The list of code starts with "Disable unused-imports warnings", which is also the option that would be defaulted to. Instead removing the redundant import should be preferred and will influence the order (depends on the language server client).

image

@andys8 andys8 force-pushed the improvement/refactor-plugin-prefer-code-action branch from ddde94c to 188a602 Compare September 15, 2022 11:20
@georgefst
Copy link
Collaborator

When implementing #1235, I did think that the disable-warning actions should probably always be at the bottom of the list, but I couldn't work out how to do that. This looks good!

@andys8
Copy link
Collaborator Author

andys8 commented Sep 15, 2022

@georgefst Cool, maybe we could (in a different PR) also set these code actions to isPreferred = Just False to explicitly mark them as not the preferred (default / go to) solution. But looks like there would be a bit of refactoring necessary in order to pass the information along.

https://github.com/haskell/haskell-language-server/pull/1235/files#diff-bf3e1eeb4b7bfd43c7bd24d10063ea6e23c0714d61ab5f5c62e7323ebf1282aaR231

@pepeiborra
Copy link
Collaborator

Just to confirm, does this work in Vim/Coc? And have you tested with VSCode?

@andys8
Copy link
Collaborator Author

andys8 commented Sep 15, 2022

Honestly, I don't know how all clients behave and I haven't tested in other editors, but I can tell what I know. That being said, the actual effect will likely depend on the client. But these changes add information of what the most reasonable choice of actions is. I think it would also make sense to mark all "disable something" actions as "not preferred", but often seems to need refactoring.

Previous Change

I've tested a similar change in #3018, but this one not again. There are screenshots demonstrating the change in behavior with Vim and CoC.

This Change

Tested this change by building it locally. Seems to show "Remove all redundant imports" before "Disable warning". Not sure why the "Remove import" is at the end, maybe they are created in different places.

image

Language Server Protocol

LSP docs say:

 * A quick fix should be marked preferred if it properly addresses the
 * underlying error. A refactoring should be marked preferred if it is the
 * most reasonable choice of actions to take.
 *
 * @since 3.15.0

https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/

CoC Implementation

Here is the sorting implementation of coc (vim client). It seems to take the property into account.

https://github.com/neoclide/coc.nvim/blob/59fa3972e4395adf1852717011d57fbfa5c169b5/src/handler/codeActions.ts#L64-L70

@andys8 andys8 force-pushed the improvement/refactor-plugin-prefer-code-action branch from 188a602 to f79310b Compare September 15, 2022 22:23
@andys8
Copy link
Collaborator Author

andys8 commented Sep 15, 2022

Rebased ✔️

`isPreferred` can influence the client side order of code actions. The
idea is that an unused import is likely to be removed and less likely
the warning will be disabled. Therefore actions to remove a single or
all redundant imports should be preferred, so that the client can
prioritize them higher.

Followup of
<haskell#3018>
@andys8 andys8 force-pushed the improvement/refactor-plugin-prefer-code-action branch from f79310b to b882966 Compare September 16, 2022 18:02
@michaelpj
Copy link
Collaborator

I think it would also make sense to mark all "disable something" actions as "not preferred", but often seems to need refactoring.

I actually don't know if clients treat "no isPreferred field" differently from "isPreferred set to false". The LSP spec of course doesn't tell us anything like usual 🙄

This LGTM, we've used this in the past for hlint and I think it's the right thing to do.

@michaelpj michaelpj added the merge me Label to trigger pull request merge label Sep 17, 2022
@andys8
Copy link
Collaborator Author

andys8 commented Sep 17, 2022

@michaelpj I don't know either. In theory isPreferred?: boolean allows 3 states in TypeScript because of its optionality: true, false, and undefined. But for example the CoC implementation only checks for truthiness with !b.isPreferred. Therefore for CoC's current implementation Just False and Nothing in Haskell should result in the same behavior. But I don't know about other clients and if that's intended or random implementation.

It's a good point though. Adding isPreferred: Just False would be meaningful information, but we could end up not changing actual client behavior.

@michaelpj michaelpj added merge me Label to trigger pull request merge and removed merge me Label to trigger pull request merge labels Sep 17, 2022
@pepeiborra pepeiborra enabled auto-merge (squash) September 18, 2022 14:49
@pepeiborra pepeiborra merged commit 362ca34 into haskell:master Sep 18, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge me Label to trigger pull request merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants