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);
}
}
}
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();
}
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;
}
}
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);
}
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;
}
Aggregations