@Nullable private static Boolean isAssignableForNativeTypes( @NotNull PsiType lType, @NotNull PsiClassType rType, @NotNull PsiElement context) { if (!(lType instanceof PsiClassType)) return null; final PsiClassType.ClassResolveResult leftResult = ((PsiClassType) lType).resolveGenerics(); final PsiClassType.ClassResolveResult rightResult = rType.resolveGenerics(); final PsiClass leftClass = leftResult.getElement(); PsiClass rightClass = rightResult.getElement(); if (rightClass == null || leftClass == null) return null; if (!InheritanceUtil.isInheritorOrSelf(rightClass, leftClass, true)) return Boolean.FALSE; PsiSubstitutor rightSubstitutor = rightResult.getSubstitutor(); if (!leftClass.hasTypeParameters()) return Boolean.TRUE; PsiSubstitutor leftSubstitutor = leftResult.getSubstitutor(); if (!leftClass.getManager().areElementsEquivalent(leftClass, rightClass)) { rightSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(leftClass, rightClass, rightSubstitutor); rightClass = leftClass; } else if (!rightClass.hasTypeParameters()) return Boolean.TRUE; Iterator<PsiTypeParameter> li = PsiUtil.typeParametersIterator(leftClass); Iterator<PsiTypeParameter> ri = PsiUtil.typeParametersIterator(rightClass); while (li.hasNext()) { if (!ri.hasNext()) return Boolean.FALSE; PsiTypeParameter lp = li.next(); PsiTypeParameter rp = ri.next(); final PsiType typeLeft = leftSubstitutor.substitute(lp); if (typeLeft == null) continue; final PsiType typeRight = rightSubstitutor.substituteWithBoundsPromotion(rp); if (typeRight == null) { return Boolean.TRUE; } if (!isAssignableWithoutConversions(typeLeft, typeRight, context)) return Boolean.FALSE; } return Boolean.TRUE; }
@Nullable public static PsiType rawSecondGeneric(PsiType type, Project project) { if (!(type instanceof PsiClassType)) return null; final PsiClassType.ClassResolveResult result = ((PsiClassType) type).resolveGenerics(); final PsiClass element = result.getElement(); if (element == null) return null; final PsiType[] parameters = ((PsiClassType) type).getParameters(); boolean changed = false; for (int i = 0; i < parameters.length; i++) { PsiType parameter = parameters[i]; if (parameter == null) continue; final Ref<PsiType> newParam = new Ref<PsiType>(); parameter.accept( new PsiTypeVisitorEx<Object>() { @Nullable @Override public Object visitClassType(PsiClassType classType) { if (classType.getParameterCount() > 0) { newParam.set(classType.rawType()); } return null; } @Nullable @Override public Object visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) { newParam.set(capturedWildcardType.getWildcard().getBound()); return null; } @Nullable @Override public Object visitWildcardType(PsiWildcardType wildcardType) { newParam.set(wildcardType.getBound()); return null; } }); if (!newParam.isNull()) { changed = true; parameters[i] = newParam.get(); } } if (!changed) return null; return JavaPsiFacade.getElementFactory(project).createType(element, parameters); }