Search in sources :

Example 16 with SiteVariance

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

the class JsonPackage method getTypeFromJson.

/**
 * Looks up a type from model data, creating it if necessary. The returned type will have its
 * type parameters substituted if needed.
 */
private Type getTypeFromJson(Map<String, Object> m, Declaration container, List<TypeParameter> typeParams) {
    TypeDeclaration td = null;
    if (m.get(KEY_METATYPE) instanceof TypeDeclaration) {
        td = (TypeDeclaration) m.get(KEY_METATYPE);
        if (td instanceof ClassOrInterface && td.getUnit().getPackage() instanceof JsonPackage) {
            ((JsonPackage) td.getUnit().getPackage()).load(td.getName(), typeParams);
        }
    }
    final String tname = (String) m.get(KEY_NAME);
    if ("$U".equals(tname)) {
        m.put(KEY_METATYPE, unknown);
        return unknown.getType();
    }
    if (td == null && m.containsKey("comp")) {
        @SuppressWarnings("unchecked") final List<Map<String, Object>> tmaps = (List<Map<String, Object>>) m.get(KEY_TYPES);
        final ArrayList<Type> types = new ArrayList<>(tmaps.size());
        if ("u".equals(m.get("comp"))) {
            UnionType ut = new UnionType(u2);
            for (Map<String, Object> tmap : tmaps) {
                types.add(getTypeFromJson(tmap, container, typeParams));
            }
            ut.setCaseTypes(types);
            td = ut;
        } else if ("i".equals(m.get("comp"))) {
            IntersectionType it = new IntersectionType(u2);
            for (Map<String, Object> tmap : tmaps) {
                types.add(getTypeFromJson(tmap, container, typeParams));
            }
            it.setSatisfiedTypes(types);
            td = it;
        } else {
            throw new IllegalArgumentException("Invalid composite type '" + m.get("comp") + "'");
        }
    } else if (td == null) {
        final String pname = (String) m.get(KEY_PACKAGE);
        if (pname == null) {
            // It's a ref to a type parameter
            final List<TypeParameter> containerTypeParameters;
            if (container instanceof Constructor) {
                containerTypeParameters = ((Generic) container.getContainer()).getTypeParameters();
            } else if (container instanceof Generic) {
                containerTypeParameters = container.getTypeParameters();
            } else {
                containerTypeParameters = null;
            }
            if (containerTypeParameters != null) {
                for (TypeParameter typeParam : containerTypeParameters) {
                    if (typeParam.getName().equals(tname)) {
                        td = typeParam;
                    }
                }
            }
            if (td == null && typeParams != null) {
                for (TypeParameter typeParam : typeParams) {
                    if (typeParam.getName().equals(tname)) {
                        td = typeParam;
                    }
                }
            }
        } else {
            String mname = (String) m.get(KEY_MODULE);
            if ("$".equals(mname)) {
                mname = LANGUAGE_MODULE_NAME;
            }
            org.eclipse.ceylon.model.typechecker.model.Package rp;
            if ("$".equals(pname) || LANGUAGE_MODULE_NAME.equals(pname)) {
                // Language module package
                rp = isLanguagePackage() ? this : getModule().getLanguageModule().getDirectPackage(LANGUAGE_MODULE_NAME);
            } else if (mname == null) {
                // local type
                if (".".equals(pname)) {
                    rp = this;
                    if (container instanceof TypeDeclaration && tname.equals(container.getName())) {
                        td = (TypeDeclaration) container;
                    }
                } else {
                    rp = getModule().getDirectPackage(pname);
                }
            } else {
                rp = getModule().getPackage(pname);
            }
            if (rp == null) {
                throw new CompilerErrorException("Package not found: " + pname);
            }
            if (rp != this && rp instanceof JsonPackage && !((JsonPackage) rp).loaded) {
                ((JsonPackage) rp).loadIfNecessary();
            }
            final boolean nested = tname.indexOf('.') > 0;
            final String level1 = nested ? tname.substring(0, tname.indexOf('.')) : tname;
            if (rp != null && !nested) {
                Declaration d = rp.getDirectMember(tname, null, false);
                if (d instanceof TypeDeclaration) {
                    td = (TypeDeclaration) d;
                    if (td.isTuple()) {
                        if (m.containsKey(KEY_TYPES)) {
                            @SuppressWarnings("unchecked") List<Map<String, Object>> elemaps = (List<Map<String, Object>>) m.get(KEY_TYPES);
                            ArrayList<Type> elems = new ArrayList<>(elemaps.size());
                            for (Map<String, Object> elem : elemaps) {
                                elems.add(getTypeFromJson(elem, container, typeParams));
                            }
                            Type tail = elems.get(elems.size() - 1);
                            if ((tail.isSequence() || tail.isSequential()) && !tail.isTuple() && !tail.isEmpty()) {
                                elems.remove(elems.size() - 1);
                            } else {
                                tail = null;
                            }
                            return u2.getTupleType(elems, tail, -1);
                        } else if (m.containsKey("count")) {
                            @SuppressWarnings("unchecked") Map<String, Object> elem = (Map<String, Object>) m.get(KEY_TYPE);
                            Type[] elems = new Type[(int) m.remove("count")];
                            Arrays.fill(elems, getTypeFromJson(elem, container, typeParams));
                            return u2.getTupleType(Arrays.asList(elems), null, -1);
                        }
                    }
                } else if (d instanceof FunctionOrValue) {
                    td = ((FunctionOrValue) d).getTypeDeclaration();
                }
            }
            if (td == null && rp instanceof JsonPackage) {
                if (nested) {
                    td = ((JsonPackage) rp).loadNestedType(tname, typeParams);
                } else {
                    td = (TypeDeclaration) ((JsonPackage) rp).load(tname, typeParams);
                }
            }
            // Then look in the top-level declarations
            if (nested && td == null) {
                for (Declaration d : rp.getMembers()) {
                    if (d instanceof TypeDeclaration && level1.equals(d.getName())) {
                        td = (TypeDeclaration) d;
                    }
                }
                final String[] path = tname.split("\\.");
                for (int i = 1; i < path.length; i++) {
                    td = (TypeDeclaration) td.getDirectMember(path[i], null, false);
                }
            }
        }
    }
    // From 1.2.3 we stored type arguments in maps
    final Type newType = loadTypeArguments(m, td, container, typeParams);
    if (newType != null) {
        return newType;
    }
    // This is the old pre 1.2.3 stuff
    @SuppressWarnings("unchecked") final List<Map<String, Object>> modelParms = (List<Map<String, Object>>) m.get(KEY_TYPE_PARAMS);
    if (td != null && modelParms != null) {
        // Substitute type parameters
        final HashMap<TypeParameter, Type> concretes = new HashMap<>();
        HashMap<TypeParameter, SiteVariance> variances = null;
        if (td.getTypeParameters().size() < modelParms.size()) {
            if (td.getUnit().getPackage() == this) {
                parseTypeParameters(modelParms, td, null);
            }
        }
        final Iterator<TypeParameter> viter = td.getTypeParameters().iterator();
        for (Map<String, Object> ptparm : modelParms) {
            TypeParameter _cparm = viter.next();
            if (ptparm.containsKey(KEY_PACKAGE) || ptparm.containsKey(KEY_TYPES)) {
                // Substitute for proper type
                final Type _pt = getTypeFromJson(ptparm, container, typeParams);
                concretes.put(_cparm, _pt);
            } else if (ptparm.containsKey(KEY_NAME) && typeParams != null) {
                // Look for type parameter with same name
                for (TypeParameter typeParam : typeParams) {
                    if (typeParam.getName().equals(ptparm.get(KEY_NAME))) {
                        concretes.put(_cparm, typeParam.getType());
                    }
                }
            }
            Integer usv = (Integer) ptparm.get(KEY_US_VARIANCE);
            if (usv != null) {
                if (variances == null) {
                    variances = new HashMap<>();
                }
                variances.put(_cparm, SiteVariance.values()[usv]);
            }
        }
        if (!concretes.isEmpty()) {
            return td.getType().substitute(concretes, variances);
        }
    }
    if (td == null) {
        try {
            throw new IllegalArgumentException(String.format("Couldn't find type %s::%s for %s in %s<%s> (FROM pkg %s)", m.get(KEY_PACKAGE), m.get(KEY_NAME), m.get(KEY_MODULE), m, typeParams, getNameAsString()));
        } catch (IllegalArgumentException ex) {
            ex.printStackTrace();
        }
    }
    return td.getType();
}
Also used : ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) HashMap(java.util.HashMap) Generic(org.eclipse.ceylon.model.typechecker.model.Generic) ArrayList(java.util.ArrayList) List(java.util.List) ParameterList(org.eclipse.ceylon.model.typechecker.model.ParameterList) ArrayList(java.util.ArrayList) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) CompilerErrorException(org.eclipse.ceylon.compiler.js.CompilerErrorException) Constructor(org.eclipse.ceylon.model.typechecker.model.Constructor) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) UnionType(org.eclipse.ceylon.model.typechecker.model.UnionType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) IntersectionType(org.eclipse.ceylon.model.typechecker.model.IntersectionType) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Map(java.util.Map) HashMap(java.util.HashMap) FunctionOrValue(org.eclipse.ceylon.model.typechecker.model.FunctionOrValue)

