6

I want to use ButterKnife for Android. I need to annotate some fields based on some expressions which are elsewhere in code. I have code like this

private String myField;
...
public myClassConstructor() {
    ...
    myField = res.getString(R.string.my_string_id);
    ...
}

I want this

@BindString(R.string.my_string_id);
String myField;
...
public myClassConstructor() {
    ...
    ...
}

In the result the expression is gone, and the field is annotated based on the old expression.

Is it possible to do this kind of search and replace in IntelliJ's structural replace? It seems it does not gracefully handle the case when the lines of interest are not adjacent and are in different locations structurally. I tried basing it on class template, and used $Statement$ (0-unbounded occurrences) but it did not work for me.

I realized its actually relatively simple to do with regular expressions, certainly much simpler than getting IntelliJ structural search to play ball, but I like to learn my tools, so I would still like to know if this is possible.

arberg
  • 4,148
  • 4
  • 31
  • 39

2 Answers2

3

While Search structurally is somehow working and it's possible to make search query, replace structuraly is kind of tools which was made by "aliens" for "predators". I hope that intelliJ team will revisit this feature and will make it more usable/understandable.

I was trying by myself to make Replace structurally query, but I could only make Search structurally clause.

I have done it with Mockito lib for example.

Structural search dialog

One of the key points here to put for $SomeStatement1$ and $SomeStatement2$ min and max count to {0, Unlimited}

enter image description here

And from this point I've tried to come with replacement clause but It was completely messing out scope of the method/fields declaration/class.

Hope this helps.

Igor Konoplyanko
  • 9,176
  • 6
  • 57
  • 100
  • I also found it messed up my code, sometimes removing far more than it should, or inserted a new class. It seemed to work for very simple and local searched. I was hoping someone would say its not possible or it is. If nobody with sure knowledge chimes in, I'll assume its because only the devs know and that it probably cannot do what I wanted. – arberg Feb 02 '16 at 10:41
0

Something like this should work.
Search template:

class $Class$ { 
    $FieldType$ $FieldName$;

    $Class$() {
        $st1$;
        $FieldName$ = res.getString($expr$);
        $st2$;
    }
}

Variables:
st1 min: 0 max: unlimited
st2 min: 0 max: unlimited

Replacement template:

class $Class$ { 
    @BindString($expr$)
    $FieldType$ $FieldName$;

    $Class$() {
        $st1$;
        $st2$;
    }
}
Bas Leijdekkers
  • 23,709
  • 4
  • 70
  • 68
  • Thank you for the attempt. I should have included this in the question, as it was one of the things I tried, and it doesn't work. I doesn't match anything. When I played around with it I remember getting some replacement to actualy occur, I think I simplified the source-code. However then it completely messed up the replacement. I'll accept the above answer to close the issue. – arberg Mar 30 '16 at 13:19