Skip to content

Commit 80a9ee0

Browse files
java-team-github-botCompile-Testing Team
authored andcommitted
Added annotation processor path to Compiler
RELNOTES=Add `withAnnotationProcessorPath()` to `Compiler`. PiperOrigin-RevId: 344881510
1 parent cd2c0a8 commit 80a9ee0

3 files changed

Lines changed: 135 additions & 16 deletions

File tree

src/main/java/com/google/testing/compile/Compiler.java

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public static Compiler javac() {
5959
/** Returns a {@link Compiler} that uses a given {@link JavaCompiler} instance. */
6060
public static Compiler compiler(JavaCompiler javaCompiler) {
6161
return new AutoValue_Compiler(
62-
javaCompiler, ImmutableList.of(), ImmutableList.of(), Optional.empty());
62+
javaCompiler, ImmutableList.of(), ImmutableList.of(), Optional.empty(), Optional.empty());
6363
}
6464

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

76+
/**
77+
* The annotation processor path. If not present, the system annotation processor path is used.
78+
*/
79+
public abstract Optional<ImmutableList<File>> annotationProcessorPath();
80+
7681
/**
7782
* Uses annotation processors during compilation. These replace any previously specified.
7883
*
@@ -92,7 +97,8 @@ public final Compiler withProcessors(Processor... processors) {
9297
* @return a new instance with the same options and the given processors
9398
*/
9499
public final Compiler withProcessors(Iterable<? extends Processor> processors) {
95-
return copy(ImmutableList.copyOf(processors), options(), classPath());
100+
return copy(
101+
ImmutableList.copyOf(processors), options(), classPath(), annotationProcessorPath());
96102
}
97103

98104
/**
@@ -113,7 +119,8 @@ public final Compiler withOptions(Iterable<?> options) {
113119
return copy(
114120
processors(),
115121
FluentIterable.from(options).transform(toStringFunction()).toList(),
116-
classPath());
122+
classPath(),
123+
annotationProcessorPath());
117124
}
118125

119126
/**
@@ -128,12 +135,32 @@ public final Compiler withOptions(Iterable<?> options) {
128135
*/
129136
@Deprecated
130137
public final Compiler withClasspathFrom(ClassLoader classloader) {
131-
return copy(processors(), options(), Optional.of(getClasspathFromClassloader(classloader)));
138+
return copy(
139+
processors(),
140+
options(),
141+
Optional.of(getClasspathFromClassloader(classloader)),
142+
annotationProcessorPath());
132143
}
133144

134145
/** Uses the given classpath for the compilation instead of the system classpath. */
135146
public final Compiler withClasspath(Iterable<File> classPath) {
136-
return copy(processors(), options(), Optional.of(ImmutableList.copyOf(classPath)));
147+
return copy(
148+
processors(),
149+
options(),
150+
Optional.of(ImmutableList.copyOf(classPath)),
151+
annotationProcessorPath());
152+
}
153+
154+
/**
155+
* Uses the given annotation processor path for the compilation instead of the system annotation
156+
* processor path.
157+
*/
158+
public final Compiler withAnnotationProcessorPath(Iterable<File> annotationProcessorPath) {
159+
return copy(
160+
processors(),
161+
options(),
162+
classPath(),
163+
Optional.of(ImmutableList.copyOf(annotationProcessorPath)));
137164
}
138165