Example 17 with SiteVariance

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

the class Metamodel method getTypeArgumentWithVariances.

public static ceylon.language.Map<? extends ceylon.language.meta.declaration.TypeParameter, ? extends ceylon.language.Sequence<? extends Object>> getTypeArgumentWithVariances(ceylon.language.meta.declaration.GenericDeclaration declaration, Reference appliedFunction) {
    java.util.Map<ceylon.language.meta.declaration.TypeParameter, ceylon.language.Sequence<? extends Object>> typeArguments = new LinkedHashMap<ceylon.language.meta.declaration.TypeParameter, ceylon.language.Sequence<? extends Object>>();
    Iterator<? extends ceylon.language.meta.declaration.TypeParameter> typeParameters = declaration.getTypeParameterDeclarations().iterator();
    Object it;
    java.util.Map<org.eclipse.ceylon.model.typechecker.model.TypeParameter, org.eclipse.ceylon.model.typechecker.model.Type> ptArguments = appliedFunction.getTypeArguments();
    Map<TypeParameter, SiteVariance> varianceOverrides = appliedFunction instanceof org.eclipse.ceylon.model.typechecker.model.Type ? ((org.eclipse.ceylon.model.typechecker.model.Type) appliedFunction).getVarianceOverrides() : null;
    while ((it = typeParameters.next()) != finished_.get_()) {
        org.eclipse.ceylon.compiler.java.runtime.metamodel.decl.TypeParameterImpl tp = (org.eclipse.ceylon.compiler.java.runtime.metamodel.decl.TypeParameterImpl) it;
        org.eclipse.ceylon.model.typechecker.model.TypeParameter tpDecl = (org.eclipse.ceylon.model.typechecker.model.TypeParameter) tp.declaration;
        org.eclipse.ceylon.model.typechecker.model.Type ptArg = ptArguments.get(tpDecl);
        ceylon.language.meta.model.Type<?> ptArgWrapped = Metamodel.getAppliedMetamodel(ptArg);
        ceylon.language.meta.declaration.Variance variance = modelVarianceToMetaModel(varianceOverrides, tpDecl);
        ceylon.language.Sequence<? extends Object> tuple = ceylon.language.Tuple.instance(TD_ClosedTypeArgumentElement, new Object[] { ptArgWrapped, variance });
        typeArguments.put(tp, tuple);
    }
    return new InternalMap<ceylon.language.meta.declaration.TypeParameter, ceylon.language.Sequence<?>>(ceylon.language.meta.declaration.TypeParameter.$TypeDescriptor$, TD_ClosedTypeArgument, typeArguments);
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) LinkedHashMap(java.util.LinkedHashMap) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Metamodel(org.eclipse.ceylon.compiler.java.runtime.metamodel.Metamodel) InternalMap(org.eclipse.ceylon.compiler.java.language.InternalMap) ReifiedType(org.eclipse.ceylon.compiler.java.runtime.model.ReifiedType) NothingType(org.eclipse.ceylon.model.typechecker.model.NothingType) OpenClassOrInterfaceType(ceylon.language.meta.declaration.OpenClassOrInterfaceType) OpenType(ceylon.language.meta.declaration.OpenType) DeclarationType(org.eclipse.ceylon.model.loader.ModelLoader.DeclarationType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance)

