如何用OpenRewrite将双参方法foo(a,b)替换为链式调用foo(a).bar(b)?
问题解决方法
你当前代码丢失调用者x.的核心原因是:模板仅定义了方法调用的foo(...)部分,未包含原方法调用的目标表达式(即x.对应的部分),替换时整个方法调用被完全替换为模板内容,自然丢失了前面的调用者。
修复方案一:修改模板保留调用目标
调整模板内容,加入目标占位符
在模板中添加#{target}占位符来保留原调用目标,同时用参数类型精准匹配避免误替换:private final JavaTemplate template = JavaTemplate.builder(this::getCursor, "#{target}.foo(#{any(acme.A)}).bar(#{any(acme.B)})") .build();替换时传入原调用目标
在调用withTemplate时,除了传入两个参数,额外传入原方法的调用目标:@Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) { J.MethodInvocation m = super.visitMethodInvocation(method, executionContext); if (....matches(method)) { // 你的方法匹配逻辑 List<Expression> arguments = m.getArguments(); // 依次传入调用目标、第一个参数、第二个参数 m = m.withTemplate(template, m.getCoordinates().replace(), m.getTarget(), arguments.get(0), arguments.get(1)); } return m; }
修复方案二:仅替换方法名与参数部分
如果不想修改模板结构,可通过指定替换坐标,只修改方法名和参数列表,保留原调用目标:
private final JavaTemplate template = JavaTemplate.builder(this::getCursor, "foo(#{any(acme.A)}).bar(#{any(acme.B)})") .build(); @Override public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext executionContext) { J.MethodInvocation m = super.visitMethodInvocation(method, executionContext); if (....matches(method)) { // 你的方法匹配逻辑 List<Expression> arguments = m.getArguments(); // 仅替换方法名和参数部分,保留原调用目标 m = m.withTemplate(template, m.getCoordinates().replaceNameAndArguments(), arguments.get(0), arguments.get(1)); } return m; }
内容的提问来源于stack exchange,提问作者Geoffrey De Smet
相关产品推荐
相关产品推荐

