public static boolean provablyDistinct(PsiWildcardType type1, PsiWildcardType type2) {
    if (type1.isSuper() && type2.isSuper()) return false;
    if (type1.isExtends() && type2.isExtends()) {
      final PsiType extendsBound1 = type1.getExtendsBound();
      final PsiType extendsBound2 = type2.getExtendsBound();
      if (extendsBound1 instanceof PsiArrayType
              && proveArrayTypeDistinct(
                  type1.getManager().getProject(), (PsiArrayType) extendsBound1, extendsBound2)
          || extendsBound2 instanceof PsiArrayType
              && proveArrayTypeDistinct(
                  type1.getManager().getProject(), (PsiArrayType) extendsBound2, extendsBound1))
        return true;

      final PsiClass boundClass1 = PsiUtil.resolveClassInType(extendsBound1);
      final PsiClass boundClass2 = PsiUtil.resolveClassInType(extendsBound2);
      if (boundClass1 != null && boundClass2 != null) {
        return proveExtendsBoundsDistinct(type1, type2, boundClass1, boundClass2);
      }
      return provablyDistinct(extendsBound1, extendsBound2, 1);
    }
    if (type2.isExtends()) return provablyDistinct(type2, type1);
    if (type1.isExtends() && type2.isSuper()) {
      final PsiType extendsBound = type1.getExtendsBound();
      final PsiType superBound = type2.getSuperBound();
      if (extendsBound instanceof PsiArrayType
              && proveArrayTypeDistinct(
                  type1.getManager().getProject(), (PsiArrayType) extendsBound, superBound)
          || superBound instanceof PsiArrayType
              && proveArrayTypeDistinct(
                  type1.getManager().getProject(), (PsiArrayType) superBound, extendsBound))
        return true;

      final PsiClass extendsBoundClass = PsiUtil.resolveClassInType(extendsBound);
      final PsiClass superBoundClass = PsiUtil.resolveClassInType(superBound);
      if (extendsBoundClass != null && superBoundClass != null) {
        if (extendsBoundClass instanceof PsiTypeParameter) {
          return try2ProveTypeParameterDistinct(type2, extendsBoundClass);
        }
        if (superBoundClass instanceof PsiTypeParameter) return false;
        return !InheritanceUtil.isInheritorOrSelf(superBoundClass, extendsBoundClass, true);
      }
      return true;
    }

    if (!type1.isBounded() || !type2.isBounded()) {
      return false;
    }
    return !type1.equals(type2);
  }
Exemplo n.º 2
0
  @Nullable
  private static PsiType doNormalizeWildcardByPosition(
      final PsiType type, final GrExpression expression, final GrExpression toplevel) {
    if (type instanceof PsiCapturedWildcardType) {
      return doNormalizeWildcardByPosition(
          ((PsiCapturedWildcardType) type).getWildcard(), expression, toplevel);
    }

    if (type instanceof PsiWildcardType) {
      final PsiWildcardType wildcardType = (PsiWildcardType) type;

      if (PsiUtil.isAccessedForWriting(toplevel)) {
        return wildcardType.isSuper()
            ? wildcardType.getBound()
            : PsiCapturedWildcardType.create(wildcardType, expression);
      } else {
        if (wildcardType.isExtends()) {
          return wildcardType.getBound();
        } else {
          return PsiType.getJavaLangObject(expression.getManager(), expression.getResolveScope());
        }
      }
    } else if (type instanceof PsiArrayType) {
      final PsiType componentType = ((PsiArrayType) type).getComponentType();
      final PsiType normalizedComponentType =
          doNormalizeWildcardByPosition(componentType, expression, toplevel);
      if (normalizedComponentType != componentType) {
        assert normalizedComponentType != null;
        return normalizedComponentType.createArrayType();
      }
    }

    return type;
  }
Exemplo n.º 3
0
  private static PsiType getLeastContainingTypeArgument(
      PsiType type1,
      PsiType type2,
      Set<Pair<PsiType, PsiType>> compared,
      PsiManager manager,
      PsiClass nestedLayer,
      PsiTypeParameter parameter) {
    Pair<PsiType, PsiType> types = new Pair<PsiType, PsiType>(type1, type2);
    if (compared.contains(types)) {
      if (nestedLayer != null) {
        PsiSubstitutor subst = PsiSubstitutor.EMPTY;
        for (PsiTypeParameter param : PsiUtil.typeParametersIterable(nestedLayer)) {
          subst = subst.put(param, PsiWildcardType.createUnbounded(manager));
        }
        subst =
            subst.put(
                parameter,
                getLeastContainingTypeArgument(type1, type2, compared, manager, null, null));

        final PsiClassType boundType =
            JavaPsiFacade.getInstance(manager.getProject())
                .getElementFactory()
                .createType(nestedLayer, subst);
        return PsiWildcardType.createExtends(manager, boundType);
      }
      return PsiWildcardType.createUnbounded(manager);
    }
    compared.add(types);

    try {
      if (type1 instanceof PsiWildcardType) {
        PsiWildcardType wild1 = (PsiWildcardType) type1;
        final PsiType bound1 = wild1.getBound();
        if (bound1 == null) return type1;
        if (type2 instanceof PsiWildcardType) {
          PsiWildcardType wild2 = (PsiWildcardType) type2;
          final PsiType bound2 = wild2.getBound();
          if (bound2 == null) return type2;
          if (wild1.isExtends() == wild2.isExtends()) {
            return wild1.isExtends()
                ? PsiWildcardType.createExtends(
                    manager, getLeastUpperBound(bound1, bound2, compared, manager))
                : PsiWildcardType.createSuper(manager, getGreatestLowerBound(bound1, bound2));
          } else {
            return bound1.equals(bound2) ? bound1 : PsiWildcardType.createUnbounded(manager);
          }
        } else {
          return wild1.isExtends()
              ? PsiWildcardType.createExtends(
                  manager, getLeastUpperBound(bound1, type2, compared, manager))
              : wild1.isSuper()
                  ? PsiWildcardType.createSuper(manager, getGreatestLowerBound(bound1, type2))
                  : wild1;
        }
      } else if (type2 instanceof PsiWildcardType) {
        return getLeastContainingTypeArgument(type2, type1, compared, manager, null, null);
      }
      // Done with wildcards

      if (type1.equals(type2)) return type1;
      return PsiWildcardType.createExtends(
          manager, getLeastUpperBound(type1, type2, compared, manager));
    } finally {
      compared.remove(types);
    }
  }