Search in sources :

Example 31 with Unit

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

the class InheritanceVisitor method checkExtensionOfMemberType.

private void checkExtensionOfMemberType(Node that, TypeDeclaration td, Type type) {
    Type qt = type.getQualifyingType();
    if (qt != null && td instanceof ClassOrInterface) {
        Unit unit = that.getUnit();
        TypeDeclaration d = type.getDeclaration();
        if (d.isStatic() || d instanceof Constructor) {
            checkExtensionOfMemberType(that, td, qt);
        } else {
            Scope s = td;
            while (s != null) {
                s = s.getContainer();
                if (s instanceof TypeDeclaration) {
                    TypeDeclaration otd = (TypeDeclaration) s;
                    if (otd.getType().isSubtypeOf(qt)) {
                        return;
                    }
                }
            }
            that.addError("qualifying type '" + qt.asString(unit) + "' of supertype '" + type.asString(unit) + "' is not an outer type or supertype of any outer type of '" + td.getName(unit) + "'");
        }
    }
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) Type(org.eclipse.ceylon.model.typechecker.model.Type) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 32 with Unit

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

the class InheritanceVisitor method validateEnumeratedSupertypeArgument.

private void validateEnumeratedSupertypeArgument(Node that, TypeDeclaration type, Type supertype, TypeParameter tp, Type arg) {
    Unit unit = that.getUnit();
    if (arg.isTypeParameter()) {
        TypeParameter atp = (TypeParameter) arg.getDeclaration();
        if (atp.getDeclaration().equals(type)) {
            // parameter of the enumerated supertype
            if (tp.isCovariant() && !atp.isCovariant()) {
                that.addError("argument to covariant type parameter of enumerated supertype must be covariant: " + typeDescription(tp, unit));
            }
            if (tp.isContravariant() && !atp.isContravariant()) {
                that.addError("argument to contravariant type parameter of enumerated supertype must be contravariant: " + typeDescription(tp, unit));
            }
        } else {
            that.addError("argument to type parameter of enumerated supertype must be a type parameter of '" + type.getName() + "': " + typeDescription(tp, unit));
        }
    } else if (tp.isCovariant()) {
        if (!(arg.isNothing())) {
            // TODO: let it be the union of the lower bounds on p
            that.addError("argument to covariant type parameter of enumerated supertype must be a type parameter or 'Nothing': " + typeDescription(tp, unit));
        }
    } else if (tp.isContravariant()) {
        List<Type> sts = tp.getSatisfiedTypes();
        // TODO: do I need to do type arg substitution here??
        Type ub = intersectionOfSupertypes(tp);
        if (!(arg.isExactly(ub))) {
            that.addError("argument to contravariant type parameter of enumerated supertype must be a type parameter or '" + typeNamesAsIntersection(sts, unit) + "': " + typeDescription(tp, unit));
        }
    } else {
        that.addError("argument to type parameter of enumerated supertype must be a type parameter: " + typeDescription(tp, unit));
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) Unit(org.eclipse.ceylon.model.typechecker.model.Unit)

Example 33 with Unit

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

the class InheritanceVisitor method collectCaseValues.

void collectCaseValues(Tree.CaseTypes that, TypeDeclaration td) {
    Unit unit = that.getUnit();
    Set<Declaration> valueSet = new HashSet<Declaration>();
    for (Tree.StaticMemberOrTypeExpression bme : that.getBaseMemberExpressions()) {
        String name = name(bme.getIdentifier());
        TypedDeclaration value = bme instanceof Tree.BaseMemberExpression ? getTypedDeclaration(bme.getScope(), name, null, false, unit) : getPackageTypedDeclaration(name, null, false, unit);
        if (value != null) {
            if (value != null && !valueSet.add(value)) {
                // this error is not really truly necessary
                bme.addError("duplicate case: '" + value.getName(unit) + "' of '" + td.getName() + "'");
            }
            Type type = value.getType();
            if (type != null) {
                TypeDeclaration caseDec = type.getDeclaration();
                if (caseDec instanceof Constructor) {
                    Scope scope = caseDec.getContainer();
                    if (scope instanceof Class) {
                        // enumerated singleton constructors
                        Constructor cons = (Constructor) caseDec;
                        Class c = (Class) scope;
                        if (!c.isToplevel() && !c.isStatic()) {
                            bme.addError("case must be a value constructor of a toplevel or static class: '" + c.getName(unit) + "' is not toplevel");
                        } else if (!cons.getParameterLists().isEmpty()) {
                            bme.addError("case must be a value constructor of a toplevel or static class: '" + cons.getName(unit) + "' is not a value constructor");
                        }
                    /*else if (!c.inherits(unit.getIdentifiableDeclaration())) {
                                bme.addError("case must be a value constructor of an identifiable class: '" + 
                                        c.getName(unit) + 
                                        "' is not a subtype of 'Identifiable'");
                            }*/
                    }
                } else {
                    // enumerated anonymous subclasses
                    if (!caseDec.isObjectClass()) {
                        bme.addError("case must be a toplevel or static anonymous class: '" + value.getName(unit) + "' is not an anonymous class");
                    } else if (!value.isToplevel() && !value.isStatic()) {
                        bme.addError("case must be a toplevel or static anonymous class: '" + value.getName(unit) + "' is neither static nor toplevel");
                    }
                }
                if (checkDirectSubtype(td, bme, type)) {
                    checkAssignable(type, td.getType(), bme, getCaseTypeExplanation(td, type));
                }
            }
        }
    }
}
Also used : AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) Type(org.eclipse.ceylon.model.typechecker.model.Type) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Class(org.eclipse.ceylon.model.typechecker.model.Class) AnalyzerUtil.getPackageTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypedDeclaration) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.getTypedDeclaration(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypedDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) HashSet(java.util.HashSet)

