Search in sources :

Example 91 with TypeDeclaration

use of org.eclipse.ceylon.model.typechecker.model.TypeDeclaration 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)

Example 92 with TypeDeclaration

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

the class TypeArgumentInference method inferTypeArg.

private Type inferTypeArg(TypeParameter tp, Type paramType, Type argType, boolean covariant, boolean contravariant, boolean findingUpperBounds, List<TypeParameter> visited, Node argNode) {
    if (paramType != null && argType != null) {
        paramType = paramType.resolveAliases();
        argType = argType.resolveAliases();
        TypeDeclaration paramTypeDec = paramType.getDeclaration();
        Map<TypeParameter, Type> paramTypeArgs = paramType.getTypeArguments();
        Map<TypeParameter, SiteVariance> paramVariances = paramType.getVarianceOverrides();
        if (paramType.isTypeParameter() && paramTypeDec.equals(tp)) {
            if (tp.isTypeConstructor()) {
                if (argType.isTypeConstructor()) {
                    return argType;
                } else {
                    return null;
                }
            } else if (findingUpperBounds && covariant || !findingUpperBounds && contravariant) {
                // covariant locations in the list
                return null;
            } else if (argType.isUnknown()) {
                // TODO: is this error really necessary now!?
                if (!argNode.hasErrors()) {
                    argNode.addError("argument of unknown type assigned to inferred type parameter: '" + tp.getName() + "' of '" + tp.getDeclaration().getName(unit) + "'");
                }
                // TODO: would it be better to return UnknownType here?
                return null;
            } else {
                return unit.denotableType(argType);
            }
        } else if (paramType.isTypeParameter() && !paramTypeDec.isParameterized()) {
            TypeParameter tp2 = (TypeParameter) paramTypeDec;
            if (!findingUpperBounds && // in the upper bounds
            !visited.contains(tp2)) {
                visited.add(tp2);
                List<Type> sts = tp2.getSatisfiedTypes();
                List<Type> list = new ArrayList<Type>(sts.size());
                for (Type upperBound : sts) {
                    // recurse to the upper bounds
                    addToUnionOrIntersection(findingUpperBounds, list, inferTypeArg(tp, upperBound, argType, covariant, contravariant, findingUpperBounds, visited, argNode));
                }
                visited.remove(tp2);
                return unionOrIntersectionOrNull(findingUpperBounds, list);
            } else {
                return null;
            }
        } else if (paramType.isUnion()) {
            // If there is more than one type parameter in
            // the union, ignore this union when inferring
            // types.
            // TODO: This is all a bit adhoc. The problem
            // is that when a parameter type involves
            // a union of type parameters, it in theory
            // imposes a compound constraint upon the
            // type parameters, but our algorithm
            // doesn't know how to deal with compound
            // constraints
            /*Type typeParamType = null;
                boolean found = false;
                for (Type ct: 
                        paramType.getDeclaration()
                            .getCaseTypes()) {
                    TypeDeclaration ctd = 
                            ct.getDeclaration();
                    if (ctd instanceof TypeParameter) {
                        typeParamType = ct;
                    }
                    if (ct.containsTypeParameters()) { //TODO: check that they are "free" type params                        
                        if (found) {
                            //the parameter type involves two type
                            //parameters which are being inferred
                            return null;
                        }
                        else {
                            found = true;
                        }
                    }
                }*/
            Type pt = paramType;
            Type apt = argType;
            if (argType.isUnion()) {
                for (Type act : argType.getCaseTypes()) {
                    // from both unions
                    if (// in a recursive generic function, T can get assigned to T
                    !act.involvesDeclaration(tp) && act.substitute(argType).isSubtypeOf(paramType)) {
                        pt = pt.shallowMinus(act);
                        apt = apt.shallowMinus(act);
                    }
                }
            }
            if (pt.isUnion()) {
                boolean found = false;
                for (Type ct : pt.getCaseTypes()) {
                    if (ct.isTypeParameter()) {
                        if (found) {
                            return null;
                        }
                        found = true;
                    }
                }
                // just one type parameter left in the union
                Map<TypeParameter, Type> args = pt.getTypeArguments();
                Map<TypeParameter, SiteVariance> variances = pt.getVarianceOverrides();
                List<Type> cts = pt.getCaseTypes();
                List<Type> list = new ArrayList<Type>(cts.size());
                for (Type ct : cts) {
                    addToUnionOrIntersection(findingUpperBounds, list, inferTypeArg(tp, ct.substitute(args, variances), apt, covariant, contravariant, findingUpperBounds, visited, argNode));
                }
                return unionOrIntersectionOrNull(findingUpperBounds, list);
            } else {
                return inferTypeArg(tp, pt, apt, covariant, contravariant, findingUpperBounds, visited, argNode);
            }
        /*else {
                    //if the param type is of form T|A1 and the arg type is
                    //of form A2|B then constrain T by B and A1 by A2
                    Type pt = paramType.minus(typeParamType);
                    addToUnionOrIntersection(tp, list, inferTypeArg(tp, 
                            paramType.minus(pt), argType.minus(pt), visited));
                    addToUnionOrIntersection(tp, list, inferTypeArg(tp, 
                            paramType.minus(typeParamType), pt, visited));
                    //return null;
                }*/
        } else if (paramType.isIntersection()) {
            List<Type> sts = paramTypeDec.getSatisfiedTypes();
            List<Type> list = new ArrayList<Type>(sts.size());
            for (Type ct : sts) {
                // recurse to intersected types
                addToUnionOrIntersection(findingUpperBounds, list, inferTypeArg(tp, ct.substitute(paramTypeArgs, paramVariances), argType, covariant, contravariant, findingUpperBounds, visited, argNode));
            }
            return unionOrIntersectionOrNull(findingUpperBounds, list);
        } else if (argType.isUnion()) {
            List<Type> cts = argType.getCaseTypes();
            List<Type> list = new ArrayList<Type>(cts.size());
            for (Type ct : cts) {
                // recurse to union types
                addToUnion(list, inferTypeArg(tp, paramType, ct.substitute(paramTypeArgs, paramVariances), covariant, contravariant, findingUpperBounds, visited, argNode));
            }
            return unionOrNull(list);
        } else if (argType.isIntersection()) {
            List<Type> sts = argType.getSatisfiedTypes();
            List<Type> list = new ArrayList<Type>(sts.size());
            for (Type st : sts) {
                // recurse to intersected types
                addToIntersection(list, inferTypeArg(tp, paramType, st.substitute(paramTypeArgs, paramVariances), covariant, contravariant, findingUpperBounds, visited, argNode), unit);
            }
            return intersectionOrNull(list);
        } else {
            Type supertype = argType.getSupertype(paramTypeDec);
            if (supertype != null) {
                List<Type> list = new ArrayList<Type>(2);
                Type pqt = paramType.getQualifyingType();
                Type sqt = supertype.getQualifyingType();
                if (pqt != null && sqt != null) {
                    // recurse to qualifying types
                    addToUnionOrIntersection(findingUpperBounds, list, inferTypeArg(tp, pqt, sqt, covariant, contravariant, findingUpperBounds, visited, argNode));
                }
                inferTypeArg(tp, paramType, supertype, covariant, contravariant, findingUpperBounds, list, visited, argNode);
                return unionOrIntersectionOrNull(findingUpperBounds, list);
            } else {
                return null;
            }
        }
    } else {
        return null;
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance) ArrayList(java.util.ArrayList) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) ModelUtil.typeParametersAsArgList(org.eclipse.ceylon.model.typechecker.model.ModelUtil.typeParametersAsArgList) List(java.util.List) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 93 with TypeDeclaration

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

