Search in sources :

Example 36 with ClassOrInterface

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

the class InheritanceVisitor method checkCaseType.

void checkCaseType(TypeDeclaration type, Tree.StaticType ct, TypeDeclaration caseTypeDec) {
    if (caseTypeDec instanceof ClassOrInterface && ct instanceof Tree.SimpleType && caseTypeDec.isParameterized()) {
        Tree.SimpleType t = (Tree.SimpleType) ct;
        Tree.TypeArgumentList tal = t.getTypeArgumentList();
        List<Tree.Type> args = tal == null ? Collections.<Tree.Type>emptyList() : tal.getTypes();
        List<TypeParameter> typeParameters = caseTypeDec.getTypeParameters();
        Set<TypeParameter> used = new HashSet<TypeParameter>();
        for (int i = 0; i < typeParameters.size(); i++) {
            TypeParameter typeParameter = typeParameters.get(i);
            Type argType;
            Node node;
            String typeArg;
            if (i < args.size()) {
                Tree.Type arg = args.get(i);
                argType = arg.getTypeModel();
                node = arg;
                typeArg = "type argument";
            } else {
                argType = typeParameter.getDefaultTypeArgument();
                node = tal;
                typeArg = "default type argument '" + argType.asString(node.getUnit()) + "' of '" + typeParameter.getName() + "' ";
            }
            if (argType != null) {
                TypeDeclaration argTypeDec = argType.getDeclaration();
                if (argType.isTypeParameter()) {
                    TypeParameter tp = (TypeParameter) argTypeDec;
                    if (!tp.getDeclaration().equals(type)) {
                        node.addError(typeArg + "is not a type parameter of the enumerated type: '" + tp.getName() + "' is not a type parameter of '" + type.getName() + "'");
                    } else if (!used.add(tp)) {
                        node.addError("type parameter of the enumerated type is used twice as a type argument: '" + argTypeDec.getName());
                    }
                } else if (typeParameter.isCovariant()) {
                    checkAssignable(typeParameter.getType(), argType, node, typeArg + " is not an upper bound of the type parameter '" + typeParameter.getName() + "' ");
                } else if (typeParameter.isContravariant()) {
                    checkAssignable(argType, typeParameter.getType(), node, typeArg + " is not a lower bound of the type parameter '" + typeParameter.getName() + "' ");
                } else {
                    node.addError(typeArg + "is not a type parameter of the enumerated type: '" + argTypeDec.getName() + "'");
                }
            }
        }
    }
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Node(org.eclipse.ceylon.compiler.typechecker.tree.Node) AnalyzerUtil.checkCasesDisjoint(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.checkCasesDisjoint) Type(org.eclipse.ceylon.model.typechecker.model.Type) Tree(org.eclipse.ceylon.compiler.typechecker.tree.Tree) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) HashSet(java.util.HashSet)

Example 37 with ClassOrInterface

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

the class LocalDeclarationVisitor method visit.

@Override
public void visit(Tree.ClassOrInterface that) {
    ClassOrInterface model = that.getDeclarationModel();
    visitLocalDecl(that);
    Map<String, Integer> oldLocalNames = null;
    if (model != null && !model.isAlias()) {
        oldLocalNames = localNames;
        localNames = new HashMap<String, Integer>();
    }
    super.visit(that);
    if (model != null && !model.isAlias()) {
        localNames = oldLocalNames;
    }
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)

Example 38 with ClassOrInterface

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

the class TypeHierarchyVisitor method visit.

@Override
public void visit(Tree.ClassOrInterface that) {
    super.visit(that);
    ClassOrInterface classOrInterface = that.getDeclarationModel();
    if (!classOrInterface.isAlias()) {
        boolean concrete = !classOrInterface.isAbstract() && !classOrInterface.isFormal();
        List<Type> orderedTypes = sortDAGAndBuildMetadata(classOrInterface, that);
        if (concrete) {
            checkForFormalsNotImplemented(that, orderedTypes, (Class) classOrInterface);
        }
        checkForDoubleMemberInheritanceNotOverridden(that, orderedTypes, classOrInterface);
        checkForDoubleMemberInheritanceWoCommonAncestor(that, orderedTypes, classOrInterface);
    }
    validateMemberRefinement(that, classOrInterface);
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType)

