Matching chained method calls with structural search

江枫思渺然 提交于 2019-12-08 11:32:57

问题


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:

  1. set Expression type of Instance to FooClass
  2. set Text/Regexp of MethodCall to doit and enable Invert 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:

  1. Matching the static method FooClass.bar(). No inverted doItcondition needed

    FooClass.$MethodCall$($Parameter$);

  2. Matching the intermediate classes FooClass,BarClass. No inverted doItcondition needed

    $Instance$.$MethodCall$($Parameter$);

    Expression type of the instance is (FooClass|BarClass)

  3. Matching the classes Bar2Class, FinalClass. The difference is here that it is possible to make a valid expression by adding doIt() 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 call doIt

    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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!