From c09dd403cb883f0df464378b4e386508f36c41c8 Mon Sep 17 00:00:00 2001 From: DuyHai DOAN Date: Sat, 21 Nov 2015 22:26:10 +0100 Subject: [PATCH] Support alternate JavaCompilers (such as ECJ) in JavaSourcesSubject --- .../google/testing/compile/Compilation.java | 10 ++-- .../testing/compile/CompilationRule.java | 54 +++++++++---------- .../testing/compile/JavaSourcesSubject.java | 25 ++++++--- .../com/google/testing/compile/MoreTrees.java | 8 +-- .../ProcessedCompileTesterFactory.java | 7 ++- .../JavaSourcesSubjectFactoryTest.java | 10 ++++ 6 files changed, 71 insertions(+), 43 deletions(-) diff --git a/src/main/java/com/google/testing/compile/Compilation.java b/src/main/java/com/google/testing/compile/Compilation.java index cbb518b7..7bee3540 100644 --- a/src/main/java/com/google/testing/compile/Compilation.java +++ b/src/main/java/com/google/testing/compile/Compilation.java @@ -54,9 +54,8 @@ private Compilation() {} * * @throws RuntimeException if compilation fails. */ - static Result compile(Iterable processors, + static Result compile(JavaCompiler compiler, Iterable processors, Iterable options, Iterable sources) { - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) { throw new IllegalStateException("Java Compiler is not present. " + "May be, you need to include tools.jar on your dependency list."); @@ -70,7 +69,7 @@ static Result compile(Iterable processors, fileManager, diagnosticCollector, ImmutableList.copyOf(options), - ImmutableSet.of(), + null, // explicitly use the default behaviour because Eclipse compiler fails with empty Set sources); task.setProcessors(processors); boolean successful = task.call(); @@ -82,8 +81,7 @@ static Result compile(Iterable processors, * Parse {@code sources} into {@linkplain CompilationUnitTree compilation units}. This method * does not compile the sources. */ - static ParseResult parse(Iterable sources) { - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); + static ParseResult parse(JavaCompiler compiler, Iterable sources) { DiagnosticCollector diagnosticCollector = new DiagnosticCollector(); InMemoryJavaFileManager fileManager = new InMemoryJavaFileManager( @@ -93,7 +91,7 @@ static ParseResult parse(Iterable sources) { fileManager, diagnosticCollector, ImmutableSet.of(), - ImmutableSet.of(), + null, // explicitly use the default behaviour because Eclipse compiler fails with empty Set sources); try { Iterable parsedCompilationUnits = task.parse(); diff --git a/src/main/java/com/google/testing/compile/CompilationRule.java b/src/main/java/com/google/testing/compile/CompilationRule.java index 9ac54565..763d4847 100644 --- a/src/main/java/com/google/testing/compile/CompilationRule.java +++ b/src/main/java/com/google/testing/compile/CompilationRule.java @@ -87,37 +87,37 @@ public Statement apply(final Statement base, Description description) { 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(); - } + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } - @Override - public Set getSupportedAnnotationTypes() { - return ImmutableSet.of("*"); - } + @Override + public Set getSupportedAnnotationTypes() { + return ImmutableSet.of("*"); + } - @Override - public synchronized void init(ProcessingEnvironment processingEnv) { - super.init(processingEnv); - elements = processingEnv.getElementUtils(); - types = processingEnv.getTypeUtils(); - } + @Override + public synchronized void init(ProcessingEnvironment processingEnv) { + super.init(processingEnv); + elements = processingEnv.getElementUtils(); + types = processingEnv.getTypeUtils(); + } - @Override - public boolean process(Set annotations, - RoundEnvironment roundEnv) { - // just run the test on the last round after compilation is over - if (roundEnv.processingOver()) { - try { - base.evaluate(); - } catch (Throwable e) { - thrown.set(e); + @Override + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + // just run the test on the last round after compilation is over + if (roundEnv.processingOver()) { + try { + base.evaluate(); + } catch (Throwable e) { + thrown.set(e); + } + } + return false; } - } - return false; - } - })); + })); boolean successful = task.call(); checkState(successful); Throwable t = thrown.get(); diff --git a/src/main/java/com/google/testing/compile/JavaSourcesSubject.java b/src/main/java/com/google/testing/compile/JavaSourcesSubject.java index 42f7dfd9..0cda7f11 100644 --- a/src/main/java/com/google/testing/compile/JavaSourcesSubject.java +++ b/src/main/java/com/google/testing/compile/JavaSourcesSubject.java @@ -48,8 +48,10 @@ import javax.tools.Diagnostic; import javax.tools.Diagnostic.Kind; import javax.tools.FileObject; +import javax.tools.JavaCompiler; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; +import javax.tools.ToolProvider; /** * A Truth {@link Subject} that evaluates the result @@ -60,12 +62,19 @@ @SuppressWarnings("restriction") // Sun APIs usage intended public final class JavaSourcesSubject extends Subject> - implements CompileTester, ProcessedCompileTesterFactory { + implements ProcessedCompileTesterFactory { private final List options = new ArrayList(Arrays.asList("-Xlint")); + private JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); JavaSourcesSubject(FailureStrategy failureStrategy, Iterable subject) { super(failureStrategy, subject); } + + @Override + public JavaSourcesSubject withCompiler(JavaCompiler javaCompiler) { + this.compiler = javaCompiler; + return this; + } @Override public JavaSourcesSubject withCompilerOptions(Iterable options) { @@ -161,7 +170,7 @@ private String reportFilesGenerated(Compilation.Result result) { @Override public void parsesAs(JavaFileObject first, JavaFileObject... rest) { - Compilation.ParseResult actualResult = Compilation.parse(getSubject()); + Compilation.ParseResult actualResult = Compilation.parse(compiler, getSubject()); ImmutableList> errors = actualResult.diagnosticsByKind().get(Kind.ERROR); if (!errors.isEmpty()) { @@ -172,7 +181,7 @@ public void parsesAs(JavaFileObject first, JavaFileObject... rest) { } failureStrategy.fail(message.toString()); } - final Compilation.ParseResult expectedResult = Compilation.parse(Lists.asList(first, rest)); + final Compilation.ParseResult expectedResult = Compilation.parse(compiler, Lists.asList(first, rest)); final FluentIterable actualTrees = FluentIterable.from( actualResult.compilationUnits()); final FluentIterable expectedTrees = FluentIterable.from( @@ -295,7 +304,7 @@ public CleanCompilationClause compilesWithoutWarnings() { private Compilation.Result successfulCompilationResult() { Compilation.Result result = - Compilation.compile(processors, options, getSubject()); + Compilation.compile(compiler, processors, options, getSubject()); if (!result.successful()) { ImmutableList> errors = result.diagnosticsByKind().get(Kind.ERROR); @@ -313,7 +322,7 @@ private Compilation.Result successfulCompilationResult() { @Override public UnsuccessfulCompilationClause failsToCompile() { - Result result = Compilation.compile(processors, options, getSubject()); + Result result = Compilation.compile(compiler, processors, options, getSubject()); if (result.successful()) { String message = Joiner.on('\n').join( "Compilation was expected to fail, but contained no errors.", @@ -748,7 +757,7 @@ public static JavaSourcesSubject assertThat(JavaFileObject... javaFileObjects) { public static final class SingleSourceAdapter extends Subject - implements CompileTester, ProcessedCompileTesterFactory { + implements ProcessedCompileTesterFactory { private final JavaSourcesSubject delegate; SingleSourceAdapter(FailureStrategy failureStrategy, JavaFileObject subject) { @@ -756,6 +765,10 @@ public static final class SingleSourceAdapter this.delegate = new JavaSourcesSubject(failureStrategy, ImmutableList.of(subject)); } + + public JavaSourcesSubject withCompiler(JavaCompiler javaCompiler) { + return this.delegate.withCompiler(javaCompiler); + } @Override public JavaSourcesSubject withCompilerOptions(Iterable options) { diff --git a/src/main/java/com/google/testing/compile/MoreTrees.java b/src/main/java/com/google/testing/compile/MoreTrees.java index e3833895..2cb2f543 100644 --- a/src/main/java/com/google/testing/compile/MoreTrees.java +++ b/src/main/java/com/google/testing/compile/MoreTrees.java @@ -38,6 +38,7 @@ import java.util.Arrays; import javax.annotation.Nullable; +import javax.tools.ToolProvider; /** * A class containing methods which are useful for gaining access to {@code Tree} instances from @@ -52,8 +53,8 @@ static CompilationUnitTree parseLinesToTree(String... source) { /** Parses the source given into a {@link CompilationUnitTree}. */ static CompilationUnitTree parseLinesToTree(Iterable source) { - Iterable parseResults = Compilation.parse(ImmutableList.of( - JavaFileObjects.forSourceLines("", source))).compilationUnits(); + Iterable parseResults = Compilation.parse(ToolProvider.getSystemJavaCompiler(), + ImmutableList.of(JavaFileObjects.forSourceLines("", source))).compilationUnits(); return Iterables.getOnlyElement(parseResults); } @@ -64,7 +65,8 @@ static Compilation.ParseResult parseLines(String... source) { /** Parses the source given and produces a {@link Compilation.ParseResult}. */ static Compilation.ParseResult parseLines(Iterable source) { - return Compilation.parse(ImmutableList.of(JavaFileObjects.forSourceLines("", source))); + return Compilation.parse(ToolProvider.getSystemJavaCompiler(), + ImmutableList.of(JavaFileObjects.forSourceLines("", source))); } /** diff --git a/src/main/java/com/google/testing/compile/ProcessedCompileTesterFactory.java b/src/main/java/com/google/testing/compile/ProcessedCompileTesterFactory.java index add8a054..11223c5b 100644 --- a/src/main/java/com/google/testing/compile/ProcessedCompileTesterFactory.java +++ b/src/main/java/com/google/testing/compile/ProcessedCompileTesterFactory.java @@ -17,6 +17,7 @@ import javax.annotation.CheckReturnValue; import javax.annotation.processing.Processor; +import javax.tools.JavaCompiler; /** * Creates {@link CompileTester} instances that test compilation with provided {@link Processor} @@ -24,7 +25,11 @@ * * @author Gregory Kick */ -public interface ProcessedCompileTesterFactory { +public interface ProcessedCompileTesterFactory extends CompileTester{ + + /** Specify compiler (Javac, Eclipse ECJ, ...) **/ + @CheckReturnValue + ProcessedCompileTesterFactory withCompiler(JavaCompiler var1); /** * Adds options that will be passed to the compiler. {@code -Xlint} is the first option, by diff --git a/src/test/java/com/google/testing/compile/JavaSourcesSubjectFactoryTest.java b/src/test/java/com/google/testing/compile/JavaSourcesSubjectFactoryTest.java index fb14c4ec..e75cf992 100644 --- a/src/test/java/com/google/testing/compile/JavaSourcesSubjectFactoryTest.java +++ b/src/test/java/com/google/testing/compile/JavaSourcesSubjectFactoryTest.java @@ -29,6 +29,7 @@ import com.google.common.truth.FailureStrategy; import com.google.common.truth.TestVerb; +import org.eclipse.jdt.internal.compiler.tool.EclipseCompiler; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; @@ -107,6 +108,15 @@ public void compilesWithoutError() { .compilesWithoutError(); } + @Test + public void compilesWithoutErrorWithEclipseCompiler() { + assertAbout(javaSource()) + .that(JavaFileObjects.forResource(Resources.getResource("HelloWorld.java"))) + .withCompiler(new EclipseCompiler()) + .withCompilerOptions("-nowarn", "-1.6") + .compilesWithoutError(); + } + @Test public void compilesWithoutWarnings() { assertAbout(javaSource()).that(HELLO_WORLD).compilesWithoutWarnings();