Example 39 with ClassOrInterface

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

the class TypeHierarchyVisitor method validateMemberRefinement.

private void validateMemberRefinement(Node that, TypeDeclaration td) {
    if (!td.isInconsistentType() && td instanceof ClassOrInterface && !td.isAbstract() && !td.isAlias() && // resulting in multiple errors
    !that.hasErrors()) {
        Set<String> errors = new HashSet<String>();
        for (TypeDeclaration std : td.getSupertypeDeclarations()) {
            for (Declaration d : std.getMembers()) {
                if (d.isShared() && !d.isStatic() && !isConstructor(d) && !isOverloadedVersion(d) && isResolvable(d) && !errors.contains(d.getName())) {
                    Declaration r = td.getMember(d.getName(), null, false);
                    // to the user!
                    if (r != null && !r.refines(d) && // is a dupe declaration
                    !r.getContainer().equals(td) && !((std instanceof Interface || r.isInterfaceMember()) && isDefinedInJava(std) && isDefinedInJava(r))) {
                        TypeDeclaration ctd = (TypeDeclaration) r.getContainer();
                        that.addError("member '" + d.getName() + "' is inherited ambiguously by '" + td.getName() + "' from '" + std.getName() + "' and a different generic instantiation of '" + ctd.getName() + "' and is not refined by '" + td.getName() + "' (refine '" + d.getName() + "' to satisfy both instantiations of '" + ctd.getName() + "')", 350);
                        errors.add(d.getName());
                    }
                }
            }
        }
    }
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) ModelUtil.getNativeDeclaration(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getNativeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet)

Example 40 with ClassOrInterface

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

the class TypeVisitor method visit.

/*@Override 
    public void visit(Tree.TypeConstraint that) {
        super.visit(that);
        if (that.getSelfType()!=null) {
            TypeDeclaration td = (TypeDeclaration) that.getSelfType().getScope();
            TypeParameter tp = that.getDeclarationModel();
            td.setSelfType(tp.getType());
            if (tp.isSelfType()) {
                that.addError("type parameter may not act as self type for two different types");
            }
            else {
                tp.setSelfTypedDeclaration(td);
            }
        }
    }*/
