Search in sources :

Example 1 with AnnotationProxyMethod

use of com.redhat.ceylon.model.loader.model.AnnotationProxyMethod in project ceylon-compiler by ceylon.

the class ExpressionTransformer method isNaturalTarget.

/**
 * Whether an annotation (with the given {@code annotationCtorDecl}
 * annotation constructor) used on the given declaration ({@code useSite})
 * should be added to the Java annotations of the given generated program
 * elements ({@code target})
 * @param annotationCtorDecl
 * @param useSite
 * @param target
 * @return
 */
private boolean isNaturalTarget(// use site is either a Declaration, or a Package, or a Module,
Function annotationCtorDecl, // module imports
Object useSite, OutputElement target) {
    EnumSet<AnnotationTarget> interopTargets;
    if (annotationCtorDecl instanceof AnnotationProxyMethod) {
        AnnotationProxyMethod annotationProxyMethod = (AnnotationProxyMethod) annotationCtorDecl;
        if (annotationProxyMethod.getAnnotationTarget() == target) {
            // Foo__WHATEVER, so honour the WHATEVER
            return true;
        }
        interopTargets = annotationProxyMethod.getProxyClass().getAnnotationTarget();
    } else {
        interopTargets = null;
    }
    if (useSite instanceof Declaration) {
        if (ModelUtil.isConstructor((Declaration) useSite)) {
            if (useSite instanceof Functional) {
                return target == OutputElement.CONSTRUCTOR;
            } else if (useSite instanceof Value) {
                return target == OutputElement.GETTER;
            }
        } else if (useSite instanceof Class) {
            if (((Class) useSite).getParameterList() != null && interopTargets != null && interopTargets.contains(AnnotationTarget.CONSTRUCTOR) && !interopTargets.contains(AnnotationTarget.TYPE)) {
                return target == OutputElement.CONSTRUCTOR;
            }
            return target == OutputElement.TYPE;
        } else if (useSite instanceof Interface) {
            return target == OutputElement.TYPE;
        } else if (useSite instanceof Value) {
            Value value = (Value) useSite;
            TypeDeclaration decltype = typeFact().getValueDeclarationType().getDeclaration();
            if (value.isParameter() && !value.isShared() && !(value.isCaptured() && value.isMember())) {
                return target == OutputElement.PARAMETER;
            } else if (annotationCtorDecl instanceof AnnotationProxyMethod) {
                if (value.isLate() || value.isVariable()) {
                    return target == OutputElement.SETTER;
                } else if (!value.isTransient()) {
                    return target == OutputElement.FIELD;
                } else {
                    return target == OutputElement.GETTER;
                }
            } else {
                return target == OutputElement.GETTER;
            }
        } else if (useSite instanceof Setter) {
            return target == OutputElement.SETTER;
        } else if (useSite instanceof Function) {
            return target == OutputElement.METHOD;
        } else if (useSite instanceof Constructor) {
            return target == OutputElement.CONSTRUCTOR;
        } else if (useSite instanceof TypeAlias) {
            return target == OutputElement.TYPE;
        }
    } else if (useSite instanceof Package) {
        return target == OutputElement.TYPE;
    } else if (useSite instanceof Module) {
        return target == OutputElement.TYPE;
    } else if (useSite instanceof Tree.ImportModule) {
        return target == OutputElement.FIELD;
    }
    throw new RuntimeException("" + useSite);
}
Also used : AnnotationTarget(com.redhat.ceylon.model.loader.model.AnnotationTarget) AnnotationProxyMethod(com.redhat.ceylon.model.loader.model.AnnotationProxyMethod) Constructor(com.redhat.ceylon.model.typechecker.model.Constructor) TypeAlias(com.redhat.ceylon.model.typechecker.model.TypeAlias) Functional(com.redhat.ceylon.model.typechecker.model.Functional) Function(com.redhat.ceylon.model.typechecker.model.Function) FunctionOrValue(com.redhat.ceylon.model.typechecker.model.FunctionOrValue) FieldValue(com.redhat.ceylon.model.loader.model.FieldValue) Value(com.redhat.ceylon.model.typechecker.model.Value) Setter(com.redhat.ceylon.model.typechecker.model.Setter) JCTree(com.sun.tools.javac.tree.JCTree) Tree(com.redhat.ceylon.compiler.typechecker.tree.Tree) Class(com.redhat.ceylon.model.typechecker.model.Class) JCNewClass(com.sun.tools.javac.tree.JCTree.JCNewClass) TypedDeclaration(com.redhat.ceylon.model.typechecker.model.TypedDeclaration) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Package(com.redhat.ceylon.model.typechecker.model.Package) Module(com.redhat.ceylon.model.typechecker.model.Module) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Interface(com.redhat.ceylon.model.typechecker.model.Interface) ClassOrInterface(com.redhat.ceylon.model.typechecker.model.ClassOrInterface)