Example 18 with SiteVariance

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

the class OpenClassOrInterfaceTypeImpl method init.

protected void init() {
    org.eclipse.ceylon.model.typechecker.model.ClassOrInterface decl = (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) producedType.getDeclaration();
    this.declaration = (ClassOrInterfaceDeclarationImpl) Metamodel.getOrCreateMetamodel(decl);
    java.util.Map<ceylon.language.meta.declaration.TypeParameter, ceylon.language.meta.declaration.OpenType> typeArguments = new LinkedHashMap<ceylon.language.meta.declaration.TypeParameter, ceylon.language.meta.declaration.OpenType>();
    java.util.Map<ceylon.language.meta.declaration.TypeParameter, ceylon.language.Sequence<? extends Object>> typeArgumentWithVariances = new LinkedHashMap<ceylon.language.meta.declaration.TypeParameter, ceylon.language.Sequence<? extends Object>>();
    Iterator<? extends ceylon.language.meta.declaration.TypeParameter> typeParameters = declaration.getTypeParameterDeclarations().iterator();
    Object it;
    java.util.Map<org.eclipse.ceylon.model.typechecker.model.TypeParameter, org.eclipse.ceylon.model.typechecker.model.Type> ptArguments = producedType.getTypeArguments();
    java.util.Map<TypeParameter, SiteVariance> varianceOverrides = producedType.getVarianceOverrides();
    while ((it = typeParameters.next()) != finished_.get_()) {
        org.eclipse.ceylon.compiler.java.runtime.metamodel.decl.TypeParameterImpl tp = (org.eclipse.ceylon.compiler.java.runtime.metamodel.decl.TypeParameterImpl) it;
        org.eclipse.ceylon.model.typechecker.model.TypeParameter tpDecl = (org.eclipse.ceylon.model.typechecker.model.TypeParameter) tp.declaration;
        org.eclipse.ceylon.model.typechecker.model.Type ptArg = ptArguments.get(tpDecl);
        OpenType ptArgWrapped = Metamodel.getMetamodel(ptArg);
        typeArguments.put(tp, ptArgWrapped);
        ceylon.language.meta.declaration.Variance variance = Metamodel.modelVarianceToMetaModel(varianceOverrides, tpDecl);
        ceylon.language.Sequence<? extends Object> tuple = ceylon.language.Tuple.instance(Metamodel.TD_OpenTypeArgumentElement, new Object[] { ptArgWrapped, variance });
        typeArgumentWithVariances.put(tp, tuple);
    }
    this.typeArguments = new InternalMap<ceylon.language.meta.declaration.TypeParameter, ceylon.language.meta.declaration.OpenType>(ceylon.language.meta.declaration.TypeParameter.$TypeDescriptor$, ceylon.language.meta.declaration.OpenType.$TypeDescriptor$, typeArguments);
    this.typeArgumentWithVariances = new InternalMap<ceylon.language.meta.declaration.TypeParameter, ceylon.language.Sequence<?>>(ceylon.language.meta.declaration.TypeParameter.$TypeDescriptor$, Metamodel.TD_OpenTypeArgument, typeArgumentWithVariances);
    org.eclipse.ceylon.model.typechecker.model.Type superType = decl.getExtendedType();
    if (superType != null) {
        org.eclipse.ceylon.model.typechecker.model.Type superTypeResolved = superType.substitute(producedType);
        this.superclass = (ceylon.language.meta.declaration.OpenClassType) Metamodel.getMetamodel(superTypeResolved);
    }
    List<org.eclipse.ceylon.model.typechecker.model.Type> satisfiedTypes = decl.getSatisfiedTypes();
    ceylon.language.meta.declaration.OpenInterfaceType[] interfaces = new ceylon.language.meta.declaration.OpenInterfaceType[satisfiedTypes.size()];
    int i = 0;
    for (org.eclipse.ceylon.model.typechecker.model.Type pt : satisfiedTypes) {
        org.eclipse.ceylon.model.typechecker.model.Type resolvedPt = pt.substitute(producedType);
        interfaces[i++] = (ceylon.language.meta.declaration.OpenInterfaceType) Metamodel.getMetamodel(resolvedPt);
    }
    this.interfaces = Util.sequentialWrapper(ceylon.language.meta.declaration.OpenInterfaceType.$TypeDescriptor$, interfaces);
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) OpenType(ceylon.language.meta.declaration.OpenType) LinkedHashMap(java.util.LinkedHashMap) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Metamodel(org.eclipse.ceylon.compiler.java.runtime.metamodel.Metamodel) Sequence(ceylon.language.Sequence) OpenType(ceylon.language.meta.declaration.OpenType) ReifiedType(org.eclipse.ceylon.compiler.java.runtime.model.ReifiedType) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance)

