Utility class that converts annotation metadata extracted from bytecode into corresponding AST node representations. Handles JSR 175 (annotation) and JSR 308 (type annotation) conversions from ASM-parsed structures to Groovy AST AnnotationNode instances. Key responsibilities: Converti
| 67 | * @see AsmReferenceResolver |
| 68 | */ |
| 69 | class Annotations { |
| 70 | /** |
| 71 | * Creates an {@link AnnotationNode} from bytecode annotation metadata. |
| 72 | * Resolves the annotation class using the provided resolver and converts all annotation members |
| 73 | * to corresponding AST expressions. Returns null if the annotation class cannot be resolved |
| 74 | * (e.g., not present on classpath). |
| 75 | * |
| 76 | * <p>If resolution fails, the annotation is silently skipped to allow compilation with missing |
| 77 | * annotation types (e.g., runtime-only annotations not in classpath). |
| 78 | * |
| 79 | * @param annotation the {@link AnnotationStub} containing bytecode annotation metadata |
| 80 | * @param resolver the {@link AsmReferenceResolver} used to resolve the annotation class type |
| 81 | * @return the created {@link AnnotationNode}, or null if the annotation class cannot be resolved |
| 82 | * @see DecompiledAnnotationNode |
| 83 | */ |
| 84 | static AnnotationNode createAnnotationNode(AnnotationStub annotation, AsmReferenceResolver resolver) { |
| 85 | ClassNode classNode = resolver.resolveClassNullable(Type.getType(annotation.className).getClassName()); |
| 86 | if (classNode == null) { |
| 87 | // there might be annotations not present in the classpath |
| 88 | // e.g. java.lang.Synthetic (http://forge.ow2.org/tracker/?aid=307392&group_id=23&atid=100023&func=detail) |
| 89 | // so skip them |
| 90 | return null; |
| 91 | } |
| 92 | |
| 93 | AnnotationNode node = new DecompiledAnnotationNode(classNode); |
| 94 | for (Map.Entry<String, Object> entry : annotation.members.entrySet()) { |
| 95 | addMemberIfFound(resolver, node, entry); |
| 96 | } |
| 97 | return node; |
| 98 | } |
| 99 | |
| 100 | /** |
| 101 | * Adds a single annotation member to the given {@link AnnotationNode} if the member value |
| 102 | * can be successfully converted to an AST expression. Silently skips members with unconvertible values. |
| 103 | * |
| 104 | * @param resolver the {@link AsmReferenceResolver} used for type resolution |
| 105 | * @param node the {@link AnnotationNode} to add the member to |
| 106 | * @param entry the key-value pair from annotation member map (name → value) |
| 107 | */ |
| 108 | private static void addMemberIfFound(AsmReferenceResolver resolver, AnnotationNode node, Map.Entry<String, Object> entry) { |
| 109 | Expression value = annotationValueToExpression(entry.getValue(), resolver); |
| 110 | if (value != null) { |
| 111 | node.addMember(entry.getKey(), value); |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | /** |
| 116 | * Converts a bytecode annotation element value to a corresponding AST expression. |
| 117 | * Handles all annotation value types according to JVMS §4.7.16: |
| 118 | * <ul> |
| 119 | * <li>{@link TypeWrapper} → {@link ClassExpression}</li> |
| 120 | * <li>{@link EnumConstantWrapper} → {@link PropertyExpression} for enum constant access</li> |
| 121 | * <li>{@link AnnotationStub} → {@link AnnotationConstantExpression} for nested annotations</li> |
| 122 | * <li>Arrays (via {@link Array.getLength()}) → {@link ListExpression} with recursive conversion</li> |
| 123 | * <li>{@link List} → {@link ListExpression} with recursive conversion</li> |
| 124 | * <li>Primitives and strings → {@link ConstantExpression}</li> |
| 125 | * </ul> |
| 126 | * |
nothing calls this directly
no outgoing calls
no test coverage detected