You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenRewrite将双参方法foo(a,b)替换为链式调用foo(a).bar(b)?

问题解决方法

你当前代码丢失调用者x.的核心原因是:模板仅定义了方法调用的foo(...)部分,未包含原方法调用的目标表达式(即x.对应的部分),替换时整个方法调用被完全替换为模板内容,自然丢失了前面的调用者。

修复方案一:修改模板保留调用目标

  1. 调整模板内容,加入目标占位符
    在模板中添加#{target}占位符来保留原调用目标,同时用参数类型精准匹配避免误替换:

    private final JavaTemplate template = JavaTemplate.builder(this::getCursor,
            "#{target}.foo(#{any(acme.A)}).bar(#{any(acme.B)})")
            .build();
    
  2. 替换时传入原调用目标
    在调用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 15:51:41