Search in sources :

Example 16 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class AbstractModelLoader method setTypeParameters.

// from java type info
private void setTypeParameters(Scope scope, List<TypeParameter> params, List<TypeParameterMirror> typeParameters, boolean isCeylon) {
    // refer to type params.
    for (TypeParameterMirror typeParam : typeParameters) {
        TypeParameter param = new TypeParameter();
        param.setUnit(scope.getUnit());
        param.setContainer(scope);
        param.setScope(scope);
        ModelUtil.setVisibleScope(param);
        param.setDeclaration((Declaration) scope);
        // let's not trigger the lazy-loading if we're completing a LazyClass/LazyInterface
        if (scope instanceof LazyContainer)
            ((LazyContainer) scope).addMember(param);
        else
            // must be a method
            scope.addMember(param);
        param.setName(typeParam.getName());
        param.setExtendedType(typeFactory.getAnythingType());
        params.add(param);
    }
    boolean needsObjectBounds = !isCeylon && scope instanceof Function;
    // Now all type params have been set, we can resolve the references parts
    Iterator<TypeParameter> paramsIterator = params.iterator();
    for (TypeParameterMirror typeParam : typeParameters) {
        TypeParameter param = paramsIterator.next();
        List<TypeMirror> bounds = typeParam.getBounds();
        for (TypeMirror bound : bounds) {
            Type boundType;
            // we turn java's default upper bound java.lang.Object into ceylon.language.Object
            if (sameType(bound, OBJECT_TYPE)) {
                // especially since we do not want it for types
                if (bounds.size() == 1)
                    break;
                boundType = getNonPrimitiveType(getLanguageModule(), CEYLON_OBJECT_TYPE, scope);
            } else
                boundType = getNonPrimitiveType(ModelUtil.getModuleContainer(scope), bound, scope);
            param.getSatisfiedTypes().add(boundType);
        }
        if (needsObjectBounds && param.getSatisfiedTypes().isEmpty()) {
            Type boundType = getNonPrimitiveType(getLanguageModule(), CEYLON_OBJECT_TYPE, scope);
            param.getSatisfiedTypes().add(boundType);
        }
    }
}
Also used : LazyContainer(org.eclipse.ceylon.model.loader.model.LazyContainer) Function(org.eclipse.ceylon.model.typechecker.model.Function) LazyFunction(org.eclipse.ceylon.model.loader.model.LazyFunction) TypeParameter(org.eclipse.ceylon.model.typechecker.model.TypeParameter) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) TypeParameterMirror(org.eclipse.ceylon.model.loader.mirror.TypeParameterMirror)

Example 17 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror 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 18 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class AbstractModelLoader method obtainTypeParameterBound.

private Type obtainTypeParameterBound(Module moduleScope, TypeMirror type, Scope scope, Set<TypeDeclaration> rawDeclarationsSeen) {
    // type variables are never mapped
    if (type.getKind() == TypeKind.TYPEVAR) {
        TypeParameterMirror typeParameter = type.getTypeParameter();
        if (!typeParameter.getBounds().isEmpty()) {
            List<Type> bounds = new ArrayList<Type>(typeParameter.getBounds().size());
            for (TypeMirror bound : typeParameter.getBounds()) {
                Type boundModel = obtainTypeParameterBound(moduleScope, bound, scope, rawDeclarationsSeen);
                bounds.add(boundModel);
            }
            return intersection(bounds, getUnitForModule(moduleScope));
        } else
            // no bound is Object
            return typeFactory.getObjectType();
    } else {
        TypeMirror mappedType = applyTypeMapping(type, TypeLocation.TYPE_PARAM);
        TypeDeclaration declaration = (TypeDeclaration) convertNonPrimitiveTypeToDeclaration(moduleScope, mappedType, scope, DeclarationType.TYPE);
        if (declaration == null) {
            throw new RuntimeException("Failed to find declaration for " + type);
        }
        if (declaration instanceof UnknownType)
            return declaration.getType();
        Type ret = applyTypeArguments(moduleScope, declaration, type, scope, TypeMappingMode.GENERATOR, rawDeclarationsSeen);
        if (ret.isCached()) {
            ret = ret.clone();
        }
        if (ret.getUnderlyingType() == null) {
            ret.setUnderlyingType(getUnderlyingType(type, TypeLocation.TYPE_PARAM));
        }
        return ret;
    }
}
Also used : UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) TypeParameterMirror(org.eclipse.ceylon.model.loader.mirror.TypeParameterMirror) ArrayList(java.util.ArrayList) TypeDeclaration(org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)

Example 19 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class AbstractModelLoader method setExtendedType.

