How do I enable in-place rename? Renaming via dialog works fine.
Hello,
I'm implementing a custom language plugin, and am working on renaming. My issue is that it always brings up the rename dialog, no matter what type of var/function I'm working with. Using the dialog to rename *does* correctly rename everything as expected, but I'd like to be able to do it inline for local vars and function arguments.
I can't find any documentation about the differences between renaming in-place and using the dialog, as far as plugin development is concerned. Searching brings up a lot of hits from the user side, but nothing for this. The documentation I have been able to find does not differentiate between these two scenarios.
What do I need to do to get inline rename working, if dialog renaming already works?
Please sign in to leave a comment.
You need to define a refactoring support provider:
http://www.jetbrains.org/intellij/sdk/docs/tutorials/custom_language_support/reference_contributor.html#define-a-refactoring-support-provider
Oh I've already done that. I was under the impression that that was required to get rename working at all, whatsoever.
You must return true from com.intellij.lang.refactoring.RefactoringSupportProvider#isMemberInplaceRenameAvailable for those elements supporting it.
Hi,
Thank you for responding.
It seems there's more to it than just that. I'm returning true for my identifier leaf nodes, and that is being called, but still the dialog comes up each time. Should I only be returning true for a subset of those nodes?
The file in question is https://github.com/xxx/intellij_lpc/blob/master/src/main/java/com/github/xxx/lpc/LPCRefactoringSupportProvider.kt
Michael Dungan, I am not an expert on this but in my plugin I found that it did not work if reference search for the element in question returned references from more than one file. I traced the code and saw a condition in the implementation if there is more than one file for references, then the dialog is used.
I had it working before but since I reworked my reference search or due to latest changes introduced in the IDE it stopped working. It could be that reference search for inplace rename is providing local scope and in my reference search I introduced a bug where the local scope is not respected so it returns references from other files.
I did not figure out what else needs to be done to get around that because the IDE implemented inplace rename does work for references across files.
If you figure it out please share it because it is convenient if available.
Vladimir Schneider, That shouldn't be the issue here, since I'm not reaching outside of the file (yet) to resolve references, but what you say will help avoid trouble in the future. Thanks!
I'll definitely post the answer here once I figure it out.
Please see com.intellij.refactoring.rename.inplace.InplaceRefactoring#performInplaceRefactoring for conditions required to suppress showing dialog:
- no references outside current file
- com.intellij.refactoring.rename.inplace.InplaceRefactoring#checkLocalScope == true
Probably you need to override getUseScope() in your element and return corresponding LocalSearchScope.
@Yann Cebron Thanks so much. getUseScope() was one missing piece. The other is that any inline-renameable element must implement PsiNameIdentifierOwner. My ID nodes were implementing PsiNamedElement, which wasn't enough.
This raises the question of whether I should ever use PsiNamedElement for anything at this point. It seems like the answer is "no". I was using PsiNamedElement for the leaf ID nodes, and PsiNameIdentifierOwner for higher level subtrees, like var declarations and function implementations. That was my understanding of how these two classes semantically relate to each other. Was I wrong?
Additionally, another unexpected behavior is that clicking on a node might give you the leaf ID node, or it might give you a higher level subtree, and I have no idea why that difference exists. Definitions would use the higher-level subtrees, while the usages would always operate on the leaf ID nodes, even though the definitions also use said ID nodes. Because of this, I also had to override getUseScope() for the higher level subtrees that were being returned.
The actual commit that moved me from not working to working is https://github.com/xxx/intellij_lpc/commit/6325212075737d38fa085aa4e9972bcb7b9db555
See also https://intellij-support.jetbrains.com/hc/en-us/community/posts/206103209-PsiNamedElement-vs-PsiNameIdentifierOwner?page=1#community_comment_206084085