Example 19 with SiteVariance

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

the class AbstractModelLoader method applyTypeArguments.

private Type applyTypeArguments(Module moduleScope, TypeDeclaration declaration, TypeMirror type, Scope scope, TypeMappingMode mode, Set<TypeDeclaration> rawDeclarationsSeen) {
    List<TypeMirror> javacTypeArguments = type.getTypeArguments();
    boolean hasTypeParameters = declaration.isParameterized();
    boolean hasTypeArguments = !javacTypeArguments.isEmpty();
    boolean isRaw = !hasTypeArguments && hasTypeParameters;
    // if we have type arguments or type parameters (raw)
    if (hasTypeArguments || isRaw) {
        // if it's raw we will need the map anyways
        if (rawDeclarationsSeen == null)
            rawDeclarationsSeen = new HashSet<TypeDeclaration>();
        // detect recursive bounds that we can't possibly satisfy, such as Foo<T extends Foo<T>>
        if (rawDeclarationsSeen != null && !rawDeclarationsSeen.add(declaration))
            throw new RecursiveTypeParameterBoundException();
        try {
            List<Type> typeArguments = new ArrayList<Type>(javacTypeArguments.size());
            List<TypeParameter> typeParameters = declaration.getTypeParameters();
            List<TypeParameterMirror> typeParameterMirrors = null;
            // SimpleReflType for Object and friends don't have a type, but don't need one
            if (type.getDeclaredClass() != null)
                typeParameterMirrors = type.getDeclaredClass().getTypeParameters();
            Map<TypeParameter, SiteVariance> siteVarianceMap = null;
            int len = hasTypeArguments ? javacTypeArguments.size() : typeParameters.size();
            for (int i = 0; i < len; i++) {
                TypeParameter typeParameter = null;
                if (i < typeParameters.size())
                    typeParameter = typeParameters.get(i);
                Type producedTypeArgument = null;
                // do we have a type argument?
                TypeMirror typeArgument = null;
                SiteVariance siteVariance = null;
                if (hasTypeArguments) {
                    typeArgument = javacTypeArguments.get(i);
                    // if a single type argument is a wildcard and we are in a covariant location, we erase to Object
                    if (typeArgument.getKind() == TypeKind.WILDCARD) {
                        TypeMirror bound = typeArgument.getUpperBound();
                        if (bound != null) {
                            siteVariance = SiteVariance.OUT;
                        } else {
                            bound = typeArgument.getLowerBound();
                            if (bound != null) {
                                // it has a lower bound
                                siteVariance = SiteVariance.IN;
                            }
                        }
                        // use the bound in any case
                        typeArgument = bound;
                    }
                }
                // if we have no type argument, or if it's a wildcard with no bound, use the type parameter bounds if we can
                if (typeArgument == null && typeParameterMirrors != null && i < typeParameterMirrors.size()) {
                    TypeParameterMirror typeParameterMirror = typeParameterMirrors.get(i);
                    // FIXME: multiple bounds?
                    if (typeParameterMirror.getBounds().size() == 1) {
                        // make sure we don't go overboard
                        if (rawDeclarationsSeen == null) {
                            rawDeclarationsSeen = new HashSet<TypeDeclaration>();
                            // detect recursive bounds that we can't possibly satisfy, such as Foo<T extends Foo<T>>
                            if (!rawDeclarationsSeen.add(declaration))
                                throw new RecursiveTypeParameterBoundException();
                        }
                        TypeMirror bound = typeParameterMirror.getBounds().get(0);
                        try {
                            producedTypeArgument = obtainTypeParameterBound(moduleScope, bound, declaration, rawDeclarationsSeen);
                            siteVariance = SiteVariance.OUT;
                            // make sure we record that the type is not what it seems it is, so we can implement
                            // the method with proper raw type args and not substituted bounds
                            isRaw = true;
                        } catch (RecursiveTypeParameterBoundException x) {
                        // damnit, go for Object later
                        }
                    }
                }
                // let's fall back to "out Object"
                if (typeArgument == null && producedTypeArgument == null) {
                    producedTypeArgument = typeFactory.getObjectType();
                    siteVariance = SiteVariance.OUT;
                }
                // record use-site variance if required
                if (!ModelUtil.isCeylonDeclaration(declaration) && siteVariance != null) {
                    // lazy alloc
                    if (siteVarianceMap == null)
                        siteVarianceMap = new HashMap<TypeParameter, SiteVariance>();
                    siteVarianceMap.put(typeParameter, siteVariance);
                }
                // in some cases we may already have a produced type argument we can use. if not let's fetch it
                if (producedTypeArgument == null) {
                    if (mode == TypeMappingMode.NORMAL)
                        producedTypeArgument = obtainType(moduleScope, typeArgument, scope, TypeLocation.TYPE_PARAM);
                    else
                        producedTypeArgument = obtainTypeParameterBound(moduleScope, typeArgument, scope, rawDeclarationsSeen);
                }
                typeArguments.add(producedTypeArgument);
            }
            Type qualifyingType = null;
            if (type.getQualifyingType() != null) {
                qualifyingType = getNonPrimitiveType(moduleScope, type.getQualifyingType(), scope);
            }
            Type ret = declaration.appliedType(qualifyingType, typeArguments);
            if (siteVarianceMap != null) {
                ret.setVarianceOverrides(siteVarianceMap);
            }
            if (ret.isCached()) {
                ret = ret.clone();
            }
            ret.setUnderlyingType(type.getQualifiedName());
            ret.setRaw(isRaw);
            return ret;
        } finally {
            if (rawDeclarationsSeen != null)
                rawDeclarationsSeen.remove(declaration);
        }
    }
    // we have no type args, but perhaps we have a qualifying type which has some?
    if (type.getQualifyingType() != null) {
        // that one may have type arguments
        Type qualifyingType = getNonPrimitiveType(moduleScope, type.getQualifyingType(), scope);
        Type ret = declaration.appliedType(qualifyingType, Collections.<Type>emptyList());
        if (ret.isCached()) {
            ret = ret.clone();
        }
        ret.setUnderlyingType(type.getQualifiedName());
        ret.setRaw(isRaw);
        return ret;
    }
    // no type arg and no qualifying type
    return declaration.getType();
}
Also used : TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) TypeParameterMirror(org.eclipse.ceylon.model.loader.mirror.TypeParameterMirror) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) HashSet(java.util.HashSet)

