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

com.redhat.ceylon.model.loader.model.AnnotationTarget Maven / Gradle / Ivy

There is a newer version: 1.3.3
Show newest version
package com.redhat.ceylon.model.loader.model;

import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.redhat.ceylon.model.loader.mirror.AnnotationMirror;
import com.redhat.ceylon.model.typechecker.model.Class;


/**
 * Mirrors the elements of {@link java.lang.annotation.ElementType} for 
 * the purpose of targeting java annotations.
 */
public enum AnnotationTarget {

    TYPE {
        @Override
        public Set outputs() {
            return Collections.singleton(OutputElement.TYPE);
        }
    },
    FIELD {
        @Override
        public Set outputs() {
            return Collections.singleton(OutputElement.FIELD);
        }
    },
    METHOD {
        @Override
        public Set outputs() {
            HashSet result = new HashSet(3);
            result.add(OutputElement.METHOD);
            result.add(OutputElement.GETTER);
            result.add(OutputElement.SETTER);
            return result;
        }
    },
    PARAMETER {
        @Override
        public Set outputs() {
            return Collections.singleton(OutputElement.PARAMETER);
        }
    },
    CONSTRUCTOR {
        @Override
        public Set outputs() {
            return Collections.singleton(OutputElement.CONSTRUCTOR);
        }
    },
    LOCAL_VARIABLE {
        @Override
        public Set outputs() {
            return Collections.singleton(OutputElement.LOCAL_VARIABLE);
        }
    },
    ANNOTATION_TYPE {
        @Override
        public Set outputs() {
            return Collections.singleton(OutputElement.ANNOTATION_TYPE);
        }
    },
    PACKAGE {
        @Override
        public Set outputs() {
            return Collections.singleton(OutputElement.PACKAGE);
        }
    },
    TYPE_USE {
        @Override
        public Set outputs() {
            return Collections.emptySet();
        }
    },
    TYPE_PARAMETER {
        @Override
        public Set outputs() {
            return Collections.emptySet();
        }
    };
    
    public abstract Set outputs();
    
    /**
     * Returns the elements in the {@code @Target} annotation of the given 
     * {@code @interface}, or null if 
     * the annotation type lacks the {@code @Target} annotation.
     */
    public static EnumSet getAnnotationTarget(LazyInterface annotationType) {
        AnnotationMirror targetAnno = annotationType.classMirror.getAnnotation("java.lang.annotation.Target");
        if (targetAnno != null) {
            @SuppressWarnings("unchecked")
            List targets = (List)targetAnno.getValue();
            EnumSet result = EnumSet.noneOf(AnnotationTarget.class);
            for (String name : targets) {
                result.add(AnnotationTarget.valueOf(name));
            }
            return result;
        }
        return null;
    }
    
    /**
     * Returns the possible targets of the given annotation proxy class
     * (according to the {@code @Target} of the {@code @interface} that 
     * the class is a proxy to), 
     * or null if {@code @interface} lacks a {@code @Target} or if 
     * the given class is not an annotation proxy.
     */
    private static EnumSet annotationTargets(Class annotationClass) {
        if (annotationClass instanceof AnnotationProxyClass) {
            return getAnnotationTarget(((AnnotationProxyClass)annotationClass).iface);
        } else {
            return null;
        }
    }
    
    /**
     * Given a set of Java annotation constraints, returns the
     * possible Java elements that could be generated by Ceylon elements 
     * that the annotation could be applied to. 
     * @param targets
     * @return
     */
    private static EnumSet possibleCeylonTargets(EnumSet targets) {
        if (targets == null) {
            targets = EnumSet.allOf(AnnotationTarget.class);
        }
        EnumSet result = EnumSet.noneOf(OutputElement.class);
        for (AnnotationTarget t : targets) {
            result.addAll(t.outputs());
        }
        return result;
    }
    
    /**
     * The set of program elements the given 
     * annotation class could be applied to, according only to 
     * the {@code @Target}s on the corresponding {@code @interface}.
     * @param annotationClass
     * @return
     */
    public static EnumSet outputTargets(Class annotationClass) {
        return possibleCeylonTargets(annotationTargets(annotationClass));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy