All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.micronaut.ast.groovy.annotation.GroovyAnnotationMetadataBuilder Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2017-2020 original authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.micronaut.ast.groovy.annotation;

import io.micronaut.ast.groovy.GroovyNativeElementHelper;
import io.micronaut.ast.groovy.utils.AstMessageUtils;
import io.micronaut.ast.groovy.utils.ExtendedParameter;
import io.micronaut.ast.groovy.visitor.GroovyVisitorContext;
import io.micronaut.core.annotation.AnnotationClassValue;
import io.micronaut.core.annotation.AnnotationMetadata;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.convert.ConversionService;
import io.micronaut.core.expressions.EvaluatedExpressionReference;
import io.micronaut.core.io.service.SoftServiceLoader;
import io.micronaut.core.reflect.ClassUtils;
import io.micronaut.core.reflect.ReflectionUtils;
import io.micronaut.core.util.CollectionUtils;
import io.micronaut.inject.annotation.AbstractAnnotationMetadataBuilder;
import io.micronaut.inject.annotation.AnnotatedElementValidator;
import io.micronaut.inject.visitor.VisitorContext;
import org.codehaus.groovy.ast.AnnotatedNode;
import org.codehaus.groovy.ast.AnnotationNode;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.FieldNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.ast.ModuleNode;
import org.codehaus.groovy.ast.PackageNode;
import org.codehaus.groovy.ast.Parameter;
import org.codehaus.groovy.ast.PropertyNode;
import org.codehaus.groovy.ast.Variable;
import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
import org.codehaus.groovy.ast.expr.ClassExpression;
import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.ListExpression;
import org.codehaus.groovy.ast.expr.PropertyExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
import org.codehaus.groovy.ast.stmt.ReturnStatement;
import org.codehaus.groovy.ast.stmt.Statement;
import org.codehaus.groovy.control.ClassNodeResolver;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.SourceUnit;

import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * Groovy implementation of {@link AbstractAnnotationMetadataBuilder}.
 *
 * @author Graeme Rocher
 * @since 1.0
 */
public class GroovyAnnotationMetadataBuilder extends AbstractAnnotationMetadataBuilder {

    public static final ClassNode ANN_OVERRIDE = ClassHelper.make(Override.class);
    public static final String VALIDATOR_KEY = "io.micronaut.VALIDATOR";

    final SourceUnit sourceUnit;
    final AnnotatedElementValidator elementValidator;
    final CompilationUnit compilationUnit;
    final GroovyNativeElementHelper nativeElementHelper;
    final GroovyVisitorContext visitorContext;

    public GroovyAnnotationMetadataBuilder(SourceUnit sourceUnit, CompilationUnit compilationUnit) {
        this(sourceUnit, compilationUnit, new GroovyNativeElementHelper(), new GroovyVisitorContext(sourceUnit, compilationUnit));
    }

    public GroovyAnnotationMetadataBuilder(SourceUnit sourceUnit,
                                           CompilationUnit compilationUnit,
                                           GroovyNativeElementHelper nativeElementHelper,
                                           GroovyVisitorContext visitorContext) {
        this.compilationUnit = compilationUnit;
        this.sourceUnit = sourceUnit;
        if (sourceUnit != null) {
            final ModuleNode ast = sourceUnit.getAST();
            if (ast != null) {
                Object validator = ast.getNodeMetaData(VALIDATOR_KEY);
                if (validator instanceof AnnotatedElementValidator annotatedElementValidator) {
                    elementValidator = annotatedElementValidator;
                } else {
                    this.elementValidator = SoftServiceLoader.load(AnnotatedElementValidator.class).firstAvailable().orElse(null);
                    ast.putNodeMetaData(VALIDATOR_KEY, this.elementValidator);
                }
            } else {
                this.elementValidator = null;
            }
        } else {
            this.elementValidator = null;
        }
        this.nativeElementHelper = nativeElementHelper;
        this.visitorContext = visitorContext;
    }

