Search in sources :

Example 36 with TypeDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.

the class AnnotationVisitor method checkAnnotationConstructor.

private void checkAnnotationConstructor(Tree.AnyMethod that, Function a) {
    Tree.Type type = that.getType();
    if (type != null) {
        Type t = type.getTypeModel();
        if (t != null) {
            TypeDeclaration td = t.getDeclaration();
            if (td != null) {
                if (td.isAnnotation()) {
                    Unit unit = that.getUnit();
                    TypeDeclaration annotationDec = unit.getAnnotationDeclaration();
                    if (t.isNothing()) {
                        that.addError("annotation constructor may not return 'Nothing'");
                    }
                    if (!td.inherits(annotationDec)) {
                        that.addError("annotation constructor must return a subtype of 'Annotation'");
                    }
                    if (!unit.getPackage().isLanguagePackage()) {
                        boolean langPackage = td.getUnit().getPackage().isLanguagePackage();
                        String typeName = td.getName();
                        if (langPackage && (typeName.equals("Shared") || typeName.equals("Abstract") || typeName.equals("Default") || typeName.equals("Formal") || typeName.equals("Actual") || typeName.equals("Final") || typeName.equals("Variable") || typeName.equals("Late") || typeName.equals("Native") || typeName.equals("Deprecated") || typeName.equals("Annotation"))) {
                            type.addError("annotation constructor may not return modifier annotation type");
                        }
                    }
                } else {
                    type.addError("annotation constructor must return an annotation type");
                }
            }
        }
    }
    List<Tree.ParameterList> pls = that.getParameterLists();
    if (pls.size() == 1) {
        for (Tree.Parameter pn : pls.get(0).getParameters()) {
            checkAnnotationParameter(a, pn);
        }
    } else {
        that.addError("annotation constructor must have exactly one parameter list");
    }
    if (that instanceof Tree.MethodDefinition) {
        Tree.MethodDefinition md = (Tree.MethodDefinition) that;
        Tree.Block block = md.getBlock();
        if (block != null) {
            List<Tree.Statement> list = getExecutableStatements(block);
            if (list.size() == 1) {
                Tree.Statement s = list.get(0);
                if (s instanceof Tree.Return) {
                    Tree.Return r = (Tree.Return) s;
                    Tree.Expression e = r.getExpression();
                    checkAnnotationInstantiation(a, e, "annotation constructor must return a newly-instantiated annotation");
                } else {
                    s.addError("annotation constructor body must return an annotation instance");
                }
            } else {
                block.addError("annotation constructor body must have exactly one statement");
            }
        }
    } else {
        Tree.MethodDeclaration md = (Tree.MethodDeclaration) that;
        Tree.SpecifierExpression se = md.getSpecifierExpression();
        if (se != null) {
            checkAnnotationInstantiation(a, se.getExpression(), "annotation constructor must return a newly-instantiated annotation");
        }
    }
}
Also used : AnalyzerUtil.isExecutableStatement(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.isExecutableStatement) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) Type(org.eclipse.ceylon.model.typechecker.model.Type) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 37 with TypeDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.

the class AnnotationVisitor method checkAnnotations.

