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

Resolve 2: Support for resolve in hls-hlint-plugin #3679

Merged
merged 16 commits into from
Jun 30, 2023

Conversation

joyfulmantis
Copy link
Collaborator

@joyfulmantis joyfulmantis commented Jun 27, 2023

Commands and resolve act very similarly, and since hlint already heavily uses commands, I am choosing to first move everything to use commands, and then offer resolve if it's available, falling back to commands for clients that don't support it.

@joyfulmantis joyfulmantis marked this pull request as ready for review June 28, 2023 15:09
@joyfulmantis joyfulmantis enabled auto-merge (squash) June 30, 2023 20:58
@joyfulmantis joyfulmantis merged commit d14d9e5 into haskell:master Jun 30, 2023
Copy link
Collaborator

@michaelpj michaelpj left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I didn't get to this sooner! I had a few thoughts. Generally I really like the approach with the command!

hls-plugin-api/src/Ide/Types.hs Show resolved Hide resolved
hls-plugin-api/src/Ide/Types.hs Show resolved Hide resolved
withIndefiniteProgress "Executing code action..." Cancellable $ do
resolveResult <- resolveProvider ideState pluginId ca
case resolveResult of
Right CodeAction {_edit = Just wedits } -> do
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if it has the command set? It probably shouldn't, right? But maybe we should fail or at least log there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, if it's cheap it would be nice to check that all the other fields of the code action are the same as the input one, i.e. the resolve handler only gave us an edit. In the more generalized case, we should check that the only fields that differ are the ones that the client says it can resolve. Then we can log if the handler does something wrong there.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I guess also the command and data fields should be unset?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, according to the spec, we can only change the set of resolvable fields, so even though it would make sense to dump the data field, it still needs to stay the same as when we received it. (We also don't have the client capabilities so can't do anything with that). Finally in this case the only thing we can execute on is the returned WorkspaceEdit. We can return an error if any other field is changed, but not sure about the performance penalty of doing that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we pass in the client caps here?

I don't know if it's worth doing the checking of field setting, it just seems like a way to sanity check plugins, which seems somewhat useful.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I guess we can't pass in the client capabilities here, but we should be able to pull them from the monad itself, since the plugin handler is effectively in the Lsp monad already

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I see, this is exactly the sort of thing we could do if we had the client caps when making the handlers!

resolveResult <- resolveProvider ideState pluginId ca
case resolveResult of
Right CodeAction {_edit = Just wedits } -> do
_ <- sendRequest SMethod_WorkspaceApplyEdit (ApplyWorkspaceEditParams Nothing wedits) (\_ -> pure ())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like we probably should care a little about the response? e.g. we probably want to do something if we fail, like at least log

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's quite hard here, as we can't use a recorder (That's defined in the ghcide package, so cyclic dependency), and we only have a callback to work with.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh. Okay, I guess we can't do much here, but that's rather unsatisfying. Maybe we need to move some of the recorder stuff into hls-plugin-api as the "lowest" package.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would really like to be able to do some logging in the generic functions you're defining, that way we can get somewhat-decent logging for lots of plugins by defining it in one place.

hls-plugin-api/src/Ide/Types.hs Show resolved Hide resolved
@fendor fendor mentioned this pull request Aug 8, 2023
19 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants