将链式方法调用与结构搜索相匹配
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$);
点击编辑变量:
- 将实例的
Expression type
设置为FooClass
- 将 MethodCall 的
Text/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;
}
}
我最后得到了两三个表达式:
匹配静态方法FooClass.bar()
。不需要反转 doIt
条件
FooClass.$MethodCall$($Parameter$);
匹配中间classes FooClass,BarClass。不需要反转 doIt
条件
$Instance$.$MethodCall$($Parameter$);
实例的表达式类型为(FooClass|BarClass)
匹配 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
我尝试匹配一些流利的这种方法调用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$);
点击编辑变量:
- 将实例的
Expression type
设置为FooClass
- 将 MethodCall 的
Text/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;
}
}
我最后得到了两三个表达式:
匹配静态方法
FooClass.bar()
。不需要反转doIt
条件FooClass.$MethodCall$($Parameter$);
匹配中间classes FooClass,BarClass。不需要反转
doIt
条件$Instance$.$MethodCall$($Parameter$);
实例的表达式类型为
(FooClass|BarClass)
匹配 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