diff --git a/doc/command_line.md b/doc/command_line.md index cedc8aba886..0499e2d9d8f 100644 --- a/doc/command_line.md +++ b/doc/command_line.md @@ -89,21 +89,6 @@ Options : [--compile] Enable compilation and output class files. - [--precompile] - Enable pre-compilation of input source files before processing. Compiled - classes will be added to the classpath so that they are accessible to - the processing manager (typically, processors, annotations, and - templates should be pre-compiled most of the time). - - [--buildOnlyOutdatedFiles] - Set Spoon to build only the source files that have been modified since - the latest source code generation, for performance purpose. Note that - this option requires to have the --ouput-type option not set to none. - This option is not appropriate to all kinds of processing. In particular - processings that implement or rely on a global analysis should avoid - this option because the processor will only have access to the outdated - source code (the files modified since the latest processing). - [--lines] Set Spoon to try to preserve the original line numbers when generating the source code (may lead to human-unfriendly formatting). diff --git a/src/main/java/spoon/Launcher.java b/src/main/java/spoon/Launcher.java index d4ce5858e3d..a29b87ab2cc 100644 --- a/src/main/java/spoon/Launcher.java +++ b/src/main/java/spoon/Launcher.java @@ -347,8 +347,7 @@ protected static JSAP defineArgs() { // Enable pre-compilation sw1 = new Switch("precompile"); sw1.setLongFlag("precompile"); - sw1.setHelp("Enable pre-compilation of input source files " + "before processing. Compiled classes " + "will be added to the classpath so that " + "they are accessible to the processing " - + "manager (typically, processors, " + "annotations, and templates should be " + "pre-compiled most of the time)."); + sw1.setHelp("[experimental] Enable pre-compilation of input source files " + "before processing. The compiled classes " + "will be added to the classpath."); sw1.setDefault("false"); jsap.registerParameter(sw1); @@ -468,6 +467,11 @@ protected void processArguments() { } } + if (jsapActualArgs.getBoolean("precompile")) { + modelBuilder.compile(InputType.FILES); + getEnvironment().setSourceClasspath(new String[]{getEnvironment().getBinaryOutputDirectory()}); + } + if (getArguments().getFile("output") != null) { setSourceOutputDirectory(getArguments().getFile("output")); } @@ -570,10 +574,6 @@ public SpoonCompiler createCompiler(Factory factory) { env.debugMessage("source classpath: " + Arrays.toString(comp.getSourceClasspath())); env.debugMessage("template classpath: " + Arrays.toString(comp.getTemplateClasspath())); - if (jsapActualArgs.getBoolean("precompile")) { - comp.compile(InputType.FILES); - } - return comp; } diff --git a/src/main/java/spoon/support/QueueProcessingManager.java b/src/main/java/spoon/support/QueueProcessingManager.java index 6c19d69427c..1781141c8ea 100644 --- a/src/main/java/spoon/support/QueueProcessingManager.java +++ b/src/main/java/spoon/support/QueueProcessingManager.java @@ -74,9 +74,9 @@ public boolean addProcessor(Processor p) { @SuppressWarnings("unchecked") public void addProcessor(String qualifiedName) { try { - addProcessor((Class>) Thread.currentThread().getContextClassLoader().loadClass(qualifiedName)); + addProcessor((Class>) getFactory().getEnvironment().getClassLoader().loadClass(qualifiedName)); } catch (ClassNotFoundException e) { - throw new SpoonException("Unable to load processor \"" + qualifiedName + "\" - Check your classpath. Did you use the --precompile option?", e); + throw new SpoonException("Unable to load processor \"" + qualifiedName + "\" - Check your classpath.", e); } } diff --git a/src/main/java/spoon/support/RuntimeProcessingManager.java b/src/main/java/spoon/support/RuntimeProcessingManager.java index 0ca23a86522..254f8d1979c 100644 --- a/src/main/java/spoon/support/RuntimeProcessingManager.java +++ b/src/main/java/spoon/support/RuntimeProcessingManager.java @@ -76,9 +76,9 @@ public boolean addProcessor(Processor p) { @SuppressWarnings("unchecked") public void addProcessor(String qualifiedName) { try { - addProcessor((Class>) Thread.currentThread().getContextClassLoader().loadClass(qualifiedName)); + addProcessor((Class>) getFactory().getEnvironment().getClassLoader().loadClass(qualifiedName)); } catch (ClassNotFoundException e) { - factory.getEnvironment().report(null, Level.ERROR, "Unable to load processor \"" + qualifiedName + "\" - Check your classpath. Did you use the --precompile option?"); + factory.getEnvironment().report(null, Level.ERROR, "Unable to load processor \"" + qualifiedName + "\" - Check your classpath."); } } diff --git a/src/main/java/spoon/support/compiler/jdt/FileCompiler.java b/src/main/java/spoon/support/compiler/jdt/FileCompiler.java index b5f906fafa5..24068d8dd3f 100644 --- a/src/main/java/spoon/support/compiler/jdt/FileCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/FileCompiler.java @@ -16,15 +16,14 @@ */ package spoon.support.compiler.jdt; -import java.util.ArrayList; -import java.util.List; - import org.apache.commons.io.IOUtils; import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; - import spoon.SpoonException; import spoon.compiler.SpoonFile; +import java.util.ArrayList; +import java.util.List; + public class FileCompiler extends JDTBatchCompiler { public FileCompiler(JDTBasedSpoonCompiler jdtCompiler) { diff --git a/src/test/java/spoon/test/comment/CommentTest.java b/src/test/java/spoon/test/comment/CommentTest.java index b248ab679a1..ab45db20f41 100644 --- a/src/test/java/spoon/test/comment/CommentTest.java +++ b/src/test/java/spoon/test/comment/CommentTest.java @@ -31,6 +31,7 @@ import spoon.reflect.factory.Factory; import spoon.reflect.factory.FactoryImpl; import spoon.reflect.visitor.filter.AbstractFilter; +import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.filter.TypeFilter; import spoon.support.DefaultCoreFactory; import spoon.support.StandardEnvironment; @@ -47,6 +48,7 @@ import static org.apache.commons.io.IOUtils.write; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; public class CommentTest { diff --git a/src/test/java/spoon/test/compilation/CompilationTest.java b/src/test/java/spoon/test/compilation/CompilationTest.java index ad979905224..f53db2e8968 100644 --- a/src/test/java/spoon/test/compilation/CompilationTest.java +++ b/src/test/java/spoon/test/compilation/CompilationTest.java @@ -16,9 +16,11 @@ import spoon.reflect.factory.CodeFactory; import spoon.reflect.factory.CoreFactory; import spoon.reflect.factory.Factory; +import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.filter.TypeFilter; import spoon.support.compiler.jdt.FileCompiler; import spoon.support.compiler.jdt.JDTBasedSpoonCompiler; +import spoon.support.reflect.reference.SpoonClassNotFoundException; import spoon.test.compilation.testclasses.Bar; import spoon.test.compilation.testclasses.IBar; import spoon.testing.utils.ModelUtils; @@ -31,6 +33,7 @@ import java.util.List; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -229,4 +232,34 @@ public CompilationUnit[] getCompilationUnits() { } + @Test + public void testPrecompile() { + // without precompile + Launcher l = new Launcher(); + l.setArgs(new String[] {"--noclasspath", "-i", "src/test/resources/compilation/"}); + l.buildModel(); + CtClass klass = l.getFactory().Class().get("compilation.Bar"); + // without precompile, actualClass does not exist (an exception is thrown) + try { + klass.getSuperInterfaces().toArray(new CtTypeReference[0])[0].getActualClass(); + fail(); + } catch (SpoonClassNotFoundException ignore) {} + + // with precompile + Launcher l2 = new Launcher(); + l2.setArgs(new String[] {"--precompile", "--noclasspath", "-i", "src/test/resources/compilation/"}); + l2.buildModel(); + CtClass klass2 = l2.getFactory().Class().get("compilation.Bar"); + // with precompile, actualClass is not null + Class actualClass = klass2.getSuperInterfaces().toArray(new CtTypeReference[0])[0].getActualClass(); + assertNotNull(actualClass); + assertEquals("IBar", actualClass.getSimpleName()); + + // precompile can be used to compile processors on the fly + Launcher l3 = new Launcher(); + l3.setArgs(new String[] {"--precompile", "--noclasspath", "-i", "src/test/resources/compilation/", "-p", "compilation.SimpleProcessor"}); + l3.run(); + } + + } diff --git a/src/test/resources/compilation/SimpleProcessor.java b/src/test/resources/compilation/SimpleProcessor.java new file mode 100644 index 00000000000..46cb1c43f14 --- /dev/null +++ b/src/test/resources/compilation/SimpleProcessor.java @@ -0,0 +1,18 @@ +package compilation; + +import spoon.processing.AbstractProcessor; +import spoon.reflect.declaration.CtType; + +/** + * Simple Processor to demonstrate --precompile issue + * + * @author Michael Stocker + * @since 0.1.0 + */ +public class SimpleProcessor extends AbstractProcessor> { + + @Override + public void process(CtType element) { + System.out.println(">> Hello: " + element.getSimpleName() + " <<"); + } +} diff --git a/src/test/resources/compilation/compilation-tests/Bar.java b/src/test/resources/compilation/compilation-tests/Bar.java new file mode 100644 index 00000000000..b773deecf18 --- /dev/null +++ b/src/test/resources/compilation/compilation-tests/Bar.java @@ -0,0 +1,11 @@ +package compilation; + +public class Bar implements IBar { + + @Override + public int m() { + return 1; + } +} + +class FooEx extends RuntimeException {} diff --git a/src/test/resources/compilation/compilation-tests/IBar.java b/src/test/resources/compilation/compilation-tests/IBar.java new file mode 100644 index 00000000000..d8296927f67 --- /dev/null +++ b/src/test/resources/compilation/compilation-tests/IBar.java @@ -0,0 +1,8 @@ +package compilation; + +/** + * Created by thomas on 28/10/16. + */ +public interface IBar { + int m(); +}