Skip to content
This repository was archived by the owner on Oct 16, 2024. It is now read-only.

Commit ac19c7e

Browse files
authored
Merge pull request #226 from google/catch.duplicate.registration
Disable duplicate Processor registrations
2 parents 72b5dce + 0aa936a commit ac19c7e

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

src/main/java/org/inferred/freebuilder/processor/Processor.java

+19
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.common.base.Objects;
2626
import com.google.common.base.Throwables;
2727
import com.google.common.collect.ImmutableSet;
28+
import com.google.common.collect.MapMaker;
2829

2930
import org.inferred.freebuilder.FreeBuilder;
3031
import org.inferred.freebuilder.processor.util.CompilationUnitBuilder;
@@ -34,6 +35,7 @@
3435

3536
import java.io.IOException;
3637
import java.util.Set;
38+
import java.util.concurrent.ConcurrentMap;
3739

3840
import javax.annotation.processing.AbstractProcessor;
3941
import javax.annotation.processing.FilerException;
@@ -53,6 +55,14 @@
5355
@AutoService(javax.annotation.processing.Processor.class)
5456
public class Processor extends AbstractProcessor {
5557

58+
/**
59+
* Keep track of which processors have been registered to avoid double-processing if FreeBuilder
60+
* ends up on the processor path twice. While we catch the resulting Filer exceptions and convert
61+
* them to warnings, it's still cleaner to issue a single NOTE-severity message.
62+
*/
63+
private static final ConcurrentMap<ProcessingEnvironment, Processor> registeredProcessors =
64+
new MapMaker().weakKeys().weakValues().concurrencyLevel(1).initialCapacity(1).makeMap();
65+
5666
private Analyser analyser;
5767
private final CodeGenerator codeGenerator = new CodeGenerator();
5868
private final FeatureSet features;
@@ -81,6 +91,11 @@ public SourceVersion getSupportedSourceVersion() {
8191
@Override
8292
public synchronized void init(ProcessingEnvironment processingEnv) {
8393
super.init(processingEnv);
94+
if (registeredProcessors.putIfAbsent(processingEnv, this) != null) {
95+
processingEnv.getMessager().printMessage(
96+
Kind.NOTE, "FreeBuilder processor registered twice; disabling duplicate instance");
97+
return;
98+
}
8499
analyser = new Analyser(
85100
processingEnv.getElementUtils(),
86101
processingEnv.getMessager(),
@@ -93,6 +108,10 @@ public synchronized void init(ProcessingEnvironment processingEnv) {
93108

94109
@Override
95110
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
111+
if (analyser == null) {
112+
// Another FreeBuilder Processor is already registered; skip processing
113+
return false;
114+
}
96115
for (TypeElement type : typesIn(annotatedElementsIn(roundEnv, FreeBuilder.class))) {
97116
try {
98117
Metadata metadata = analyser.analyse(type);

src/test/java/org/inferred/freebuilder/processor/ProcessorTest.java

+18
Original file line numberDiff line numberDiff line change
@@ -1105,4 +1105,22 @@ public void testJacksonInteroperability() {
11051105
.runTest();
11061106
}
11071107

1108+
@Test
1109+
public void testDoubleRegistration() {
1110+
// See also https://github.com/google/FreeBuilder/issues/21
1111+
behaviorTester
1112+
.with(new Processor(features))
1113+
.with(new Processor(features))
1114+
.with(TWO_PROPERTY_FREE_BUILDER_INTERFACE)
1115+
.with(new TestBuilder()
1116+
.addLine("com.example.DataType value = new com.example.DataType.Builder()")
1117+
.addLine(" .setPropertyA(11)")
1118+
.addLine(" .setPropertyB(true)")
1119+
.addLine(" .build();")
1120+
.addLine("assertEquals(11, value.getPropertyA());")
1121+
.addLine("assertTrue(value.isPropertyB());")
1122+
.build())
1123+
.compiles()
1124+
.withNoWarnings();
1125+
}
11081126
}

0 commit comments

Comments
 (0)