Skip to content

Commit

Permalink
Added annotation processor path to Compiler
Browse files Browse the repository at this point in the history
RELNOTES=Add `withAnnotationProcessorPath()` to `Compiler`.
PiperOrigin-RevId: 344881510
  • Loading branch information
java-team-github-bot authored and Compile-Testing Team committed Nov 30, 2020
1 parent cd2c0a8 commit 80a9ee0
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 16 deletions.
65 changes: 49 additions & 16 deletions src/main/java/com/google/testing/compile/Compiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public static Compiler javac() {
/** Returns a {@link Compiler} that uses a given {@link JavaCompiler} instance. */
public static Compiler compiler(JavaCompiler javaCompiler) {
return new AutoValue_Compiler(
javaCompiler, ImmutableList.of(), ImmutableList.of(), Optional.empty());
javaCompiler, ImmutableList.of(), ImmutableList.of(), Optional.empty(), Optional.empty());
}

abstract JavaCompiler javaCompiler();
Expand All @@ -73,6 +73,11 @@ public static Compiler compiler(JavaCompiler javaCompiler) {
/** The compilation class path. If not present, the system class path is used. */
public abstract Optional<ImmutableList<File>> classPath();

/**
* The annotation processor path. If not present, the system annotation processor path is used.
*/
public abstract Optional<ImmutableList<File>> annotationProcessorPath();

/**
* Uses annotation processors during compilation. These replace any previously specified.
*
Expand All @@ -92,7 +97,8 @@ public final Compiler withProcessors(Processor... processors) {
* @return a new instance with the same options and the given processors
*/
public final Compiler withProcessors(Iterable<? extends Processor> processors) {
return copy(ImmutableList.copyOf(processors), options(), classPath());
return copy(
ImmutableList.copyOf(processors), options(), classPath(), annotationProcessorPath());
}

/**
Expand All @@ -113,7 +119,8 @@ public final Compiler withOptions(Iterable<?> options) {
return copy(
processors(),
FluentIterable.from(options).transform(toStringFunction()).toList(),
classPath());
classPath(),
annotationProcessorPath());
}

/**
Expand All @@ -128,12 +135,32 @@ public final Compiler withOptions(Iterable<?> options) {
*/
@Deprecated
public final Compiler withClasspathFrom(ClassLoader classloader) {
return copy(processors(), options(), Optional.of(getClasspathFromClassloader(classloader)));
return copy(
processors(),
options(),
Optional.of(getClasspathFromClassloader(classloader)),
annotationProcessorPath());
}

/** Uses the given classpath for the compilation instead of the system classpath. */
public final Compiler withClasspath(Iterable<File> classPath) {
return copy(processors(), options(), Optional.of(ImmutableList.copyOf(classPath)));
return copy(
processors(),
options(),
Optional.of(ImmutableList.copyOf(classPath)),
annotationProcessorPath());
}

/**
* Uses the given annotation processor path for the compilation instead of the system annotation
* processor path.
*/
public final Compiler withAnnotationProcessorPath(Iterable<File> annotationProcessorPath) {
return copy(
processors(),
options(),
classPath(),
Optional.of(ImmutableList.copyOf(annotationProcessorPath)));
}

/**
Expand All @@ -155,16 +182,10 @@ public final Compilation compile(Iterable<? extends JavaFileObject> files) {
InMemoryJavaFileManager fileManager =
new InMemoryJavaFileManager(
javaCompiler().getStandardFileManager(diagnosticCollector, Locale.getDefault(), UTF_8));
classPath()
classPath().ifPresent(path -> setLocation(fileManager, StandardLocation.CLASS_PATH, path));
annotationProcessorPath()
.ifPresent(
classPath -> {
try {
fileManager.setLocation(StandardLocation.CLASS_PATH, classPath);
} catch (IOException e) {
// impossible by specification
throw new UncheckedIOException(e);
}
});
path -> setLocation(fileManager, StandardLocation.ANNOTATION_PROCESSOR_PATH, path));
CompilationTask task =
javaCompiler()
.getTask(
Expand Down Expand Up @@ -247,10 +268,22 @@ private static ImmutableList<File> getClasspathFromClassloader(ClassLoader curre
return classpaths.stream().map(File::new).collect(toImmutableList());
}

private static void setLocation(
InMemoryJavaFileManager fileManager, StandardLocation location, ImmutableList<File> path) {
try {
fileManager.setLocation(location, path);
} catch (IOException e) {
// impossible by specification
throw new UncheckedIOException(e);
}
}

private Compiler copy(
ImmutableList<Processor> processors,
ImmutableList<String> options,
Optional<ImmutableList<File>> classPath) {
return new AutoValue_Compiler(javaCompiler(), processors, options, classPath);
Optional<ImmutableList<File>> classPath,
Optional<ImmutableList<File>> annotationProcessorPath) {
return new AutoValue_Compiler(
javaCompiler(), processors, options, classPath, annotationProcessorPath);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.google.testing.compile;

import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import javax.tools.StandardLocation;

final class AnnotationFileProcessor extends AbstractProcessor {

@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
Filer filer = processingEnv.getFiler();
try {
filer.getResource(StandardLocation.ANNOTATION_PROCESSOR_PATH, "", "tmp.txt");
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
return false;
}

@Override
public Set<String> getSupportedAnnotationTypes() {
return ImmutableSet.of("*");
}

@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
}
}
45 changes: 45 additions & 0 deletions src/test/java/com/google/testing/compile/CompilerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@
import static com.google.testing.compile.CompilationSubject.assertThat;
import static com.google.testing.compile.Compiler.javac;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.junit.Assert.assertThrows;
import static org.junit.Assume.assumeTrue;

import com.google.common.collect.ImmutableList;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Locale;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.annotation.processing.Processor;
import javax.lang.model.SourceVersion;
import javax.tools.JavaCompiler;
Expand Down Expand Up @@ -198,6 +202,47 @@ public void classPath_customFiles_urlClassLoader() throws Exception {
assertThat(compilation).succeeded();
}

@Test
public void annotationProcessorPath_empty() {
AnnotationFileProcessor processor = new AnnotationFileProcessor();
Compiler compiler =
javac().withProcessors(processor).withAnnotationProcessorPath(ImmutableList.of());
RuntimeException expected =
assertThrows(
RuntimeException.class,
() -> compiler.compile(JavaFileObjects.forSourceLines("Test", "class Test {}")));
assumeTrue(
isJdk9OrLater()); // with JDK 8, NullPointerException is thrown instead of the expected
// exception, and this bug is fixed after JDK 8
assertThat(expected).hasCauseThat().hasCauseThat().hasMessageThat().contains("tmp.txt");
}

@Test
public void annotationProcessorPath_customFiles() throws Exception {
AnnotationFileProcessor processor = new AnnotationFileProcessor();
File jar = compileTestJar();
// compile with only 'tmp.txt' on the annotation processor path
Compilation compilation =
javac()
.withProcessors(processor)
.withAnnotationProcessorPath(ImmutableList.of(jar))
.compile(JavaFileObjects.forSourceLines("Test", "class Test {}"));
assertThat(compilation).succeeded();
}

/**
* Sets up a jar containing a single file 'tmp.txt', for use in annotation processor path tests.
*/
private static File compileTestJar() throws IOException {
File file = File.createTempFile("tmp", ".jar");
try (ZipOutputStream zipOutput = new ZipOutputStream(new FileOutputStream(file))) {
ZipEntry entry = new ZipEntry("tmp.txt");
zipOutput.putNextEntry(entry);
zipOutput.closeEntry();
}
return file;
}

@Test
public void releaseFlag() {
assumeTrue(isJdk9OrLater());
Expand Down

0 comments on commit 80a9ee0

Please sign in to comment.