What I want to do
I am trying to add single-line comments around a method annotated with Lombok's @Generated
to tell Parasoft Jtest to suppress the reporting of findings in the method like this:
class FooBar {
// parasoft-begin-suppress ALL
@Generated
public String hello() {
return "Hello from com.yourorg.FooBar!";
}
//parasoft-end-suppress ALL
}
What I tried
I have found that JavaParser breaks up single-line comments at the end of the line (see How to prepend to move a line comment to the middle of field declaration with JavaParser), so I have tried to write an OpenRewrite recipe. I have successfully added the comment before the annotation with this code:
public class JtestSuppressDelombokVisitor extends JavaIsoVisitor<ExecutionContext> {
@Override
public MethodDeclaration visitMethodDeclaration(MethodDeclaration methodDecl, ExecutionContext context) {
boolean hasGeneratedAnnotation = methodDecl.getLeadingAnnotations().stream()
.anyMatch(annotation -> annotation.getType().toString().equals("lombok.Generated"));
Iterator<Comment> it = methodDecl.getPrefix().getComments().iterator();
boolean alreadyHasSuppressComment = false;
while (it.hasNext()) {
Comment comment = it.next();
PrintOutputCapture<String> p = new PrintOutputCapture<String>("");
comment.printComment(this.getCursor(), p);
if (p.out.toString().matches(".*parasoft-begin-suppress\sALL.*")) {
alreadyHasSuppressComment = true;
break;
}
}
if (hasGeneratedAnnotation && !alreadyHasSuppressComment) {
String methodDeclWhitespace = methodDecl.getPrefix().getWhitespace();
if (methodDecl.getPrefix().getComments().size() == 0) {
methodDecl = methodDecl.withComments(Arrays.asList(new TextComment(false, "parasoft-begin-suppress ALL", methodDeclWhitespace, Markers.EMPTY)));
} else {
methodDecl.getPrefix().getComments().add(new TextComment(false, "parasoft-begin-suppress ALL", methodDeclWhitespace, Markers.EMPTY));
}
return methodDecl;
}
return methodDecl;
}
}
Problem
I couldn't add the comment after the method. I have tried three ways:
1. Create a comment with JavaTemplate and add it to the method
I have tried the following code, but nothing is added to the code.
final JavaTemplate endSuppressCommentTemplate =
JavaTemplate.builder(this::getCursor, "// parasoft-end-suppress ALL").build();
methodDecl = methodDecl.withBody(methodDecl.getBody().withTemplate(
endSuppressCommentTemplate,
methodDecl.getBody().getCoordinates().lastStatement()
));
2. Added comment at the end of the method body
I have tried the following code.
methodDecl.getBody().getEnd().getComments().add(new TextComment(false, "parasoft-end-suppress ALL", "\n", Markers.EMPTY));
This code added the comment on the last line of the method (not after the method). This code also inserted the comment not only on the last line of the method but also on the other line and overwrote the comment before the annotation like this:
class FooBar {
//parasoft-end-suppress ALL
@Generated
//parasoft-end-suppress ALL
public String hello() {
return "Hello from com.yourorg.FooBar!";
//parasoft-end-suppress ALL
}
3. Create a Space
instance with a comment and add it to the method
The following code resulted in the same as 2.
Space currentSpace = methodDecl.getBody().getEnd();
Space newSpace = Space.build(currentSpace.getWhitespace(), currentSpace.getComments());
newSpace.getComments().add(new TextComment(false, "parasoft-end-suppress ALL", "\n", Markers.EMPTY));
methodDecl = methodDecl.withBody(methodDecl.getBody().withEnd(newSpace));
Question
How can I add a line comment just after a method (or, at the end of a method) with an OpenRewrite recipe?
By the given example code below
If you debug and put a breakpoint anywhere in the method
visitMethodDeclaration
, evaluate expressionTreeVisitingPrinter.printTree(getCursor());
, you can get a printed LST tree looks like thisI put 3 comments there to indicate where is the comment located in the tree. you can see the expected method end comment
parasoft-end-suppress ALL
actually doesn't belong to the 1st method declaration, but the 2nd method declaration, or if there is only one method there, the commentcomment2
is at the end of the J.Block. So the solution should be to add a method-end comment to the next method declaration prefix. or the parent block's end if there is not following method.Hope this helps.
If you have further questions, welcome to ask in the openRewrite slack here