private void checkAnnotations(Tree.AnnotationList annotationList, Type declarationType, Type modelType, Node that) {
    Unit unit = annotationList.getUnit();
    List<Tree.Annotation> annotations = annotationList.getAnnotations();
    for (Tree.Annotation annotation : annotations) {
        Type t = annotation.getTypeModel();
        if (t != null) {
            TypeDeclaration cad = unit.getConstrainedAnnotationDeclaration();
            Type cat = t.getSupertype(cad);
            if (cat != null) {
                // check *Ceylon* annotation constraints
                List<Type> args = cat.getTypeArgumentList();
                if (args.size() > 2) {
                    Type constraint = args.get(2);
                    checkAssignable(declarationType, constraint, annotation, "annotated program element does not satisfy annotation constraint");
                }
                if (args.size() > 3) {
                    Type constraint = args.get(3);
                    if (!constraint.isAnything()) {
                        checkAssignable(modelType, constraint, annotation, "annotated program element does not satisfy annotation constraint");
                    }
                }
            }
            EnumSet<AnnotationTarget> target = null;
            Tree.Primary primary = annotation.getPrimary();
            if (primary instanceof Tree.MemberOrTypeExpression) {
                Declaration ac = ((Tree.MemberOrTypeExpression) primary).getDeclaration();
                if (ac instanceof TypedDeclaration) {
                    target = ((TypedDeclaration) ac).getAnnotationTargets();
                }
            }
            if (target != null) {
                // check the *Java* annotation constraints
                boolean ok = false;
                if (that instanceof Tree.PackageDescriptor) {
                    if (target.contains(PACKAGE)) {
                        ok = true;
                    }
                }
                if (that instanceof Tree.InterfaceDefinition) {
                    if (target.contains(TYPE)) {
                        ok = true;
                    }
                }
                if (that instanceof Tree.ClassDefinition) {
                    Tree.ClassDefinition c = (Tree.ClassDefinition) that;
                    boolean initializer = c.getParameterList() != null;
                    if (target.contains(TYPE)) {
                        // it always goes on the class,
                        // not on the constructor
                        ok = true;
                    }
                    if (target.contains(CONSTRUCTOR) && initializer) {
                        // it goes on the constructor
                        ok = true;
                    }
                    if (target.contains(ANNOTATION_TYPE) && c.getDeclarationModel().isAnnotation()) {
                        // it goes on the annotation type
                        ok = true;
                    }
                }
                if (that instanceof Tree.ObjectDefinition) {
                    if (target.contains(FIELD)) {
                        ok = true;
                    }
                }
                if (that instanceof Tree.Constructor || that instanceof Tree.Enumerated) {
                    if (target.contains(CONSTRUCTOR)) {
                        ok = true;
                    }
                }
                if (that instanceof Tree.MethodDefinition || that instanceof Tree.MethodDeclaration || that instanceof Tree.AttributeGetterDefinition || that instanceof Tree.AttributeSetterDefinition) {
                    if (target.contains(METHOD)) {
                        // it goes on the method, getter,
                        // or setter, unambiguously
                        ok = true;
                    }
                }
                if (that instanceof Tree.AttributeDeclaration) {
                    Tree.AttributeDeclaration ad = (Tree.AttributeDeclaration) that;
                    Value model = ad.getDeclarationModel();
                    boolean parameter = model.isParameter();
                    boolean classMember = model.isClassMember();
                    boolean toplevel = model.isToplevel();
                    boolean local = !toplevel && !model.isClassOrInterfaceMember();
                    if (target.contains(PARAMETER) && parameter) {
                        // in this case there is a parameter,
                        // so the annotation *never* goes on
                        // the field, getter, nor setter
                        ok = true;
                    }
                    Tree.SpecifierOrInitializerExpression se = ad.getSpecifierOrInitializerExpression();
                    if (se instanceof Tree.LazySpecifierExpression || model.isFormal()) {
                        if (target.contains(METHOD)) {
                            // there is no field, so it
                            // goes on the getter
                            ok = true;
                        }
                    } else {
                        // if it's cannot go on the field
                        if (classMember || toplevel) {
                            if (target.contains(FIELD)) {
                                ok = true;
                            } else if (target.contains(METHOD)) {
                                ok = true;
                            }
                        }
                        if (target.contains(LOCAL_VARIABLE) && !parameter && local) {
                            ok = true;
                        }
                    }
                }
                if (!ok) {
                    StringBuilder message = new StringBuilder();
                    for (AnnotationTarget at : target) {
                        if (message.length() > 0) {
                            message.append(", ");
                        }
                        message.append(at);
                    }
                    annotation.addError("annotated program element does not satisfy annotation constraint: the annotation is declared 'target {" + message + "}'");
                }
            }
        }
    }
    TypeDeclaration od = unit.getOptionalAnnotationDeclaration();
    for (int i = 0; i < annotations.size(); i++) {
        Tree.Annotation ann = annotations.get(i);
        Type t = ann.getTypeModel();
        if (t != null) {
            TypeDeclaration td = t.getDeclaration();
            // this implicitly excludes Java annotations but they are checked in the backend for duplicates
            if (td.inherits(od)) {
                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)) {
                            ann.addError("duplicate annotation: there are multiple annotations of type '" + td.getName() + "'");
                            break;
                        }
                    }
                }
            }
        }
    }
}
Also used : Unit(org.eclipse.ceylon.model.typechecker.model.Unit) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) AnnotationTarget(org.eclipse.ceylon.model.loader.model.AnnotationTarget) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) Type(org.eclipse.ceylon.model.typechecker.model.Type) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 38 with TypeDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.

the class ExpressionVisitor method handleStaticReferenceImplicitTypeArguments.

/**
 * Validate the type arguments to the qualifying type
 * in a static reference when no type arguments are
 * given explicitly.
 *
 * This is called later than usual because the type args
 * might be inferrable from an invocation of the whole
 * static reference.
 *
 * @param that the static reference
 */
