Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to change a Kotlin code reference from a function to a field in an intellij plugin?

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?

like image 798
ADev Avatar asked Jun 08 '18 08:06

ADev


People also ask

How do I refactor a method in IntelliJ?

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.

How can I view source code in IntelliJ?

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 .

How do I move a method from one class to another in IntelliJ?

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.

How do I get to method definition in IntelliJ?

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).


1 Answers

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>)
like image 52
Ricardo Avatar answered Oct 06 '22 12:10

Ricardo