Example #1
0
 private final boolean isCoerceableFromParameterizedType(ResolvedType other) {
   if (!other.isParameterizedType()) return false;
   ResolvedType myRawType = (ResolvedType) getRawType();
   ResolvedType theirRawType = (ResolvedType) other.getRawType();
   if (myRawType == theirRawType) {
     if (getTypeParameters().length == other.getTypeParameters().length) {
       // there's a chance it can be done
       ResolvedType[] myTypeParameters = getResolvedTypeParameters();
       ResolvedType[] theirTypeParameters = other.getResolvedTypeParameters();
       for (int i = 0; i < myTypeParameters.length; i++) {
         if (myTypeParameters[i] != theirTypeParameters[i]) {
           // thin ice now... but List<String> may still be coerceable from e.g. List<T>
           if (myTypeParameters[i].isGenericWildcard()) {
             BoundedReferenceType wildcard = (BoundedReferenceType) myTypeParameters[i];
             if (!wildcard.canBeCoercedTo(theirTypeParameters[i])) return false;
           } else if (myTypeParameters[i].isTypeVariableReference()) {
             TypeVariableReferenceType tvrt = (TypeVariableReferenceType) myTypeParameters[i];
             TypeVariable tv = tvrt.getTypeVariable();
             tv.resolve(world);
             if (!tv.canBeBoundTo(theirTypeParameters[i])) return false;
           } else if (theirTypeParameters[i].isTypeVariableReference()) {
             TypeVariableReferenceType tvrt = (TypeVariableReferenceType) theirTypeParameters[i];
             TypeVariable tv = tvrt.getTypeVariable();
             tv.resolve(world);
             if (!tv.canBeBoundTo(myTypeParameters[i])) return false;
           } else {
             return false;
           }
         }
       }
       return true;
     }
   } else {
     // we do this walk for situations like the following:
     // Base<T>, Sub<S,T> extends Base<S>
     // is Sub<Y,Z> coerceable from Base<X> ???
     for (Iterator i = getDirectSupertypes(); i.hasNext(); ) {
       ReferenceType parent = (ReferenceType) i.next();
       if (parent.isCoerceableFromParameterizedType(other)) return true;
     }
   }
   return false;
 }
Example #2
0
  // true iff the statement "this = other" would compile.
  public boolean isAssignableFrom(ResolvedType other, boolean allowMissing) {
    if (other.isPrimitiveType()) {
      if (!world.isInJava5Mode()) return false;
      if (ResolvedType.validBoxing.contains(this.getSignature() + other.getSignature()))
        return true;
    }
    if (this == other) return true;
    if (this.getSignature().equals(ResolvedType.OBJECT.getSignature())) return true;

    if ((this.isRawType() || this.isGenericType()) && other.isParameterizedType()) {
      if (isAssignableFrom((ResolvedType) other.getRawType())) return true;
    }
    if (this.isRawType() && other.isGenericType()) {
      if (isAssignableFrom((ResolvedType) other.getRawType())) return true;
    }
    if (this.isGenericType() && other.isRawType()) {
      if (isAssignableFrom((ResolvedType) other.getGenericType())) return true;
    }

    if (this.isParameterizedType()) {
      // look at wildcards...
      if (((ReferenceType) this.getRawType()).isAssignableFrom(other)) {
        boolean wildcardsAllTheWay = true;
        ResolvedType[] myParameters = this.getResolvedTypeParameters();
        for (int i = 0; i < myParameters.length; i++) {
          if (!myParameters[i].isGenericWildcard()) {
            wildcardsAllTheWay = false;
          } else if (myParameters[i].isExtends() || myParameters[i].isSuper()) {
            wildcardsAllTheWay = false;
          }
        }
        if (wildcardsAllTheWay && !other.isParameterizedType()) return true;
        // we have to match by parameters one at a time
        ResolvedType[] theirParameters = other.getResolvedTypeParameters();
        boolean parametersAssignable = true;
        if (myParameters.length == theirParameters.length) {
          for (int i = 0; i < myParameters.length; i++) {
            if (myParameters[i] == theirParameters[i]) continue;
            if (myParameters[i].isAssignableFrom(theirParameters[i], allowMissing)) {
              continue;
            }
            if (!myParameters[i].isGenericWildcard()) {
              parametersAssignable = false;
              break;
            } else {
              BoundedReferenceType wildcardType = (BoundedReferenceType) myParameters[i];
              if (!wildcardType.alwaysMatches(theirParameters[i])) {
                parametersAssignable = false;
                break;
              }
            }
          }
        } else {
          parametersAssignable = false;
        }
        if (parametersAssignable) return true;
      }
    }

    if (isTypeVariableReference()
        && !other.isTypeVariableReference()) { // eg. this=T  other=Ljava/lang/Object;
      TypeVariable aVar = ((TypeVariableReference) this).getTypeVariable();
      return aVar.resolve(world).canBeBoundTo(other);
    }

    if (other.isTypeVariableReference()) {
      TypeVariableReferenceType otherType = (TypeVariableReferenceType) other;
      if (this instanceof TypeVariableReference) {
        return ((TypeVariableReference) this)
            .getTypeVariable()
            .canBeBoundTo(otherType.getTypeVariable().getFirstBound().resolve(world)); // pr171952
        //       			return
        // ((TypeVariableReference)this).getTypeVariable()==otherType.getTypeVariable();
      } else {
        // FIXME asc should this say canBeBoundTo??
        return this.isAssignableFrom(otherType.getTypeVariable().getFirstBound().resolve(world));
      }
    }

    if (allowMissing && other.isMissing()) return false;

    for (Iterator i = other.getDirectSupertypes(); i.hasNext(); ) {
      if (this.isAssignableFrom((ResolvedType) i.next(), allowMissing)) return true;
    }
    return false;
  }