private void handleStaticReferenceImplicitTypeArguments(Tree.QualifiedMemberOrTypeExpression that) {
    Declaration member = that.getDeclaration();
    Tree.TypeArguments tas = that.getTypeArguments();
    // without type arguments to the qualifying type
    if (isStaticReference(that)) {
        if (member != null && !explicitTypeArguments(member, tas)) {
            that.addError("type arguments could not be inferred: '" + member.getName(unit) + "' is generic");
        }
        // the reference to the qualifying type
        Tree.StaticMemberOrTypeExpression smte = (Tree.StaticMemberOrTypeExpression) that.getPrimary();
        // we have to get the type args from the tree
        // here because the calling code doesn't know
        // them (it is walking the qualifying reference)
        Tree.TypeArguments typeArgs = smte.getTypeArguments();
        TypeDeclaration type = (TypeDeclaration) smte.getDeclaration();
        if (type != null && !explicitTypeArguments(type, typeArgs) && typeArgs.getTypeModels() == null) {
            // nothing inferred
            Declaration declaration = smte.getDeclaration();
            smte.addError("missing type arguments to generic type qualifying static reference: '" + declaration.getName(unit) + "' declares type parameters " + typeParameterList(declaration));
        }
    }
    Tree.Primary primary = that.getPrimary();
    if (!that.getDirectlyInvoked() && (member.isStatic() || isConstructor(member)) && primary instanceof Tree.StaticMemberOrTypeExpression) {
        Tree.StaticMemberOrTypeExpression smte = (Tree.StaticMemberOrTypeExpression) primary;
        Declaration qualifyingType = smte.getDeclaration();
        Tree.TypeArguments qtas = smte.getTypeArguments();
        if (qualifyingType != null && qualifyingType.isParameterized() && !qualifyingType.isJava() && !explicitTypeArguments(qualifyingType, qtas)) {
            if (explicitTypeArguments(member, tas)) {
                Type functionType = genericFunctionType(qualifyingType, that.getScope(), member, that.getTarget(), unit);
                that.setTypeModel(functionType);
                checkNotJvm(that, "type functions are not supported on the JVM: '" + qualifyingType.getName(unit) + "' is generic (specify explicit type arguments)");
            } else {
                that.addError("missing explicit type arguments to generic qualifying type: '" + qualifyingType.getName(unit) + "' declares type parameters " + typeParameterList(qualifyingType));
            }
        }
    }
}
Also used : ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) ModelUtil.getNativeDeclaration(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getNativeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)

Example 39 with TypeDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.

the class ExpressionVisitor method getDeclaration.

private TypeDeclaration getDeclaration(Tree.QualifiedMemberOrTypeExpression that, Type pt) {
    TypeDeclaration td;
    if (that.getStaticMethodReference()) {
        Tree.MemberOrTypeExpression primary = (Tree.MemberOrTypeExpression) that.getPrimary();
        td = (TypeDeclaration) primary.getDeclaration();
        td = td == null ? new UnknownType(unit) : td;
    } else {
        td = unwrap(pt, that).getDeclaration();
    }
    if (td != null && td.isNativeImplementation()) {
        TypeDeclaration header = (TypeDeclaration) getNativeHeader(td);
        if (header != null) {
            td = header;
        }
    }
    return td;
}
Also used : UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) CustomTree(org.eclipse.ceylon.compiler.typechecker.tree.CustomTree) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)

Example 40 with TypeDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration in project ceylon by eclipse.

the class ExpressionVisitor method enterConstructorDelegation.

private TypeDeclaration enterConstructorDelegation(Constructor c) {
    TypeDeclaration occ = constructorClass;
    Type et = c.getExtendedType();
    constructorClass = et == null ? null : et.getDeclaration();
    return occ;
}
Also used : ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.unionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.unionType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) ModelUtil.genericFunctionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.genericFunctionType) AnalyzerUtil.getPackageTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypeDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)

Aggregations

TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)303 Type (org.eclipse.ceylon.model.typechecker.model.Type)180 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)88 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)86 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)80 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)70 Class (org.eclipse.ceylon.model.typechecker.model.Class)68 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)65 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)57 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)57 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)55 IntersectionType (org.eclipse.ceylon.model.typechecker.model.IntersectionType)51 Test (org.junit.Test)51 AnalyzerUtil.getPackageTypeDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration)49 AnalyzerUtil.getTypeDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)49 ArrayList (java.util.ArrayList)48 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)44 Interface (org.eclipse.ceylon.model.typechecker.model.Interface)43 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)39 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)34