the class TypeArgumentInference method constrainInferredTypes.

private List<Type> constrainInferredTypes(List<TypeParameter> typeParameters, List<Type> inferredTypeArgs, Type qualifyingType, Declaration declaration) {
    int size = inferredTypeArgs.size();
    boolean found = false;
    for (int i = 0; i < size; i++) {
        TypeParameter tp = typeParameters.get(i);
        // if (!tp.isCovariant()) {
        List<Type> bounds = tp.getSatisfiedTypes();
        if (!bounds.isEmpty()) {
            found = true;
        }
    // }
    }
    if (found) {
        Reference ref;
        if (declaration instanceof Value) {
            Value value = (Value) declaration;
            if (value.getType().isTypeConstructor()) {
                if (qualifyingType == null) {
                    ref = declaration.appliedReference(null, NO_TYPE_ARGS);
                } else {
                    ref = qualifyingType.getTypedReference(declaration, NO_TYPE_ARGS);
                }
                TypeDeclaration dec = ref.getType().getDeclaration();
                ref = dec.appliedReference(null, inferredTypeArgs);
            } else {
                return inferredTypeArgs;
            }
        } else {
            if (qualifyingType == null) {
                ref = declaration.appliedReference(null, inferredTypeArgs);
            } else {
                ref = qualifyingType.getTypedReference(declaration, inferredTypeArgs);
            }
        }
        Map<TypeParameter, Type> args = ref.getTypeArguments();
        ArrayList<Type> result = new ArrayList<Type>(size);
        for (int i = 0; i < size; i++) {
            TypeParameter tp = typeParameters.get(i);
            Type arg = inferredTypeArgs.get(i);
            Type constrainedArg = // tp.isCovariant() ? arg :
            constrainInferredType(tp, arg, args);
            result.add(constrainedArg);
        }
        return result;
    } else {
        return inferredTypeArgs;
    }
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) ModelUtil.intersectionType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType) ModelUtil.appliedType(org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType) AnalyzerUtil.spreadType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.spreadType) AnalyzerUtil.getTupleType(org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTupleType) Reference(org.eclipse.ceylon.model.typechecker.model.Reference) TypedReference(org.eclipse.ceylon.model.typechecker.model.TypedReference) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue) Value(org.eclipse.ceylon.model.typechecker.model.Value) ArrayList(java.util.ArrayList) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 94 with TypeDeclaration

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

