Skip to content

Commit 45ef21f

Browse files
scottfrederickphilwebb
authored andcommitted
Add support for annotation processors with TestCompiler
Closes spring-projectsgh-28582
1 parent 4128a71 commit 45ef21f

File tree

2 files changed

+92
-9
lines changed

2 files changed

+92
-9
lines changed

spring-core-test/src/main/java/org/springframework/aot/test/generator/compile/TestCompiler.java

+43-8
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,13 @@
1818

1919
import java.io.PrintStream;
2020
import java.util.ArrayList;
21+
import java.util.Arrays;
22+
import java.util.Collections;
2123
import java.util.List;
2224
import java.util.Locale;
2325
import java.util.function.Consumer;
2426

27+
import javax.annotation.processing.Processor;
2528
import javax.tools.Diagnostic;
2629
import javax.tools.DiagnosticListener;
2730
import javax.tools.JavaCompiler;
@@ -43,6 +46,7 @@
4346
* Utility that can be used to dynamically compile and test Java source code.
4447
*
4548
* @author Phillip Webb
49+
* @author Scott Frederick
4650
* @since 6.0
4751
* @see #forSystem()
4852
*/
@@ -57,13 +61,18 @@ public final class TestCompiler {
5761

5862
private final ResourceFiles resourceFiles;
5963

64+
private final List<Processor> processors;
65+
6066

6167
private TestCompiler(@Nullable ClassLoader classLoader, JavaCompiler compiler,
62-
SourceFiles sourceFiles, ResourceFiles resourceFiles) {
68+
SourceFiles sourceFiles, ResourceFiles resourceFiles,
69+
List<Processor> processors) {
70+
6371
this.classLoader = classLoader;
6472
this.compiler = compiler;
6573
this.sourceFiles = sourceFiles;
6674
this.resourceFiles = resourceFiles;
75+
this.processors = processors;
6776
}
6877

6978

@@ -83,7 +92,7 @@ public static TestCompiler forSystem() {
8392
*/
8493
public static TestCompiler forCompiler(JavaCompiler javaCompiler) {
8594
return new TestCompiler(null, javaCompiler, SourceFiles.none(),
86-
ResourceFiles.none());
95+
ResourceFiles.none(), Collections.emptyList());
8796
}
8897

8998
/**
@@ -110,7 +119,7 @@ public TestCompiler withFiles(InMemoryGeneratedFiles generatedFiles) {
110119
*/
111120
public TestCompiler withSources(SourceFile... sourceFiles) {
112121
return new TestCompiler(this.classLoader, this.compiler,
113-
this.sourceFiles.and(sourceFiles), this.resourceFiles);
122+
this.sourceFiles.and(sourceFiles), this.resourceFiles, this.processors);
114123
}
115124

116125
/**
@@ -120,7 +129,7 @@ public TestCompiler withSources(SourceFile... sourceFiles) {
120129
*/
121130
public TestCompiler withSources(Iterable<SourceFile> sourceFiles) {
122131
return new TestCompiler(this.classLoader, this.compiler,
123-
this.sourceFiles.and(sourceFiles), this.resourceFiles);
132+
this.sourceFiles.and(sourceFiles), this.resourceFiles, this.processors);
124133
}
125134

126135
/**
@@ -130,7 +139,7 @@ public TestCompiler withSources(Iterable<SourceFile> sourceFiles) {
130139
*/
131140
public TestCompiler withSources(SourceFiles sourceFiles) {
132141
return new TestCompiler(this.classLoader, this.compiler,
133-
this.sourceFiles.and(sourceFiles), this.resourceFiles);
142+
this.sourceFiles.and(sourceFiles), this.resourceFiles, this.processors);
134143
}
135144

136145
/**
@@ -140,7 +149,7 @@ public TestCompiler withSources(SourceFiles sourceFiles) {
140149
*/
141150
public TestCompiler withResources(ResourceFile... resourceFiles) {
142151
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
143-
this.resourceFiles.and(resourceFiles));
152+
this.resourceFiles.and(resourceFiles), this.processors);
144153
}
145154

146155
/**
@@ -150,7 +159,7 @@ public TestCompiler withResources(ResourceFile... resourceFiles) {
150159
*/
151160
public TestCompiler withResources(Iterable<ResourceFile> resourceFiles) {
152161
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
153-
this.resourceFiles.and(resourceFiles));
162+
this.resourceFiles.and(resourceFiles), this.processors);
154163
}
155164

156165
/**
@@ -160,9 +169,32 @@ public TestCompiler withResources(Iterable<ResourceFile> resourceFiles) {
160169
*/
161170
public TestCompiler withResources(ResourceFiles resourceFiles) {
162171
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
163-
this.resourceFiles.and(resourceFiles));
172+
this.resourceFiles.and(resourceFiles), this.processors);
173+
}
174+
175+
/**
176+
* Return a new {@link TestCompiler} instance with additional annotation processors.
177+
* @param processors the additional annotation processors
178+
* @return a new {@link TestCompiler} instance
179+
*/
180+
public TestCompiler withProcessors(Processor... processors) {
181+
List<Processor> mergedProcessors = new ArrayList<>(this.processors);
182+
mergedProcessors.addAll(Arrays.asList(processors));
183+
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
184+
this.resourceFiles, mergedProcessors);
164185
}
165186

