use of spoon.SpoonModelBuilder in project spoon by INRIA.
the class TypeReferenceTest method doNotCloseLoader.
@SuppressWarnings({ "rawtypes", "unchecked" })
@Test
public void doNotCloseLoader() throws Exception {
/* Given the following scenario:
* - ClassA has a field of ClassB.
* - ClassB has a field of ClassC.
* - Spoon only models ClassA.
*
* We want to get the field of ClassB, which should be accessible because
* the definitions of ClassB and ClassC were provided in the class path.
*/
SpoonModelBuilder comp = new Launcher().createCompiler();
Factory factory = comp.getFactory();
String qualifiedName = "spoontest.a.ClassA";
String referenceQualifiedName = "spoontest.b.ClassB";
// we only create the model for ClassA
List<SpoonResource> fileToBeSpooned = SpoonResourceHelper.resources("./src/test/resources/reference-test-2/" + qualifiedName.replace('.', '/') + ".java");
comp.addInputSources(fileToBeSpooned);
// for ClassA
assertEquals(1, fileToBeSpooned.size());
// Spoon requires the binary version of dependencies
List<SpoonResource> classpath = SpoonResourceHelper.resources("./src/test/resources/reference-test-2/ReferenceTest2.jar");
String[] dependencyClasspath = new String[] { classpath.get(0).getPath() };
factory.getEnvironment().setSourceClasspath(dependencyClasspath);
assertEquals(1, classpath.size());
// now we can build the model
comp.build();
// we can get the model of ClassA
CtType<?> theClass = factory.Type().get(qualifiedName);
// we get ClassA's field of type ClassB
List<CtField<?>> fields = theClass.getFields();
assertEquals(1, fields.size());
CtField<?> bField = fields.get(0);
CtTypeReference referencedType = bField.getType();
assertEquals(referenceQualifiedName, referencedType.getQualifiedName());
// we get ClassB's field of type ClassC
Collection<CtFieldReference<?>> fieldsOfB = referencedType.getAllFields();
if (fieldsOfB.size() == 2) {
// Jacoco instruments all dependencies with an agent.
// So, when we use reflection on ClassB, we don't have one field but two fields.
// First, it is the field of ClassB. Second, it is the field of Jacoco.
final CtFieldReference<?> potentialJacoco = (CtFieldReference<?>) fieldsOfB.toArray()[1];
if ("$jacocoData".equals(potentialJacoco.getSimpleName())) {
fieldsOfB.remove(potentialJacoco);
}
}
assertEquals(1, fieldsOfB.size());
CtFieldReference<?> cField = fieldsOfB.iterator().next();
assertEquals("spoontest.c.ClassC", cField.getType().getQualifiedName());
}
use of spoon.SpoonModelBuilder in project spoon by INRIA.
the class CtRenameLocalVariableRefactoringTest method testRenameAllLocalVariablesOfRenameTestSubject.
/**
* The {@link CtRenameLocalVariableRefactoringTestSubject} class is loaded as spoon model. Then:
* - It looks for each CtVariable and it's CtAnnotation and tries to rename that variable to the name defined by annotation.
* - If the annotation name is prefixed with "-", then that refactoring should fail.
* - If the annotation name is not prefixed, then that refactoring should pass.
* If it behaves different then expected, then this test fails
*/
@Test
public void testRenameAllLocalVariablesOfRenameTestSubject() throws Exception {
final Launcher launcher = new Launcher();
final SpoonModelBuilder comp = launcher.createCompiler();
comp.addInputSources(SpoonResourceHelper.resources("./src/test/java/" + CtRenameLocalVariableRefactoringTestSubject.class.getName().replace('.', '/') + ".java"));
comp.build();
final Factory factory = comp.getFactory();
CtClass<?> varRenameClass = (CtClass<?>) factory.Type().get(CtRenameLocalVariableRefactoringTestSubject.class);
CtTypeReference<TestTryRename> tryRename = varRenameClass.getFactory().createCtTypeReference(TestTryRename.class);
varRenameClass.getMethods().forEach(method -> {
// debugging support
if (DEBUG.length == 3 && DEBUG[0].equals(method.getSimpleName()) == false)
return;
method.filterChildren((CtVariable var) -> true).map((CtVariable var) -> var.getAnnotation(tryRename)).forEach((CtAnnotation<TestTryRename> annotation) -> {
String[] newNames = annotation.getActualAnnotation().value();
CtVariable<?> targetVariable = (CtVariable<?>) annotation.getAnnotatedElement();
for (String newName : newNames) {
boolean renameShouldPass = newName.startsWith("-") == false;
if (!renameShouldPass) {
newName = newName.substring(1);
}
if (targetVariable instanceof CtLocalVariable<?>) {
// debugging support
if (DEBUG.length == 3 && DEBUG[1].equals(targetVariable.getSimpleName()) && DEBUG[2].equals(newName)) {
// put breakpoint here and continue debugging of the buggy case
this.getClass();
}
checkLocalVariableRename(launcher, (CtLocalVariable<?>) targetVariable, newName, renameShouldPass);
} else {
// TODO test rename of other variables, e.g. parameters and catch... later
}
}
});
});
}
use of spoon.SpoonModelBuilder in project spoon by INRIA.
the class DefaultPrettyPrinterTest method printerCanPrintInvocationWithoutException.
@Test
public void printerCanPrintInvocationWithoutException() throws Exception {
String packageName = "spoon.test.subclass.prettyprinter";
String className = "DefaultPrettyPrinterExample";
String qualifiedName = packageName + "." + className;
SpoonModelBuilder comp = new Launcher().createCompiler();
List<SpoonResource> fileToBeSpooned = SpoonResourceHelper.resources("./src/test/resources/printer-test/" + qualifiedName.replace('.', '/') + ".java");
assertEquals(1, fileToBeSpooned.size());
comp.addInputSources(fileToBeSpooned);
List<SpoonResource> classpath = SpoonResourceHelper.resources("./src/test/resources/printer-test/DefaultPrettyPrinterDependency.jar");
assertEquals(1, classpath.size());
comp.setSourceClasspath(classpath.get(0).getPath());
comp.build();
Factory factory = comp.getFactory();
CtType<?> theClass = factory.Type().get(qualifiedName);
List<CtInvocation<?>> elements = Query.getElements(theClass, new TypeFilter<CtInvocation<?>>(CtInvocation.class));
assertEquals(3, elements.size());
CtInvocation<?> mathAbsInvocation = elements.get(1);
assertEquals("java.lang.Math.abs(message.length())", mathAbsInvocation.toString());
}
use of spoon.SpoonModelBuilder in project spoon by INRIA.
the class DefaultPrettyPrinterTest method superInvocationWithEnclosingInstance.
@Test
public void superInvocationWithEnclosingInstance() throws Exception {
/**
* To extend a nested class an enclosing instance must be provided
* to call the super constructor.
*/
String sourcePath = "./src/test/resources/spoon/test/prettyprinter/NestedSuperCall.java";
List<SpoonResource> files = SpoonResourceHelper.resources(sourcePath);
assertEquals(1, files.size());
SpoonModelBuilder comp = new Launcher().createCompiler();
comp.addInputSources(files);
comp.build();
Factory factory = comp.getFactory();
CtType<?> theClass = factory.Type().get("spoon.test.prettyprinter.NestedSuperCall");
assertTrue(theClass.toString().contains("nc.super(\"a\")"));
}
use of spoon.SpoonModelBuilder in project spoon by INRIA.
the class DefaultPrettyPrinterTest method autoImportUsesFullyQualifiedNameWhenImportedNameAlreadyPresent.
@Test
public void autoImportUsesFullyQualifiedNameWhenImportedNameAlreadyPresent() throws Exception {
final Launcher launcher = new Launcher();
final Factory factory = launcher.getFactory();
factory.getEnvironment().setAutoImports(true);
final SpoonModelBuilder compiler = launcher.createCompiler();
compiler.addInputSource(new File("./src/test/java/spoon/test/prettyprinter/testclasses/sub/TypeIdentifierCollision.java"));
compiler.addInputSource(new File("./src/test/java/spoon/test/prettyprinter/testclasses/TypeIdentifierCollision.java"));
compiler.build();
final CtClass<?> aClass = (CtClass<?>) factory.Type().get(spoon.test.prettyprinter.testclasses.TypeIdentifierCollision.class);
String expected = "public void setFieldUsingExternallyDefinedEnumWithSameNameAsLocal() {" + nl + " localField = spoon.test.prettyprinter.testclasses.sub.TypeIdentifierCollision.ENUM.E1.ordinal();" + nl + "}";
String computed = aClass.getMethodsByName("setFieldUsingExternallyDefinedEnumWithSameNameAsLocal").get(0).toString();
assertEquals("We use FQN for E1", expected, computed);
// This is correct however it could be more concise.
expected = "public void setFieldUsingLocallyDefinedEnum() {" + nl + " localField = TypeIdentifierCollision.ENUM.E1.ordinal();" + nl + "}";
computed = aClass.getMethodsByName("setFieldUsingLocallyDefinedEnum").get(0).toString();
assertEquals(expected, computed);
expected = "public void setFieldOfClassWithSameNameAsTheCompilationUnitClass() {" + nl + " spoon.test.prettyprinter.testclasses.sub.TypeIdentifierCollision.globalField = localField;" + nl + "}";
computed = aClass.getMethodsByName("setFieldOfClassWithSameNameAsTheCompilationUnitClass").get(0).toString();
assertEquals("The static field of an external type with the same identifier as the compilation unit is printed with FQN", expected, computed);
// This is correct however it could be more concise.
expected = "public void referToTwoInnerClassesWithTheSameName() {" + nl + " TypeIdentifierCollision.Class0.ClassA.VAR0 = TypeIdentifierCollision.Class0.ClassA.getNum();" + nl + " TypeIdentifierCollision.Class1.ClassA.VAR1 = TypeIdentifierCollision.Class1.ClassA.getNum();" + nl + "}";
// Ensure the ClassA of Class0 takes precedence over an import statement for ClassA in Class1, and it's identifier can be the short version.
computed = aClass.getMethodsByName("referToTwoInnerClassesWithTheSameName").get(0).toString();
assertEquals("where inner types have the same identifier only one may be shortened and the other should be fully qualified", expected, computed);
expected = "public enum ENUM {" + nl + " E1(spoon.test.prettyprinter.testclasses.sub.TypeIdentifierCollision.globalField,spoon.test.prettyprinter.testclasses.sub.TypeIdentifierCollision.ENUM.E1);" + nl + " final int NUM;" + nl + nl + " final Enum<?> e;" + nl + nl + " private ENUM(int num, Enum<?> e) {" + nl + " NUM = num;" + nl + " this.e = e;" + nl + " }" + nl + "}";
computed = aClass.getNestedType("ENUM").toString();
assertEquals(expected, computed);
}
Aggregations