Search in sources :

Example 1 with AnnotationProxyMethod

use of org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod in project ceylon by eclipse.

the class AnnotationUtil 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
 */
public static 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.getAnnotationTargets();
    } 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) {
                // If the constructor has a getter we can't annotate, let's
                // put the annotations on the constructor
                Class constructedClass = ModelUtil.getConstructedClass((Declaration) useSite);
                // See CeylonVisitor.transformSingletonConstructor for those tests
                if (constructedClass.isToplevel() || constructedClass.isClassMember())
                    return target == OutputElement.GETTER;
                return target == OutputElement.CONSTRUCTOR;
            }
        } 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;
            boolean p = value.isParameter() && target == OutputElement.PARAMETER;
            if (annotationCtorDecl instanceof AnnotationProxyMethod) {
                if (!value.isTransient() && (interopTargets == null || interopTargets.contains(AnnotationTarget.FIELD))) {
                    return target == OutputElement.FIELD;
                } else {
                    return target == OutputElement.GETTER;
                }
            } else {
                return p || 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 (annotationCtorDecl instanceof AnnotationProxyMethod) ? target == OutputElement.PACKAGE : 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(org.eclipse.ceylon.model.loader.model.AnnotationTarget) AnnotationProxyMethod(org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) TypeAlias(org.eclipse.ceylon.model.typechecker.model.TypeAlias) Functional(org.eclipse.ceylon.model.typechecker.model.Functional) Function(org.eclipse.ceylon.model.typechecker.model.Function) Value(org.eclipse.ceylon.model.typechecker.model.Value) Setter(org.eclipse.ceylon.model.typechecker.model.Setter) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnnotationProxyClass(org.eclipse.ceylon.model.loader.model.AnnotationProxyClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Package(org.eclipse.ceylon.model.typechecker.model.Package) Module(org.eclipse.ceylon.model.typechecker.model.Module) Interface(org.eclipse.ceylon.model.typechecker.model.Interface)

Example 2 with AnnotationProxyMethod

use of org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod in project ceylon by eclipse.

the class AbstractModelLoader method makeInteropAnnotationConstructor.

public AnnotationProxyMethod makeInteropAnnotationConstructor(LazyInterface iface, AnnotationProxyClass klass, OutputElement oe, Scope scope) {
    String ctorName = oe == null ? NamingBase.getJavaBeanName(iface.getName()) : NamingBase.getDisambigAnnoCtorName(iface, oe);
    AnnotationProxyMethod ctor = new AnnotationProxyMethod(this, klass, oe);
    ctor.setAnnotationTarget(oe);
    ctor.setContainer(scope);
    ctor.setScope(scope);
    if (!(scope instanceof Package)) {
        ctor.setStatic(true);
    }
    ctor.setAnnotation(true);
    ctor.setName(ctorName);
    ctor.setShared(iface.isShared());
    Annotation annotationAnnotation2 = new Annotation();
    annotationAnnotation2.setName("annotation");
    ctor.getAnnotations().add(annotationAnnotation2);
    ctor.setType(((TypeDeclaration) iface).getType());
    ctor.setUnit(iface.getUnit());
    return ctor;
}
Also used : AnnotationProxyMethod(org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod) LazyPackage(org.eclipse.ceylon.model.loader.model.LazyPackage) Package(org.eclipse.ceylon.model.typechecker.model.Package) Annotation(org.eclipse.ceylon.model.typechecker.model.Annotation)

Example 3 with AnnotationProxyMethod

use of org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod in project ceylon by eclipse.

the class AbstractModelLoader method makeInteropAnnotation.

/**
 * Creates extra members to be added to the {@code container} for annotation interop.
 * For a Java declaration {@code @interface Annotation} we generate
 * a model corresponding to:
 * <pre>
 *   annotation class Annotation$Proxy(...) satisfies Annotation {
 *       // a `shared` class parameter for each method of Annotation
 *   }
 *   annotation JavaAnnotation javaAnnotation(...) => JavaAnnotation$Proxy(...);
 * </pre>
 *
 * We also make a {@code *__method}, {@code *__field} etc version for each
 * {@code @Target} program element
 * @param iface The model of the annotation @interface
 * @param container The container in which the generated members belong
 * @return A list of members to add to the container
 */
public List<Declaration> makeInteropAnnotation(LazyInterface iface, Scope container) {
    List<Declaration> declarations = new ArrayList<>();
    AnnotationProxyClass klass = makeInteropAnnotationClass(iface, container);
    AnnotationProxyMethod method = makeInteropAnnotationConstructor(iface, klass, null, container);
    declarations.add(method);
    for (OutputElement target : AnnotationTarget.outputTargets(klass)) {
        declarations.add(makeInteropAnnotationConstructor(iface, klass, target, container));
    }
    declarations.add(klass);
    return declarations;
}
Also used : AnnotationProxyMethod(org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod) OutputElement(org.eclipse.ceylon.model.loader.model.OutputElement) ArrayList(java.util.ArrayList) AnnotationProxyClass(org.eclipse.ceylon.model.loader.model.AnnotationProxyClass) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration)

Example 4 with AnnotationProxyMethod

use of org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod in project ceylon by eclipse.

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 ambiguous/impossible targets.
 */
public static EnumSet<OutputElement> interopAnnotationTargeting(boolean isEe, EnumSet<OutputElement> outputs, Tree.Annotation annotation, boolean errors, boolean warnings, Declaration d) {
    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 (warnings) {
                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);
            }
            checkForLateFieldAnnotation(isEe, annotation, d, annoCtor, possibleTargets, actualTargets);
            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);
            }
        }
        checkForLateFieldAnnotation(isEe, annotation, d, annoCtor, possibleTargets, actualTargets);
        return actualTargets;
    } else {
        return null;
    }
}
Also used : AnnotationProxyMethod(org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod) OutputElement(org.eclipse.ceylon.model.loader.model.OutputElement) AnnotationProxyClass(org.eclipse.ceylon.model.loader.model.AnnotationProxyClass) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Interface(org.eclipse.ceylon.model.typechecker.model.Interface)

Aggregations

AnnotationProxyMethod (org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod)4 AnnotationProxyClass (org.eclipse.ceylon.model.loader.model.AnnotationProxyClass)3 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)3 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)3 OutputElement (org.eclipse.ceylon.model.loader.model.OutputElement)2 Interface (org.eclipse.ceylon.model.typechecker.model.Interface)2 Package (org.eclipse.ceylon.model.typechecker.model.Package)2 ArrayList (java.util.ArrayList)1 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)1 AnnotationTarget (org.eclipse.ceylon.model.loader.model.AnnotationTarget)1 LazyPackage (org.eclipse.ceylon.model.loader.model.LazyPackage)1 Annotation (org.eclipse.ceylon.model.typechecker.model.Annotation)1 Class (org.eclipse.ceylon.model.typechecker.model.Class)1 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)1 Function (org.eclipse.ceylon.model.typechecker.model.Function)1 Functional (org.eclipse.ceylon.model.typechecker.model.Functional)1 Module (org.eclipse.ceylon.model.typechecker.model.Module)1 Setter (org.eclipse.ceylon.model.typechecker.model.Setter)1 TypeAlias (org.eclipse.ceylon.model.typechecker.model.TypeAlias)1 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)1