0

Given a chained invocation (builder pattern):

return new ThingBuilder().withA(a).withB(b).build();

How can I use JavaParser to add another chained invocation to end up with code like this:

return new ThingBuilder().withA(a).withB(b).withC(c).build();

I'm already familiar with the ModifierVisitor, but am unable to find a good way to add the call in the right place, i.e to the relevant MethodCallExpr (the one where the expression is new ThingBuilder().withA(a).withB(b) and the method is build()).

It would be fine to add it at the top level too if that's possible:

return new ThingBuilder().withC(c).withA(a).withB(b).build();
Ovesh
  • 5,209
  • 11
  • 53
  • 73

1 Answers1

0

I was able to get this to work:

    @Override
    public Visitable visit(final MethodCallExpr n, final Void arg) {
        final Visitable visit = super.visit(n, arg);
        if (!n.getName().getIdentifier().equals("build")) {
            return visit;
        }
        n.getScope()
                .filter(Expression::isMethodCallExpr)
                .map(Expression::asMethodCallExpr)
                .filter(method -> method.getName().getIdentifier().equals("withB"))
                .ifPresent(method -> {
                    final Node leftSide = n.getChildNodes().get(0);
                    final Optional<Expression> scope = n.getScope();
                    final MethodCallExpr withC = new MethodCallExpr("withC", new NameExpr("c"));
                    leftSide.replace(withC);
                    scope.ifPresent(withC::setScope);
                });
        return visit;
    }

I'd be happy to learn if there's a more elegant way to do this.

Ovesh
  • 5,209
  • 11
  • 53
  • 73