Search code examples
javaintellij-ideaannotationsstatic-analysisstructural-search

Intellij structural replace unwanted behavior based on target


I am trying to find and replace all usages of @JsonCreator on nonstatic methods by using an inspection to suggest a replacement for the method to make it static. I have the following template:

// Search template

@$Annotation$
$MethodType$ $Method$($ParameterType$ $Parameter$)

/** Modifiers
* Annotation{count=[1, inf], text=JsonCreator}
* Method{Script=!__context__.hasModifierProperty("static")}
* Parameter{count=[0, inf]}
*/ 

// Replace template

@$Annotation$
static $MethodType$ $Method$($ParameterType$ $Parameter$)

/** Modifiers
* Annotation{count=[1, inf], text=JsonCreator}
* Method{Script=!__context__.hasModifierProperty("static")}
* Parameter{count=[0, inf]}
*/ 

When the target for the search is Complete Match or Method, this works as desired, performing the following:

// Before
@JsonCreator
BasicEnum fromString(String value) 
{
  // ...
}

// After
@JsonCreator
static BasicEnum fromString(String value) 
{
  // ...
}

However, when the target is Annotation, it fails, performing the following instead.

// Before
@JsonCreator
BasicEnum fromString(String value) 
{
  // ...
}

//After
BasicEnum fromString(String value) 
{
  // ...
}

It removes the annotation and does not add the static modifier.

I'd like to have the target be Annotation, as getting the warning squiggles across the whole method feels clunky. Why does the replace fail when targeting Annotation? Is there a way around this such that the squiggles only show up on the annotation?

To note, I'm aware that @JsonCreator can also be used on constructor methods, but managing those are not something I'm concerned about right now. I just want to find situations where @JsonCreator is used on a nonstatic method, and provide an inspection to replace.


Solution

  • Why not use "Method" as the target? The replacement modifies the method, not the annotation. And then only the method name is highlighted.

    The current behaviour seems to be some sort of bug. It can be worked around with a template like the following:

    <replaceConfiguration name="Squigly" text="class $A$ {&#10;@$Annotation$&#10;$MethodType$ $Method$($ParameterType$ $Parameter$);&#10;}" recursive="false" type="JAVA" pattern_context="default" search_injected="false" reformatAccordingToStyle="true" shortenFQN="true" replacement="@$Annotation$ static">
      <constraint name="__context__" within="" contains="" />
      <constraint name="Annotation" regexp="JsonCreator" target="true" within="" contains="" />
      <constraint name="MethodType" within="" contains="" />
      <constraint name="Method" script="&quot;!__context__.hasModifierProperty(&quot;static&quot;)&quot;" within="" contains="" />
      <constraint name="ParameterType" within="" contains="" />
      <constraint name="Parameter" minCount="0" maxCount="2147483647" within="" contains="" />
      <constraint name="A" within="" contains="" />
    </replaceConfiguration>
    

    (Use the "Import Template from Clipboard" button in the top left toolbar of the dialog above the existing templates panel)

    Unfortunately the formatting of the final result is not so nice:

    //After
    @JsonCreator
    static
    BasicEnum fromString(String value) 
    {
      // ...
    }