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()); } } }
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()); } } }
@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()); }
@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()); }
@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()); }
@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(); }
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 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); }
@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; }
protected void generateProcessedSourceFilesUsingCUs() { factory.getEnvironment().debugMessage("Generating source using compilation units..."); // Check output directory if (outputDirectory == null) { throw new RuntimeException("You should set output directory before generating source files"); } // Create spooned directory if (outputDirectory.isFile()) { throw new RuntimeException("Output must be a directory"); } if (!outputDirectory.exists()) { if (!outputDirectory.mkdirs()) { throw new RuntimeException("Error creating output directory"); } } try { outputDirectory = outputDirectory.getCanonicalFile(); } catch (IOException e1) { throw new SpoonException(e1); } factory.getEnvironment().debugMessage("Generating source files to: " + outputDirectory); List<File> printedFiles = new ArrayList<File>(); for (spoon.reflect.cu.CompilationUnit cu : factory.CompilationUnit().getMap().values()) { factory .getEnvironment() .debugMessage("Generating source for compilation unit: " + cu.getFile()); CtType<?> element = cu.getMainType(); CtPackage pack = element.getPackage(); // create package directory File packageDir; if (pack.getQualifiedName().equals(CtPackage.TOP_LEVEL_PACKAGE_NAME)) { packageDir = new File(outputDirectory.getAbsolutePath()); } else { // Create current package directory packageDir = new File( outputDirectory.getAbsolutePath() + File.separatorChar + pack.getQualifiedName().replace('.', File.separatorChar)); } if (!packageDir.exists()) { if (!packageDir.mkdirs()) { throw new RuntimeException("Error creating output directory"); } } // print type try { File file = new File( packageDir.getAbsolutePath() + File.separatorChar + element.getSimpleName() + DefaultJavaPrettyPrinter.JAVA_FILE_EXTENSION); file.createNewFile(); // the path must be given relatively to to the working directory InputStream is = getCompilationUnitInputStream(cu.getFile().getPath()); IOUtils.copy(is, new FileOutputStream(file)); if (!printedFiles.contains(file)) { printedFiles.add(file); } } catch (Exception e) { Launcher.LOGGER.error(e.getMessage(), e); } } }
@Test public void autoImportUsesFullyQualifiedNameWhenImportedNameAlreadyPresent() throws Exception { Factory factory = TestUtils.build( spoon.test.prettyprinter.testclasses.sub.TypeIdentifierCollision.class, spoon.test.prettyprinter.testclasses.TypeIdentifierCollision.class); factory.getEnvironment().setAutoImports(true); 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( "the externally defined enum should be fully qualified to avoid a name clash with the local enum of the same name", expected, computed); expected = // This is what is expected "public void setFieldUsingLocallyDefinedEnum() {" + nl + " localField = ENUM.E1.ordinal();" + nl + "}"; expected = // This is correct however it could be more concise. "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 should be fully qualified", expected, computed); expected = // This is what is expected "public void referToTwoInnerClassesWithTheSameName() {" + nl + " ClassA.VAR0 = ClassA.getNum();" + nl + " Class1.ClassA.VAR1 = Class1.ClassA.getNum();" + nl + "}"; expected = // This is correct however it could be more concise. "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 + " final Enum<?> e;" + nl + " private ENUM(int num ,Enum<?> e) {" + nl + " NUM = num;" + nl + " this.e = e;" + nl + " }}"; computed = aClass.getNestedType("ENUM").toString(); assertEquals( "Parameters in an enum constructor should be fully typed when they refer to externally defined static field of a class with the same identifier as another locally defined type", expected, computed); }
@Override public void setFactory(Factory factory) { this.factory = factory; LOGGER.setLevel(factory.getEnvironment().getLevel()); }