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?
Press Ctrl+Alt+M or from the main menu, select Refactor | Extract | Method. In the dialog that opens, configure a method options, such as visibility, parameters, and so on. You can also change a name of the method if you need. Click OK.
You can use the structure view popup to locate a code element in the file you are working on. To open the structure view popup, press Ctrl+F12 .
Open your class in the editor, place a caret at the static method you want to move and press F6 . In the Move Members dialog specify the following options: In the Members to be moved to another class (static only) field, select the checkboxes next to the methods that you want to move to another class.
In IntelliJ IDEA, you can see where and how symbols, such as tags, classes, fields, methods, or functions are defined in your project. For this purpose, the IDE features the Quick Definition popup. To view definition of a symbol, select it in the editor and press Ctrl+Shift+I (or click View | Quick Definition).
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>)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With