Search code examples
openrewrite

OpenRewrite - How to replace one statement with multiple new statements using JavaTemplate?


I was writing a recipe that replaces one statement with other multiple ones using a JavaTemplate but I couldn't make it work.

After investigating, I realized that changing only one statement with only another one worked fine, the problem came when I tried to replace one statement with multiple ones.

The error I saw was that it didn't build well the statement. In my case I was trying to substitute one mocking statement with two mocking statements. While the first mocking statement was well written the second one seemed to be wrongly parsed.

Here is a code snippet of how code looked after applying the recipe:

given(methodToMock1).willReturn(expectedResponse1);
Templategiven(methodToMock2 <error>();

After trying other things I also saw an error telling me that I was trying to substitute one statement with two and that doing this is not valid.

WHAT I HAVE TRIED:

I tried applying the JavaTemplate doing the following:

Note: In the example I show below oldMockStatement refers to the mock statement I want to replace (is only one statement) and methodDeclarationWhereApplyingChanges refers to the method where this changes are being applied:

// New mocks we want to include
String NEW_MOCK_STATEMENTS =
        """
        given(methodToMock1).willReturn(expectedResponse1);
        given(methodToMock2).willReturn(expectedResponse2);
        """;

// Building JavaTemplate
JavaTemplate javaTemplate = JavaTemplate.builder(NEW_MOCK_STATEMENTS).build();

// We replace old mock statement with two new ones
methodDeclarationWhereApplyingChanges = methodDeclarationWhereApplyingChanges.withBody(
              javaTemplate.apply(
                  new Cursor(getCursor(), methodDeclarationWhereApplyingChanges.getBody()),
                  oldMockStatement.getCoordinates().replace()));

MY QUESTION:

Using OpenRewrite what is the correct approach for substituting one statement with multiple ones? Are there any examples?


Solution

  • Conceptually, you will want to modify or replace a single LST element with a single other LST element, anywhere up the hierarchy. This limitation is most easily realized when you try to assign the result of JavaTemplate apply(..) to a local variable: You'll need to assign it to some class that extends org.openrewrite.java.tree.J.

    What you can do though is either modify/extend the statements contained in the parent block, or introduce a new block containing two statements, and then doAfterVisit(new RemoveUnneededBlock().getVisitor()) to remove the surrounding braces.

    I hope that helps! Also welcome to join our Slack, linked from the top of the docs is that's more convenient for any follow up questions.