Search in sources :

Example 1 with OutputElement

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

the class AnnotationUtil method outputs.

public static EnumSet<OutputElement> outputs(Tree.AttributeDeclaration that) {
    EnumSet<OutputElement> result = EnumSet.noneOf(OutputElement.class);
    Value declarationModel = that.getDeclarationModel();
    if (declarationModel != null) {
        if (declarationModel.isClassMember()) {
            if (declarationModel.isParameter()) {
                result.add(PARAMETER);
            }
            if (ModelUtil.isCaptured(declarationModel)) {
                result.add(GETTER);
                if (!(that.getSpecifierOrInitializerExpression() instanceof Tree.LazySpecifierExpression)) {
                    result.add(FIELD);
                }
            } else if (!declarationModel.isParameter()) {
                result.add(LOCAL_VARIABLE);
            }
        } else if (declarationModel.isInterfaceMember()) {
            result.add(GETTER);
        } else if (declarationModel.isToplevel()) {
            result.add(GETTER);
            // only non-lazy get fields
            if (!declarationModel.isTransient())
                result.add(FIELD);
        } else {
            if (declarationModel.isParameter()) {
                result.add(PARAMETER);
            } else {
                result.add(LOCAL_VARIABLE);
            }
        }
    }
    if (result.contains(GETTER) && // variables with lazy value MUST have a distinct setter
    ((declarationModel.isVariable() && !declarationModel.isTransient()) || declarationModel.isLate())) {
        result.add(SETTER);
    }
    return result;
}
Also used : OutputElement(org.eclipse.ceylon.model.loader.model.OutputElement) Value(org.eclipse.ceylon.model.typechecker.model.Value)

Example 2 with OutputElement

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

the class ExpressionTransformer method transform.

private List<JCAnnotation> transform(Object useSite, OutputElement target, Tree.AnnotationList annotationList, EnumSet<OutputElement> outputs) {
    if (annotationList == null) {
        return List.nil();
    }
    if ((gen().disableAnnotations & CeylonTransformer.DISABLE_USER_ANNOS) != 0) {
        return List.nil();
    }
    LinkedHashMap<Class, ListBuffer<JCAnnotation>> annotationSet = new LinkedHashMap<>();
    if (annotationList != null) {
        if (annotationList.getAnonymousAnnotation() != null && AnnotationUtil.isNaturalTarget((Function) typeFact().getLanguageModuleDeclaration("doc"), useSite, target)) {
            transformAnonymousAnnotation(annotationList.getAnonymousAnnotation(), annotationSet);
        }
        if (annotationList.getAnnotations() != null) {
            for (Tree.Annotation annotation : annotationList.getAnnotations()) {
                Function annoCtorDecl = ((Function) ((Tree.BaseMemberExpression) annotation.getPrimary()).getDeclaration());
                if (annoCtorDecl != null) {
                    String aname = annoCtorDecl.getQualifiedNameString();
                    if ("java.lang::transient".equals(aname) || "java.lang::volatile".equals(aname) || "java.lang::synchronized".equals(aname) || "java.lang::native".equals(aname) || "java.lang::strictfp".equals(aname) || "java.lang::overloaded".equals(aname) || "java.lang::nonbean".equals(aname)) {
                        continue;
                    }
                }
                boolean isNaturalTarget = AnnotationUtil.isNaturalTarget(annoCtorDecl, useSite, target);
                EnumSet<OutputElement> possibleTargets = AnnotationUtil.interopAnnotationTargeting(useSite instanceof Declaration ? isEe((Declaration) useSite) : false, outputs, annotation, false, false, useSite instanceof Declaration ? (Declaration) useSite : null);
                if ((isNaturalTarget && possibleTargets == null) || (possibleTargets != null && possibleTargets.equals(EnumSet.of(target)))) {
                    transformAnnotation(annotation, annotationSet);
                }
            }
        }
    }
    ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
    for (Class annotationClass : annotationSet.keySet()) {
        ListBuffer<JCAnnotation> annotations = annotationSet.get(annotationClass);
        if (isSequencedAnnotation(annotationClass)) {
            JCAnnotation wrapperAnnotation = make().Annotation(makeJavaType(annotationClass.getType(), JT_ANNOTATIONS), List.<JCExpression>of(make().NewArray(null, null, upcastExprList(annotations.toList()))));
            result.append(wrapperAnnotation);
        } else if (isRepeatableAnnotation(annotationClass)) {
            Interface containerAnnotation = getRepeatableContainer(annotationClass);
            JCAnnotation wrapperAnnotation = make().Annotation(makeJavaType(containerAnnotation.appliedType(null, Collections.<Type>emptyList())), List.<JCExpression>of(make().NewArray(null, null, upcastExprList(annotations.toList()))));
            result.append(wrapperAnnotation);
        } else {
            if (annotations.size() > 1) {
                makeErroneous(annotationList, "compiler bug: multiple occurances of non-sequenced annotation class " + annotationClass.getQualifiedNameString());
            }
            result.appendList(annotations);
        }
    }
    // Special case: Generate a @java.lang.Deprecated() if Ceylon deprecated
    if (annotationList != null) {
        for (Tree.Annotation annotation : annotationList.getAnnotations()) {
            if (AnnotationUtil.isNaturalTarget((Function) typeFact().getLanguageModuleDeclaration("deprecated"), useSite, target) && isDeprecatedAnnotation(annotation.getPrimary()) && !(useSite instanceof Function) && !(useSite instanceof Constructor)) {
                result.appendList(makeAtDeprecated());
            }
        }
    }
    return result.toList();
}
Also used : Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) ListBuffer(org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer) LinkedHashMap(java.util.LinkedHashMap) Function(org.eclipse.ceylon.model.typechecker.model.Function) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) JCExpression(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression) OutputElement(org.eclipse.ceylon.model.loader.model.OutputElement) JCTree(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) JCNewClass(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) JCAnnotation(org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface)

