Example #1
0
  /**
   * A restricted version of areClassTypesAssignable that is used for comparing the type arguments
   * of parameterized types, where the lhsTypeArg is the container.
   */
  private static boolean doesTypeArgumentContain(JClassType lhsTypeArg, JClassType rhsTypeArg) {
    if (lhsTypeArg == rhsTypeArg) {
      return true;
    }

    // Check for wildcard types
    JWildcardType lhsWildcard = lhsTypeArg.isWildcard();
    JWildcardType rhsWildcard = rhsTypeArg.isWildcard();

    if (lhsWildcard != null) {
      if (rhsWildcard != null) {
        return areWildcardsAssignable(lhsWildcard, rhsWildcard);
      } else {
        // LHS is a wildcard but the RHS is not.
        if (lhsWildcard.getLowerBounds().length > 0) {
          return areClassTypesAssignable(rhsTypeArg, lhsWildcard.getFirstBound());
        } else {
          return areClassTypesAssignable(lhsWildcard.getFirstBound(), rhsTypeArg);
        }
      }
    }

    /*
     * At this point the arguments are not the same and they are not wildcards
     * so, they cannot be assignable, Eh.
     */
    return false;
  }
Example #2
0
  /**
   * Returns <code>true</code> if the rhsWildcard can be assigned to the lhsWildcard. This method
   * does not consider supertypes of either lhs or rhs.
   */
  private static boolean areWildcardsAssignable(
      JWildcardType lhsWildcard, JWildcardType rhsWildcard) {
    // areClassTypesAssignable should prevent us from getting here if the types
    // are referentially equal.
    assert (lhsWildcard != rhsWildcard);
    assert (lhsWildcard != null && rhsWildcard != null);

    if (lhsWildcard.getLowerBounds().length > 0 && rhsWildcard.getLowerBounds().length > 0) {
      // lhsType: ? super T, rhsType ? super U
      return areClassTypesAssignable(rhsWildcard.getFirstBound(), lhsWildcard.getFirstBound());
    } else if (lhsWildcard.getUpperBounds().length > 0
        && lhsWildcard.getLowerBounds().length == 0
        && rhsWildcard.getUpperBounds().length > 0
        && rhsWildcard.getLowerBounds().length == 0) {
      // lhsType: ? extends T, rhsType: ? extends U
      return areClassTypesAssignable(lhsWildcard.getFirstBound(), rhsWildcard.getFirstBound());
    }

    return false;
  }
Example #3
0
  /**
   * Returns <code>true</code> if the lhs and rhs are assignable without consideration of the
   * supertypes of the rhs.
   *
   * @param lhsType
   * @param rhsType
   * @return true if rhsType can be assigned to lhsType
   */
  private static boolean areClassTypesAssignableNoSupers(JClassType lhsType, JClassType rhsType) {
    if (lhsType == rhsType) {
      // Done, these are the same types.
      return true;
    }

    if (lhsType == lhsType.getOracle().getJavaLangObject()) {
      // Done, any type can be assigned to object.
      return true;
    }

    /*
     * Get the generic base type, if there is one, for the lhs type and convert
     * it to a raw type if it is generic.
     */
    if (lhsType.isGenericType() != null) {
      lhsType = lhsType.isGenericType().getRawType();
    }

    if (rhsType.isGenericType() != null) {
      // Treat the generic rhs type as a raw type.
      rhsType = rhsType.isGenericType().getRawType();
    }

    // Check for JTypeParameters.
    JTypeParameter lhsTypeParam = lhsType.isTypeParameter();
    JTypeParameter rhsTypeParam = rhsType.isTypeParameter();
    if (lhsTypeParam != null) {
      JClassType[] lhsTypeBounds = lhsTypeParam.getBounds();
      for (JClassType lhsTypeBound : lhsTypeBounds) {
        if (!areClassTypesAssignable(lhsTypeBound, rhsType)) {
          // Done, the rhsType was not assignable to one of the bounds.
          return false;
        }
      }

      // Done, the rhsType was assignable to all of the bounds.
      return true;
    } else if (rhsTypeParam != null) {
      JClassType[] possibleSubtypeBounds = rhsTypeParam.getBounds();
      for (JClassType possibleSubtypeBound : possibleSubtypeBounds) {
        if (areClassTypesAssignable(lhsType, possibleSubtypeBound)) {
          // Done, at least one bound is assignable to this type.
          return true;
        }
      }

      return false;
    }

    /*
     * Check for JWildcards. We have not examined this part in great detail
     * since there should not be top level wildcard types.
     */
    JWildcardType lhsWildcard = lhsType.isWildcard();
    JWildcardType rhsWildcard = rhsType.isWildcard();
    if (lhsWildcard != null && rhsWildcard != null) {
      // Both types are wildcards.
      return areWildcardsAssignable(lhsWildcard, rhsWildcard);
    } else if (lhsWildcard != null) {
      // The lhs type is a wildcard but the rhs is not.
      // ? extends T, U OR ? super T, U
      JClassType[] lowerBounds = lhsWildcard.getLowerBounds();
      if (lowerBounds.length > 0) {
        // ? super T will reach object no matter what the rhs type is
        return true;
      } else {
        return areClassTypesAssignable(lhsWildcard.getFirstBound(), rhsType);
      }
    }

    // Check for JArrayTypes.
    JArrayType lhsArray = lhsType.isArray();
    JArrayType rhsArray = rhsType.isArray();
    if (lhsArray != null) {
      if (rhsArray == null) {
        return false;
      } else {
        return areArraysAssignable(lhsArray, rhsArray);
      }
    } else if (rhsArray != null) {
      // Safe although perhaps not necessary
      return false;
    }

    // Check for JParameterizedTypes and JRawTypes.
    JMaybeParameterizedType lhsMaybeParameterized = lhsType.isMaybeParameterizedType();
    JMaybeParameterizedType rhsMaybeParameterized = rhsType.isMaybeParameterizedType();
    if (lhsMaybeParameterized != null && rhsMaybeParameterized != null) {
      if (lhsMaybeParameterized.getBaseType() == rhsMaybeParameterized.getBaseType()) {
        if (lhsMaybeParameterized.isRawType() != null
            || rhsMaybeParameterized.isRawType() != null) {
          /*
           * Any raw type can be assigned to or from any parameterization of its
           * generic type.
           */
          return true;
        }

        assert (lhsMaybeParameterized.isRawType() == null
            && rhsMaybeParameterized.isRawType() == null);
        JParameterizedType lhsParameterized = lhsMaybeParameterized.isParameterized();
        JParameterizedType rhsParameterized = rhsMaybeParameterized.isParameterized();
        assert (lhsParameterized != null && rhsParameterized != null);

        return areTypeArgumentsAssignable(lhsParameterized, rhsParameterized);
      }
    }

    // Default to not being assignable.
    return false;
  }