TypeParameter typeParameter = null;
if(i < typeParameters.size())
typeParameter = typeParameters.get(i);
ProducedType 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;
}catch(RecursiveTypeParameterBoundException x){
// damnit, go for Object later