Skip to content

Commit

Permalink
fix: Handle comments at the bottom of a file (#1976)
Browse files Browse the repository at this point in the history
  • Loading branch information
tdurieux authored and monperrus committed Apr 27, 2018
1 parent f3032be commit 094d7f5
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 27 deletions.
15 changes: 13 additions & 2 deletions src/main/java/spoon/reflect/visitor/DefaultJavaPrettyPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,7 @@ public <T> void visitCtExecutableReference(CtExecutableReference<T> reference) {

@Override
public <T> void visitCtField(CtField<T> f) {
elementPrinterHelper.writeComment(f);
elementPrinterHelper.writeComment(f, CommentOffset.BEFORE);
elementPrinterHelper.visitCtNamedElement(f, sourceCompilationUnit);
elementPrinterHelper.writeModifiers(f);
scan(f.getType());
Expand All @@ -757,6 +757,7 @@ public <T> void visitCtField(CtField<T> f) {
scan(f.getDefaultExpression());
}
printer.writeSeparator(";");
elementPrinterHelper.writeComment(f, CommentOffset.AFTER);
}

@Override
Expand Down Expand Up @@ -1326,7 +1327,7 @@ public <T> void visitCtCatchVariableReference(CtCatchVariableReference<T> refere

@Override
public <T> void visitCtMethod(CtMethod<T> m) {
elementPrinterHelper.writeComment(m);
elementPrinterHelper.writeComment(m, CommentOffset.BEFORE);
elementPrinterHelper.visitCtNamedElement(m, sourceCompilationUnit);
elementPrinterHelper.writeModifiers(m);
elementPrinterHelper.writeFormalTypeParameters(m);
Expand Down Expand Up @@ -1357,6 +1358,7 @@ public <T> void visitCtMethod(CtMethod<T> m) {
} else {
printer.writeSeparator(";");
}
elementPrinterHelper.writeComment(m, CommentOffset.AFTER);
}

@Override
Expand Down Expand Up @@ -1921,6 +1923,14 @@ public DefaultJavaPrettyPrinter writeHeader(List<CtType<?>> types, Collection<Ct
return this;
}

/**
* Write the compilation unit footer.
*/
public DefaultJavaPrettyPrinter writeFooter(List<CtType<?>> types) {
elementPrinterHelper.writeFooter(types);
return this;
}

@Override
public void calculate(CompilationUnit sourceCompilationUnit, List<CtType<?>> types) {
// reset the importsContext to avoid errors with multiple CU
Expand All @@ -1945,6 +1955,7 @@ public void calculate(CompilationUnit sourceCompilationUnit, List<CtType<?>> typ
getPrinterHelper().adjustEndPosition(t);
}
}
this.writeFooter(types);
}

@Override
Expand Down
21 changes: 18 additions & 3 deletions src/main/java/spoon/reflect/visitor/ElementPrinterHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,17 @@ public void writeHeader(List<CtType<?>> types, Collection<CtImport> imports) {
}
}

/**
* Write the compilation unit footer.
*/
public void writeFooter(List<CtType<?>> types) {
if (!types.isEmpty()) {
for (CtType<?> ctType : types) {
writeComment(ctType, CommentOffset.BOTTOM_FILE);
}
}
}

public void writePackageLine(String packageQualifiedName) {
printer.writeKeyword("package").writeSpace();
writeQualifiedName(packageQualifiedName).writeSeparator(";").writeln();
Expand Down Expand Up @@ -407,7 +418,11 @@ public List<CtComment> getComments(CtElement element, CommentOffset offset) {
return commentsToPrint;
}
for (CtComment comment : element.getComments()) {
if (comment.getCommentType() == CtComment.CommentType.FILE && offset == CommentOffset.TOP_FILE) {
if (comment.getCommentType() == CtComment.CommentType.FILE && offset == CommentOffset.TOP_FILE && element.getPosition().getSourceEnd() > comment.getPosition().getSourceStart()) {
commentsToPrint.add(comment);
continue;
}
if (comment.getCommentType() == CtComment.CommentType.FILE && offset == CommentOffset.BOTTOM_FILE && element.getPosition().getSourceEnd() < comment.getPosition().getSourceStart()) {
commentsToPrint.add(comment);
continue;
}
Expand All @@ -423,9 +438,9 @@ 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()))) {
if (offset == CommentOffset.BEFORE && (comment.getPosition().getLine() < line || (sourceStart <= comment.getPosition().getSourceStart() && sourceEnd > comment.getPosition().getSourceEnd()))) {
commentsToPrint.add(comment);
} else if (offset == CommentOffset.AFTER && comment.getPosition().getSourceStart() > sourceEnd) {
} else if (offset == CommentOffset.AFTER && (comment.getPosition().getSourceStart() > sourceEnd || comment.getPosition().getSourceEnd() == sourceEnd)) {
commentsToPrint.add(comment);
} else {
final int endLine = element.getPosition().getEndLine();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package spoon.reflect.visitor.printer;

public enum CommentOffset {
BOTTOM_FILE,
TOP_FILE,
BEFORE,
AFTER,
Expand Down
12 changes: 10 additions & 2 deletions src/main/java/spoon/support/compiler/jdt/JDTCommentBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtModule;
import spoon.reflect.declaration.CtParameter;
import spoon.reflect.declaration.CtType;
import spoon.reflect.declaration.CtTypeMember;
import spoon.reflect.declaration.CtVariable;
import spoon.reflect.declaration.ParentNotInitializedException;
import spoon.reflect.factory.Factory;
import spoon.reflect.reference.CtReference;
import spoon.reflect.visitor.CtInheritanceScanner;
import spoon.reflect.visitor.CtScanner;
import spoon.reflect.visitor.DefaultJavaPrettyPrinter;
Expand Down Expand Up @@ -145,7 +147,7 @@ private void buildComment(int[] positions) {
String commentContent = getCommentContent(start, end);

int[] lineSeparatorPositions = declarationUnit.compilationResult.lineSeparatorPositions;
SourcePosition sourcePosition = factory.Core().createSourcePosition(spoonUnit, start, end, lineSeparatorPositions);
SourcePosition sourcePosition = factory.Core().createSourcePosition(spoonUnit, start, end - 1, lineSeparatorPositions);

// create the Spoon comment element
comment = parseTags(comment, commentContent);
Expand Down Expand Up @@ -238,7 +240,7 @@ private CtElement addCommentToNear(final CtComment comment, final Collection<CtE
int elementEndLine = element.getPosition().getEndLine();
int commentLine = comment.getPosition().getLine();

if (distance < smallDistance && (!isAfter || elementEndLine == commentLine)) {
if (distance < smallDistance && (!isAfter || elementEndLine == commentLine || element instanceof CtType)) {
best = element;
smallDistance = distance;
}
Expand Down Expand Up @@ -288,6 +290,12 @@ public void scan(CtElement e) {
}
}

@Override
public void scanCtReference(CtReference reference) {
reference.addComment(comment);
super.scanCtReference(reference);
}

@Override
public <R> void visitCtStatementList(CtStatementList e) {
addCommentToNear(comment, new ArrayList<CtElement>(e.getStatements()));
Expand Down
29 changes: 13 additions & 16 deletions src/test/java/spoon/test/comment/CommentTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,14 @@
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static org.apache.commons.io.IOUtils.write;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;

public class CommentTest {

Expand Down Expand Up @@ -250,9 +244,9 @@ public void testRemoveComment() {
Factory f = getSpoonFactory();
CtClass<?> type = (CtClass<?>) f.Type().get(InlineComment.class);
List<CtComment> comments = type.getComments();
assertEquals(5, comments.size());
assertEquals(6, comments.size());
type.removeComment(comments.get(0));
assertEquals(4, type.getComments().size());
assertEquals(5, type.getComments().size());
}

@Test
Expand All @@ -263,7 +257,7 @@ public void testInLineComment() {

List<CtComment> comments = type.getElements(new TypeFilter<CtComment>(CtComment.class));
// verify that the number of comment present in the AST is correct
assertEquals(66, comments.size());
assertEquals(69, comments.size());

// verify that all comments present in the AST is printed
for (CtComment comment : comments) {
Expand All @@ -275,17 +269,18 @@ public void testInLineComment() {
assertTrue(comment.toString() + ":" + comment.getParent() + " is not printed", strType.contains(comment.toString()));
}

assertEquals(5, type.getComments().size());
assertEquals(6, type.getComments().size());
assertEquals(CtComment.CommentType.FILE, type.getComments().get(0).getCommentType());
assertEquals(createFakeComment(f, "comment class"), type.getComments().get(1));
assertEquals("Bottom File", type.getComments().get(5).getContent());

CtField<?> field = type.getField("field");
assertEquals(3, field.getComments().size());
assertEquals(4, field.getComments().size());
assertEquals(createFakeComment(f, "Comment Field"), field.getComments().get(0));
assertEquals("// Comment Field" + newLine
+ "// comment field 2" + newLine
+ "// comment in field" + newLine
+ "private int field = 10;", field.toString());
+ "private int field = 10;// after field\n", field.toString());

CtAnonymousExecutable ctAnonymousExecutable = type.getAnonymousExecutables().get(0);
assertEquals(1, ctAnonymousExecutable.getComments().size());
Expand Down Expand Up @@ -461,7 +456,7 @@ public void testBlockComment() {

List<CtComment> comments = type.getElements(new TypeFilter<CtComment>(CtComment.class));
// verify that the number of comment present in the AST is correct
assertEquals(51, comments.size());
assertEquals(52, comments.size());

// verify that all comments present in the AST is printed
for (CtComment comment : comments) {
Expand All @@ -473,8 +468,9 @@ public void testBlockComment() {
assertTrue(comment.toString() + ":" + comment.getParent() + " is not printed", strType.contains(comment.toString()));
}

assertEquals(4, type.getComments().size());
assertEquals(5, type.getComments().size());
assertEquals(createFakeBlockComment(f, "comment class"), type.getComments().get(1));
assertEquals("Bottom File", type.getComments().get(4).getContent());

CtField<?> field = type.getField("field");
assertEquals(2, field.getComments().size());
Expand Down Expand Up @@ -704,8 +700,9 @@ public void testSnippedWithComments(){

CtClass<?> clazz1 = (CtClass<?>) factory.Type().getAll().get(0);
assertNotNull(clazz1);
assertEquals(1, clazz1.getComments().size());
assertEquals(2, clazz1.getComments().size());
assertEquals("class comment", clazz1.getComments().get(0).getContent());
assertEquals("after class comment", clazz1.getComments().get(1).getContent());

assertEquals(1, builder.getSnippetCompilationUnit().getDeclaredTypes().size());
assertTrue(clazz1==builder.getSnippetCompilationUnit().getDeclaredTypes().get(0));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,8 @@ public void m3() {
m3();
}
/* comment after class */
}
}

/*
* Bottom File
*/
10 changes: 7 additions & 3 deletions src/test/java/spoon/test/comment/testclasses/InlineComment.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public class InlineComment
// Comment Field
// comment field 2
private int field // comment in field
= 10;
= 10; // after field

// comment static block
static {
Expand Down Expand Up @@ -102,7 +102,7 @@ public void m1() {

String m = "" +
"" + // comment multi line string
"";
""; // after statement

boolean c = (i == 1) ?
// comment before then boolean CtConditional
Expand Down Expand Up @@ -148,4 +148,8 @@ public void m3() {
m3();
}
// comment after class
}
}

/*
* Bottom File
*/

0 comments on commit 094d7f5

Please sign in to comment.