Example 34 with Unit

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

the class InheritanceVisitor method checkSelfTypes.

private void checkSelfTypes(Tree.StaticType that, TypeDeclaration td, Type type) {
    if (!(td instanceof TypeParameter)) {
        // TODO: is this really ok?!
        List<TypeParameter> params = type.getDeclaration().getTypeParameters();
        List<Type> args = type.getTypeArgumentList();
        Unit unit = that.getUnit();
        for (int i = 0; i < params.size(); i++) {
            TypeParameter param = params.get(i);
            if (param.isSelfType() && !args.isEmpty()) {
                Type arg = args.get(i);
                if (arg == null) {
                    arg = unit.getUnknownType();
                }
                TypeDeclaration std = param.getSelfTypedDeclaration();
                Type at;
                TypeDeclaration mtd;
                if (param.getContainer().equals(std)) {
                    at = td.getType();
                    mtd = td;
                } else {
                    // TODO: lots wrong here?
                    mtd = (TypeDeclaration) td.getMember(std.getName(), null, false);
                    at = mtd == null ? null : mtd.getType();
                }
                if (at != null && !at.isSubtypeOf(arg)) {
                    Type st = mtd.getSelfType();
                    if (st == null || !st.isExactly(arg)) {
                        String help = "";
                        TypeDeclaration atd = at.getDeclaration();
                        TypeDeclaration ad = arg.getDeclaration();
                        if (ad instanceof TypeParameter) {
                            TypeParameter tp = (TypeParameter) ad;
                            if (tp.getDeclaration().equals(td)) {
                                help = " (try making '" + ad.getName() + "' a self type of '" + td.getName() + "')";
                            }
                        } else if (ad instanceof Interface) {
                            help = " (try making " + message(atd) + " satisfy '" + ad.getName() + "')";
                        } else if (ad instanceof Class && td instanceof Class) {
                            help = " (try making " + message(atd) + " extend '" + ad.getName() + "')";
                        }
                        that.addError("type argument does not satisfy self type constraint on type parameter '" + param.getName() + "' of '" + type.getDeclaration().getName(unit) + "': '" + arg.asString(unit) + "' is not a supertype or self type of " + message(atd) + help);
                    }
                }
            }
        }
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) Class(org.eclipse.ceylon.model.typechecker.model.Class) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) AnalyzerUtil.checkCasesDisjoint(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)

Example 35 with Unit

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

the class InheritanceVisitor method visit.

@Override
public void visit(Tree.ExtendedType that) {
    super.visit(that);
    TypeDeclaration td = (TypeDeclaration) that.getScope();
    if (!td.isAlias()) {
        Tree.SimpleType et = that.getType();
        if (et != null) {
            Tree.InvocationExpression ie = that.getInvocationExpression();
            Class clazz = (Class) td;
            boolean hasConstructors = clazz.hasConstructors() || clazz.hasEnumerated();
            boolean anonymous = clazz.isAnonymous();
            if (ie == null) {
                if (!hasConstructors || anonymous) {
                    et.addError("missing instantiation arguments");
                }
            } else {
                if (hasConstructors && !anonymous) {
                    et.addError("unnecessary instantiation arguments");
                }
            }
            Unit unit = that.getUnit();
            Type type = et.getTypeModel();
            if (type != null) {
                checkSelfTypes(et, td, type);
                checkExtensionOfMemberType(et, td, type);
                // checkCaseOfSupertype(et, td, type);
                Type ext = td.getExtendedType();
                TypeDeclaration etd = ext == null ? null : ext.getDeclaration();
                TypeDeclaration aetd = type.getDeclaration();
                if (aetd instanceof Constructor && aetd.isAbstract()) {
                    et.addError("extends a partial constructor: '" + aetd.getName(unit) + "' is declared abstract");
                }
                while (etd != null && etd.isAlias()) {
                    Type etdet = etd.getExtendedType();
                    etd = etdet == null ? null : etdet.getDeclaration();
                }
                if (etd != null) {
                    if (etd.isFinal()) {
                        et.addError("extends a final class: '" + etd.getName(unit) + "' is declared final");
                    }
                    if (aetd instanceof Class && !contains(aetd, that.getScope())) {
                        Class c = (Class) aetd;
                        Constructor dc = c.getDefaultConstructor();
                        if (dc != null && !dc.isShared()) {
                            that.addError("extends a class with an unshared default constructor: default constructor of '" + c.getName(unit) + "' is not 'shared'");
                        }
                    }
                    if (etd.isSealed() && !unit.inSameModule(etd)) {
                        String moduleName = etd.getUnit().getPackage().getModule().getNameAsString();
                        et.addError("extends a sealed class in a different module: '" + etd.getName(unit) + "' in '" + moduleName + "' is sealed");
                    }
                }
            }
            checkSupertypeVarianceAnnotations(et);
        }
    }
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) Class(org.eclipse.ceylon.model.typechecker.model.Class) Unit(org.eclipse.ceylon.model.typechecker.model.Unit) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

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