diff --git a/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java b/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java index d16f89e150b..27488914432 100644 --- a/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java +++ b/src/main/java/spoon/support/compiler/jdt/PositionBuilder.java @@ -26,16 +26,19 @@ import org.eclipse.jdt.internal.compiler.ast.Javadoc; import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; - import org.eclipse.jdt.internal.compiler.ast.TypeParameter; import org.eclipse.jdt.internal.compiler.ast.TypeReference; - import spoon.SpoonException; import spoon.reflect.code.CtStatementList; import spoon.reflect.cu.CompilationUnit; import spoon.reflect.cu.SourcePosition; import spoon.reflect.declaration.CtElement; +import spoon.reflect.declaration.CtModifiable; import spoon.reflect.factory.CoreFactory; +import spoon.support.reflect.CtExtendedModifier; + +import java.util.Arrays; +import java.util.Set; import static spoon.support.compiler.jdt.JDTTreeBuilderQuery.getModifiers; @@ -115,6 +118,8 @@ SourcePosition buildPositionCtElement(CtElement e, ASTNode node) { // when no modifier if (modifiersSourceStart > modifiersSourceEnd) { modifiersSourceEnd = modifiersSourceStart - 1; + } else if (e instanceof CtModifiable) { + setModifiersPosition((CtModifiable) e, modifiersSourceStart, modifiersSourceEnd); } return cf.createDeclarationSourcePosition(cu, @@ -144,6 +149,9 @@ SourcePosition buildPositionCtElement(CtElement e, ASTNode node) { int modifiersSourceEnd = findPrevNonWhitespace(contents, modifiersSourceStart - 1, findPrevWhitespace(contents, modifiersSourceStart - 1, findPrevNonWhitespace(contents, modifiersSourceStart - 1, sourceStart - 1))); + if (e instanceof CtModifiable) { + setModifiersPosition((CtModifiable) e, modifiersSourceStart, bodyStart); + } if (modifiersSourceEnd < modifiersSourceStart) { //there is no modifier modifiersSourceEnd = modifiersSourceStart - 1; @@ -193,6 +201,10 @@ SourcePosition buildPositionCtElement(CtElement e, ASTNode node) { int modifiersSourceEnd = sourceStart - 1; + if (e instanceof CtModifiable) { + setModifiersPosition((CtModifiable) e, modifiersSourceStart, declarationSourceEnd); + } + if (methodDeclaration instanceof MethodDeclaration && ((MethodDeclaration) methodDeclaration).returnType != null) { modifiersSourceEnd = ((MethodDeclaration) methodDeclaration).returnType.sourceStart() - 2; } @@ -239,6 +251,31 @@ SourcePosition buildPositionCtElement(CtElement e, ASTNode node) { return cf.createSourcePosition(cu, sourceStart, sourceEnd, lineSeparatorPositions); } + + private void setModifiersPosition(CtModifiable e, int start, int end) { + CoreFactory cf = this.jdtTreeBuilder.getFactory().Core(); + CompilationUnit cu = this.jdtTreeBuilder.getFactory().CompilationUnit().getOrCreate(new String(this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.getFileName())); + CompilationResult cr = this.jdtTreeBuilder.getContextBuilder().compilationunitdeclaration.compilationResult; + char[] contents = cr.compilationUnit.getContents(); + + Set modifiers = e.getExtendedModifiers(); + String modifierContent = String.valueOf( + Arrays.copyOfRange(contents, start, end + 1)); + for (CtExtendedModifier modifier: modifiers) { + if (modifier.isImplicit()) { + continue; + } + int index = modifierContent.indexOf(modifier.getKind().toString()); + if (index == -1) { + throw new SpoonException("Explicit modifier not found"); + } + int indexStart = index + start; + int indexEnd = indexStart + modifier.getKind().toString().length() - 1; + + modifier.setPosition(cf.createSourcePosition(cu, indexStart, indexEnd, cr.lineSeparatorPositions)); + } + } + private int getSourceEndOfTypeReference(char[] contents, TypeReference node, int sourceEnd) { //e.g. SomeType TypeReference[][] typeArgs = ((TypeReference) node).getTypeArguments(); diff --git a/src/main/java/spoon/support/reflect/CtExtendedModifier.java b/src/main/java/spoon/support/reflect/CtExtendedModifier.java index e6c491a8d43..41ea9dc16ba 100644 --- a/src/main/java/spoon/support/reflect/CtExtendedModifier.java +++ b/src/main/java/spoon/support/reflect/CtExtendedModifier.java @@ -82,4 +82,4 @@ public int hashCode() { result = 31 * result + (kind != null ? kind.hashCode() : 0); return result; } -} \ No newline at end of file +} diff --git a/src/test/java/spoon/test/interfaces/TestInterfaceWithoutSetup.java b/src/test/java/spoon/test/interfaces/TestInterfaceWithoutSetup.java index 4d3c9dcf3de..19959567243 100644 --- a/src/test/java/spoon/test/interfaces/TestInterfaceWithoutSetup.java +++ b/src/test/java/spoon/test/interfaces/TestInterfaceWithoutSetup.java @@ -3,6 +3,7 @@ import org.apache.commons.lang3.StringUtils; import org.junit.Test; import spoon.Launcher; +import spoon.reflect.cu.position.NoSourcePosition; import spoon.reflect.declaration.CtField; import spoon.reflect.declaration.CtMethod; import spoon.reflect.declaration.CtType; @@ -12,7 +13,6 @@ import java.io.File; import java.io.IOException; import java.nio.file.Files; -import java.util.List; import java.util.Set; import static org.junit.Assert.assertEquals; @@ -64,6 +64,8 @@ public void testModifierFromInterfaceFieldAndMethod() { counter++; } else { assertFalse(extendedModifier.isImplicit()); + assertFalse(extendedModifier.getPosition() instanceof NoSourcePosition); + assertEquals(extendedModifier.getKind().toString(), extendedModifier.getPosition().getCompilationUnit().getOriginalSourceCode().substring(extendedModifier.getPosition().getSourceStart(),extendedModifier.getPosition().getSourceEnd() + 1)); counter++; } }