package spoon.test.position;
import org.junit.Test;
import spoon.reflect.code.CtAssignment;
import spoon.reflect.code.CtBlock;
import spoon.reflect.code.CtExpression;
import spoon.reflect.code.CtFieldAccess;
import spoon.reflect.code.CtIf;
import spoon.reflect.code.CtStatement;
import spoon.reflect.cu.SourcePosition;
import spoon.reflect.cu.position.BodyHolderSourcePosition;
import spoon.reflect.cu.position.DeclarationSourcePosition;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtConstructor;
import spoon.reflect.declaration.CtMethod;
import spoon.reflect.declaration.CtType;
import spoon.reflect.factory.Factory;
import spoon.test.position.testclasses.Foo;
import spoon.test.position.testclasses.FooClazz;
import spoon.test.position.testclasses.FooClazz2;
import spoon.test.position.testclasses.FooField;
import spoon.test.position.testclasses.FooGeneric;
import spoon.test.position.testclasses.FooMethod;
import spoon.test.position.testclasses.FooStatement;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static spoon.testing.utils.ModelUtils.build;
import static spoon.testing.utils.ModelUtils.buildClass;
public class PositionTest {
@Test
public void testPositionClass() throws Exception {
final Factory build = build(new File("src/test/java/spoon/test/position/testclasses/"));
final CtType<FooClazz> foo = build.Type().get(FooClazz.class);
String classContent = getClassContent(foo);
BodyHolderSourcePosition position = (BodyHolderSourcePosition) foo.getPosition();
assertEquals(4, position.getLine());
assertEquals(6, position.getEndLine());
assertEquals(42, position.getSourceStart());
assertEquals(79, position.getSourceEnd());
assertEquals("@Deprecated\n"
+ "public class FooClazz {\n"
+ "\n"
+ "}", contentAtPosition(classContent, position));
assertEquals("{\n\n}", contentAtPosition(classContent, position.getBodyStart(), position.getBodyEnd()));
// this specifies that getLine starts at name (and not at Javadoc or annotation)
final CtType<FooClazz> foo2 = build.Type().get(FooClazz2.class);
assertEquals(42, foo2.getPosition().getSourceStart());
assertEquals(4, foo2.getPosition().getLine());
assertEquals(4, foo2.getPosition().getEndLine());
assertEquals("FooClazz", contentAtPosition(classContent, position.getNameStart(), position.getNameEnd()));
assertEquals("public", contentAtPosition(classContent, position.getModifierSourceStart(), position.getModifierSourceEnd()));
}
@Test
public void testPositionField() throws Exception {
final Factory build = build(FooField.class);
final CtType<FooField> foo = build.Type().get(FooField.class);
String classContent = getClassContent(foo);
DeclarationSourcePosition position1 = (DeclarationSourcePosition) foo.getField("field1").getPosition();
assertEquals(5, position1.getLine());
assertEquals(5, position1.getEndLine());
assertEquals(68, position1.getSourceStart());
assertEquals(95, position1.getSourceEnd());
assertEquals("public final int field1 = 0;", contentAtPosition(classContent, position1));
assertEquals("field1", contentAtPosition(classContent, position1.getNameStart(), position1.getNameEnd()));
assertEquals("public final", contentAtPosition(classContent, position1.getModifierSourceStart(), position1.getModifierSourceEnd()));
DeclarationSourcePosition position2 = (DeclarationSourcePosition) foo.getField("field2").getPosition();
assertEquals(7, position2.getLine());
assertEquals(8, position2.getEndLine());
assertEquals(99, position2.getSourceStart());
assertEquals(116, position2.getSourceEnd());
assertEquals("int field2 =\n"
+ "\t\t\t0;", contentAtPosition(classContent, position2));
assertEquals("field2", contentAtPosition(classContent, position2.getNameStart(), position2.getNameEnd()));
assertEquals("", contentAtPosition(classContent, position2.getModifierSourceStart(), position2.getModifierSourceEnd()));
CtAssignment m = foo.getMethod("m").getBody().getStatement(0);
CtFieldAccess assigned = (CtFieldAccess) m.getAssigned();
SourcePosition position3 = assigned.getPosition();
assertEquals(13, position3.getLine());
assertEquals(13, position3.getEndLine());
assertEquals(168, position3.getSourceStart());
assertEquals(184, position3.getSourceEnd());
assertEquals("FooField.f.field2", contentAtPosition(classContent, position3));
CtFieldAccess target = (CtFieldAccess) assigned.getTarget();
SourcePosition position4 = target.getPosition();
assertEquals(13, position4.getLine());
assertEquals(13, position4.getEndLine());
assertEquals(168, position4.getSourceStart());
assertEquals(177, position4.getSourceEnd());
assertEquals("FooField.f", contentAtPosition(classContent, position4));
CtExpression typeAccess = target.getTarget();
SourcePosition position5 = typeAccess.getPosition();
assertEquals(13, position5.getLine());
assertEquals(13, position5.getEndLine());
assertEquals(168, position5.getSourceStart());
assertEquals(175, position5.getSourceEnd());
assertEquals("FooField", contentAtPosition(classContent, position5));
}
@Test
public void testPositionGeneric() throws Exception {
final Factory build = build(FooGeneric.class);
final CtClass<FooGeneric> foo = build.Class().get(FooGeneric.class);
String classContent = getClassContent(foo);
BodyHolderSourcePosition position = (BodyHolderSourcePosition) foo.getPosition();
assertEquals(3, position.getLine());
assertEquals(31, position.getEndLine());
assertEquals(42, position.getSourceStart());
assertEquals(411, position.getSourceEnd());
assertEquals("FooGeneric", contentAtPosition(classContent, position.getNameStart(), position.getNameEnd()));
assertEquals("public", contentAtPosition(classContent, position.getModifierSourceStart(), position.getModifierSourceEnd()));
DeclarationSourcePosition position1 = (DeclarationSourcePosition) foo.getField("variable").getPosition();
assertEquals(5, position1.getLine());
assertEquals(5, position1.getEndLine());
assertEquals(88, position1.getSourceStart());
assertEquals(118, position1.getSourceEnd());
assertEquals("public final T variable = null;", contentAtPosition(classContent, position1));
assertEquals("variable", contentAtPosition(classContent, position1.getNameStart(), position1.getNameEnd()));
assertEquals("public final", contentAtPosition(classContent, position1.getModifierSourceStart(), position1.getModifierSourceEnd()));
CtMethod<?> method1 = foo.getMethodsByName("m").get(0);
BodyHolderSourcePosition position2 = (BodyHolderSourcePosition) method1
.getPosition();
assertEquals("public @Deprecated static <S> S m(int parm1) {\n"
+ "\t\treturn null;\n"
+ "\t}", contentAtPosition(classContent, position2));
assertEquals("m", contentAtPosition(classContent, position2.getNameStart(), position2.getNameEnd()));
// /!\ the annotations can be between two modifiers
assertEquals("public @Deprecated static", contentAtPosition(classContent, position2.getModifierSourceStart(), position2.getModifierSourceEnd()));
}
@Test
public void testPositionMethod() throws Exception {
final Factory build = build(FooMethod.class);
final CtClass<FooMethod> foo = build.Class().get(FooMethod.class);
String classContent = getClassContent(foo);
CtMethod<?> method1 = foo.getMethodsByName("m").get(0);
BodyHolderSourcePosition position1 = (BodyHolderSourcePosition) method1.getPosition();
assertEquals(5, position1.getLine());
assertEquals(7, position1.getEndLine());
assertEquals(69, position1.getSourceStart());
assertEquals(114, position1.getSourceEnd());
assertEquals("public static void m(int parm1) {\n"
+ "\t\treturn;\n"
+ "\t}", contentAtPosition(classContent, position1));
assertEquals("m", contentAtPosition(classContent, position1.getNameStart(), position1.getNameEnd()));
assertEquals("public static", contentAtPosition(classContent, position1.getModifierSourceStart(), position1.getModifierSourceEnd()));
DeclarationSourcePosition positionParam1 = (DeclarationSourcePosition) method1.getParameters().get(0).getPosition();
assertEquals(5, positionParam1.getLine());
assertEquals(5, positionParam1.getEndLine());
assertEquals(90, positionParam1.getSourceStart());
assertEquals(98, positionParam1.getSourceEnd());
assertEquals("int parm1", contentAtPosition(classContent, positionParam1));
assertEquals("parm1", contentAtPosition(classContent, positionParam1.getNameStart(), positionParam1.getNameEnd()));
assertEquals("", contentAtPosition(classContent, positionParam1.getModifierSourceStart(), positionParam1.getModifierSourceEnd()));
CtMethod method2 = foo.getMethodsByName("mWithDoc").get(0);
BodyHolderSourcePosition position2 = (BodyHolderSourcePosition) method2.getPosition();
assertEquals(13, position2.getLine());
assertEquals(15, position2.getEndLine());
assertEquals("/**\n"
+ "\t * Mathod with javadoc\n"
+ "\t * @param parm1 the parameter\n"
+ "\t */\n"
+ "\tint mWithDoc(int parm1) {\n"
+ "\t\treturn parm1;\n"
+ "\t}", contentAtPosition(classContent, position2));
assertEquals("mWithDoc", contentAtPosition(classContent, position2.getNameStart(), position2.getNameEnd()));
assertEquals("", contentAtPosition(classContent, position2.getModifierSourceStart(), position2.getModifierSourceEnd()));
CtConstructor<FooMethod> constructor = foo.getConstructor(build.Type().integerPrimitiveType());
SourcePosition position3 = constructor.getPosition();
contentAtPosition(classContent, position3);
CtMethod mWithLine = foo.getMethod("mWithLine", build.Type().integerPrimitiveType());
SourcePosition position4 = mWithLine.getPosition();
contentAtPosition(classContent, position4);
}
@Test
public void testPositionStatement() throws Exception {
final Factory build = build(FooStatement.class);
final CtType<FooStatement> foo = build.Type().get(FooStatement.class);
String classContent = getClassContent(foo);
CtMethod<?> method1 = foo.getMethodsByName("m").get(0);
CtBlock<?> body = method1.getBody();
SourcePosition positionBody = body.getPosition();
assertEquals(7, positionBody.getLine());
assertEquals(23, positionBody.getEndLine());
assertEquals("{\n"
+ "\t\tint field2 = m2(parm1);\n"
+ "\t\tthis.field = m2(parm1);\n"
+ "\t\tif(parm1 > 2 && true) {\n"
+ "\t\t\tswitch (parm1) {\n"
+ "\t\t\tcase 1:\n"
+ "\t\t\t\treturn;\n"
+ "\t\t\tdefault:\n"
+ "\t\t\t\tparm1++;\n"
+ "\t\t\t}\n"
+ "\t\t\tint count = 0;\n"
+ "\t\t\tfor (int i =0; i< parm1; i++) {\n"
+ "\t\t\t\tcount ++;\n"
+ "\t\t\t}\n"
+ "\t\t}\n"
+ "\t\treturn;\n"
+ "\t}", contentAtPosition(classContent, positionBody));
SourcePosition positionLocalVariable = body.getStatement(0).getPosition();
assertEquals(8, positionLocalVariable.getLine());
assertEquals(8, positionLocalVariable.getEndLine());
assertEquals("int field2 = m2(parm1);", contentAtPosition(classContent, positionLocalVariable));
SourcePosition positionFieldWrite = body.getStatement(1).getPosition();
assertEquals(9, positionFieldWrite.getLine());
assertEquals(9, positionFieldWrite.getEndLine());
assertEquals("this.field = m2(parm1);", contentAtPosition(classContent, positionFieldWrite));
CtIf ctIf = body.getStatement(2);
SourcePosition positionIf = ctIf.getPosition();
assertEquals(10, positionIf.getLine());
assertEquals(21, positionIf.getEndLine());
assertEquals("if(parm1 > 2 && true) {\n"
+ "\t\t\tswitch (parm1) {\n"
+ "\t\t\tcase 1:\n"
+ "\t\t\t\treturn;\n"
+ "\t\t\tdefault:\n"
+ "\t\t\t\tparm1++;\n"
+ "\t\t\t}\n"
+ "\t\t\tint count = 0;\n"
+ "\t\t\tfor (int i =0; i< parm1; i++) {\n"
+ "\t\t\t\tcount ++;\n"
+ "\t\t\t}\n"
+ "\t\t}", contentAtPosition(classContent, positionIf));
SourcePosition positionSwitch = ((CtBlock)ctIf.getThenStatement()).getStatement(0).getPosition();
assertEquals(11, positionSwitch.getLine());
assertEquals(16, positionSwitch.getEndLine());
assertEquals("switch (parm1) {\n"
+ "\t\t\tcase 1:\n"
+ "\t\t\t\treturn;\n"
+ "\t\t\tdefault:\n"
+ "\t\t\t\tparm1++;\n"
+ "\t\t\t}", contentAtPosition(classContent, positionSwitch));
positionLocalVariable = ((CtBlock)ctIf.getThenStatement()).getStatement(1).getPosition();
assertEquals(17, positionLocalVariable.getLine());
assertEquals(17, positionLocalVariable.getEndLine());
assertEquals("int count = 0;", contentAtPosition(classContent, positionLocalVariable));
SourcePosition positionFor = ((CtBlock)ctIf.getThenStatement()).getStatement(2).getPosition();
assertEquals(18, positionFor.getLine());
assertEquals(20, positionFor.getEndLine());
assertEquals("for (int i =0; i< parm1; i++) {\n"
+ "\t\t\t\tcount ++;\n"
+ "\t\t\t}", contentAtPosition(classContent, positionFor));
SourcePosition positionReturn = method1.getBody().getStatement(3).getPosition();
assertEquals(22, positionReturn.getLine());
assertEquals(22, positionReturn.getEndLine());
assertEquals("return;", contentAtPosition(classContent, positionReturn));
}
private String getClassContent(CtType type) {
File file = type.getPosition().getFile();
String content = "";
Charset charset = Charset.forName("UTF-8");
try (BufferedReader reader = Files.newBufferedReader(
Paths.get(file.getPath()), charset)) {
String line = null;
while ((line = reader.readLine()) != null) {
content+=line + "\n";
}
} catch (IOException x) {
System.err.format("IOException: %s%n", x);
}
return content;
}
private String contentAtPosition(String content, int start, int end) {
return content.substring(start, end + 1);
}
private String contentAtPosition(String content, SourcePosition position) {
return content.substring(position.getSourceStart(), position.getSourceEnd() + 1);
}
@Test
public void testSourcePosition() throws Exception {
SourcePosition s = new spoon.Launcher().getFactory().Core().createClass().getPosition();
assertEquals(-1, s.getSourceStart());
assertEquals(-1, s.getSourceEnd());
assertEquals(-1, s.getColumn());
assertEquals(-1, s.getLine());
assertEquals("(unknown file)", s.toString());
assertTrue(s.hashCode() > 0); // no NPE
}
@Test
public void defaultConstructorPositionTest() throws Exception {
CtClass<Foo> aClass = (CtClass<Foo>) buildClass(Foo.class);
CtConstructor<Foo> defaultConstructor = aClass.getConstructor();
assertEquals(SourcePosition.NOPOSITION, defaultConstructor.getPosition());
CtStatement implicitSuperCall = defaultConstructor.getBody().getStatement(0);
assertTrue(implicitSuperCall.isImplicit());
assertEquals(SourcePosition.NOPOSITION, implicitSuperCall.getPosition());
}
}