Example 20 with SiteVariance

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

the class TypeParser method loadType.

private Type loadType(String pkg, String fullName, Part part, Type qualifyingType) {
    // try to find a qualified type
    try {
        Declaration newDeclaration;
        if (qualifyingType == null) {
            // FIXME: this only works for packages not contained in multiple modules
            Package foundPackage = moduleScope.getPackage(pkg);
            if (foundPackage != null)
                newDeclaration = loader.getDeclaration(foundPackage.getModule(), pkg, fullName, scope);
            else if (scope != null && !pkg.isEmpty() && loader.isDynamicMetamodel()) {
                // try the default module, damnit
                newDeclaration = loader.getDeclaration(loader.getLoadedModule(Module.DEFAULT_MODULE_NAME, null), pkg, fullName, scope);
            } else if (scope != null) {
                // if we did not find any package and the scope is null, chances are we're after a type variable
                // or a relative type, so use the module scope
                newDeclaration = loader.getDeclaration(moduleScope, pkg, fullName, scope);
            } else
                newDeclaration = null;
        } else {
            // look it up via its qualifying type or decl
            Declaration qualifyingDeclaration = qualifyingType.getDeclaration();
            if (qualifyingType.isUnion() || qualifyingType.isIntersection()) {
                newDeclaration = qualifyingDeclaration.getMember(part.name, null, false);
            } else {
                if (qualifyingDeclaration instanceof FunctionOrValueInterface)
                    qualifyingDeclaration = ((FunctionOrValueInterface) qualifyingDeclaration).getUnderlyingDeclaration();
                newDeclaration = AbstractModelLoader.getDirectMember((Scope) qualifyingDeclaration, part.name);
            }
            if (newDeclaration == null)
                throw new ModelResolutionException("Failed to resolve inner type or declaration " + part.name + " in " + qualifyingDeclaration.getQualifiedNameString());
        }
        if (newDeclaration == null)
            return null;
        TypeDeclaration newTypeDeclaration;
        if (newDeclaration instanceof TypeDeclaration)
            newTypeDeclaration = (TypeDeclaration) newDeclaration;
        else
            newTypeDeclaration = new FunctionOrValueInterface((TypedDeclaration) newDeclaration);
        Type ret = newTypeDeclaration.appliedType(qualifyingType, part.getParameters());
        // set the use-site variance if required, now that we know the TypeParameter declarations
        if (!part.getVariance().isEmpty()) {
            List<TypeParameter> tps = newTypeDeclaration.getTypeParameters();
            List<SiteVariance> variance = part.getVariance();
            for (int i = 0, l1 = tps.size(), l2 = variance.size(); i < l1 && i < l2; i++) {
                SiteVariance siteVariance = variance.get(i);
                if (siteVariance != null) {
                    ret.setVariance(tps.get(i), siteVariance);
                }
            }
        }
        return ret;
    } catch (ModelResolutionException x) {
        // - if we have type parameters we must have a type
        if (qualifyingType != null || (part.parameters != null && !part.parameters.isEmpty()))
            throw x;
        return null;
    }
}
Also used : FunctionOrValueInterface(org.eclipse.ceylon.model.loader.model.FunctionOrValueInterface) Type(org.eclipse.ceylon.model.typechecker.model.Type) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Scope(org.eclipse.ceylon.model.typechecker.model.Scope) SiteVariance(org.eclipse.ceylon.model.typechecker.model.SiteVariance) TypedDeclaration(org.eclipse.ceylon.model.typechecker.model.TypedDeclaration) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration) Declaration(org.eclipse.ceylon.model.typechecker.model.Declaration) Package(org.eclipse.ceylon.model.typechecker.model.Package) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Aggregations

