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

io.morethan.daggerdoc.Util Maven / Gradle / Ivy

package io.morethan.daggerdoc;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.Consumer;

import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.AnnotationValue;
import javax.lang.model.element.AnnotationValueVisitor;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.ErrorType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.IntersectionType;
import javax.lang.model.type.NoType;
import javax.lang.model.type.NullType;
import javax.lang.model.type.PrimitiveType;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.UnionType;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.AbstractTypeVisitor8;
import javax.lang.model.util.SimpleAnnotationValueVisitor8;

import dagger.Provides;
import io.morethan.daggerdoc.model.DependencyGraph;

/**
 * Helper for navigating the {@link Element} tree with its annotations and annotation values.
 */
class Util {

    public static void consumeAnnotationValues(
            Element element,
            Class annotationClass,
            String annotationFieldName,
            Consumer> consumer) {

        for (AnnotationMirror annotationMirror : element.getAnnotationMirrors()) {
            if (annotationMirror.getAnnotationType().toString().equals(annotationClass.getName())) {
                for (Map.Entry entry : annotationMirror.getElementValues().entrySet()) {
                    if (entry.getKey().getSimpleName().contentEquals(annotationFieldName)) {
                        consumer.accept(entry);
                    }
                }
            }
        }
    }

    public static void consumeClassValues(AnnotationValue annotationValue, Consumer typeConsumer) {
        new ClassValueAnnotationVisitor(typeConsumer).visit(annotationValue);
    }

    /**
     * Getting values of type {@link Class} from an annotation is not straightforward. See
     * http://hauchee.blogspot.com/2015/12/compile-time-annotation-processing-getting-class-value.html.
     * 
     * This {@link AnnotationValueVisitor} helps to simplify the retrieval.
     */
    private static class ClassValueAnnotationVisitor extends SimpleAnnotationValueVisitor8 {

        private final Consumer _typeConsumer;

        private ClassValueAnnotationVisitor(Consumer typeConsumer) {
            _typeConsumer = typeConsumer;
        }

        @Override
        public Void visitArray(List vals, Void p) {
            for (AnnotationValue annotationValue : vals) {
                visit(annotationValue);
            }
            return super.visitArray(vals, p);
        }

        @Override
        public Void visitType(TypeMirror t, Void p) {
            _typeConsumer.accept(t);
            return super.visitType(t, p);
        }

    }

    /**
     * Is applied to the parameters of a {@link Provides} method for information extraction.
     */
    static class ProvidesParamEvaluator extends AbstractTypeVisitor8 {

        private final ProcessingEnvironment _processingEnv;
        private final DependencyGraph.Builder _graphBuilder;
        private final Element _containerElement;
        private final TypeMirror _typeOfSet;

        public ProvidesParamEvaluator(ProcessingEnvironment processingEnv, DependencyGraph.Builder graphBuilder, Element containerElement) {
            _processingEnv = processingEnv;
            _graphBuilder = graphBuilder;
            _containerElement = containerElement;
            _typeOfSet = _processingEnv.getElementUtils().getTypeElement("java.util.Set").asType();
        }

        @Override
        public Void visitPrimitive(PrimitiveType t, Void p) {
            return null;
        }

        @Override
        public Void visitNull(NullType t, Void p) {
            return null;
        }

        @Override
        public Void visitArray(ArrayType t, Void p) {
            return null;
        }

        @Override
        public Void visitDeclared(DeclaredType t, Void p) {

            // Detect multi-binding consumers
            if (_processingEnv.getTypeUtils().isSubtype(t.asElement().asType(), _typeOfSet)) {
                TypeMirror typeMirrorOfSet = t.getTypeArguments().get(0);
                _graphBuilder.addMultibindingConsumer(_containerElement, typeMirrorOfSet);
            }
            return null;
        }

        @Override
        public Void visitError(ErrorType t, Void p) {
            return null;
        }

        @Override
        public Void visitTypeVariable(TypeVariable t, Void p) {
            return null;
        }

        @Override
        public Void visitWildcard(WildcardType t, Void p) {
            return null;
        }

        @Override
        public Void visitExecutable(ExecutableType t, Void p) {
            return null;
        }

        @Override
        public Void visitNoType(NoType t, Void p) {
            return null;
        }

        @Override
        public Void visitIntersection(IntersectionType t, Void p) {
            return null;
        }

        @Override
        public Void visitUnion(UnionType t, Void p) {
            return null;
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy