@Nullable private PsiType extractContentTypeFromType(PsiType collectionType) { if (!(collectionType instanceof PsiClassType)) { return null; } final PsiClassType classType = (PsiClassType) collectionType; final PsiType[] parameterTypes = classType.getParameters(); if (parameterTypes.length == 0) { return null; } final PsiType parameterType = parameterTypes[0]; if (parameterType == null) { return null; } if (parameterType instanceof PsiWildcardType) { final PsiWildcardType wildcardType = (PsiWildcardType) parameterType; return wildcardType.getExtendsBound(); } else if (parameterType instanceof PsiCapturedWildcardType) { final PsiCapturedWildcardType capturedWildcardType = (PsiCapturedWildcardType) parameterType; final PsiWildcardType wildcardType = capturedWildcardType.getWildcard(); return wildcardType.getExtendsBound(); } return parameterType; }
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); }