Tutorial: Structural search and replace in Kotlin
Structural search and replace is a powerful tool that can search for a specific pattern in code and replace it in an automated way.
In this tutorial we will get acquainted with templates and filters, modify a predefined template, and then create a code inspection based on it.
The functionality covered in this tutorial is by no means the exhaustive list of what Structural Search and Replace can do. Our goal is to get you started. After that, you can explore various templates, filters, and options and combine them to create your own specific searches.
For the tutorial, we will use the following code:
class Point constructor(locationX: Int, locationY: Int) {
var x: Int = locationX
var y: Int = locationY
}
open class OpenClass {
open var openProperty = 0
open fun display() {
println("Some text")
print("More text")
print(0)
}
}
In the main menu, go to Edit | Find | Search Structurally.
In the Structural Search dialog, select Kotlin from the list on the left.
Expand the Class-based node and click All vars of a class.
Make sure that Kotlin is selected as Language. This makes the search only apply to Kotlin files.
Click Find to run the search. As the result, in the Find tool window, IntelliJ IDEA shows all the properties declared in Kotlin classes.
While in the Structural Search dialog, expand the Recent node to browse the history of your recent searches and quickly rerun any of them.
Now, let's return to our structural search dialog to alter the predefined template a bit.
In the Structural Search dialog, let's update our template to only search for open properties by adding
open
before the$Field$
variable.tip
If we change the scope, IntelliJ IDEA will notify you right away whether the code pattern can be found in the specified scope.
Click Find and check the result in the Find tool window.
As you can see, the search used the filter this time and only shows the open properties now.
With Structural Search, we can run some interesting searches. Let's choose another existing template (Method calls) as our example. Assume we're doing this search to replace all print
statements with logging calls and exclude all calls that do not have a String
as the argument.
In the main menu, go to Edit | Find | Replace Structurally.
Under the Kotlin | Expressions node, select Method calls.
If we run the search now, we'll end up with results that include all the function calls in the code. So, we should alter our template a bit and use filters to be more specific about what we are looking for.
Place the caret at
$MethodCall$
and in the right-hand pane, click Add modifier. Add a Text filter with the value ofprint.*
.tip
Using
print
without the wildcard would only find calls to functions named exactlyprint
. The regex will ensure that the result will include calls to all functions that haveprint
in their name, for example,println
.Place the caret at
$Before$
and in the right-hand pane, make sure that the only modifier isCount=[0,1]
.Place the caret at
$Parameter$
and in the right-hand pane, click . Add a Type filter with the value ofString
.In the Replace template area, add the replacement code:
java.util.logging.Logger.getLogger(this.javaClass.getName()).fine($Parameter$)
Check the results in the Find tool window and use the replace options to select which of the results you want to replace.
We can save this template for later use if we need.
In the Structural Replace dialog, click .
In the list that opens, select Save current template.
Specify the name for the template and click OK.
The template is saved under the Saved Templates node.
We can also use our template as an inspection, so when we come across the same code, we'll see a warning and can quickly replace the code.
In the Find tool window, where you get the results for the replace pattern, click Create Inspection from Template.
In the dialog that opens, add the name for the inspection. Optionally, add a tooltip (provides a more detailed description of the problem on hovering over the highlighted code). Click OK.
The newly created inspection appears under the Structural search node in Settings | Editor | Inspections.
tip
To quickly run an inspection, select Code | Analyze Code | Run Inspection by Name. from the main menu or press CtrlAltShift0I) and enter the name of the inspection.
Thanks for your feedback!