I'm writing an intellij plugin where I'm refactoring a class, changing its getters (e.g., fun name(): String
) to fields (e.g., val name: String
).
However, I don't know how best to update the corresponding PsiReference
instances. A Kotlin caller needs to change from myObj.name()
to myObj.name
without the parenthesis.
Currently, I'm doing the following:
ReferencesSearch.search(function).findAll().forEach {
val nextSibling = it.element.nextSibling
if ((nextSibling as? KtValueArgumentList)?.arguments?.isEmpty() == true) {
nextSibling.delete()
}
}
The above works somewhat. That is, the conversion happens correctly. However, the IDE still thinks it is calling a function. It underlines an error in the converted myObj.name
with the following message:
Expression 'name' of type
String
cannot be invoked as a function. The function 'invoke()' is not found
Manually rewriting name
in the editor forces intellij to refresh the reference and error disappears.
What should I do instead to prevent this from happening?
You are getting that error message because you are not modifying the reference to the old method. Intellij still thinks your call myObj.name
is trying to access some method called name()
that doesn't exist anymore.
Also, the search result is going to point to the leaf node in the AST that uses your method. In this case name()
has a parent PSI object that holds a reference to name
and to ()
. That's why calling element.nextSibling
gives you the ()
which you can then call delete()
on. But this doesn't change the parent's reference.
I'm not sure what is the best way to do what you want but you could try to replace the parent's reference directly. Try:
element.parent.replace(<reference to your the data class field>)