protected void initInputClassLoader() { ClassLoader cl = Thread.currentThread().getContextClassLoader(); if (buildOnlyOutdatedFiles && getBinaryOutputDirectory() != null) { CompilerClassLoader ccl = getCompilerClassLoader(cl); if (ccl == null) { try { Launcher.LOGGER.debug( "setting classloader for " + getBinaryOutputDirectory().toURI().toURL()); Thread.currentThread() .setContextClassLoader( new CompilerClassLoader( new URL[] {getBinaryOutputDirectory().toURI().toURL()}, factory.getEnvironment().getInputClassLoader())); } catch (Exception e) { Launcher.LOGGER.error(e.getMessage(), e); } } } else { if (!hasClassLoader( Thread.currentThread().getContextClassLoader(), factory.getEnvironment().getInputClassLoader())) { Thread.currentThread() .setContextClassLoader(factory.getEnvironment().getInputClassLoader()); } } }
private ITypeModel processTypeReference(CtTypeReference<?> typeReference) { String qualifiedName = typeReference.getQualifiedName(); ITypeModel existingType = registry.getType(qualifiedName); if (existingType != null) { return new ProxyType(registry, qualifiedName); } CtClass<Object> ctClass = factory.Class().get(qualifiedName); if (ctClass != null) { return processType(ctClass); } CtType<Object> ctType = factory.Type().get(qualifiedName); if (ctType != null) { return processType(ctType); } TypeModel type = new TypeModel(); type.setFullyQualifiedName(qualifiedName); registry.registerType(type); fillReference(type, typeReference); Collection<CtExecutableReference<?>> methods = typeReference.getDeclaredExecutables(); for (CtExecutableReference<?> m : methods) { IMethodModel methodModel = processMethodReference(m); type.addMethod(methodModel); } Collection<CtFieldReference<?>> fields = typeReference.getDeclaredFields(); for (CtFieldReference<?> m : fields) { IFieldModel methodModel = processFieldReference(m); type.addField(methodModel); } return new ProxyType(registry, qualifiedName); }
@Test public void testPrintAMethodWithGeneric() throws Exception { final Launcher launcher = new Launcher(); final Factory factory = launcher.getFactory(); factory.getEnvironment().setAutoImports(true); final SpoonCompiler compiler = launcher.createCompiler(); compiler.addInputSource(new File("./src/test/java/spoon/test/prettyprinter/testclasses/")); compiler.build(); final CtClass<?> aClass = (CtClass<?>) factory.Type().get(AClass.class); final String expected = "public List<? extends ArrayList> aMethodWithGeneric() {" + System.lineSeparator() + " return new ArrayList<>();" + System.lineSeparator() + "}"; assertEquals(expected, aClass.getMethodsByName("aMethodWithGeneric").get(0).toString()); final CtConstructorCall<?> constructorCall = aClass.getElements(new TypeFilter<CtConstructorCall<?>>(CtConstructorCall.class)).get(0); final CtTypeReference<?> ctTypeReference = constructorCall.getType().getActualTypeArguments().get(0); assertTrue(ctTypeReference instanceof CtImplicitTypeReference); assertEquals("Object", ctTypeReference.getSimpleName()); }
protected Map<Statement, Double> buildCodeFragmentFor(CtType cl, Coverage coverage) { Factory factory = cl.getFactory(); Map<Statement, Double> codeFragments = new LinkedHashMap<>(); for (CtMethod<?> mth : (Set<CtMethod>) cl.getMethods()) { if (!mth.getModifiers().contains(ModifierKind.ABSTRACT) && !mth.getModifiers().contains(ModifierKind.PRIVATE)) { // && getCoverageForMethod(coverage, cl, mth) != 1.0) { CtExecutableReference executableRef = factory.Executable().createReference(mth); executableRef.setStatic(mth.getModifiers().contains(ModifierKind.STATIC)); CtInvocation invocation = factory.Code().createInvocation(buildVarRef(cl.getReference(), factory), executableRef); invocation.setArguments( mth.getParameters() .stream() .map(param -> buildVarRef(param.getType(), factory)) .collect(Collectors.toList())); invocation.setType(mth.getType()); Statement stmt = new Statement(invocation); codeFragments.put(stmt, getCoverageForMethod(coverage, cl, mth)); } } return codeFragments; }
@Test public void printerCanPrintInvocationWithoutException() throws Exception { String packageName = "spoon.test.subclass.prettyprinter"; String className = "DefaultPrettyPrinterExample"; String qualifiedName = packageName + "." + className; SpoonCompiler 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()); }
/** return all executables of this class */ public static Collection<CtExecutableReference<?>> getAllExecutables( Class<?> clazz, Factory factory) { Collection<CtExecutableReference<?>> l = new ArrayList<CtExecutableReference<?>>(); for (Method m : clazz.getDeclaredMethods()) { l.add(factory.Method().createReference(m)); } for (Constructor<?> c : clazz.getDeclaredConstructors()) { l.add(factory.Constructor().createReference(c)); } return l; }
@Test public void testClone() throws Exception { final Factory factory = build(Adobada.class); final CtClass<Adobada> adobada = factory.Class().get(Adobada.class); final CtMethod<?> m2 = adobada.getMethod("m2"); CtMethod<?> clone = m2.clone(); clone.setVisibility(ModifierKind.PRIVATE); assertEquals(ModifierKind.PUBLIC, m2.getModifiers().iterator().next()); }
protected CtVariableRead buildVarRef(CtTypeReference type, Factory factory) { CtTypeReference<Object> typeRef = factory.Core().clone(type); CtLocalVariable<Object> localVar = factory.Core().createLocalVariable(); localVar.setType(typeRef); localVar.setSimpleName("var_" + type.getSimpleName() + "_" + System.currentTimeMillis()); CtVariableReadImpl varRead = new CtVariableReadImpl(); varRead.setVariable(factory.Code().createLocalVariableReference(localVar)); return varRead; }
protected void generateProcessedSourceFilesUsingTypes(Filter<CtType<?>> typeFilter) { if (factory.getEnvironment().getDefaultFileGenerator() != null) { factory.getEnvironment().debugMessage("Generating source using types..."); ProcessingManager processing = new QueueProcessingManager(factory); processing.addProcessor(factory.getEnvironment().getDefaultFileGenerator()); if (typeFilter != null) { processing.process(Query.getElements(factory.Package().getRootPackage(), typeFilter)); } else { processing.process(factory.Package().getRootPackage()); } } }
@Override public void instantiateAndProcess(List<String> processors) { initInputClassLoader(); // processing (consume all the processors) ProcessingManager processing = new QueueProcessingManager(factory); for (String processorName : processors) { processing.addProcessor(processorName); factory.getEnvironment().debugMessage("Loaded processor " + processorName + "."); } processing.process(factory.Package().getRootPackage()); }
@Override public void process(Collection<Processor<? extends CtElement>> processors) { initInputClassLoader(); // processing (consume all the processors) ProcessingManager processing = new QueueProcessingManager(factory); for (Processor<? extends CtElement> processorName : processors) { processing.addProcessor(processorName); factory.getEnvironment().debugMessage("Loaded processor " + processorName + "."); } processing.process(factory.Package().getRootPackage()); }
protected InputStream getCompilationUnitInputStream(String path) { Environment env = factory.getEnvironment(); spoon.reflect.cu.CompilationUnit cu = factory.CompilationUnit().getMap().get(path); List<CtType<?>> toBePrinted = cu.getDeclaredTypes(); PrettyPrinter printer = null; if (printer == null) { printer = new DefaultJavaPrettyPrinter(env); } printer.calculate(cu, toBePrinted); return new ByteArrayInputStream(printer.getResult().toString().getBytes()); }
@Test public void testConstructorCallFactory() throws Exception { CtTypeReference<ArrayList> ctTypeReference = factory.Code().createCtTypeReference(ArrayList.class); CtConstructorCall<ArrayList> constructorCall = factory.Code().createConstructorCall(ctTypeReference); assertEquals("new java.util.ArrayList()", constructorCall.toString()); CtConstructorCall<ArrayList> constructorCallWithParameter = factory.Code().createConstructorCall(ctTypeReference, constructorCall); assertEquals( "new java.util.ArrayList(new java.util.ArrayList())", constructorCallWithParameter.toString()); }
/** Gets all the field references for a given class (including the superclasses'). */ public static Collection<CtFieldReference<?>> getAllFields(Class<?> c, Factory factory) { Collection<CtFieldReference<?>> l = new ArrayList<CtFieldReference<?>>(); for (Field f : getAllFields(c)) { l.add(factory.Field().createReference(f)); } return l; }
@Test public void testBasicAPIUsage() throws Exception { // this test shows a basic usage of the Launcher API without command line // and asserts there is no exception SpoonAPI spoon = new Launcher(); spoon.addInputResource("src/test/resources/spoon/test/api"); spoon.setSourceOutputDirectory("target/spooned"); spoon.run(); Factory factory = spoon.getFactory(); for (CtPackage p : factory.Package().getAll()) { spoon.getEnvironment().debugMessage("package: " + p.getQualifiedName()); } for (CtType<?> s : factory.Class().getAll()) { spoon.getEnvironment().debugMessage("class: " + s.getQualifiedName()); } }
@Test public void useFullyQualifiedNamesInCtElementImpl_toString() throws Exception { Factory factory = TestUtils.build(AClass.class); factory.getEnvironment().setAutoImports(false); final CtClass<?> aClass = (CtClass<?>) factory.Type().get(AClass.class); String computed = aClass.getMethodsByName("aMethod").get(0).toString(); final String expected = "public java.util.List<?> aMethod() {" + nl + " return new java.util.ArrayList<>();" + nl + "}"; assertEquals( "the toString method of CtElementImpl should not shorten type names as it has no context or import statements", expected, computed); }
@Test public void testAccessToStringOnPostIncrement() throws Exception { // contract: a target to a post increment on a variable access write brackets. Factory factory = createFactory(); CtClass<?> clazz = factory.Code() .createCodeSnippetStatement( // "class X {" // + "public void foo() {" // + " Integer i = 1;" // + " (i++).toString();" // + " int k = 0;" // + " k++;" // + "}};") .compile(); CtMethod<?> foo = (CtMethod<?>) clazz.getMethods().toArray()[0]; assertEquals("(i++).toString()", foo.getBody().getStatement(1).toString()); assertEquals("k++", foo.getBody().getStatement(3).toString()); }
@Test public void testAddSameMethodsTwoTimes() throws Exception { final Factory factory = createFactory(); final CtClass<Object> tacos = factory.Class().create("Tacos"); final CtMethod<Void> method = factory.Method() .create( tacos, new HashSet<>(), factory.Type().voidType(), "m", new ArrayList<>(), new HashSet<>()); try { tacos.addMethod(method.clone()); } catch (ConcurrentModificationException e) { fail(); } }
@Test public void testTransformationOnConstructorWithInsertBegin() throws Exception { final CtConstructor<?> ctConstructor = aClass.getElements(new TypeFilter<CtConstructor<?>>(CtConstructor.class)).get(0); ctConstructor.getBody().insertBegin(factory.Code().createCodeSnippetStatement("int i = 0")); assertEquals(2, ctConstructor.getBody().getStatements().size()); assertEquals("super()", ctConstructor.getBody().getStatement(0).toString()); TestUtils.canBeBuilt("./target/spooned/spoon/test/constructor/testclasses/", 8); }
@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()); SpoonCompiler 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\")")); }
@Override public CtElement[] getMutatedEntries(CtBinaryOperator<?> element, Factory factory) { ArrayList<CtElement> ret = new ArrayList<CtElement>(); if (element == null) return emptySet(); for (BinaryOperatorKind kind : operators) { if (element.getKind() != kind) { CtExpression<?> right_c = factory.Core().clone(element.getRightHandOperand()); CtExpression<?> left_c = factory.Core().clone(element.getLeftHandOperand()); CtBinaryOperator<?> binaryOp = factory.Code().createBinaryOperator(left_c, right_c, kind); // Set parent right_c.setParent(binaryOp); left_c.setParent(binaryOp); ret.add(binaryOp); } } return ret.toArray(new CtElement[1]); }
@Before public void setUp() throws Exception { SpoonAPI launcher = new Launcher(); launcher.run( new String[] { "-i", "./src/test/java/spoon/test/constructor/testclasses/", "-o", "./target/spooned/" }); factory = launcher.getFactory(); aClass = factory.Class().get(Tacos.class); }
@Test public void callParamConstructor() throws Exception { CtClass<Object> aClass = factory.Class().get(AClass.class); CtConstructor<Object> constructor = aClass.getConstructors().iterator().next(); assertEquals( "{" + System.lineSeparator() + " enclosingInstance.super();" + System.lineSeparator() + "}", constructor.getBody().toString()); }
@Before public void setUp() throws Exception { final File testDirectory = new File("./src/test/java/spoon/test/interfaces/testclasses/"); final Launcher launcher = new Launcher(); this.factory = launcher.createFactory(); factory.getEnvironment().setComplianceLevel(8); SpoonCompiler compiler = launcher.createCompiler(this.factory); compiler.addInputSource(testDirectory); compiler.build(); }
public CtStatement apply(CtType<?> targetType) { CtClass<?> c; Factory factory; // we first need a factory if (targetType != null) { // if it's template with reference replacement factory = targetType.getFactory(); } else { // else we have at least one template parameter with a factory factory = getFactory(); } c = factory.Class().get(this.getClass()); if (c == null) { c = factory.Class().get(this.getClass()); } // we substitute the first statement of method statement CtStatement result = factory.Core().clone(c.getMethod("statement").getBody().getStatements().get(0)); new SubstitutionVisitor(factory, targetType, this).scan(result); return result; }
@Test public void testTransformationOnConstructorWithInsertBefore() throws Exception { final CtConstructor<?> ctConstructor = aClass.getElements(new TypeFilter<CtConstructor<?>>(CtConstructor.class)).get(0); try { ctConstructor .getBody() .getStatement(0) .insertBefore(factory.Code().createCodeSnippetStatement("int i = 0")); fail(); } catch (RuntimeException ignore) { } assertEquals(1, ctConstructor.getBody().getStatements().size()); assertEquals("super()", ctConstructor.getBody().getStatement(0).toString()); }
@Test public void testDefaultMethodInInterface() throws Exception { final CtInterface<?> ctInterface = (CtInterface<?>) factory.Type().get(InterfaceWithDefaultMethods.class); final CtMethod<?> ctMethod = ctInterface.getMethodsByName("getZonedDateTime").get(0); assertTrue("The method in the interface must to be default", ctMethod.isDefaultMethod()); final String expected = "default java.time.ZonedDateTime getZonedDateTime(java.lang.String zoneString) {" + System.lineSeparator() + " return java.time.ZonedDateTime.of(getLocalDateTime(), spoon.test.interfaces.testclasses.InterfaceWithDefaultMethods.getZoneId(zoneString));" + System.lineSeparator() + "}"; assertEquals("The default method must to be well printed", expected, ctMethod.toString()); }
@Test public void testRedefinesStaticMethodInSubInterface() throws Exception { final CtInterface<?> ctInterface = (CtInterface<?>) factory.Type().get(RedefinesStaticMethodInterface.class); assertEquals( "Sub interface must have only one method in its interface", 1, ctInterface.getMethods().size()); assertEquals( "Sub interface must have 6+12(from java.lang.Object) methods in its interface and its super interfaces", 18, ctInterface.getAllMethods().size()); final CtMethod<?> getZoneIdMethod = ctInterface.getMethodsByName("getZoneId").get(0); assertFalse( "Method in the sub interface mustn't be a static method", getZoneIdMethod.getModifiers().contains(ModifierKind.STATIC)); assertEquals( "Interface of the static method must be the sub interface", RedefinesStaticMethodInterface.class, getZoneIdMethod.getDeclaringType().getActualClass()); }
@Test public void testRedefinesDefaultMethodInSubInterface() throws Exception { final CtInterface<?> ctInterface = (CtInterface<?>) factory.Type().get(RedefinesDefaultMethodInterface.class); assertEquals( "Sub interface must have only one method in its interface", 1, ctInterface.getMethods().size()); assertEquals( "Sub interface must have 6+12(from java.lang.Object) methods in its interface and its super interfaces", 18, ctInterface.getAllMethods().size()); final CtMethod<?> getZonedDateTimeMethod = ctInterface.getMethodsByName("getZonedDateTime").get(0); assertFalse( "Method in the sub interface mustn't be a default method", getZonedDateTimeMethod.isDefaultMethod()); assertEquals( "Interface of the default method must be the sub interface", RedefinesDefaultMethodInterface.class, getZonedDateTimeMethod.getDeclaringType().getActualClass()); }
@Override public boolean compileInputSources() { initInputClassLoader(); factory.getEnvironment().debugMessage("compiling input sources: " + sources.getAllJavaFiles()); long t = System.currentTimeMillis(); javaCompliance = factory.getEnvironment().getComplianceLevel(); Main batchCompiler = createBatchCompiler(false); List<String> args = new ArrayList<String>(); args.add("-1." + javaCompliance); if (encoding != null) { args.add("-encoding"); args.add(encoding); } args.add("-preserveAllLocals"); args.add("-enableJavadoc"); args.add("-noExit"); args.add("-proc:none"); if (getBinaryOutputDirectory() != null) { args.add("-d"); args.add(getBinaryOutputDirectory().getAbsolutePath()); } else { args.add("-d"); args.add("none"); } String finalClassPath = null; if (getSourceClasspath() != null) { finalClassPath = computeJdtClassPath(); } else { ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); if (currentClassLoader instanceof URLClassLoader) { URL[] urls = ((URLClassLoader) currentClassLoader).getURLs(); if (urls != null && urls.length > 0) { String classpath = "."; for (URL url : urls) { classpath += File.pathSeparator + url.getFile(); } if (classpath != null) { finalClassPath = classpath; } } } } args.add("-cp"); args.add(finalClassPath); // Set<String> paths = new HashSet<String>(); // for (SpoonFile file : sources.getAllJavaFiles()) { // paths.add(file.getParent().getPath()); // } // args.addAll(paths); args.addAll(toStringList(sources.getAllJavaFiles())); // configure(args.toArray(new String[0])); batchCompiler.compile(args.toArray(new String[0])); factory .getEnvironment() .debugMessage("compiled in " + (System.currentTimeMillis() - t) + " ms"); return probs.size() == 0; }