Skip to content

Commit

Permalink
fix: Improve comment handling in lambda parameters and local variables (
Browse files Browse the repository at this point in the history
#6076)

Print inline comments on the same line as their element
Do not crash for comments inside lambda parameters 
Attribute comments to local variable default expressions
Previously comments like `int a = /* foo */ 5` were attributed to the
CtLocalVariable, which did not print them (as they appear within and not
before/after).
  • Loading branch information
I-Al-Istannen authored Nov 17, 2024
1 parent 77a8226 commit 4c8531f
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -454,7 +454,10 @@ public List<CtComment> getComments(CtElement element, CommentOffset offset) {
final int line = element.getPosition().getLine();
final int sourceEnd = element.getPosition().getSourceEnd();
final int sourceStart = element.getPosition().getSourceStart();
if (offset == CommentOffset.BEFORE && (comment.getPosition().getLine() < line || (sourceStart <= comment.getPosition().getSourceStart() && sourceEnd > comment.getPosition().getSourceEnd()))) {
boolean commentStartsInLineBefore = comment.getPosition().getLine() < line;
boolean commentStartsInsideUs = sourceStart <= comment.getPosition().getSourceStart() && sourceEnd > comment.getPosition().getSourceEnd();
boolean commentStartsBeforeUs = sourceStart >= comment.getPosition().getSourceStart() && sourceEnd > comment.getPosition().getSourceEnd();
if (offset == CommentOffset.BEFORE && (commentStartsInLineBefore || commentStartsInsideUs || commentStartsBeforeUs)) {
commentsToPrint.add(comment);
} else if (offset == CommentOffset.AFTER && (comment.getPosition().getSourceStart() > sourceEnd || comment.getPosition().getSourceEnd() == sourceEnd)) {
commentsToPrint.add(comment);
Expand Down
22 changes: 20 additions & 2 deletions src/main/java/spoon/support/compiler/jdt/JDTCommentBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import spoon.reflect.code.CtCatch;
import spoon.reflect.code.CtComment;
import spoon.reflect.code.CtConditional;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtIf;
import spoon.reflect.code.CtLambda;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.code.CtLocalVariable;
import spoon.reflect.code.CtNewArray;
import spoon.reflect.code.CtStatement;
import spoon.reflect.code.CtStatementList;
Expand Down Expand Up @@ -350,7 +352,21 @@ public void visitCtImport(CtImport ctImport) {

@Override
public <T> void scanCtVariable(CtVariable<T> e) {
e.addComment(comment);
if (e instanceof CtLocalVariable<T> lv && lv.getDefaultExpression() != null) {
CtExpression<T> defaultExpression = lv.getDefaultExpression();
int variableStart = e.getPosition().getSourceStart();
int commentStart = comment.getPosition().getSourceStart();
int defaultExprStart = defaultExpression.getPosition().getSourceStart();
// Handle `int a = /* foobar */ foo();` by attaching the comment to `foo()`
// In those cases the comment and `foo()` start at the same position
if (commentStart > variableStart && commentStart >= defaultExprStart) {
defaultExpression.addComment(comment);
} else {
e.addComment(comment);
}
} else {
e.addComment(comment);
}
}

private <S> void visitSwitch(CtAbstractSwitch<S> e) {
Expand Down Expand Up @@ -456,7 +472,9 @@ public void visitCtAnonymousExecutable(CtAnonymousExecutable e) {

@Override
public <T> void visitCtLambda(CtLambda<T> e) {
if (e.getExpression() != null) {
if (e.getExpression() != null && e.getParameters().isEmpty()) {
e.getExpression().addComment(comment);
} else if (e.getExpression() != null && !e.getParameters().isEmpty()) {
CtParameter<?> lastParameter = e.getParameters().get(e.getParameters().size() - 1);
if (comment.getPosition().getSourceStart() > lastParameter.getPosition().getSourceEnd()) {
e.getExpression().addComment(comment);
Expand Down
28 changes: 28 additions & 0 deletions src/test/java/spoon/test/comment/CommentTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.extension.ExtendWith;
import spoon.Launcher;
import spoon.LauncherTest;
import spoon.SpoonException;
import spoon.reflect.CtModel;
import spoon.reflect.code.CtArrayAccess;
Expand Down Expand Up @@ -110,6 +111,7 @@
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
import static spoon.testing.assertions.SpoonAssertions.assertThat;


public class CommentTest {
Expand Down Expand Up @@ -1325,4 +1327,30 @@ public void testTypeParameterComments(CtModel model) {
assertEquals("comment 3", typeParameters.get(1).getComments().get(1).getContent());
assertEquals("comment 4", typeParameters.get(1).getComments().get(2).getContent());
}

@Test
@GitHubIssue(issueNumber = 6069, fixed = true)
@ExtendWith(LineSeparatorExtension.class)
public void testCommentInLambda() {
// contract: Comments inside lambdas should not crash or disappear.
CtClass<?> ctClass = Launcher.parseClass("""
class Foo {
public void bar() {
Runnable r = () -> {
/* hello */ System.exit(1);
};
Runnable b = () -> /* hello2 */ System.exit(1);
Runnable c = /* hello3 */ () -> System.exit(1);
java.util.function.IntFunction<Void> d = ( /* hello4 */ int a ) -> null;
int e = /* hello5 */ 5;
}
}
""");
assertThat(ctClass).asString().contains("/* hello */");
// Wrong output, there should not be a newline here. Codify it for now in the test case
assertThat(ctClass).asString().containsPattern("/\\* hello2 \\*/\n\\s+System");
assertThat(ctClass).asString().contains("/* hello3 */");
assertThat(ctClass).asString().contains("/* hello4 */");
assertThat(ctClass).asString().contains("/* hello5 */");
}
}

0 comments on commit 4c8531f

Please sign in to comment.