From 7a2121927ee441aea290f285ca4a9cffabe3fb90 Mon Sep 17 00:00:00 2001 From: Thomas Broyer Date: Sat, 11 Jul 2015 13:05:22 +0200 Subject: [PATCH] Support alternate JavaCompilers (such as ECJ) in CompilationRule ECJ expects all JavaFileObjects to be Files, so the rule no longer uses Compilation.compile() but instead directly uses the JavaCompiler, and processes a class rather than compiling a dummy (in-memory) source. --- pom.xml | 6 +++ .../testing/compile/CompilationRule.java | 44 +++++++++++++++---- .../compile/EclipseCompilationRuleTest.java | 21 +++++++++ 3 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 src/test/java/com/google/testing/compile/EclipseCompilationRuleTest.java diff --git a/pom.xml b/pom.xml index ce2b9f23..958a5346 100644 --- a/pom.xml +++ b/pom.xml @@ -72,6 +72,12 @@ ${jsr305.version} true + + org.eclipse.jdt.core.compiler + ecj + 4.4.2 + test + diff --git a/src/main/java/com/google/testing/compile/CompilationRule.java b/src/main/java/com/google/testing/compile/CompilationRule.java index 0be82843..9ac54565 100644 --- a/src/main/java/com/google/testing/compile/CompilationRule.java +++ b/src/main/java/com/google/testing/compile/CompilationRule.java @@ -17,9 +17,10 @@ import static com.google.common.base.Preconditions.checkState; +import com.google.common.base.Charsets; +import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; -import com.google.testing.compile.Compilation.Result; import org.junit.Rule; import org.junit.rules.TestRule; @@ -37,26 +38,55 @@ import javax.lang.model.element.TypeElement; import javax.lang.model.util.Elements; import javax.lang.model.util.Types; +import javax.tools.DiagnosticCollector; +import javax.tools.JavaCompiler; +import javax.tools.JavaCompiler.CompilationTask; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.ToolProvider; /** - * A {@link JUnit4} {@link Rule} that executes tests such that a instances of {@link Elements} and + * A {@link JUnit4} {@link Rule} that executes tests such that instances of {@link Elements} and * {@link Types} are available during execution. * *

To use this rule in a test, just add the following field:


  *   {@code @Rule} public CompilationRule compilationRule = new CompilationRule();
* + *

This rule uses {@link ToolProvider#getSystemJavaCompiler() javac} by default, but you can + * also pass a supplier of {@link JavaCompiler} to use other compilers, such as Eclipse ECJ. + * * @author Gregory Kick */ public final class CompilationRule implements TestRule { + private final Supplier compilerSupplier; + private Elements elements; private Types types; + public CompilationRule() { + this(new Supplier() { + @Override + public JavaCompiler get() { + return ToolProvider.getSystemJavaCompiler(); + } + }); + } + + public CompilationRule(Supplier compilerSupplier) { + this.compilerSupplier = compilerSupplier; + } + @Override public Statement apply(final Statement base, Description description) { return new Statement() { @Override public void evaluate() throws Throwable { final AtomicReference thrown = new AtomicReference(); - Result result = Compilation.compile(ImmutableList.of(new AbstractProcessor() { + JavaCompiler compiler = compilerSupplier.get(); + DiagnosticCollector diagnosticCollector = new DiagnosticCollector(); + JavaFileManager fileManager = compiler.getStandardFileManager(diagnosticCollector, null, Charsets.UTF_8); + CompilationTask task = compiler.getTask(null, fileManager, diagnosticCollector, null, + ImmutableSet.of(CompilationRule.class.getCanonicalName()), null); + task.setProcessors(ImmutableList.of(new AbstractProcessor() { @Override public SourceVersion getSupportedSourceVersion() { return SourceVersion.latest(); @@ -87,11 +117,9 @@ public boolean process(Set annotations, } return false; } - }), - ImmutableSet.of(), - // just compile _something_ - ImmutableList.of(JavaFileObjects.forSourceLines("Dummy", "final class Dummy {}"))); - checkState(result.successful(), result); + })); + boolean successful = task.call(); + checkState(successful); Throwable t = thrown.get(); if (t != null) { throw t; diff --git a/src/test/java/com/google/testing/compile/EclipseCompilationRuleTest.java b/src/test/java/com/google/testing/compile/EclipseCompilationRuleTest.java new file mode 100644 index 00000000..c7cadc2d --- /dev/null +++ b/src/test/java/com/google/testing/compile/EclipseCompilationRuleTest.java @@ -0,0 +1,21 @@ +package com.google.testing.compile; + +import javax.tools.JavaCompiler; + +import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +import com.google.common.base.Supplier; + +@RunWith(JUnit4.class) +public class EclipseCompilationRuleTest extends CompilationRuleTest { + { + compilationRule = new CompilationRule(new Supplier() { + @Override + public JavaCompiler get() { + return new EclipseCompiler(); + } + }); + } +}