11
11
import java .util .ArrayList ;
12
12
import java .util .Comparator ;
13
13
import java .util .HashMap ;
14
+ import java .util .LinkedHashSet ;
14
15
import java .util .List ;
15
16
import java .util .Map ;
16
17
import java .util .Set ;
18
+ import java .util .stream .Collectors ;
19
+ import java .util .stream .Stream ;
17
20
import javax .annotation .processing .AbstractProcessor ;
18
21
import javax .annotation .processing .RoundEnvironment ;
19
22
import javax .annotation .processing .SupportedAnnotationTypes ;
@@ -90,15 +93,15 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
90
93
e );
91
94
});
92
95
96
+ var loggedTypes = getLoggedTypes (roundEnv );
97
+
93
98
// Handlers are declared in order of priority. If an element could be logged in more than one
94
99
// way (eg a class implements both Sendable and StructSerializable), the order of the handlers
95
100
// in this list will determine how it gets logged.
96
101
m_handlers =
97
102
List .of (
98
103
new LoggableHandler (
99
- processingEnv ,
100
- roundEnv .getElementsAnnotatedWith (
101
- Logged .class )), // prioritize epilogue logging over Sendable
104
+ processingEnv , loggedTypes ), // prioritize epilogue logging over Sendable
102
105
new ConfiguredLoggerHandler (
103
106
processingEnv , customLoggers ), // then customized logging configs
104
107
new ArrayHandler (processingEnv ),
@@ -118,12 +121,39 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
118
121
.findAny ()
119
122
.ifPresent (
120
123
epilogue -> {
121
- processEpilogue (roundEnv , epilogue );
124
+ processEpilogue (roundEnv , epilogue , loggedTypes );
122
125
});
123
126
124
127
return false ;
125
128
}
126
129
130
+ /**
131
+ * Gets the set of all loggable types in the compilation unit. A type is considered loggable if it
132
+ * is directly annotated with {@code @Logged} or contains a field or method with a {@code @Logged}
133
+ * annotation.
134
+ *
135
+ * @param roundEnv the compilation round environment
136
+ * @return the set of all loggable types
137
+ */
138
+ private Set <TypeElement > getLoggedTypes (RoundEnvironment roundEnv ) {
139
+ // Fetches everything annotated with @Logged; classes, methods, values, etc.
140
+ var annotatedElements = roundEnv .getElementsAnnotatedWith (Logged .class );
141
+ return Stream .concat (
142
+ // 1. All type elements (classes, interfaces, or enums) with the @Logged annotation
143
+ annotatedElements .stream ()
144
+ .filter (e -> e instanceof TypeElement )
145
+ .map (e -> (TypeElement ) e ),
146
+ // 2. All type elements containing a field or method with the @Logged annotation
147
+ annotatedElements .stream ()
148
+ .filter (e -> e instanceof VariableElement || e instanceof ExecutableElement )
149
+ .map (Element ::getEnclosingElement )
150
+ .filter (e -> e instanceof TypeElement )
151
+ .map (e -> (TypeElement ) e ))
152
+ .sorted (Comparator .comparing (e -> e .getSimpleName ().toString ()))
153
+ .collect (
154
+ Collectors .toCollection (LinkedHashSet ::new )); // Collect to a set to avoid duplicates
155
+ }
156
+
127
157
private boolean validateFields (Set <? extends Element > annotatedElements ) {
128
158
var fields =
129
159
annotatedElements .stream ()
@@ -340,7 +370,8 @@ private Map<DeclaredType, DeclaredType> processCustomLoggers(
340
370
return customLoggers ;
341
371
}
342
372
343
- private void processEpilogue (RoundEnvironment roundEnv , TypeElement epilogueAnnotation ) {
373
+ private void processEpilogue (
374
+ RoundEnvironment roundEnv , TypeElement epilogueAnnotation , Set <TypeElement > loggedTypes ) {
344
375
var annotatedElements = roundEnv .getElementsAnnotatedWith (epilogueAnnotation );
345
376
346
377
List <String > loggerClassNames = new ArrayList <>();
@@ -358,12 +389,7 @@ private void processEpilogue(RoundEnvironment roundEnv, TypeElement epilogueAnno
358
389
return ;
359
390
}
360
391
361
- var classes =
362
- annotatedElements .stream ()
363
- .filter (e -> e instanceof TypeElement )
364
- .map (e -> (TypeElement ) e )
365
- .toList ();
366
- for (TypeElement clazz : classes ) {
392
+ for (TypeElement clazz : loggedTypes ) {
367
393
try {
368
394
warnOfNonLoggableElements (clazz );
369
395
m_loggerGenerator .writeLoggerFile (clazz );
@@ -391,7 +417,7 @@ private void processEpilogue(RoundEnvironment roundEnv, TypeElement epilogueAnno
391
417
392
418
private void warnOfNonLoggableElements (TypeElement clazz ) {
393
419
var config = clazz .getAnnotation (Logged .class );
394
- if (config .strategy () == Logged .Strategy .OPT_IN ) {
420
+ if (config == null || config .strategy () == Logged .Strategy .OPT_IN ) {
395
421
// field and method validations will have already checked everything
396
422
return ;
397
423
}
0 commit comments