1
1
package io .avaje .prism .internal ;
2
2
3
+ import static io .avaje .prism .internal .APContext .jdkVersion ;
4
+
3
5
import java .io .PrintWriter ;
4
6
5
7
public class VisitorWriter {
6
8
private VisitorWriter () {}
7
9
8
- public static void write (PrintWriter out , String packageName ) {
10
+ private static String compilerImports () {
11
+ if (jdkVersion () >= 23 && APContext .previewEnabled ()) {
12
+ return "import module java.base;\n " + "import module java.compiler;\n " ;
13
+ }
14
+ return "import java.util.*;\n "
15
+ + "\n "
16
+ + "import javax.annotation.processing.Generated;\n "
17
+ + "import javax.lang.model.element.*;\n "
18
+ + "import javax.lang.model.type.*;\n "
19
+ + "import javax.lang.model.util.AbstractTypeVisitor9;\n " ;
20
+ }
9
21
22
+ public static void write (PrintWriter out , String packageName ) {
10
23
out .append (
11
24
"package "
12
25
+ packageName
13
26
+ ";\n "
14
27
+ "\n "
15
28
+ "import static java.util.stream.Collectors.toSet;\n "
16
29
+ "\n "
17
- + "import java.util.ArrayList;\n "
18
- + "import java.util.HashMap;\n "
19
- + "import java.util.HashSet;\n "
20
- + "import java.util.LinkedHashMap;\n "
21
- + "import java.util.List;\n "
22
- + "import java.util.Locale;\n "
23
- + "import java.util.Map;\n "
24
- + "import java.util.Objects;\n "
25
- + "import java.util.Set;\n "
26
- + "\n "
27
- + "import javax.annotation.processing.Generated;\n "
28
- + "import javax.lang.model.element.AnnotationMirror;\n "
29
- + "import javax.lang.model.element.Element;\n "
30
- + "import javax.lang.model.element.QualifiedNameable;\n "
31
- + "import javax.lang.model.element.TypeElement;\n "
32
- + "import javax.lang.model.type.ArrayType;\n "
33
- + "import javax.lang.model.type.DeclaredType;\n "
34
- + "import javax.lang.model.type.ErrorType;\n "
35
- + "import javax.lang.model.type.ExecutableType;\n "
36
- + "import javax.lang.model.type.*;\n "
37
- + "import javax.lang.model.util.AbstractTypeVisitor9;\n "
30
+ + compilerImports ()
38
31
+ "\n "
39
32
+ "@Generated(\" avaje-prism-generator\" )\n "
40
- + "class TypeMirrorVisitor extends AbstractTypeVisitor9<StringBuilder, StringBuilder>\n "
41
- + " implements UType {\n "
33
+ + "class TypeMirrorVisitor extends AbstractTypeVisitor9<StringBuilder, StringBuilder> implements UType {\n "
42
34
+ "\n "
43
35
+ " private final int depth;\n "
44
- + "\n "
45
36
+ " private final boolean includeAnnotations;\n "
46
37
+ "\n "
47
38
+ " private final Map<TypeVariable, String> typeVariables;\n "
@@ -69,8 +60,7 @@ public static void write(PrintWriter out, String packageName) {
69
60
+ " this(1, new HashMap<>(), true);\n "
70
61
+ " }\n "
71
62
+ "\n "
72
- + " private TypeMirrorVisitor(\n "
73
- + " int depth, Map<TypeVariable, String> typeVariables, boolean includeAnnotations) {\n "
63
+ + " private TypeMirrorVisitor(int depth, Map<TypeVariable, String> typeVariables, boolean includeAnnotations) {\n "
74
64
+ " this.includeAnnotations = includeAnnotations;\n "
75
65
+ " this.depth = depth;\n "
76
66
+ " this.typeVariables = new HashMap<>();\n "
@@ -152,7 +142,6 @@ public static void write(PrintWriter out, String packageName) {
152
142
+ " }\n "
153
143
+ "\n "
154
144
+ " private void child(TypeMirror ct, StringBuilder p, boolean setMain) {\n "
155
- + "\n "
156
145
+ " var child = new TypeMirrorVisitor(depth + 1, typeVariables, includeAnnotations);\n "
157
146
+ " child.allTypes = allTypes;\n "
158
147
+ " child.everyAnnotation = everyAnnotation;\n "
@@ -185,7 +174,6 @@ public static void write(PrintWriter out, String packageName) {
185
174
+ " mainType = primitiveStr;\n "
186
175
+ " }\n "
187
176
+ " p.append(primitiveStr);\n "
188
- + "\n "
189
177
+ " return p;\n "
190
178
+ " }\n "
191
179
+ "\n "
@@ -222,8 +210,8 @@ public static void write(PrintWriter out, String packageName) {
222
210
+ " @Override\n "
223
211
+ " public StringBuilder visitDeclared(DeclaredType t, StringBuilder p) {\n "
224
212
+ " kind = t.getKind();\n "
225
- + " final String fqn = fullyQualfiedName (t, includeAnnotations);\n "
226
- + " var trimmed = fullyQualfiedName (t, false);\n "
213
+ + " final String fqn = fullyQualifiedName (t, includeAnnotations);\n "
214
+ + " var trimmed = fullyQualifiedName (t, false);\n "
227
215
+ " allTypes.add(ProcessorUtils.extractEnclosingFQN(trimmed));\n "
228
216
+ "\n "
229
217
+ " if (this.mainType == null) {\n "
@@ -246,17 +234,19 @@ public static void write(PrintWriter out, String packageName) {
246
234
+ " return p;\n "
247
235
+ " }\n "
248
236
+ "\n "
249
- + " String fullyQualfiedName (DeclaredType t, boolean includeAnnotations) {\n "
237
+ + " String fullyQualifiedName (DeclaredType t, boolean includeAnnotations) {\n "
250
238
+ " final TypeElement element = (TypeElement) t.asElement();\n "
251
- + " final var typeUseAnnotations = t.getAnnotationMirrors();\n "
239
+ + " final var directAnnotations = t.getAnnotationMirrors();\n "
252
240
+ "\n "
253
- + " if (typeUseAnnotations .isEmpty() || !includeAnnotations) {\n "
241
+ + " if (directAnnotations .isEmpty() || !includeAnnotations) {\n "
254
242
+ " return element.getQualifiedName().toString();\n "
255
243
+ " }\n "
244
+ + " final var annotations = extractAnnotations(directAnnotations);\n "
245
+ + "\n "
256
246
+ " final StringBuilder sb = new StringBuilder();\n "
257
247
+ " // if not too nested, write annotations before the fqn like @someAnnotation io.YourType\n "
258
248
+ " if (depth < 3) {\n "
259
- + " for (final var ta : typeUseAnnotations ) {\n "
249
+ + " for (final var ta : annotations ) {\n "
260
250
+ " sb.append(ta.toString()).append(\" \" );\n "
261
251
+ " }\n "
262
252
+ " }\n "
@@ -271,19 +261,41 @@ public static void write(PrintWriter out, String packageName) {
271
261
+ "\n "
272
262
+ " // if too nested, write annotations in the fqn like io.@someAnnotation YourType\n "
273
263
+ " if (depth > 2) {\n "
274
- + " for (final var ta : typeUseAnnotations ) {\n "
264
+ + " for (final var ta : annotations ) {\n "
275
265
+ " sb.append(ta.toString()).append(\" \" );\n "
276
266
+ " }\n "
277
267
+ " }\n "
278
- + " for (final var ta : typeUseAnnotations) {\n "
268
+ + " sb.append(element.getSimpleName());\n "
269
+ + " return sb.toString();\n "
270
+ + " }\n "
271
+ + "\n "
272
+ + " private List<AnnotationMirror> extractAnnotations(final List<? extends AnnotationMirror> typeUseAnnotations) {\n "
273
+ + " var directAnnotations = new ArrayList<AnnotationMirror>();\n "
279
274
+ "\n "
275
+ + " for (final var ta : typeUseAnnotations) {\n "
280
276
+ " final TypeElement annotation = (TypeElement) ta.getAnnotationType().asElement();\n "
277
+ + " @SuppressWarnings(\" unchecked\" )\n "
278
+ + " List<AnnotationMirror> repeatableNested =\n "
279
+ + " ta.getElementValues().entrySet().stream()\n "
280
+ + " .findAny()\n "
281
+ + " .filter(e -> \" value\" .equals(e.getKey().getSimpleName().toString()))\n "
282
+ + " .map(e -> e.getValue().getValue())\n "
283
+ + " .filter(List.class::isInstance)\n "
284
+ + " .map(List.class::cast)\n "
285
+ + " .filter(e -> !e.isEmpty() && e.get(0) instanceof AnnotationValue)\n "
286
+ + " .map(e -> ((List<AnnotationMirror>) e))\n "
287
+ + " .orElse(List.of());\n "
288
+ + " if (!repeatableNested.isEmpty()) {\n "
289
+ + " directAnnotations.addAll(extractAnnotations(repeatableNested));\n "
290
+ + " continue;\n "
291
+ + " }\n "
292
+ + "\n "
281
293
+ " allTypes.add(annotation.getQualifiedName().toString());\n "
282
294
+ " annotations.add(ta);\n "
295
+ + " directAnnotations.add(ta);\n "
283
296
+ " everyAnnotation.add(ta);\n "
284
297
+ " }\n "
285
- + " sb.append(element.getSimpleName());\n "
286
- + " return sb.toString();\n "
298
+ + " return directAnnotations;\n "
287
299
+ " }\n "
288
300
+ "\n "
289
301
+ " @Override\n "
@@ -296,22 +308,15 @@ public static void write(PrintWriter out, String packageName) {
296
308
+ " @Override\n "
297
309
+ " public StringBuilder visitTypeVariable(TypeVariable t, StringBuilder p) {\n "
298
310
+ " kind = t.getKind();\n "
299
- + " /*\n "
300
- + " * Types can be recursive so we have to check if we have already done this type.\n "
301
- + " */\n "
311
+ + " // Types can be recursive so we have to check if we have already done this type.\n "
302
312
+ " final String previous = typeVariables.get(t);\n "
303
- + "\n "
304
313
+ " if (previous != null) {\n "
305
314
+ " p.append(previous);\n "
306
315
+ " return p;\n "
307
316
+ " }\n "
308
317
+ "\n "
309
318
+ " final StringBuilder sb = new StringBuilder();\n "
310
- + "\n "
311
- + " /*\n "
312
- + " * We do not have to print the upper and lower bound as those are defined usually\n "
313
- + " * on the method.\n "
314
- + " */\n "
319
+ + " // not printing the upper and lower bound as those are defined usually on the method\n "
315
320
+ " if (includeAnnotations) {\n "
316
321
+ " for (final var ta : t.getAnnotationMirrors()) {\n "
317
322
+ " p.append(ta.toString()).append(\" \" );\n "
0 commit comments