@Override
public void visit(Tree.CaseTypes that) {
    super.visit(that);
    TypeDeclaration td = (TypeDeclaration) that.getScope();
    List<Tree.StaticMemberOrTypeExpression> bmes = that.getBaseMemberExpressions();
    List<Tree.StaticType> cts = that.getTypes();
    List<TypedDeclaration> caseValues = new ArrayList<TypedDeclaration>(bmes.size());
    List<Type> caseTypes = new ArrayList<Type>(bmes.size() + cts.size());
    if (td instanceof TypeParameter) {
        if (!bmes.isEmpty()) {
            that.addError("cases of type parameter must be a types");
        }
    } else {
        for (Tree.StaticMemberOrTypeExpression bme : bmes) {
            // bmes have not yet been resolved
            String name = name(bme.getIdentifier());
            TypedDeclaration od = bme instanceof Tree.BaseMemberExpression ? getTypedDeclaration(bme.getScope(), name, null, false, unit) : getPackageTypedDeclaration(name, null, false, unit);
            if (od != null) {
                caseValues.add(od);
                Type type = od.getType();
                if (type != null) {
                    caseTypes.add(type);
                }
            }
        }
    }
    for (Tree.StaticType ct : cts) {
        inheritedType(ct);
        Type type = ct.getTypeModel();
        if (!isTypeUnknown(type)) {
            if (type.isUnion() || type.isIntersection() || type.isNothing()) {
                // union/intersection types don't have equals()
                if (td instanceof TypeParameter) {
                    ct.addError("enumerated bound must be a class or interface type");
                } else {
                    ct.addError("case type must be a class, interface, or self type");
                }
            } else {
                TypeDeclaration ctd = type.getDeclaration();
                if (ctd.equals(td)) {
                    ct.addError("directly enumerates itself: '" + td.getName() + "'");
                } else if (type.isClassOrInterface()) {
                    caseTypes.add(type);
                } else if (type.isTypeParameter()) {
                    if (td instanceof TypeParameter) {
                        caseTypes.add(type);
                    } else {
                        TypeParameter tp = (TypeParameter) ctd;
                        td.setSelfType(type);
                        if (tp.isSelfType()) {
                            ct.addError("type parameter may not act as self type for two different types");
                        } else {
                            tp.setSelfTypedDeclaration(td);
                            caseTypes.add(type);
                        }
                        if (cts.size() > 1) {
                            ct.addError("a type may not have more than one self type");
                        }
                    }
                } else {
                    if (td instanceof TypeParameter) {
                        ct.addError("enumerated bound must be a class or interface type");
                    } else {
                        ct.addError("case type must be a class, interface, or self type");
                    }
                }
            }
        }
    }
    if (!caseTypes.isEmpty()) {
        TypeDeclaration first = caseTypes.get(0).getDeclaration();
        if (caseTypes.size() == 1 && first.isSelfType()) {
            // for a type family, the type that declares
            // the type parameter may not be the same
            // type for which it acts as a self type
            Scope scope = first.getContainer();
            if (scope instanceof ClassOrInterface) {
                ClassOrInterface ci = (ClassOrInterface) scope;
                if (!ci.isAbstract()) {
                    Tree.StaticType ct = cts.get(0);
                    if (ci.equals(td)) {
                        ct.addError("concrete class parameterized by self type: '" + ci.getName() + "' is not abstract but has the self type '" + first.getName() + "' (make '" + ci.getName() + "' abstract)", 905);
                    } else {
                        // type family
                        ct.addError("concrete class parameterized by self type: '" + ci.getName() + "' is not abstract but declares the self type '" + first.getName() + "' of '" + td.getName() + "' (make '" + ci.getName() + "' abstract)", 905);
                    }
                }
            }
        } else {
            if (td instanceof ClassOrInterface) {
                ClassOrInterface ci = (ClassOrInterface) td;
                if (!ci.isAbstract()) {
                    Class c = (Class) ci;
                    if (!c.hasEnumerated()) {
                        that.addError("concrete class has enumerated subtypes: " + "enumerated class '" + ci.getName() + "' is not abstract" + " (make '" + ci.getName() + "' abstract)", 905);
                    }
                }
            }
        }
        td.setCaseTypes(caseTypes);
        td.setCaseValues(caseValues);
    }
}
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) ModelUtil.getContainingClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ModelUtil.getContainingClassOrInterface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) ArrayList(java.util.ArrayList) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) 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) 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.isVeryAbstractClass(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.isVeryAbstractClass) 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

ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)102 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)62 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)48 TypedDeclaration (org.eclipse.ceylon.model.typechecker.model.TypedDeclaration)46 Type (org.eclipse.ceylon.model.typechecker.model.Type)44 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)27 Class (org.eclipse.ceylon.model.typechecker.model.Class)24 Interface (org.eclipse.ceylon.model.typechecker.model.Interface)23 Scope (org.eclipse.ceylon.model.typechecker.model.Scope)23 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)20 ModelUtil.getContainingClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ModelUtil.getContainingClassOrInterface)19 Value (org.eclipse.ceylon.model.typechecker.model.Value)19 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)18 ArrayList (java.util.ArrayList)17 FunctionOrValue (org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)17 Constructor (org.eclipse.ceylon.model.typechecker.model.Constructor)16 Function (org.eclipse.ceylon.model.typechecker.model.Function)14 LazyInterface (org.eclipse.ceylon.model.loader.model.LazyInterface)13 JCExpression (org.eclipse.ceylon.langtools.tools.javac.tree.JCTree.JCExpression)12 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)12