11package io .avaje .prism .internal ;
22
3+ import static io .avaje .prism .internal .APContext .jdkVersion ;
4+
35import java .io .PrintWriter ;
46
57public class VisitorWriter {
68 private VisitorWriter () {}
79
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+ }
921
22+ public static void write (PrintWriter out , String packageName ) {
1023 out .append (
1124 "package "
1225 + packageName
1326 + ";\n "
1427 + "\n "
1528 + "import static java.util.stream.Collectors.toSet;\n "
1629 + "\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 ()
3831 + "\n "
3932 + "@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 "
4234 + "\n "
4335 + " private final int depth;\n "
44- + "\n "
4536 + " private final boolean includeAnnotations;\n "
4637 + "\n "
4738 + " private final Map<TypeVariable, String> typeVariables;\n "
@@ -69,8 +60,7 @@ public static void write(PrintWriter out, String packageName) {
6960 + " this(1, new HashMap<>(), true);\n "
7061 + " }\n "
7162 + "\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 "
7464 + " this.includeAnnotations = includeAnnotations;\n "
7565 + " this.depth = depth;\n "
7666 + " this.typeVariables = new HashMap<>();\n "
@@ -152,7 +142,6 @@ public static void write(PrintWriter out, String packageName) {
152142 + " }\n "
153143 + "\n "
154144 + " private void child(TypeMirror ct, StringBuilder p, boolean setMain) {\n "
155- + "\n "
156145 + " var child = new TypeMirrorVisitor(depth + 1, typeVariables, includeAnnotations);\n "
157146 + " child.allTypes = allTypes;\n "
158147 + " child.everyAnnotation = everyAnnotation;\n "
@@ -185,7 +174,6 @@ public static void write(PrintWriter out, String packageName) {
185174 + " mainType = primitiveStr;\n "
186175 + " }\n "
187176 + " p.append(primitiveStr);\n "
188- + "\n "
189177 + " return p;\n "
190178 + " }\n "
191179 + "\n "
@@ -222,8 +210,8 @@ public static void write(PrintWriter out, String packageName) {
222210 + " @Override\n "
223211 + " public StringBuilder visitDeclared(DeclaredType t, StringBuilder p) {\n "
224212 + " 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 "
227215 + " allTypes.add(ProcessorUtils.extractEnclosingFQN(trimmed));\n "
228216 + "\n "
229217 + " if (this.mainType == null) {\n "
@@ -246,17 +234,19 @@ public static void write(PrintWriter out, String packageName) {
246234 + " return p;\n "
247235 + " }\n "
248236 + "\n "
249- + " String fullyQualfiedName (DeclaredType t, boolean includeAnnotations) {\n "
237+ + " String fullyQualifiedName (DeclaredType t, boolean includeAnnotations) {\n "
250238 + " final TypeElement element = (TypeElement) t.asElement();\n "
251- + " final var typeUseAnnotations = t.getAnnotationMirrors();\n "
239+ + " final var directAnnotations = t.getAnnotationMirrors();\n "
252240 + "\n "
253- + " if (typeUseAnnotations .isEmpty() || !includeAnnotations) {\n "
241+ + " if (directAnnotations .isEmpty() || !includeAnnotations) {\n "
254242 + " return element.getQualifiedName().toString();\n "
255243 + " }\n "
244+ + " final var annotations = extractAnnotations(directAnnotations);\n "
245+ + "\n "
256246 + " final StringBuilder sb = new StringBuilder();\n "
257247 + " // if not too nested, write annotations before the fqn like @someAnnotation io.YourType\n "
258248 + " if (depth < 3) {\n "
259- + " for (final var ta : typeUseAnnotations ) {\n "
249+ + " for (final var ta : annotations ) {\n "
260250 + " sb.append(ta.toString()).append(\" \" );\n "
261251 + " }\n "
262252 + " }\n "
@@ -271,19 +261,41 @@ public static void write(PrintWriter out, String packageName) {
271261 + "\n "
272262 + " // if too nested, write annotations in the fqn like io.@someAnnotation YourType\n "
273263 + " if (depth > 2) {\n "
274- + " for (final var ta : typeUseAnnotations ) {\n "
264+ + " for (final var ta : annotations ) {\n "
275265 + " sb.append(ta.toString()).append(\" \" );\n "
276266 + " }\n "
277267 + " }\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 "
279274 + "\n "
275+ + " for (final var ta : typeUseAnnotations) {\n "
280276 + " 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 "
281293 + " allTypes.add(annotation.getQualifiedName().toString());\n "
282294 + " annotations.add(ta);\n "
295+ + " directAnnotations.add(ta);\n "
283296 + " everyAnnotation.add(ta);\n "
284297 + " }\n "
285- + " sb.append(element.getSimpleName());\n "
286- + " return sb.toString();\n "
298+ + " return directAnnotations;\n "
287299 + " }\n "
288300 + "\n "
289301 + " @Override\n "
@@ -296,22 +308,15 @@ public static void write(PrintWriter out, String packageName) {
296308 + " @Override\n "
297309 + " public StringBuilder visitTypeVariable(TypeVariable t, StringBuilder p) {\n "
298310 + " 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 "
302312 + " final String previous = typeVariables.get(t);\n "
303- + "\n "
304313 + " if (previous != null) {\n "
305314 + " p.append(previous);\n "
306315 + " return p;\n "
307316 + " }\n "
308317 + "\n "
309318 + " 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 "
315320 + " if (includeAnnotations) {\n "
316321 + " for (final var ta : t.getAnnotationMirrors()) {\n "
317322 + " p.append(ta.toString()).append(\" \" );\n "
0 commit comments