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

Improve handling of nonsense rename attempts #4111

Merged
merged 3 commits into from
Mar 2, 2024

Conversation

jhrcek
Copy link
Collaborator

@jhrcek jhrcek commented Mar 2, 2024

First step towards improving behavior when renaming unsupported things (e.g. keywords or words within comments).
Instead of throwing plugin error (reporte here #3915)
we detect that there is no Name to rename under cursor and throw less scary looking Invalid Param warning.

Behavior after this PR:

Peek 2024-03-02 08-30

EDIT: Actually in the end I included @michaelpj's suggestion to implement Prepare Rename handler that "prefilters" invalid requests on the client and doesn't even allow creating rename request for them.


renameProvider :: PluginMethodHandler IdeState Method_TextDocumentRename
renameProvider state pluginId (RenameParams _prog (TextDocumentIdentifier uri) pos newNameText) = do
nfp <- getNormalizedFilePathE uri
Copy link
Collaborator Author

@jhrcek jhrcek Mar 2, 2024

Choose a reason for hiding this comment

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

Most of this is indentation changes. I recommend reviewing with "Hide whitespace"
Peek 2024-03-02 08-36

@jhrcek jhrcek force-pushed the jhrcek/improve-nonsense-rename-handling branch from 237d7c7 to f20dfa5 Compare March 2, 2024 07:38
@jhrcek jhrcek marked this pull request as ready for review March 2, 2024 07:41
@jhrcek jhrcek requested review from joyfulmantis and michaelpj March 2, 2024 07:41
@jhrcek jhrcek requested a review from fendor as a code owner March 2, 2024 08:31
@jhrcek
Copy link
Collaborator Author

jhrcek commented Mar 2, 2024

Actually it was relatively easy to implement PrepareRename handler and the behavior is now even better with it:

Peek 2024-03-02 09-47

@@ -657,6 +660,10 @@ instance PluginRequestMethod Method_CodeLensResolve where

instance PluginRequestMethod Method_TextDocumentRename where

instance PluginRequestMethod Method_TextDocumentPrepareRename where
-- TODO more intelligent combining?
combineResponses _ _ _ _ (x :| _) = x
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it is fine we only pick up the newest

Copy link
Collaborator Author

@jhrcek jhrcek Mar 2, 2024

Choose a reason for hiding this comment

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

I think this is used for combining of responses in case multiple plugins happen to handle same type of request.
I'd say it's ok to leave it like this for now, because this PR introduces this new request type and for now rename plugin is the only one that supports it.

Copy link
Collaborator

@fendor fendor left a comment

Choose a reason for hiding this comment

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

Nice job!

@jhrcek jhrcek merged commit 5502b76 into master Mar 2, 2024
39 checks passed
@jhrcek jhrcek deleted the jhrcek/improve-nonsense-rename-handling branch March 2, 2024 15:52
-- In particular it allows some cases through (e.g. cross-module renames),
-- so that the full rename handler can give more informative error about them.
let renameValid = not $ null namesUnderCursor
pure $ InL $ PrepareRenameResult $ InR $ InR $ #defaultBehavior .== renameValid
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm unsure if this is the correct behaviour. It's very hard to tell what the intention of the various options for results of prepareRename are. Worth a comment anyway. We could consider returning the range corresponding to the name, although it's unclear if we have that...

Copy link
Collaborator Author

@jhrcek jhrcek Mar 4, 2024

Choose a reason for hiding this comment

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

I would say that lsp spec is quite clear in this regard:

If { defaultBehavior: boolean } is returned (since 3.16) the rename position is valid and the client should use its default behavior to compute the rename range.

I looked at what the vscode-languageclient is doing with that response (see here) and when you return the boolean:
if true it triggers the default rename behavior (finds the range of the symbol under cursor itself, opens input box where you can specify the new name, it uses the current name of the symbol as placeholder).
if false it gives you a small error popup saying "The element can't be renamed".

Since I find the default behavior unproblematic (by pressing F2 on bunch of things you can see that vscode's default behavior correctly finds the range of symbol under cursor), I went with this Bool return type.

I'll let you read this / react and I can open a PR with some additional clarifying comment later today.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I guess I'm just wondering if we can rely on the "default behaviour" or whether it would be better for us to be returning the actual range of the name? Maybe it's fine?

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 played with it for a bit and it seems it would be hard to get this right if we're to provide the Range under cursor.

The thing I had trouble to make work was qualified names.
e.g. if you rename IO.putStrLn the HieAST contains the range of the whole thing (including IO.) so if you trigger rename on it, you get the whole thing prefilled into the rename input which is confusing.

I'd be more comfortable keeping the current implementation which seems to work robustly on all cases we have in tests.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Huh, and vscode does the right thing and just changes putStrLn? IDK, seems potentially fragile but maybe it's fine.

Anyway, this all seems like super useful information, so worth writing down!

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.

4 participants