Should useScope include a declaration?
Answered
What scope should I return from getUseScope
for a function parameter in my custom language plugin? Should it be a whole function or just a function body? Javadoc says: Returns the scope in which
references
to this element are searched
but I'm not sure.
Context:
I have LocalSearchScope(myFunctionBodyPsiElement)
as the return value and renaming and other features worked fine until I implemented inplace renaming which doesn't work and fails with a negative offset at com.intellij.codeInsight.template.TemplateBuilderImpl.initTemplate(TemplateBuilderImpl.java:212)
. Returning LocalSearchScope(myFunctionPsiElement)
works BTW.
Should useScope include the declaration too?
Please sign in to leave a comment.
I'd suggest whole function as parameters in some languages can be used in function signature (default values)
Anna
It's not my case. I have a simple function with a single parameter (without any default value) and the parameter is used only inside the function body.
I'll provide some details below.
NOTE: I use 2020.3 version but the code is the same in the latest IDEA version.
The code:
The stack trace:
RangeMarker(25, 45) represents the function body other markers are the parameter and it's usage in the function body. The function body element was obtained via 'InplaceRefactoring#checkLocalScope' method that looks like:
So for LocalSearchScope with single element it just returns this element.
In other words inplace renaming of 'value' parameter fails becuase it's declaration (in parameters) is out of scope of the function body that was returned as useScope of that parameter.
I see 3 reasons of such behavior:
- The statement 'Returns the scope in which references to this element are searched.' in javadoc of 'PsiElement#getUseScope' method is missleading and should include declaration as well.
- Method 'InplaceRefactoring#checkLocalScope' doesn't work right and should take declaration into account.
- I just use InplaceRefactoring wrong and should customize it. Maybe `VariableInplaceRenamer` shouldn't be used at all in my case.
I'd say that probably `InplaceRefactoring` should have explicitly added declaration itself to the scope. But given that for all "non-local declarations" the scope already contains declaration, I'd avoid changes in the platform and return slightly bigger scope in your case.