问题
I try to match this kind of method calls of some fluent API. There can be an arbitrary number of method calls (at least 2 calls, but no upper limit). The whole expression should be matched. Actually, the goal is to find chained method calls in a fluent api which omit doIt()
, as in this case the fluent API does nothing.
FooClass.some("fluent")
.api()
.bar(()->"somelambda")
.doIt();
I tried something like
FooClass.$a$($b$)
and use different "occurence counts" like 0,∞
for $a$
, and 0,1
for $b$
, but this still only matches FooClass.some("fluent")
回答1:
Assuming all the fluent api methods return an instance of FooClass
, the following should work.
Start with the existing template method calls and add a semicolon to search for statements:
$Instance$.$MethodCall$($Parameter$);
Click Edit variables:
- set
Expression type
of Instance toFooClass
- set
Text/Regexp
of MethodCall todoit
and enableInvert condition
回答2:
A solution based on the answer of Bas Leijdekkers, if anyone has a similar problem.
Using these class definitions for the example:
static class FooClass{
static BarClass bar(){
return new BarClass();
}
}
static class BarClass{
Bar2Class bar2(){
return new Bar2Class();
}
BarClass self(){return this;}
}
static class Bar2Class{
FinalClass bar3(){
return new FinalClass();
}
Bar2Class self(){return this;}
}
static class FinalClass{
void doIt(){
System.out.println("bar2");
}
FinalClass doSomethingElse(){
return this;
}
}
I ended up with two-three expressions:
Matching the static method
FooClass.bar()
. No inverteddoIt
condition neededFooClass.$MethodCall$($Parameter$);
Matching the intermediate classes FooClass,BarClass. No inverted
doIt
condition needed$Instance$.$MethodCall$($Parameter$);
Expression type of the instance is
(FooClass|BarClass)
Matching the classes
Bar2Class
,FinalClass
. The difference is here that it is possible to make a valid expression by addingdoIt()
to the expression. This probably only works when there is only one final call.$Instance$.$MethodCall$($Parameter$);
Expression type of the instance is
(Bar2Class|FinalClass)
Here using the inverted constraint on the method calldoIt
The replacement template is
$Instance$.$MethodCall$($Parameter$).doIt();
These structural search pattern can then also be used as inspections in IntelliJ.
Test cases:
FooClass.bar().bar2();
FooClass.bar();
FooClass.bar().self().self().bar2();
FooClass.bar().bar2().bar3(); // do it can be added
FooClass.bar().bar2();
FooClass.bar().self().bar2();
FooClass.bar().bar2().bar3().doSomethingElse(); // do it can be added
FooClass.bar().bar2().self().bar3().doSomethingElse(); // do it can be added
FooClass.bar().bar2().bar3().doSomethingElse().doIt(); // all but this are invalid and found by the inspections
来源:https://stackoverflow.com/questions/37837061/matching-chained-method-calls-with-structural-search