the class TypeArgumentVisitor method visit.

@Override
public void visit(Tree.Enumerated that) {
    TypeDeclaration occ = beginConstructor(that.getEnumerated());
    super.visit(that);
    endConstructor(occ);
}
Also used : TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 95 with TypeDeclaration

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

the class TypeHierarchyVisitor method getOrBuildType.

/*private void removeTrailing(String trailingString, StringBuilder sb) {
        final int length = sb.length();
        sb.delete(length-trailingString.length(), length);
    }*/
private Type getOrBuildType(TypeDeclaration declaration) {
    Type type = types.get(new TypeDeclKey(declaration));
    if (type == null) {
        type = new Type();
        type.declaration = declaration;
        for (Declaration member : declaration.getMembers()) {
            if (!(member instanceof FunctionOrValue || member instanceof Class) || isConstructor(member) || member.isStatic() || isAbstraction(member)) {
                continue;
            }
            if (declaration.isNative() && member.isNative()) {
                // Make sure we get the right member declaration (the one for the same backend as its container)
                Backends backends = declaration.getNativeBackends();
                member = getNativeDeclaration(member, backends);
                if (member == null) {
                    continue;
                }
            }
            final String name = member.getName();
            Type.Members members = type.membersByName.get(name);
            if (members == null) {
                members = new Type.Members();
                members.name = name;
                type.membersByName.put(name, members);
            }
            if (member.isActual()) {
                members.actuals.add(member);
                if (!member.isFormal()) {
                    members.actualsNonFormals.add(member);
                }
            }
            if (member.isFormal()) {
                members.formals.add(member);
            }
            /*if (!member.isFormal() && member.isInterfaceMember()) {
                    members.concretesOnInterfaces.add(member);
                }*/
            if (member.isDefault()) {
                members.defaults.add(member);
            }
            if (!member.isFormal() && !member.isDefault() && member.isShared()) {
                members.nonFormalsNonDefaults.add(member);
            }
            if (member.isShared()) {
                members.shared.add(member);
            }
        }
        types.put(new TypeDeclKey(declaration), type);
    }
    return type;
}
Also used : IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Backends(org.eclipse.ceylon.common.Backends) Class(org.eclipse.ceylon.model.typechecker.model.Class) 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) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

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