    @Override
    public CachedAnnotationMetadata lookupOrBuildForParameter(AnnotatedNode owningType, AnnotatedNode methodElement, AnnotatedNode parameterElement) {
        return super.lookupOrBuildForParameter(owningType, methodElement, new ExtendedParameter((MethodNode) methodElement, (Parameter) parameterElement));
    }

    @Override
    protected boolean isValidationRequired(AnnotatedNode member) {
        if (member != null) {
            final List annotations = member.getAnnotations();
            if (CollectionUtils.isNotEmpty(annotations)) {
                return annotations.stream().anyMatch((it) ->
                    it.getClassNode().getName().startsWith("jakarta.validation"));
            }
        }
        return false;
    }

    @Override
    protected boolean isExcludedAnnotation(@NonNull AnnotatedNode element, @NonNull String annotationName) {
        if (element instanceof ClassNode classNode && classNode.isAnnotationDefinition()
            && (annotationName.startsWith("java.lang.annotation") || annotationName.startsWith("org.codehaus.groovy.transform"))) {
            return false;
        } else {
            return super.isExcludedAnnotation(element, annotationName);
        }
    }

    @Override
    protected AnnotatedNode getAnnotationMember(AnnotatedNode annotationElement, CharSequence member) {
        if (annotationElement instanceof ClassNode classNode) {
            final List methods = classNode.getMethods(member.toString());
            if (CollectionUtils.isNotEmpty(methods)) {
                return methods.iterator().next();
            }
        }
        return null;
    }

    @Override
    protected String getOriginatingClassName(@NonNull AnnotatedNode originatingElement) {
        if (originatingElement instanceof ClassNode classNode) {
            return classNode.getName();
        } else if (originatingElement instanceof ExtendedParameter extendedParameter) {
            return extendedParameter.getMethodNode().getDeclaringClass().getName();
        } else if (originatingElement instanceof MethodNode methodNode) {
            return methodNode.getDeclaringClass().getName();
        }

        ClassNode declaringClass = originatingElement.getDeclaringClass();
        if (declaringClass != null) {
            return declaringClass.getName();
        } else {
            return null;
        }
    }

    @Override
    protected @NonNull RetentionPolicy getRetentionPolicy(@NonNull AnnotatedNode annotation) {
        List annotations = annotation.getAnnotations();
        for (AnnotationNode ann : annotations) {
            if (ann.getClassNode().getName().equals(Retention.class.getName())) {
                final Iterator i = ann.getMembers().values().iterator();
                if (i.hasNext()) {
                    final Expression expr = i.next();
                    if (expr instanceof PropertyExpression propertyExpression) {
                        try {
                            return RetentionPolicy.valueOf(propertyExpression.getPropertyAsString());
                        } catch (Throwable e) {
                            // should never happen
                            return RetentionPolicy.RUNTIME;
                        }
                    }
                }
            }
        }
        return RetentionPolicy.RUNTIME;
    }

    @Override
    protected AnnotatedElementValidator getElementValidator() {
        return this.elementValidator;
    }

    @Override
    protected void addError(@NonNull AnnotatedNode originatingElement, @NonNull String error) {
        AstMessageUtils.error(sourceUnit, originatingElement, error);
    }

    @Override
    protected void addWarning(@NonNull AnnotatedNode originatingElement, @NonNull String warning) {
        AstMessageUtils.warning(sourceUnit, originatingElement, warning);
    }

    @Override
    protected boolean hasAnnotation(AnnotatedNode element, Class annotation) {
        return !element.getAnnotations(ClassHelper.makeCached(annotation)).isEmpty();
    }