private void setExtendedType(ClassOrInterface klass, ClassMirror classMirror) {
    // look at its super type
    TypeMirror superClass = classMirror.getSuperclass();
    Type extendedType;
    if (klass instanceof Interface) {
        // interfaces need to have their superclass set to Object
        if (superClass == null || superClass.getKind() == TypeKind.NONE)
            extendedType = getNonPrimitiveType(getLanguageModule(), CEYLON_OBJECT_TYPE, klass);
        else
            extendedType = getNonPrimitiveType(ModelUtil.getModule(klass), superClass, klass);
    } else if (klass instanceof Class && ((Class) klass).isOverloaded()) {
        // if the class is overloaded we already have it stored
        extendedType = klass.getExtendedType();
    } else {
        String className = classMirror.getQualifiedName();
        String superClassName = superClass == null ? null : superClass.getQualifiedName();
        if (className.equals("ceylon.language.Anything")) {
            // ceylon.language.Anything has no super type
            extendedType = null;
        } else if (className.equals("java.lang.Object")) {
            // we pretend its superclass is something else, but note that in theory we shouldn't
            // be seeing j.l.Object at all due to unerasure
            extendedType = getNonPrimitiveType(getLanguageModule(), CEYLON_BASIC_TYPE, klass);
        } else {
            // read it from annotation first
            String annotationSuperClassName = getAnnotationStringValue(classMirror, CEYLON_CLASS_ANNOTATION, "extendsType");
            if (annotationSuperClassName != null && !annotationSuperClassName.isEmpty()) {
                extendedType = decodeType(annotationSuperClassName, klass, ModelUtil.getModuleContainer(klass), "extended type");
            } else {
                // now deal with type erasure, avoid having Object as superclass
                if ("java.lang.Object".equals(superClassName)) {
                    extendedType = getNonPrimitiveType(getLanguageModule(), CEYLON_BASIC_TYPE, klass);
                } else if (superClass != null) {
                    try {
                        extendedType = getNonPrimitiveType(ModelUtil.getModule(klass), superClass, klass);
                    } catch (ModelResolutionException x) {
                        extendedType = logModelResolutionException(x, klass, "Error while resolving extended type of " + klass.getQualifiedNameString());
                    }
                } else {
                    // FIXME: should this be UnknownType?
                    extendedType = null;
                }
            }
        }
    }
    if (extendedType != null)
        klass.setExtendedType(extendedType);
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror) AnnotationProxyClass(org.eclipse.ceylon.model.loader.model.AnnotationProxyClass) LazyClass(org.eclipse.ceylon.model.loader.model.LazyClass) Class(org.eclipse.ceylon.model.typechecker.model.Class) Interface(org.eclipse.ceylon.model.typechecker.model.Interface) ClassOrInterface(org.eclipse.ceylon.model.typechecker.model.ClassOrInterface) LazyInterface(org.eclipse.ceylon.model.loader.model.LazyInterface)

Example 20 with TypeMirror

use of org.eclipse.ceylon.model.loader.mirror.TypeMirror in project ceylon by eclipse.

the class AbstractModelLoader method obtainType.

public Type obtainType(Module moduleScope, TypeMirror type, Scope scope, TypeLocation location) {
    TypeMirror originalType = type;
    // ERASURE
    type = applyTypeMapping(type, location);
    Type ret = getNonPrimitiveType(moduleScope, type, scope);
    if (ret.isCached()) {
        ret = ret.clone();
    }
    if (ret.getUnderlyingType() == null) {
        ret.setUnderlyingType(getUnderlyingType(originalType, location));
    }
    return ret;
}
Also used : Type(org.eclipse.ceylon.model.typechecker.model.Type) UnknownType(org.eclipse.ceylon.model.typechecker.model.UnknownType) FunctionalInterfaceType(org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType) TypeMirror(org.eclipse.ceylon.model.loader.mirror.TypeMirror)

Aggregations

TypeMirror (org.eclipse.ceylon.model.loader.mirror.TypeMirror)23 FunctionalInterfaceType (org.eclipse.ceylon.model.loader.mirror.FunctionalInterfaceType)10 Type (org.eclipse.ceylon.model.typechecker.model.Type)10 UnknownType (org.eclipse.ceylon.model.typechecker.model.UnknownType)10 ArrayList (java.util.ArrayList)7 TypeDeclaration (org.eclipse.ceylon.model.typechecker.model.TypeDeclaration)6 AnnotationMirror (org.eclipse.ceylon.model.loader.mirror.AnnotationMirror)5 Type (org.eclipse.ceylon.langtools.tools.javac.code.Type)4 LazyFunction (org.eclipse.ceylon.model.loader.model.LazyFunction)4 TypeParameter (org.eclipse.ceylon.model.typechecker.model.TypeParameter)4 Type (java.lang.reflect.Type)3 ClassMirror (org.eclipse.ceylon.model.loader.mirror.ClassMirror)3 TypeParameterMirror (org.eclipse.ceylon.model.loader.mirror.TypeParameterMirror)3 LazyClass (org.eclipse.ceylon.model.loader.model.LazyClass)3 LazyValue (org.eclipse.ceylon.model.loader.model.LazyValue)3 ClassOrInterface (org.eclipse.ceylon.model.typechecker.model.ClassOrInterface)3 Declaration (org.eclipse.ceylon.model.typechecker.model.Declaration)3 Function (org.eclipse.ceylon.model.typechecker.model.Function)3 Module (org.eclipse.ceylon.model.typechecker.model.Module)3 ParameterList (org.eclipse.ceylon.model.typechecker.model.ParameterList)3