Skip to content

Commit 95e749d

Browse files
netdpbCompile-Testing Team
authored andcommitted
Allow sources being compiled to be read from annotation processors.
Fixes #189. RELNOTES=Allow sources being compiled to be read from annotation processors. PiperOrigin-RevId: 364564477
1 parent 1142aec commit 95e749d

10 files changed

Lines changed: 164 additions & 80 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ public final Compilation compile(Iterable<? extends JavaFileObject> files) {
182182
InMemoryJavaFileManager fileManager =
183183
new InMemoryJavaFileManager(
184184
javaCompiler().getStandardFileManager(diagnosticCollector, Locale.getDefault(), UTF_8));
185+
fileManager.addSourceFiles(files);
185186
classPath().ifPresent(path -> setLocation(fileManager, StandardLocation.CLASS_PATH, path));
186187
annotationProcessorPath()
187188
.ifPresent(

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

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
*/
1616
package com.google.testing.compile;
1717

18+
import static com.google.common.collect.MoreCollectors.toOptional;
19+
1820
import com.google.common.base.MoreObjects;
1921
import com.google.common.base.Optional;
2022
import com.google.common.cache.CacheBuilder;
@@ -32,7 +34,8 @@
3234
import java.io.Writer;
3335
import java.net.URI;
3436
import java.nio.charset.Charset;
35-
import java.util.Map.Entry;
37+
import java.util.HashMap;
38+
import java.util.Map;
3639
import javax.tools.FileObject;
3740
import javax.tools.JavaFileObject;
3841
import javax.tools.JavaFileObject.Kind;
@@ -47,13 +50,17 @@
4750
*/
4851
// TODO(gak): under java 1.7 this could all be done with a PathFileManager
4952
final class InMemoryJavaFileManager extends ForwardingStandardJavaFileManager {
50-
private final LoadingCache<URI, JavaFileObject> inMemoryFileObjects =
51-
CacheBuilder.newBuilder().build(new CacheLoader<URI, JavaFileObject>() {
52-
@Override
53-
public JavaFileObject load(URI key) {
54-
return new InMemoryJavaFileObject(key);
55-
}
56-
});
53+
private final LoadingCache<URI, JavaFileObject> inMemoryOutputs =
54+
CacheBuilder.newBuilder()
55+
.build(
56+
new CacheLoader<URI, JavaFileObject>() {
57+
@Override
58+
public JavaFileObject load(URI key) {
59+
return new InMemoryJavaFileObject(key);
60+
}
61+
});
62+
63+
private final Map<URI, JavaFileObject> inMemoryInputs = new HashMap<>();
5764

5865
InMemoryJavaFileManager(StandardJavaFileManager fileManager) {
5966
super(fileManager);
@@ -86,40 +93,64 @@ public boolean isSameFile(FileObject a, FileObject b) {
8693
public FileObject getFileForInput(Location location, String packageName,
8794
String relativeName) throws IOException {
8895
if (location.isOutputLocation()) {
89-
return inMemoryFileObjects.getIfPresent(
90-
uriForFileObject(location, packageName, relativeName));
91-
} else {
92-
return super.getFileForInput(location, packageName, relativeName);
96+
return inMemoryOutputs.getIfPresent(uriForFileObject(location, packageName, relativeName));
9397
}
98+
Optional<JavaFileObject> inMemoryInput = findInMemoryInput(packageName, relativeName);
99+
if (inMemoryInput.isPresent()) {
100+
return inMemoryInput.get();
101+
}
102+
return super.getFileForInput(location, packageName, relativeName);
94103
}
95104

96105
@Override
97106
public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind)
98107
throws IOException {
99108
if (location.isOutputLocation()) {
100-
return inMemoryFileObjects.getIfPresent(uriForJavaFileObject(location, className, kind));
101-
} else {
102-
return super.getJavaFileForInput(location, className, kind);
109+
return inMemoryOutputs.getIfPresent(uriForJavaFileObject(location, className, kind));
110+
}
111+
Optional<JavaFileObject> inMemoryInput = findInMemoryInput(className);
112+
if (inMemoryInput.isPresent()) {
113+
return inMemoryInput.get();
103114
}
115+
return super.getJavaFileForInput(location, className, kind);
116+
}
117+
118+
private Optional<JavaFileObject> findInMemoryInput(String className) {
119+
int lastDot = className.lastIndexOf('.');
120+
return findInMemoryInput(
121+
lastDot == -1 ? "" : className.substring(0, lastDot - 1),
122+
className.substring(lastDot + 1) + ".java");
123+
}
124+
125+
private Optional<JavaFileObject> findInMemoryInput(String packageName, String relativeName) {
126+
// Assume each input file's URI ends with the package/relative name. It might have other parts
127+
// to the left.
128+
String suffix =
129+
packageName.isEmpty() ? relativeName : packageName.replace('.', '/') + "/" + relativeName;
130+
return Optional.fromJavaUtil(
131+
inMemoryInputs.entrySet().stream()
132+
.filter(entry -> entry.getKey().getPath().endsWith(suffix))
133+
.map(Map.Entry::getValue)
134+
.collect(toOptional())); // Might have problems if more than one input file matches.
104135
}
105136

106137
@Override
107138
public FileObject getFileForOutput(Location location, String packageName,
108139
String relativeName, FileObject sibling) throws IOException {
109140
URI uri = uriForFileObject(location, packageName, relativeName);
110-
return inMemoryFileObjects.getUnchecked(uri);
141+
return inMemoryOutputs.getUnchecked(uri);
111142
}
112143

113144
@Override
114145
public JavaFileObject getJavaFileForOutput(Location location, String className, final Kind kind,
115146
FileObject sibling) throws IOException {
116147
URI uri = uriForJavaFileObject(location, className, kind);
117-
return inMemoryFileObjects.getUnchecked(uri);
148+
return inMemoryOutputs.getUnchecked(uri);
118149
}
119150

120151
ImmutableList<JavaFileObject> getGeneratedSources() {
121152
ImmutableList.Builder<JavaFileObject> result = ImmutableList.builder();
122-
for (Entry<URI, JavaFileObject> entry : inMemoryFileObjects.asMap().entrySet()) {
153+
for (Map.Entry<URI, JavaFileObject> entry : inMemoryOutputs.asMap().entrySet()) {
123154
if (entry.getKey().getPath().startsWith("/" + StandardLocation.SOURCE_OUTPUT.name())
124155
&& (entry.getValue().getKind() == Kind.SOURCE)) {
125156
result.add(entry.getValue());
@@ -129,7 +160,14 @@ ImmutableList<JavaFileObject> getGeneratedSources() {
129160
}
130161

131162
ImmutableList<JavaFileObject> getOutputFiles() {
132-
return ImmutableList.copyOf(inMemoryFileObjects.asMap().values());
163+
return ImmutableList.copyOf(inMemoryOutputs.asMap().values());
164+
}
165+
166+
/** Adds files that should be available in the source path. */
167+
void addSourceFiles(Iterable<? extends JavaFileObject> files) {
168+
for (JavaFileObject file : files) {
169+
inMemoryInputs.put(file.toUri(), file);
170+
}
133171
}
134172

135173
private static final class InMemoryJavaFileObject extends SimpleJavaFileObject

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,13 @@ public class CompilationSubjectTest {
7777
"}");
7878

7979
private static final JavaFileObject HELLO_WORLD_RESOURCE =
80-
JavaFileObjects.forResource("HelloWorld.java");
80+
JavaFileObjects.forResource("test/HelloWorld.java");
8181

8282
private static final JavaFileObject HELLO_WORLD_BROKEN_RESOURCE =
83-
JavaFileObjects.forResource("HelloWorld-broken.java");
83+
JavaFileObjects.forResource("test/HelloWorld-broken.java");
8484

8585
private static final JavaFileObject HELLO_WORLD_DIFFERENT_RESOURCE =
86-
JavaFileObjects.forResource("HelloWorld-different.java");
86+
JavaFileObjects.forResource("test/HelloWorld-different.java");
8787

8888
@RunWith(JUnit4.class)
8989
public static class StatusTest {

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

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,27 @@
2323
import static org.junit.Assume.assumeTrue;
2424

2525
import com.google.common.collect.ImmutableList;
26+
import com.google.common.collect.ImmutableSet;
2627
import java.io.File;
2728
import java.io.FileOutputStream;
2829
import java.io.IOException;
30+
import java.io.UncheckedIOException;
2931
import java.net.URL;
3032
import java.net.URLClassLoader;
3133
import java.util.Arrays;
3234
import java.util.Locale;
35+
import java.util.Set;
36+
import java.util.concurrent.atomic.AtomicReference;
3337
import java.util.zip.ZipEntry;
3438
import java.util.zip.ZipOutputStream;
39+
import javax.annotation.processing.AbstractProcessor;
40+
import javax.annotation.processing.Filer;
41+
import javax.annotation.processing.ProcessingEnvironment;
3542
import javax.annotation.processing.Processor;
43+
import javax.annotation.processing.RoundEnvironment;
3644
import javax.lang.model.SourceVersion;
45+
import javax.lang.model.element.TypeElement;
46+
import javax.tools.FileObject;
3747
import javax.tools.JavaCompiler;
3848
import javax.tools.JavaCompiler.CompilationTask;
3949
import javax.tools.JavaFileObject;
@@ -52,7 +62,8 @@ public final class CompilerTest {
5262

5363
@Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder();
5464

55-
private static final JavaFileObject HELLO_WORLD = JavaFileObjects.forResource("HelloWorld.java");
65+
private static final JavaFileObject HELLO_WORLD =
66+
JavaFileObjects.forResource("test/HelloWorld.java");
5667

5768
@Test
5869
public void options() {
@@ -230,6 +241,47 @@ public void annotationProcessorPath_customFiles() throws Exception {
230241
assertThat(compilation).succeeded();
231242
}
232243

244+
@Test // See https://github.com/google/compile-testing/issues/189
245+
public void readInputFile() throws IOException {
246+
AtomicReference<String> content = new AtomicReference<>();
247+
Compilation compilation =
248+
javac()
249+
.withProcessors(
250+
new AbstractProcessor() {
251+
@Override
252+
public synchronized void init(ProcessingEnvironment processingEnv) {
253+
Filer filer = processingEnv.getFiler();
254+
try {
255+
FileObject helloWorld =
256+
filer.getResource(
257+
StandardLocation.SOURCE_PATH, "test", "HelloWorld.java");
258+
content.set(helloWorld.getCharContent(true).toString());
259+
} catch (IOException e) {
260+
throw new UncheckedIOException(e);
261+
}
262+
}
263+
264+
@Override
265+
public boolean process(
266+
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
267+
return false;
268+
}
269+
270+
@Override
271+
public ImmutableSet<String> getSupportedAnnotationTypes() {
272+
return ImmutableSet.of("*");
273+
}
274+
275+
@Override
276+
public SourceVersion getSupportedSourceVersion() {
277+
return SourceVersion.latestSupported();
278+
}
279+
})
280+
.compile(HELLO_WORLD);
281+
assertThat(compilation).succeeded();
282+
assertThat(content.get()).isEqualTo(HELLO_WORLD.getCharContent(true).toString());
283+
}
284+
233285
/**
234286
* Sets up a jar containing a single file 'tmp.txt', for use in annotation processor path tests.
235287
*/

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

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,18 @@
1919
import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource;
2020

2121
import com.google.common.io.Resources;
22-
23-
import org.junit.Before;
24-
import org.junit.Rule;
25-
import org.junit.Test;
26-
import org.junit.rules.TemporaryFolder;
27-
import org.junit.runner.RunWith;
28-
import org.junit.runners.JUnit4;
29-
3022
import java.io.File;
3123
import java.io.FileOutputStream;
3224
import java.io.IOException;
3325
import java.net.URL;
3426
import java.util.jar.JarEntry;
3527
import java.util.jar.JarOutputStream;
28+
import org.junit.Before;
29+
import org.junit.Rule;
30+
import org.junit.Test;
31+
import org.junit.rules.TemporaryFolder;
32+
import org.junit.runner.RunWith;
33+
import org.junit.runners.JUnit4;
3634

3735
/**
3836
* An integration test to ensure that testing works when resources are in jar files.
@@ -52,7 +50,7 @@ public void createJarFile() throws IOException {
5250
JarOutputStream out = new JarOutputStream(new FileOutputStream(jarFile));
5351
JarEntry helloWorldEntry = new JarEntry("test/HelloWorld.java");
5452
out.putNextEntry(helloWorldEntry);
55-
out.write(Resources.toByteArray(Resources.getResource("HelloWorld.java")));
53+
out.write(Resources.toByteArray(Resources.getResource("test/HelloWorld.java")));
5654
out.close();
5755
}
5856

0 commit comments

Comments
 (0)