187+
/**
188+
* Return a new {@link TestCompiler} instance with additional annotation processors.
189+
* @param processors the additional annotation processors
190+
* @return a new {@link TestCompiler} instance
191+
*/
192+
public TestCompiler withProcessors(Iterable<Processor> processors) {
193+
List<Processor> mergedProcessors = new ArrayList<>(this.processors);
194+
processors.forEach(mergedProcessors::add);
195+
return new TestCompiler(this.classLoader, this.compiler, this.sourceFiles,
196+
this.resourceFiles, mergedProcessors);
197+
}
166198

167199
/**
168200
* Compile content from this instance along with the additional provided
@@ -244,6 +276,9 @@ private DynamicClassLoader compile() {
244276
Errors errors = new Errors();
245277
CompilationTask task = this.compiler.getTask(null, fileManager, errors, null,
246278
null, compilationUnits);
279+
if (!this.processors.isEmpty()) {
280+
task.setProcessors(this.processors);
281+
}
247282
boolean result = task.call();
248283
if (!result || errors.hasReportedErrors()) {
249284
throw new CompilationException(errors.toString(), this.sourceFiles, this.resourceFiles);

spring-core-test/src/test/java/org/springframework/aot/test/generator/compile/TestCompilerTests.java

+49-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,17 @@
1616

1717
package org.springframework.aot.test.generator.compile;
1818

19+
import java.util.ArrayList;
20+
import java.util.List;
21+
import java.util.Set;
1922
import java.util.function.Supplier;
2023

24+
import javax.annotation.processing.AbstractProcessor;
25+
import javax.annotation.processing.Processor;
26+
import javax.annotation.processing.RoundEnvironment;
27+
import javax.annotation.processing.SupportedAnnotationTypes;
28+
import javax.lang.model.element.TypeElement;
29+
2130
import com.example.PublicInterface;
2231
import org.junit.jupiter.api.Test;
2332

@@ -33,9 +42,9 @@
3342

3443
/**
3544
* Tests for {@link TestCompiler}.
36-
*
3745
* @author Phillip Webb
3846
* @author Andy Wilkinson
47+
* @author Scott Frederick
3948
*/
4049
class TestCompilerTests {
4150

@@ -140,6 +149,29 @@ void withResourcesAddsResource() {
140149
this::assertHasResource);
141150
}
142151

152+
@Test
153+
void withProcessorsArrayAddsProcessors() {
154+
SourceFile sourceFile = SourceFile.of(HELLO_WORLD);
155+
TestProcessor processor = new TestProcessor();
156+
TestCompiler.forSystem().withSources(sourceFile).withProcessors(processor).compile((compiled -> {
157+
assertThat(processor.getProcessedAnnotations()).isNotEmpty();
158+
assertThat(processor.getProcessedAnnotations()).satisfiesExactly(element ->
159+
assertThat(element.getQualifiedName().toString()).isEqualTo("java.lang.Deprecated"));
160+
}));
161+
}
162+
163+
@Test
164+
void withProcessorsAddsProcessors() {
165+
SourceFile sourceFile = SourceFile.of(HELLO_WORLD);
166+
TestProcessor processor = new TestProcessor();
167+
List<Processor> processors = List.of(processor);
168+
TestCompiler.forSystem().withSources(sourceFile).withProcessors(processors).compile((compiled -> {
169+
assertThat(processor.getProcessedAnnotations()).isNotEmpty();
170+
assertThat(processor.getProcessedAnnotations()).satisfiesExactly(element ->
171+
assertThat(element.getQualifiedName().toString()).isEqualTo("java.lang.Deprecated"));
172+
}));
173+
}
174+
143175
@Test
144176
void compileWithWritableContent() {
145177
WritableContent content = appendable -> appendable.append(HELLO_WORLD);
@@ -217,4 +249,20 @@ private void assertHasResource(Compiled compiled) {
217249
"META-INF/myfile")).hasContent("test");
218250
}
219251

252+
@SupportedAnnotationTypes("java.lang.Deprecated")
253+
static class TestProcessor extends AbstractProcessor {
254+
255+
private final List<TypeElement> processedAnnotations = new ArrayList<>();
256+
257+
@Override
258+
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
259+
this.processedAnnotations.addAll(annotations);
260+
return true;
261+
}
262+
263+
public List<TypeElement> getProcessedAnnotations() {
264+
return this.processedAnnotations;
265+
}
266+
}
267+
220268
}

0 commit comments

Comments
 (0)