Example 3 with OutputElement

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

the class UnsupportedVisitor method interopAnnotationTargeting.

private void interopAnnotationTargeting(EnumSet<OutputElement> outputs, Tree.AnnotationList annotationList, Tree.Declaration annotated) {
    OutputElement target = null;
    // let's do them as they come. See https://github.com/ceylon/ceylon/issues/5751
    if (annotated instanceof Tree.AttributeDeclaration) {
        if (((Tree.AttributeDeclaration) annotated).getSpecifierOrInitializerExpression() instanceof Tree.LazySpecifierExpression)
            target = OutputElement.METHOD;
        else
            target = OutputElement.FIELD;
    }
    Declaration useSite = annotated.getDeclarationModel();
    List<Annotation> annotations = annotationList.getAnnotations();
    for (Tree.Annotation annotation : annotations) {
        Function annoCtorDecl = ((Function) ((Tree.BaseMemberExpression) annotation.getPrimary()).getDeclaration());
        boolean addWarnings = true;
        // only add warnings if we don't have a natural target to pick from
        if (target != null) {
            addWarnings = !AnnotationUtil.isNaturalTarget(annoCtorDecl, useSite, target);
        }
        AnnotationUtil.interopAnnotationTargeting(eeVisitor.isEeMode(useSite), outputs, annotation, true, addWarnings, annotated.getDeclarationModel());
    }
    AnnotationUtil.duplicateInteropAnnotation(eeVisitor.isEeMode(useSite), outputs, annotations, annotated.getDeclarationModel());
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) OutputElement(org.eclipse.ceylon.model.loader.model.OutputElement) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Annotation(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Annotation) Annotation(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Annotation)

Example 4 with OutputElement

use of org.eclipse.ceylon.model.loader.model.OutputElement 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 5 with OutputElement

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

the class AnnotationUtil method duplicateInteropAnnotation.

public static void duplicateInteropAnnotation(boolean isEe, EnumSet<OutputElement> outputs, List<Annotation> annotations, Declaration d) {
    for (int i = 0; i < annotations.size(); i++) {
        Tree.Annotation ann = annotations.get(i);
        Type t = ann.getTypeModel();
        EnumSet<OutputElement> mainTargets = interopAnnotationTargeting(isEe, outputs, ann, false, false, d);
        if (t != null && mainTargets != null) {
            TypeDeclaration td = t.getDeclaration();
            if (!ModelUtil.isCeylonDeclaration(td)) {
                for (int j = 0; j < i; j++) {
                    Tree.Annotation other = annotations.get(j);
                    Type ot = other.getTypeModel();
                    if (ot != null) {
                        TypeDeclaration otd = ot.getDeclaration();
                        if (otd.equals(td)) {
                            // check if they have the same targets (if not that's fine)
                            EnumSet<OutputElement> dupeTargets = interopAnnotationTargeting(isEe, outputs, other, false, false, d);
                            if (dupeTargets != null) {
                                EnumSet<OutputElement> sameTargets = intersection(mainTargets, dupeTargets);
                                if (!sameTargets.isEmpty()) {
                                    ann.addError("duplicate annotation: there are multiple annotations of type '" + td.getName() + "' for targets: '" + sameTargets + "'");
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) OutputElement(org.eclipse.ceylon.model.loader.model.OutputElement) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Annotation(org.eclipse.ceylon.compiler.typechecker.tree.Tree.Annotation) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Aggregations

OutputElement (org.eclipse.ceylon.model.loader.model.OutputElement)6 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)4 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)4 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)3 Annotation (org.eclipse.ceylon.compiler.typechecker.tree.Tree.Annotation)2 AnnotationProxyClass (org.eclipse.ceylon.model.loader.model.AnnotationProxyClass)2 AnnotationProxyMethod (org.eclipse.ceylon.model.loader.model.AnnotationProxyMethod)2 Function (org.eclipse.ceylon.model.typechecker.model.Function)2 Interface (org.eclipse.ceylon.model.typechecker.model.Interface)2 Type (org.eclipse.ceylon.model.typechecker.model.Type)2 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)2 ArrayList (java.util.ArrayList)1 LinkedHashMap (java.util.LinkedHashMap)1 JCTree (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree)1 JCAnnotation (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCAnnotation)1 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)1 JCNewClass (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCNewClass)1 ListBuffer (org.eclipse.ceylon.langtools.tools.javac.util.ListBuffer)1 LazyInterface (org.eclipse.ceylon.model.loader.model.LazyInterface)1 Class (org.eclipse.ceylon.model.typechecker.model.Class)1