diff --git a/src/main/java/spoon/SpoonModelBuilder.java b/src/main/java/spoon/SpoonModelBuilder.java index 45bdeeee7fb..7228e263ca0 100644 --- a/src/main/java/spoon/SpoonModelBuilder.java +++ b/src/main/java/spoon/SpoonModelBuilder.java @@ -23,6 +23,9 @@ import spoon.reflect.declaration.CtType; import spoon.reflect.factory.Factory; import spoon.reflect.visitor.Filter; +import spoon.support.compiler.jdt.FactoryCompilerConfig; +import spoon.support.compiler.jdt.FileCompilerConfig; +import spoon.support.compiler.jdt.JDTBatchCompiler; import java.io.File; import java.util.Collection; @@ -76,9 +79,17 @@ public interface SpoonModelBuilder { */ boolean build(JDTBuilder builder); - /** The types of compilable elements */ - enum InputType { - FILES, CTTYPES + /** The types of compilable elements + * FILES - compiles the java files from the file system, which were registered by {@see SpoonModelBuilder#addInputSource()} and {@see SpoonModelBuilder#addTemplateSource(File)} + * CTTYPES - compiles virtual java files, which are dynamically generated from the all top level classes of the CtModel by {@see DefaultJavaPrettyPrinter} + */ + interface InputType { + InputType FILES = FileCompilerConfig.INSTANCE; + InputType CTTYPES = FactoryCompilerConfig.INSTANCE; + /** + * responsible for setting the parameters of JDTBatchCompiler, must call setCompilationUnits() + */ + void initializeCompiler(JDTBatchCompiler compiler); } diff --git a/src/main/java/spoon/support/compiler/jdt/FactoryCompiler.java b/src/main/java/spoon/support/compiler/jdt/FactoryCompilerConfig.java similarity index 67% rename from src/main/java/spoon/support/compiler/jdt/FactoryCompiler.java rename to src/main/java/spoon/support/compiler/jdt/FactoryCompilerConfig.java index b07160350eb..5f92daa0f79 100644 --- a/src/main/java/spoon/support/compiler/jdt/FactoryCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/FactoryCompilerConfig.java @@ -21,27 +21,29 @@ import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; +import spoon.SpoonModelBuilder; import spoon.reflect.declaration.CtType; -class FactoryCompiler extends JDTBatchCompiler { +public class FactoryCompilerConfig implements SpoonModelBuilder.InputType { - FactoryCompiler(JDTBasedSpoonCompiler jdtCompiler) { - super(jdtCompiler); - } + public static final SpoonModelBuilder.InputType INSTANCE = new FactoryCompilerConfig(); + + //avoid direct instantiation. But somebody can inherit + protected FactoryCompilerConfig() { + }; /** * returns the compilation units corresponding to the types in the factory. */ @Override - public CompilationUnit[] getCompilationUnits() { - // gets the one that are in factory (when compiling the model to bytecode ) - List unitList = new ArrayList(); + public void initializeCompiler(JDTBatchCompiler compiler) { + JDTBasedSpoonCompiler jdtCompiler = compiler.getJdtCompiler(); + List unitList = new ArrayList<>(); for (CtType ctType : jdtCompiler.getFactory().Type().getAll()) { if (ctType.isTopLevel()) { unitList.add(new CompilationUnitWrapper(ctType)); } } - return unitList.toArray(new CompilationUnit[unitList.size()]); + compiler.setCompilationUnits(unitList.toArray(new CompilationUnit[unitList.size()])); } - } diff --git a/src/main/java/spoon/support/compiler/jdt/FileCompiler.java b/src/main/java/spoon/support/compiler/jdt/FileCompiler.java deleted file mode 100644 index 24068d8dd3f..00000000000 --- a/src/main/java/spoon/support/compiler/jdt/FileCompiler.java +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Copyright (C) 2006-2016 INRIA and contributors - * Spoon - http://spoon.gforge.inria.fr/ - * - * This software is governed by the CeCILL-C License under French law and - * abiding by the rules of distribution of free software. You can use, modify - * and/or redistribute the software under the terms of the CeCILL-C license as - * circulated by CEA, CNRS and INRIA at http://www.cecill.info. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. - * - * The fact that you are presently reading this means that you have had - * knowledge of the CeCILL-C license and that you accept its terms. - */ -package spoon.support.compiler.jdt; - -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) { - super(jdtCompiler); - } - - /** - * returns the compilation units corresponding to the types in the factory. - */ - @Override - public CompilationUnit[] getCompilationUnits() { - List files = new ArrayList<>(); - files.addAll(jdtCompiler.sources.getAllJavaFiles()); - files.addAll(jdtCompiler.templates.getAllJavaFiles()); - List culist = new ArrayList<>(); - for (SpoonFile f : files) { - if (filesToBeIgnored.contains(f.getPath())) { - continue; - } - try { - String fName = ""; - if (f.isActualFile()) { - fName = f.getPath(); - } else { - fName = f.getName(); - } - culist.add(new CompilationUnit(IOUtils.toCharArray(f - .getContent()), fName, null)); - } catch (Exception e) { - throw new SpoonException(e); - } - } - return culist.toArray(new CompilationUnit[0]); - } - -} diff --git a/src/main/java/spoon/support/compiler/jdt/FileCompilerConfig.java b/src/main/java/spoon/support/compiler/jdt/FileCompilerConfig.java new file mode 100644 index 00000000000..72ac6f3a52d --- /dev/null +++ b/src/main/java/spoon/support/compiler/jdt/FileCompilerConfig.java @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2006-2016 INRIA and contributors + * Spoon - http://spoon.gforge.inria.fr/ + * + * This software is governed by the CeCILL-C License under French law and + * abiding by the rules of distribution of free software. You can use, modify + * and/or redistribute the software under the terms of the CeCILL-C license as + * circulated by CEA, CNRS and INRIA at http://www.cecill.info. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL-C License for more details. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL-C license and that you accept its terms. + */ +package spoon.support.compiler.jdt; + +import java.util.ArrayList; +import java.util.List; + +import spoon.SpoonException; +import spoon.SpoonModelBuilder; +import spoon.compiler.SpoonFile; +import spoon.compiler.SpoonFolder; + +import org.apache.commons.io.IOUtils; +import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; + +public class FileCompilerConfig implements SpoonModelBuilder.InputType { + + /** + * Default implementation of which initializes {@link JDTBatchCompiler} by all sources and templates registered in {@link SpoonModelBuilder} + */ + public static final SpoonModelBuilder.InputType INSTANCE = new FileCompilerConfig((List) null) { + @Override + public List getFiles(JDTBatchCompiler compiler) { + JDTBasedSpoonCompiler jdtCompiler = compiler.getJdtCompiler(); + List files = new ArrayList<>(); + files.addAll(jdtCompiler.sources.getAllJavaFiles()); + files.addAll(jdtCompiler.templates.getAllJavaFiles()); + return files; + } + }; + + private final List files; + + public FileCompilerConfig(List files) { + this.files = files; + } + + public FileCompilerConfig(SpoonFolder folder) { + this(folder.getAllJavaFiles()); + } + + @Override + public void initializeCompiler(JDTBatchCompiler compiler) { + JDTBasedSpoonCompiler jdtCompiler = compiler.getJdtCompiler(); + List culist = new ArrayList<>(); + for (SpoonFile f : getFiles(compiler)) { + if (compiler.filesToBeIgnored.contains(f.getPath())) { + continue; + } + try { + String fName = ""; + if (f.isActualFile()) { + fName = f.getPath(); + } else { + fName = f.getName(); + } + culist.add(new CompilationUnit(IOUtils.toCharArray(f + .getContent(), jdtCompiler.encoding), fName, null)); + } catch (Exception e) { + throw new SpoonException(e); + } + } + compiler.setCompilationUnits(culist.toArray(new CompilationUnit[0])); + } + + protected List getFiles(JDTBatchCompiler compiler) { + return files; + } +} diff --git a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java index 02c18f4a82b..903cfca8c95 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTBasedSpoonCompiler.java @@ -344,7 +344,7 @@ protected boolean buildSources(JDTBuilder jdtBuilder) { if (sources.getAllJavaFiles().isEmpty()) { return true; } - JDTBatchCompiler batchCompiler = createBatchCompiler(InputType.FILES); + JDTBatchCompiler batchCompiler = createBatchCompiler(new FileCompilerConfig(sources)); String[] args; if (jdtBuilder == null) { args = new JDTBuilderImpl() // @@ -376,13 +376,20 @@ protected boolean buildSources(JDTBuilder jdtBuilder) { return probs.size() == 0; } + protected JDTBatchCompiler createBatchCompiler() { + return new JDTBatchCompiler(this); + } + protected JDTBatchCompiler createBatchCompiler(InputType... types) { + JDTBatchCompiler batchCompiler = createBatchCompiler(); // backward compatible - if (types.length == 0 || types[0] == InputType.CTTYPES) { - return new FactoryCompiler(this); - } else { - return new FileCompiler(this); + if (types.length == 0) { + types = new InputType[]{InputType.CTTYPES}; + } + for (InputType inputType : types) { + inputType.initializeCompiler(batchCompiler); } + return batchCompiler; } protected boolean buildTemplates(JDTBuilder jdtBuilder) { @@ -390,7 +397,7 @@ protected boolean buildTemplates(JDTBuilder jdtBuilder) { return true; } - JDTBatchCompiler batchCompiler = createBatchCompiler(InputType.FILES); + JDTBatchCompiler batchCompiler = createBatchCompiler(new FileCompilerConfig(templates)); File f = null; String[] templateClasspath = new String[0]; diff --git a/src/main/java/spoon/support/compiler/jdt/JDTBatchCompiler.java b/src/main/java/spoon/support/compiler/jdt/JDTBatchCompiler.java index 177b129e984..a48a48607dd 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTBatchCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTBatchCompiler.java @@ -44,9 +44,10 @@ * * (we use a fully qualified name in inheritance to make it clear we are extending jdt) */ -abstract class JDTBatchCompiler extends org.eclipse.jdt.internal.compiler.batch.Main { +public class JDTBatchCompiler extends org.eclipse.jdt.internal.compiler.batch.Main { - protected JDTBasedSpoonCompiler jdtCompiler; + protected final JDTBasedSpoonCompiler jdtCompiler; + protected CompilationUnit[] compilationUnits; JDTBatchCompiler(JDTBasedSpoonCompiler jdtCompiler) { // by default we don't want anything from JDT @@ -63,9 +64,14 @@ abstract class JDTBatchCompiler extends org.eclipse.jdt.internal.compiler.batch. } } - /** we force this method of JDT to be re-implemented, see subclasses */ @Override - public abstract CompilationUnit[] getCompilationUnits(); + public CompilationUnit[] getCompilationUnits() { + return compilationUnits; + } + + public void setCompilationUnits(CompilationUnit[] compilationUnits) { + this.compilationUnits = compilationUnits; + } @Override public ICompilerRequestor getBatchRequestor() { @@ -136,4 +142,8 @@ this.jdtCompiler.requestor, getProblemFactory(), this.out, return result; } + public JDTBasedSpoonCompiler getJdtCompiler() { + return jdtCompiler; + } + } diff --git a/src/main/java/spoon/support/compiler/jdt/JDTSnippetCompiler.java b/src/main/java/spoon/support/compiler/jdt/JDTSnippetCompiler.java index 760fb71f8d8..5c611d54af1 100644 --- a/src/main/java/spoon/support/compiler/jdt/JDTSnippetCompiler.java +++ b/src/main/java/spoon/support/compiler/jdt/JDTSnippetCompiler.java @@ -86,7 +86,7 @@ protected boolean buildSources(JDTBuilder jdtBuilder) { if (sources.getAllJavaFiles().isEmpty()) { return true; } - JDTBatchCompiler batchCompiler = createBatchCompiler(InputType.FILES); + JDTBatchCompiler batchCompiler = createBatchCompiler(new FileCompilerConfig(sources)); File source = createTmpJavaFile(new File(".")); String[] args; diff --git a/src/test/java/spoon/support/compiler/jdt/ExtendedStringLiteralTest.java b/src/test/java/spoon/support/compiler/jdt/ExtendedStringLiteralTest.java index 060fc31ecca..fbc3c86a8cb 100644 --- a/src/test/java/spoon/support/compiler/jdt/ExtendedStringLiteralTest.java +++ b/src/test/java/spoon/support/compiler/jdt/ExtendedStringLiteralTest.java @@ -26,8 +26,8 @@ public void testExtendedStringLiteral() throws Exception { public SpoonCompiler createCompiler() { return new JDTBasedSpoonCompiler(getFactory()) { @Override - protected JDTBatchCompiler createBatchCompiler(InputType... types) { - return new FileCompiler(this) { + protected JDTBatchCompiler createBatchCompiler() { + return new JDTBatchCompiler(this) { @Override public CompilationUnitDeclaration[] getUnits(List files) { startTime = System.currentTimeMillis(); diff --git a/src/test/java/spoon/test/compilation/CompilationTest.java b/src/test/java/spoon/test/compilation/CompilationTest.java index ea6ea666513..7afdff9ec84 100644 --- a/src/test/java/spoon/test/compilation/CompilationTest.java +++ b/src/test/java/spoon/test/compilation/CompilationTest.java @@ -1,17 +1,14 @@ package spoon.test.compilation; -import org.eclipse.jdt.internal.compiler.batch.CompilationUnit; import org.junit.Assert; import org.junit.Test; import spoon.Launcher; -import spoon.compiler.SpoonCompiler; import spoon.reflect.code.BinaryOperatorKind; import spoon.reflect.code.CtBinaryOperator; import spoon.reflect.code.CtBlock; import spoon.reflect.code.CtReturn; import spoon.reflect.declaration.CtClass; import spoon.reflect.declaration.CtMethod; -import spoon.reflect.declaration.CtType; import spoon.reflect.declaration.ModifierKind; import spoon.reflect.factory.CodeFactory; import spoon.reflect.factory.CoreFactory; @@ -19,8 +16,6 @@ import spoon.reflect.reference.CtTypeReference; import spoon.reflect.visitor.CtScanner; 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; @@ -34,8 +29,8 @@ 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.assertNotNull; import static org.junit.Assert.fail; public class CompilationTest { @@ -158,7 +153,7 @@ public void testNewInstance() throws Exception { } } - +/* @Test public void testFilterResourcesFile() throws Exception { // shows how to filter input java files, for https://github.com/INRIA/spoon/issues/877 @@ -232,7 +227,7 @@ public CompilationUnit[] getCompilationUnits() { } } - + */ @Test public void testPrecompile() { // without precompile diff --git a/src/test/java/spoon/test/pkg/PackageTest.java b/src/test/java/spoon/test/pkg/PackageTest.java index b1e8dc0fa1f..48af877f83f 100644 --- a/src/test/java/spoon/test/pkg/PackageTest.java +++ b/src/test/java/spoon/test/pkg/PackageTest.java @@ -4,6 +4,7 @@ import org.junit.Test; import spoon.Launcher; import spoon.OutputType; +import spoon.compiler.Environment; import spoon.compiler.SpoonCompiler; import spoon.compiler.SpoonResourceHelper; import spoon.reflect.code.CtComment; @@ -20,6 +21,7 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static spoon.testing.Assert.assertThat; +import static spoon.testing.utils.ModelUtils.canBeBuilt; public class PackageTest { @Test @@ -101,4 +103,20 @@ public void testPrintPackageInfoWhenNothingInPackage() throws Exception { assertThat(aPackage).isEqualTo(ModelUtils.build(new File("./target/spooned/package/spoon/test/pkg/testclasses/internal")).Package().get("spoon.test.pkg.testclasses.internal")); } + + @Test + public void testAnnotationInPackageInfoWhenTemplatesCompiled() throws Exception { + final Launcher launcher = new Launcher(); + Environment environment = launcher.getEnvironment(); + + environment.setAutoImports(true); + environment.setCommentEnabled(true); + launcher.addInputResource("./src/test/java/spoon/test/pkg/package-info.java"); + launcher.setSourceOutputDirectory("./target/spooned/packageAndTemplate"); +// SpoonResourceHelper.resources("./src/test/java/spoon/test/pkg/test_templates").forEach(r->launcher.addTemplateResource(r)); + launcher.addTemplateResource(SpoonResourceHelper.createResource(new File("./src/test/java/spoon/test/pkg/test_templates/FakeTemplate.java"))); + launcher.buildModel(); + launcher.prettyprint(); + canBeBuilt("./target/spooned/packageAndTemplate/spoon/test/pkg/package-info.java", 8); + } } diff --git a/src/test/java/spoon/test/pkg/test_templates/FakeTemplate.java b/src/test/java/spoon/test/pkg/test_templates/FakeTemplate.java new file mode 100644 index 00000000000..a78ca29a4de --- /dev/null +++ b/src/test/java/spoon/test/pkg/test_templates/FakeTemplate.java @@ -0,0 +1,10 @@ +package spoon.test.pkg.test_templates; + +import spoon.template.ExtensionTemplate; + +public class FakeTemplate extends ExtensionTemplate +{ + public FakeTemplate() + { + } +}