25
25
import com .google .common .base .Objects ;
26
26
import com .google .common .base .Throwables ;
27
27
import com .google .common .collect .ImmutableSet ;
28
+ import com .google .common .collect .MapMaker ;
28
29
29
30
import org .inferred .freebuilder .FreeBuilder ;
30
31
import org .inferred .freebuilder .processor .util .CompilationUnitBuilder ;
34
35
35
36
import java .io .IOException ;
36
37
import java .util .Set ;
38
+ import java .util .concurrent .ConcurrentMap ;
37
39
38
40
import javax .annotation .processing .AbstractProcessor ;
39
41
import javax .annotation .processing .FilerException ;
53
55
@ AutoService (javax .annotation .processing .Processor .class )
54
56
public class Processor extends AbstractProcessor {
55
57
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
+
56
66
private Analyser analyser ;
57
67
private final CodeGenerator codeGenerator = new CodeGenerator ();
58
68
private final FeatureSet features ;
@@ -81,6 +91,11 @@ public SourceVersion getSupportedSourceVersion() {
81
91
@ Override
82
92
public synchronized void init (ProcessingEnvironment processingEnv ) {
83
93
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
+ }
84
99
analyser = new Analyser (
85
100
processingEnv .getElementUtils (),
86
101
processingEnv .getMessager (),
@@ -93,6 +108,10 @@ public synchronized void init(ProcessingEnvironment processingEnv) {
93
108
94
109
@ Override
95
110
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
+ }
96
115
for (TypeElement type : typesIn (annotatedElementsIn (roundEnv , FreeBuilder .class ))) {
97
116
try {
98
117
Metadata metadata = analyser .analyse (type );
0 commit comments