139166
/**
@@ -155,16 +182,10 @@ public final Compilation compile(Iterable<? extends JavaFileObject> files) {
155182
InMemoryJavaFileManager fileManager =
156183
new InMemoryJavaFileManager(
157184
javaCompiler().getStandardFileManager(diagnosticCollector, Locale.getDefault(), UTF_8));
158-
classPath()
185+
classPath().ifPresent(path -> setLocation(fileManager, StandardLocation.CLASS_PATH, path));
186+
annotationProcessorPath()
159187
.ifPresent(
160-
classPath -> {
161-
try {
162-
fileManager.setLocation(StandardLocation.CLASS_PATH, classPath);
163-
} catch (IOException e) {
164-
// impossible by specification
165-
throw new UncheckedIOException(e);
166-
}
167-
});
188+
path -> setLocation(fileManager, StandardLocation.ANNOTATION_PROCESSOR_PATH, path));
168189
CompilationTask task =
169190
javaCompiler()
170191
.getTask(
@@ -247,10 +268,22 @@ private static ImmutableList<File> getClasspathFromClassloader(ClassLoader curre
247268
return classpaths.stream().map(File::new).collect(toImmutableList());
248269
}
249270

271+
private static void setLocation(
272+
InMemoryJavaFileManager fileManager, StandardLocation location, ImmutableList<File> path) {
273+
try {
274+
fileManager.setLocation(location, path);
275+
} catch (IOException e) {
276+
// impossible by specification
277+
throw new UncheckedIOException(e);
278+
}
279+
}
280+
250281
private Compiler copy(
251282
ImmutableList<Processor> processors,
252283
ImmutableList<String> options,
253-
Optional<ImmutableList<File>> classPath) {
254-
return new AutoValue_Compiler(javaCompiler(), processors, options, classPath);
284+
Optional<ImmutableList<File>> classPath,
285+
Optional<ImmutableList<File>> annotationProcessorPath) {
286+
return new AutoValue_Compiler(
287+
javaCompiler(), processors, options, classPath, annotationProcessorPath);
255288
}
256289
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.google.testing.compile;
2+
3+
import com.google.common.collect.ImmutableSet;
4+
import java.io.IOException;
5+
import java.io.UncheckedIOException;
6+
import java.util.Set;
7+
import javax.annotation.processing.AbstractProcessor;
8+
import javax.annotation.processing.Filer;
9+
import javax.annotation.processing.ProcessingEnvironment;
10+
import javax.annotation.processing.RoundEnvironment;
11+
import javax.lang.model.SourceVersion;
12+
import javax.lang.model.element.TypeElement;
13+
import javax.tools.StandardLocation;
14+
15+
final class AnnotationFileProcessor extends AbstractProcessor {
16+
17+
@Override
18+
public synchronized void init(ProcessingEnvironment processingEnv) {
19+
Filer filer = processingEnv.getFiler();
20+
try {
21+
filer.getResource(StandardLocation.ANNOTATION_PROCESSOR_PATH, "", "tmp.txt");
22+
} catch (IOException e) {
23+
throw new UncheckedIOException(e);
24+
}
25+
}
26+
27+
@Override
28+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
29+
return false;
30+
}
31+
32+
@Override
33+
public Set<String> getSupportedAnnotationTypes() {
34+
return ImmutableSet.of("*");
35+
}
36+
37+
@Override
38+
public SourceVersion getSupportedSourceVersion() {
39+
return SourceVersion.latestSupported();
40+
}
41+
}

src/test/java/com/google/testing/compile/CompilerTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,19 @@
1919
import static com.google.testing.compile.CompilationSubject.assertThat;
2020
import static com.google.testing.compile.Compiler.javac;
2121
import static java.nio.charset.StandardCharsets.UTF_8;
22+
import static org.junit.Assert.assertThrows;
2223
import static org.junit.Assume.assumeTrue;
2324

2425
import com.google.common.collect.ImmutableList;
2526
import java.io.File;
27+
import java.io.FileOutputStream;
2628
import java.io.IOException;
2729
import java.net.URL;
2830
import java.net.URLClassLoader;
2931
import java.util.Arrays;
3032
import java.util.Locale;
33+
import java.util.zip.ZipEntry;
34+
import java.util.zip.ZipOutputStream;
3135
import javax.annotation.processing.Processor;
3236
import javax.lang.model.SourceVersion;
3337
import javax.tools.JavaCompiler;
@@ -198,6 +202,47 @@ public void classPath_customFiles_urlClassLoader() throws Exception {
198202
assertThat(compilation).succeeded();
199203
}
200204

205+
@Test
206+
public void annotationProcessorPath_empty() {
207+
AnnotationFileProcessor processor = new AnnotationFileProcessor();
208+
Compiler compiler =
209+
javac().withProcessors(processor).withAnnotationProcessorPath(ImmutableList.of());
210+
RuntimeException expected =
211+
assertThrows(
212+
RuntimeException.class,
213+
() -> compiler.compile(JavaFileObjects.forSourceLines("Test", "class Test {}")));
214+
assumeTrue(
215+
isJdk9OrLater()); // with JDK 8, NullPointerException is thrown instead of the expected
216+
// exception, and this bug is fixed after JDK 8
217+
assertThat(expected).hasCauseThat().hasCauseThat().hasMessageThat().contains("tmp.txt");
218+
}
219+
220+
@Test
221+
public void annotationProcessorPath_customFiles() throws Exception {
222+
AnnotationFileProcessor processor = new AnnotationFileProcessor();
223+
File jar = compileTestJar();
224+
// compile with only 'tmp.txt' on the annotation processor path
225+
Compilation compilation =
226+
javac()
227+
.withProcessors(processor)
228+
.withAnnotationProcessorPath(ImmutableList.of(jar))
229+
.compile(JavaFileObjects.forSourceLines("Test", "class Test {}"));
230+
assertThat(compilation).succeeded();
231+
}
232+
233+
/**
234+
* Sets up a jar containing a single file 'tmp.txt', for use in annotation processor path tests.
235+
*/
236+
private static File compileTestJar() throws IOException {
237+
File file = File.createTempFile("tmp", ".jar");
238+
try (ZipOutputStream zipOutput = new ZipOutputStream(new FileOutputStream(file))) {
239+
ZipEntry entry = new ZipEntry("tmp.txt");
240+
zipOutput.putNextEntry(entry);
241+
zipOutput.closeEntry();
242+
}
243+
return file;
244+
}
245+
201246
@Test
202247
public void releaseFlag() {
203248
assumeTrue(isJdk9OrLater());

0 commit comments

Comments
 (0)