SiteVariance (org.eclipse.ceylon.model.typechecker.model.SiteVariance)20 Type (org.eclipse.ceylon.model.typechecker.model.Type)18 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)18 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)11 IntersectionType (org.eclipse.ceylon.model.typechecker.model.IntersectionType)8 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)8 ArrayList (java.util.ArrayList)7 HashMap (java.util.HashMap)7 UnionType (org.eclipse.ceylon.model.typechecker.model.UnionType)7 NothingType (org.eclipse.ceylon.model.typechecker.model.NothingType)6 ModelUtil.appliedType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.appliedType)5 ModelUtil.intersectionType (org.eclipse.ceylon.model.typechecker.model.ModelUtil.intersectionType)5 Map (java.util.Map)4 Tree (org.eclipse.ceylon.compiler.typechecker.tree.Tree)4 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)4 LinkedHashMap (java.util.LinkedHashMap)3 AnalyzerUtil.getPackageTypeDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getPackageTypeDeclaration)3 AnalyzerUtil.getTypeDeclaration (org.eclipse.ceylon.compiler.typechecker.analyzer.AnalyzerUtil.getTypeDeclaration)3 TypeParser (org.eclipse.ceylon.model.loader.TypeParser)3 LazyType (org.eclipse.ceylon.model.typechecker.model.LazyType)3