将链式方法调用与结构搜索相匹配

Matching chained method calls with structural search

我尝试匹配一些流利的这种方法调用API。可以有任意数量的方法调用(至少 2 次调用,但没有上限)。整个表达式应该匹配。实际上,目标是在省略 doIt() 的流利 api 中找到链式方法调用,因为在这种情况下,流利 API 什么都不做。

FooClass.some("fluent")
        .api()
        .bar(()->"somelambda")
        .doIt();

我试过

FooClass.$a$($b$) 

并使用不同的 "occurence counts",例如 0,∞ 用于 $a$0,1 用于 $b$,但这仍然只匹配 FooClass.some("fluent")

假设所有流畅的 api 方法 return 是 FooClass 的一个实例,以下应该有效。 从现有模板方法调用开始,添加分号搜索语句:

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

点击编辑变量:

  1. 实例Expression type设置为FooClass
  2. MethodCallText/Regexp 设置为 doit 并启用 Invert condition

基于 Bas Leijdekkers 的回答的解决方案,如果有人有类似的问题。

使用这些 class 定义作为示例:

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;
    }
}

我最后得到了两三个表达式:

  1. 匹配静态方法FooClass.bar()。不需要反转 doIt条件

    FooClass.$MethodCall$($Parameter$);

  2. 匹配中间classes FooClass,BarClass。不需要反转 doIt条件

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

    实例的表达式类型为(FooClass|BarClass)

  3. 匹配 classes Bar2Class, FinalClass。不同之处在于,可以通过向表达式添加 doIt() 来生成有效表达式。这可能仅在只有一个最终调用时才有效。

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

    实例的表达式类型是(Bar2Class|FinalClass) 这里在方法调用上使用倒置约束 doIt

    替换模板是 $Instance$.$MethodCall$($Parameter$).doIt();

这些结构搜索模式也可以用作 IntelliJ 中的检查。

测试用例:

    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