    @Override
    protected boolean hasAnnotation(AnnotatedNode element, String annotation) {
        for (AnnotationNode ann : element.getAnnotations()) {
            if (ann.getClassNode().getName().equals(annotation)) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected boolean hasAnnotations(AnnotatedNode element) {
        return CollectionUtils.isNotEmpty(element.getAnnotations());
    }

    @Override
    protected VisitorContext getVisitorContext() {
        return visitorContext;
    }

    @Override
    protected AnnotatedNode getTypeForAnnotation(AnnotationNode annotationMirror) {
        return annotationMirror.getClassNode();
    }

    @Override
    protected String getRepeatableName(AnnotationNode annotationMirror) {
        return getRepeatableContainerNameForType(annotationMirror.getClassNode());
    }

    @Override
    protected String getRepeatableContainerNameForType(AnnotatedNode annotationType) {
        List annotationNodes = annotationType.getAnnotations(ClassHelper.makeCached(Repeatable.class));
        if (CollectionUtils.isNotEmpty(annotationNodes)) {
            Expression expression = annotationNodes.get(0).getMember("value");
            if (expression instanceof ClassExpression) {
                return expression.getType().getName();
            }
        }
        return null;
    }

    @Override
    protected Optional getAnnotationMirror(String annotationName) {
        if (compilationUnit != null) {
            ClassNodeResolver.LookupResult lookupResult = compilationUnit.getClassNodeResolver().resolveName(annotationName, compilationUnit);
            if (lookupResult != null) {
                return Optional.ofNullable(lookupResult.getClassNode());
            }

            Optional classNode = Optional.ofNullable(compilationUnit.getClassNode(annotationName));
            if (classNode.isPresent()) {
                return classNode;
            }
        }
        ClassNode cn = ClassUtils.forName(annotationName, GroovyAnnotationMetadataBuilder.class.getClassLoader())
            .map(ClassHelper::make)
            .orElseGet(() -> ClassHelper.make(annotationName));
        if (!cn.getName().equals(ClassHelper.OBJECT)) {
            return Optional.of(cn);
        } else {
            return Optional.empty();
        }
    }

    @Override
    protected String getAnnotationTypeName(AnnotationNode annotationMirror) {
        return annotationMirror.getClassNode().getName();
    }

    @Override
    protected String getElementName(AnnotatedNode element) {
        if (element instanceof ClassNode node) {
            return node.getName();
        } else if (element instanceof MethodNode node) {
            return node.getName();
        } else if (element instanceof FieldNode node) {
            return node.getName();
        } else if (element instanceof PropertyNode node) {
            return node.getName();
        } else if (element instanceof PackageNode node) {
            return node.getName();
        }
        throw new IllegalArgumentException("Cannot establish name for node type: " + element.getClass().getName());
    }

    @Override
    protected List getAnnotationsForType(AnnotatedNode element) {
        List annotations = element.getAnnotations();
        var expanded = new ArrayList(annotations.size());
        expandAnnotations(annotations, expanded);
        return expanded;
    }

    private void expandAnnotations(List annotations, List expanded) {
        for (AnnotationNode node : annotations) {
            Expression value = node.getMember(AnnotationMetadata.VALUE_MEMBER);
            boolean repeatable = false;
            if (value instanceof ListExpression listExpression) {
                for (Expression expression : listExpression.getExpressions()) {
                    if (expression instanceof AnnotationConstantExpression annotationConstantExpression) {
                        String name = getRepeatableContainerNameForType(expression.getType());
                        if (name != null && name.equals(node.getClassNode().getName())) {
                            repeatable = true;
                            expanded.add((AnnotationNode) annotationConstantExpression.getValue());
                        }
                    }
                }
            }
            if (!repeatable || node.getMembers().size() > 1) {
                expanded.add(node);
            }
        }
    }

    @Override
    protected List buildHierarchy(AnnotatedNode element, boolean inheritTypeAnnotations, boolean declaredOnly) {
        if (declaredOnly) {
            return new ArrayList<>(Collections.singletonList(element));
        } else if (element instanceof ClassNode classNode) {
            var hierarchy = new ArrayList();
            if (classNode.isAnnotationDefinition()) {
                hierarchy.add(classNode);
            } else {
                nativeElementHelper.populateTypeHierarchy(classNode, hierarchy);
            }
            return (List) hierarchy;

        } else if (element instanceof MethodNode methodNode) {
            List hierarchy;
            if (inheritTypeAnnotations) {
                hierarchy = buildHierarchy(methodNode.getDeclaringClass(), false, declaredOnly);
            } else {
                hierarchy = new ArrayList<>();
            }
            if (!methodNode.getAnnotations(ANN_OVERRIDE).isEmpty()) {
                hierarchy.addAll(nativeElementHelper.findOverriddenMethods(methodNode.getDeclaringClass(), methodNode));
            }
            hierarchy.add(methodNode);
            return hierarchy;
        } else if (element instanceof ExtendedParameter extendedParameter) {
            var hierarchy = new ArrayList();
            MethodNode methodNode = extendedParameter.getMethodNode();
            if (!methodNode.getAnnotations(ANN_OVERRIDE).isEmpty()) {
                int variableIdx = Arrays.asList(methodNode.getParameters()).indexOf(extendedParameter.getParameter());
                for (MethodNode overridden : nativeElementHelper.findOverriddenMethods(methodNode.getDeclaringClass(), methodNode)) {
                    hierarchy.add(new ExtendedParameter(overridden, overridden.getParameters()[variableIdx]));
                }
            }
            hierarchy.add(extendedParameter);
            return hierarchy;
        } else {
            if (element == null) {
                return new ArrayList<>();
            } else {
                return new ArrayList<>(Collections.singletonList(element));
            }
        }
    }

    @Override
    protected void readAnnotationRawValues(
        AnnotatedNode originatingElement,
        String annotationName,
        AnnotatedNode member,
        String memberName,
        Object annotationValue,
        Map annotationValues) {
        if (!annotationValues.containsKey(memberName)) {
            Object v = readAnnotationValue(originatingElement, member, annotationName, memberName, annotationValue);
            if (v != null) {
                validateAnnotationValue(originatingElement, annotationName, member, memberName, v);
                annotationValues.put(memberName, v);
            }
        }
    }

    @Override
    protected Map readAnnotationDefaultValues(String annotationName, AnnotatedNode annotationType) {
        var defaultValues = new LinkedHashMap();
        if (annotationType instanceof ClassNode classNode) {
            var methods = new ArrayList<>(classNode.getMethods());
            for (MethodNode method : methods) {
                Statement stmt = method.getCode();
                Expression expression = null;
                if (stmt instanceof ReturnStatement returnStatement) {
                    expression = returnStatement.getExpression();
                } else if (stmt instanceof ExpressionStatement expressionStatement) {
                    expression = expressionStatement.getExpression();
                }
                if (expression instanceof ConstantExpression constantExpression) {
                    final Object v = constantExpression.getValue();
                    if (v instanceof String s) {
                        defaultValues.put(method, new ConstantExpression(s));
                    } else if (v != null) {
                        defaultValues.put(method, expression);
                    }
                }
            }
        }
        return defaultValues;
    }

    @Override
    protected Object readAnnotationValue(AnnotatedNode originatingElement, AnnotatedNode member, String annotationName, String memberName, Object annotationValue) {
        if (annotationValue instanceof ConstantExpression constantExpression) {
            return readConstantExpression(originatingElement, annotationName, member, constantExpression);
        } else if (annotationValue instanceof PropertyExpression pe) {
            if (pe.getObjectExpression() instanceof ClassExpression classExpression) {
                ClassNode propertyType = classExpression.getType();
                if (propertyType.isEnum()) {
                    return pe.getPropertyAsString();
                } else {
                    if (propertyType.isResolved()) {
                        Class typeClass = propertyType.getTypeClass();
                        try {
                            final Field f = ReflectionUtils.getRequiredField(typeClass, pe.getPropertyAsString());
                            f.setAccessible(true);
                            return f.get(typeClass);
                        } catch (Throwable e) {
                            // ignore
                        }
                    }
                }
            }
        } else if (annotationValue instanceof ClassExpression classExpression) {
            return new AnnotationClassValue<>(classExpression.getType().getName());
        } else if (annotationValue instanceof ListExpression listExpression) {
            List expressions = listExpression.getExpressions();
            var converted = new ArrayList<>(expressions.size());
            for (Expression exp : expressions) {
                if (exp instanceof PropertyExpression propertyExpression) {
                    Expression valueExpression = propertyExpression.getProperty();
                    Expression objectExpression = propertyExpression.getObjectExpression();
                    if (valueExpression instanceof ConstantExpression constantExpression && objectExpression instanceof ClassExpression) {
                        Object value = readConstantExpression(originatingElement, annotationName, member, constantExpression);
                        if (value != null) {
                            converted.add(value);
                        }
                    }
                }
                if (exp instanceof ConstantExpression constantExpression) {
                    Object value = readConstantExpression(originatingElement, annotationName, member, constantExpression);
                    if (value != null) {
                        // if value is an expression reference, since we're iterating through a list,
                        //  we extract initial annotation value to wrap it into a single expression reference
                        //  after the iteration is complete
                        if (value instanceof EvaluatedExpressionReference expressionReference) {
                            value = expressionReference.annotationValue();
                        }
                        converted.add(value);
                    }
                } else if (exp instanceof ClassExpression classExpression) {
                    String typeName;
                    if (classExpression.getType().isArray()) {
                        typeName = "[L" + classExpression.getType().getComponentType().getName() + ";";
                    } else {
                        typeName = classExpression.getType().getName();
                    }
                    converted.add(new AnnotationClassValue<>(typeName));
                }
            }
            Object array = toArray(member, converted);
            if (isEvaluatedExpression(array)) {
                return buildEvaluatedExpressionReference(originatingElement, annotationName, memberName, array);
            }
            return array;
        } else if (annotationValue instanceof VariableExpression variableExpression) {
            Variable variable = variableExpression.getAccessedVariable();
            if (variable != null && variable.hasInitialExpression()) {
                return readAnnotationValue(originatingElement, member, annotationName, memberName, variable.getInitialExpression());
            }
        } else if (annotationValue != null) {
            if (ClassUtils.isJavaLangType(annotationValue.getClass())) {
                return annotationValue;
            }
        }
        return null;
    }

    private static Object toArray(AnnotatedNode member, Collection collection) {
        if (!(member instanceof MethodNode methodNode)) {
            throw new IllegalStateException("Expected instance of MethodNode got: " + member);
        }
        ClassNode returnType = methodNode.getReturnType();
        if (!returnType.isArray()) {
            throw new IllegalStateException("Expected a method returning an array got: " + member);
        }
        Class arrayType = Object.class;
        ClassNode component = returnType.getComponentType();
        if (component != null) {
            if (component.isEnum()) {
                arrayType = String.class;
                collection = collection.stream().map(val -> {
                    if (val instanceof Enum anEnum) {
                        return anEnum.name();
                    }
                    return val;
                }).toList();
            } else if (component.isResolved()) {
                arrayType = component.getTypeClass();
                if (Annotation.class.isAssignableFrom(arrayType)) {
                    arrayType = AnnotationValue.class;
                } else if (Class.class.isAssignableFrom(arrayType)) {
                    arrayType = AnnotationClassValue.class;
                } else if (EvaluatedExpressionReference.class.isAssignableFrom(arrayType)) {
                    arrayType = EvaluatedExpressionReference.class;
                }
            }
        }
        if (collection.isEmpty()) {
            return Array.newInstance(arrayType, 0);
        }
        if (collection.stream().allMatch(val -> val instanceof AnnotationClassValue)) {
            arrayType = AnnotationClassValue.class;
        } else if (collection.stream().allMatch(val -> val instanceof AnnotationValue)) {
            arrayType = AnnotationValue.class;
        } else if (collection.stream().anyMatch(val -> val instanceof EvaluatedExpressionReference)) {
            arrayType = Object.class;
        }
        if (arrayType.isPrimitive()) {
            Class wrapperType = ReflectionUtils.getWrapperType(arrayType);
            Class primitiveArrayType = Array.newInstance(arrayType, 0).getClass();
            var emptyWrapperArray = (Object[]) Array.newInstance(wrapperType, 0);
            Object[] wrapperArray = collection.toArray(emptyWrapperArray);
            // Convert to a proper primitive type array
            return ConversionService.SHARED.convertRequired(wrapperArray, primitiveArrayType);
        }
        return ConversionService.SHARED.convert(collection, Array.newInstance(arrayType, 0).getClass())
            .orElse(null);
    }

    private Object readConstantExpression(AnnotatedNode originatingElement, String annotationName, AnnotatedNode member, ConstantExpression constantExpression) {
        if (constantExpression instanceof AnnotationConstantExpression ann) {
            var value = (AnnotationNode) ann.getValue();
            return readNestedAnnotationValue(originatingElement, value);
        } else {
            Object value = constantExpression.getValue();
            if (value == null) {
                return null;
            }
            if (isEvaluatedExpression(value)) {
                String memberName = getAnnotationMemberName(member);
                return buildEvaluatedExpressionReference(originatingElement, annotationName, memberName, value);
            }
            if (value instanceof Collection collection) {
                collection = collection.stream().map(this::convertConstantValue).toList();
                Object array = toArray(member, collection);
                if (isEvaluatedExpression(array)) {
                    return buildEvaluatedExpressionReference(originatingElement, annotationName, getAnnotationMemberName(member), array);
                }
                return array;
            }
            return convertConstantValue(value);
        }
    }

    @SuppressWarnings("java:S1872")
    private Object convertConstantValue(Object value) {
        if (value instanceof ClassNode classNode) {
            return new AnnotationClassValue<>(classNode.getName());
        }
        Class valueClass = value.getClass();
        // Groovy 4.0.6 will return EnumConstantWrapper as a default value
        if (valueClass.getName().equals("org.codehaus.groovy.ast.decompiled.EnumConstantWrapper")) {
            return ReflectionUtils.getFieldValue(valueClass, "constant", value).orElse(null);
        }
        if (valueClass.getName().equals("org.codehaus.groovy.ast.decompiled.TypeWrapper")) {
            String desc = (String) ReflectionUtils.getFieldValue(valueClass, "desc", value).orElse(null);
            if (desc == null) {
                return null;
            }
            // Desc will return "Ljava/lang/String;"
            var arraySuffix = new StringBuilder();
            while (desc.startsWith("[")) {
                desc = desc.substring(1);
                arraySuffix.append("[]");
            }
            String className = desc.substring(1, desc.length() - 1).replace("/", ".") + arraySuffix;
            return new AnnotationClassValue<>(className);
        }
        if (value instanceof CharSequence) {
            value = value.toString();
        }
        return value;
    }

    @Override
    protected Map readAnnotationRawValues(AnnotationNode annotationMirror) {
        Map members = annotationMirror.getMembers();
        var values = new LinkedHashMap();
        ClassNode annotationClassNode = annotationMirror.getClassNode();
        members.forEach((key, value) ->
            values.put(annotationClassNode.getMethods(key).get(0), value));
        return values;
    }

    @Override
    protected  Optional> getAnnotationValues(AnnotatedNode originatingElement, AnnotatedNode member, Class annotationType) {
        if (member != null) {
            ClassNode annotationTypeNode = ClassHelper.make(annotationType);
            final List anns = member.getAnnotations(annotationTypeNode);
            if (CollectionUtils.isNotEmpty(anns)) {
                AnnotationNode ann = anns.get(0);
                var converted = new LinkedHashMap();
                ClassNode annotationNode = ann.getClassNode();
                for (Map.Entry entry : ann.getMembers().entrySet()) {
                    String key = entry.getKey();
                    Expression value = entry.getValue();
                    AnnotatedNode annotationMember = annotationNode.getMethod(key, new Parameter[0]);
                    readAnnotationRawValues(originatingElement, annotationType.getName(), annotationMember, key, value, converted);
                }
                Map annotationDefaults = getCachedAnnotationDefaults(annotationType.getName(), annotationTypeNode);
                if (!annotationDefaults.isEmpty()) {
                    Iterator> i = converted.entrySet().iterator();
                    while (i.hasNext()) {
                        Map.Entry next = i.next();
                        Object v = annotationDefaults.get(next.getKey());
                        if (v != null && v.equals(next.getValue())) {
                            i.remove();
                        }
                    }
                }
                return Optional.of(AnnotationValue.builder(annotationType).members(converted).build());
            }
        }
        return Optional.empty();
    }

    @Override
    protected String getAnnotationMemberName(AnnotatedNode member) {
        return ((MethodNode) member).getName();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy