diff --git a/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java b/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java index fcd1722cd2b..2120a7ef4d5 100644 --- a/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java @@ -671,6 +671,7 @@ static int findNextChar(char[] contents, int maxOff, int off, char expectedChar) static int findNextNonWhitespace(char[] content, int maxOff, int off) { return findNextNonWhitespace(true, content, maxOff, off); } + static int findNextNonWhitespace(boolean commentIsWhiteSpace, char[] content, int maxOff, int off) { maxOff = Math.min(maxOff, content.length - 1); while (off >= 0 && off <= maxOff) { @@ -697,10 +698,16 @@ static int findNextNonWhitespace(boolean commentIsWhiteSpace, char[] content, in * Note: all kinds of java comments are understood as whitespace too. Then it returns offset of the first character of the comment */ static int findNextWhitespace(char[] content, int maxOff, int off) { + boolean inString = false; maxOff = Math.min(maxOff, content.length - 1); while (off >= 0 && off <= maxOff) { char c = content[off]; - if (Character.isWhitespace(c) || getEndOfComment(content, maxOff, off) >= 0) { + if (c == '"' && !inString) { + inString = true; + } else if (c == '"' && inString) { + inString = false; + } + if (Character.isWhitespace(c) || (!inString && getEndOfComment(content, maxOff, off) >= 0)) { //it is whitespace or comment starts there return off; } @@ -708,6 +715,7 @@ static int findNextWhitespace(char[] content, int maxOff, int off) { } return -1; } + /** * @param minOff the minimal acceptable return value * @return index of first non whitespace char, searching backward. Can return `off` if it is already a non whitespace. diff --git a/src/test/java/spoon/test/sourcePosition/SourcePositionTest.java b/src/test/java/spoon/test/sourcePosition/SourcePositionTest.java index bb119c763ac..38f1b689956 100644 --- a/src/test/java/spoon/test/sourcePosition/SourcePositionTest.java +++ b/src/test/java/spoon/test/sourcePosition/SourcePositionTest.java @@ -18,20 +18,26 @@ import org.junit.Test; +import spoon.Launcher; +import spoon.reflect.CtModel; import spoon.reflect.code.CtInvocation; import spoon.reflect.cu.CompilationUnit; import spoon.reflect.cu.SourcePosition; +import spoon.reflect.declaration.CtElement; import spoon.reflect.declaration.CtMethod; +import spoon.reflect.declaration.CtModifiable; import spoon.reflect.declaration.CtType; import spoon.reflect.factory.Factory; import spoon.reflect.reference.CtExecutableReference; import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.Filter; import spoon.reflect.visitor.filter.TypeFilter; +import spoon.support.reflect.CtExtendedModifier; import spoon.support.reflect.cu.CompilationUnitImpl; import spoon.support.reflect.cu.position.BodyHolderSourcePositionImpl; import spoon.support.reflect.cu.position.DeclarationSourcePositionImpl; import spoon.support.reflect.cu.position.SourcePositionImpl; +import spoon.support.reflect.declaration.CtClassImpl; import spoon.test.sourcePosition.testclasses.Brambora; import spoon.testing.utils.ModelUtils; @@ -112,4 +118,15 @@ public String getOriginalSourceCode() { "name = |4;7|4567|\n" + "body = |8;9|89|", bhsp.getSourceDetails()); } + + @Test + public void testSourcePositionWhenCommentInAnnotation() { + // contract: comment characters as element values in annotations should not break position assignment to modifiers + Launcher launcher = new Launcher(); + launcher.addInputResource("./src/test/resources/spoon/test/sourcePosition/ClassWithAnnotation.java"); + launcher.addInputResource("./src/test/resources/spoon/test/sourcePosition/TestAnnotation.java"); + CtModel model = launcher.buildModel(); + List list = model.getElements(new TypeFilter<>(CtClassImpl.class)); + assertEquals(4,list.get(0).getPosition().getLine()); + } } \ No newline at end of file diff --git a/src/test/resources/spoon/test/sourcePosition/ClassWithAnnotation.java b/src/test/resources/spoon/test/sourcePosition/ClassWithAnnotation.java new file mode 100644 index 00000000000..b5ec4c1dae1 --- /dev/null +++ b/src/test/resources/spoon/test/sourcePosition/ClassWithAnnotation.java @@ -0,0 +1,4 @@ +package spoon.test.sourcePosition + +@TestAnnotation("/*") +public class ClassWithAnnotation { } \ No newline at end of file diff --git a/src/test/resources/spoon/test/sourcePosition/TestAnnotation.java b/src/test/resources/spoon/test/sourcePosition/TestAnnotation.java new file mode 100644 index 00000000000..a07fb3e95b4 --- /dev/null +++ b/src/test/resources/spoon/test/sourcePosition/TestAnnotation.java @@ -0,0 +1,6 @@ +package spoon.test.sourcePosition; + +// resource for https://github.com/INRIA/spoon/issues/3606 +public @interface TestAnnotation { + String value() default ""; +}