Example 2 with AnnotationProxyMethod

use of com.redhat.ceylon.model.loader.model.AnnotationProxyMethod in project ceylon-compiler by ceylon.

the class AnnotationUtil method interopAnnotationTargeting.

/**
 * Returns the set of output program elements that the given annotation
 * could be applied to. If the {@code errors} flag is true then add
 * warnings/errors to the tree about ambigous/impossible targets.
 */
public static EnumSet<OutputElement> interopAnnotationTargeting(EnumSet<OutputElement> outputs, Tree.Annotation annotation, boolean errors) {
    Declaration annoCtor = ((Tree.BaseMemberExpression) annotation.getPrimary()).getDeclaration();
    if (annoCtor instanceof AnnotationProxyMethod) {
        AnnotationProxyMethod proxyCtor = (AnnotationProxyMethod) annoCtor;
        AnnotationProxyClass annoClass = proxyCtor.getProxyClass();
        EnumSet<OutputElement> possibleTargets;
        if (proxyCtor.getAnnotationTarget() != null) {
            possibleTargets = EnumSet.of(proxyCtor.getAnnotationTarget());
        } else {
            possibleTargets = AnnotationTarget.outputTargets(annoClass);
        }
        EnumSet<OutputElement> actualTargets = possibleTargets.clone();
        actualTargets.retainAll(outputs);
        if (actualTargets.size() > 1) {
            if (errors) {
                StringBuffer sb = new StringBuffer();
                sb.append("ambiguous annotation target: ").append(annoCtor.getName());
                sb.append(" could be applied to several targets, use one of ");
                for (Iterator<OutputElement> iterator = actualTargets.iterator(); iterator.hasNext(); ) {
                    OutputElement x = iterator.next();
                    sb.append(Naming.getDisambigAnnoCtorName((Interface) ((AnnotationProxyMethod) annoCtor).getProxyClass().iface, x));
                    if (iterator.hasNext()) {
                        sb.append(", ");
                    }
                }
                sb.append(" to disambiguate");
                annotation.addUsageWarning(Warning.ambiguousAnnotation, sb.toString(), Backend.Java);
            }
            return null;
        } else if (actualTargets.size() == 0) {
            if (errors) {
                annotation.addError("no target for " + annoCtor.getName() + " annotation: @Target of @interface " + ((AnnotationProxyClass) annoClass).iface.getName() + " lists " + possibleTargets + " but annotated element tranforms to " + outputs, Backend.Java);
            }
        }
        return actualTargets;
    } else {
        return null;
    }
}
Also used : AnnotationProxyMethod(com.redhat.ceylon.model.loader.model.AnnotationProxyMethod) OutputElement(com.redhat.ceylon.model.loader.model.OutputElement) AnnotationProxyClass(com.redhat.ceylon.model.loader.model.AnnotationProxyClass) Declaration(com.redhat.ceylon.model.typechecker.model.Declaration) TypeDeclaration(com.redhat.ceylon.model.typechecker.model.TypeDeclaration) Interface(com.redhat.ceylon.model.typechecker.model.Interface)

Aggregations

AnnotationProxyMethod (com.redhat.ceylon.model.loader.model.AnnotationProxyMethod)2 Declaration (com.redhat.ceylon.model.typechecker.model.Declaration)2 Interface (com.redhat.ceylon.model.typechecker.model.Interface)2 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)2 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)1 AnnotationProxyClass (com.redhat.ceylon.model.loader.model.AnnotationProxyClass)1 AnnotationTarget (com.redhat.ceylon.model.loader.model.AnnotationTarget)1 FieldValue (com.redhat.ceylon.model.loader.model.FieldValue)1 OutputElement (com.redhat.ceylon.model.loader.model.OutputElement)1 Class (com.redhat.ceylon.model.typechecker.model.Class)1 ClassOrInterface (com.redhat.ceylon.model.typechecker.model.ClassOrInterface)1 Constructor (com.redhat.ceylon.model.typechecker.model.Constructor)1 Function (com.redhat.ceylon.model.typechecker.model.Function)1 FunctionOrValue (com.redhat.ceylon.model.typechecker.model.FunctionOrValue)1 Functional (com.redhat.ceylon.model.typechecker.model.Functional)1 Module (com.redhat.ceylon.model.typechecker.model.Module)1 Package (com.redhat.ceylon.model.typechecker.model.Package)1 Setter (com.redhat.ceylon.model.typechecker.model.Setter)1 TypeAlias (com.redhat.ceylon.model.typechecker.model.TypeAlias)1 TypedDeclaration (com.redhat.ceylon.model.typechecker.model.TypedDeclaration)1