Search in sources :

Example 16 with Unit

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

the class AnnotationVisitor method visit.

@Override
public void visit(Tree.Constructor that) {
    super.visit(that);
    Function f = that.getDeclarationModel();
    Unit unit = that.getUnit();
    checkAnnotations(that.getAnnotationList(), unit.getCallableConstructorDeclarationType(), unit.getConstructorMetatype(f.getTypedReference()), that);
}
Also used : Function(org.eclipse.ceylon.model.typechecker.model.Function) Unit(org.eclipse.ceylon.model.typechecker.model.Unit)

Example 17 with Unit

use of org.eclipse.ceylon.model.typechecker.model.Unit 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 18 with Unit

use of org.eclipse.ceylon.model.typechecker.model.Unit 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 19 with Unit

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

the class AnnotationVisitor method visit.

@Override
public void visit(Tree.TypeConstraint that) {
    Tree.SatisfiedTypes sts = that.getSatisfiedTypes();
    if (sts != null) {
        Unit unit = that.getUnit();
        for (Tree.StaticType t : sts.getTypes()) {
            Type type = t.getTypeModel();
            if (type != null && unit.isJavaArrayType(type)) {
                t.addError("type parameter upper bound is a Java array type");
            }
        }
    }
    super.visit(that);
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Unit(org.eclipse.ceylon.model.typechecker.model.Unit)

Example 20 with Unit

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

the class Strategy method inlinePowerAsMultiplication.

/**
 * Determines whether we should inline {@code x^n} as a repeated multiplication
 * ({@code x*x*...*x}) instead of calling {@code x.power(n)}.
 */
public static boolean inlinePowerAsMultiplication(Tree.PowerOp op) {
    java.lang.Number power_;
    try {
        power_ = ExpressionTransformer.getIntegerLiteralPower(op);
        if (power_ != null) {
            long power = power_.longValue();
            Unit unit = op.getUnit();
            Type baseType = op.getLeftTerm().getTypeModel();
            // up bloating the code (e.g. imagine x^1_000_000_000)
            if (power > 0 && power <= 64 && baseType.isExactly(unit.getIntegerType())) {
                return true;
            } else if (power > 0 && power <= 64 && baseType.isExactly(unit.getFloatType())) {
                return true;
            }
        }
    } catch (ErroneousException e) {
        return false;
    }
    return false;
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) Unit(org.eclipse.ceylon.model.typechecker.model.Unit)

Aggregations

Unit (org.eclipse.ceylon.model.typechecker.model.Unit)82 Type (org.eclipse.ceylon.model.typechecker.model.Type)41 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)31 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)25 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)23 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)16 AnalyzerUtil.getTypedDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration)11 ArrayList (java.util.ArrayList)10 Class (org.eclipse.ceylon.model.typechecker.model.Class)10 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)10 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)9 Function (org.eclipse.ceylon.model.typechecker.model.Function)9 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)9 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)9 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)9 Value (org.eclipse.ceylon.model.typechecker.model.Value)9 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)7 Module (org.eclipse.ceylon.model.typechecker.model.Module)7 IntersectionType (org.eclipse.ceylon.model.typechecker.model.IntersectionType)6 LazyType (org.eclipse.ceylon.model.typechecker.model.LazyType)6