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
  public JParameterizedType asParameterizationOf(
      com.google.gwt.core.ext.typeinfo.JGenericType type) {
    Set<JClassType> supertypes = getFlattenedSuperTypeHierarchy(this);
    for (JClassType supertype : supertypes) {
      JParameterizedType isParameterized = supertype.isParameterized();
      if (isParameterized != null && isParameterized.getBaseType() == type) {
        return isParameterized;
      }

      JRawType isRaw = supertype.isRawType();
      if (isRaw != null && isRaw.getBaseType() == type) {
        return isRaw.asParameterizedByWildcards();
      }
    }

    return null;
  }
Example #3
0
  private static void getFlattenedSuperTypeHierarchyRecursive(
      JClassType type, Set<JClassType> typesSeen) {
    if (typesSeen.contains(type)) {
      return;
    }
    typesSeen.add(type);

    // Check the interfaces
    JClassType[] intfs = type.getImplementedInterfaces();
    for (JClassType intf : intfs) {
      typesSeen.addAll(getFlattenedSuperTypeHierarchy(intf));
    }

    // Superclass
    JClassType superclass = type.getSuperclass();
    if (superclass != null) {
      typesSeen.addAll(getFlattenedSuperTypeHierarchy(superclass));
    }
  }
Example #4
0
 /**
  * Returns all of the superclasses and superinterfaces for a given type including the type itself.
  * The returned set maintains an internal breadth-first ordering of the type, followed by its
  * interfaces (and their super-interfaces), then the supertype and its interfaces, and so on.
  */
 protected static Set<JClassType> getFlattenedSuperTypeHierarchy(JClassType type) {
   Set<JClassType> flattened = type.flattenedSupertypes;
   if (flattened == null) {
     flattened = new LinkedHashSet<JClassType>();
     getFlattenedSuperTypeHierarchyRecursive(type, flattened);
     // flattened.size() > 1 for all types other than Object
     type.flattenedSupertypes = Collections.unmodifiableSet(flattened);
   }
   return flattened;
 }
Example #5
0
  /**
   * Find an annotation on a type or on one of its superclasses or superinterfaces.
   *
   * <p>This provides semantics similar to that of {@link java.lang.annotation.Inherited} except
   * that it checks all types to which this type is assignable. {@code @Inherited} only works on
   * superclasses, not superinterfaces.
   *
   * <p>Annotations present on the superclass chain will be returned preferentially over those found
   * in the superinterface hierarchy. Note that the annotation does not need to be tagged with
   * {@code @Inherited} in order to be returned from the superclass chain.
   *
   * @param annotationType the type of the annotation to look for
   * @return the desired annotation or <code>null</code> if the annotation is not present in the
   *     type's type hierarchy
   */
  @Override
  public <T extends Annotation> T findAnnotationInTypeHierarchy(Class<T> annotationType) {

    // Remember what we've seen to avoid loops
    Set<JClassType> seen = new HashSet<JClassType>();

    // Work queue
    List<JClassType> searchTypes = new LinkedList<JClassType>();
    searchTypes.add(this);

    T toReturn = null;

    while (!searchTypes.isEmpty()) {
      JClassType current = searchTypes.remove(0);

      if (!seen.add(current)) {
        continue;
      }

      toReturn = current.getAnnotation(annotationType);
      if (toReturn != null) {
        /*
         * First one wins. It might be desirable at some point to have a
         * variation that can return more than one instance of the annotation if
         * it is present on multiple supertypes.
         */
        break;
      }

      if (current.getSuperclass() != null) {
        // Add the superclass at the front of the list
        searchTypes.add(0, current.getSuperclass());
      }

      // Superinterfaces
      Collections.addAll(searchTypes, current.getImplementedInterfaces());
    }

    return toReturn;
  }
Example #6
0
 /**
  * Return the real argument names for a given method from the source.
  *
  * @param method method to lookup parameter names for
  * @return array of argument names or null if no source is available
  */
 public synchronized String[] getArguments(JAbstractMethod method) {
   JClassType type = method.getEnclosingType();
   JClassType topType = getTopmostType(type);
   CompilationUnitDeclaration cud = getCudForTopLevelType(topType);
   if (cud == null) {
     return null;
   }
   TypeDeclaration jdtType = findType(cud, type.getQualifiedBinaryName());
   if (jdtType == null) {
     // TODO(jat): any thing else to do here?
     return null;
   }
   AbstractMethodDeclaration jdtMethod = findMethod(jdtType, method);
   if (jdtMethod == null) {
     // TODO(jat): any thing else to do here?
     return null;
   }
   int n = jdtMethod.arguments.length;
   String[] argNames = new String[n];
   for (int i = 0; i < n; ++i) {
     argNames[i] = String.valueOf(jdtMethod.arguments[i].name);
   }
   return argNames;
 }
Example #7
0
 public static JClassType getTopmostType(JClassType type) {
   while (type.getEnclosingType() != null) {
     type = type.getEnclosingType();
   }
   return type;
 }
Example #8
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;
  }