PsiType (@NotNull PsiType type, final boolean openCaptured) { PsiClass refClass = PsiUtil.resolveClassInType(type); if (refClass instanceof PsiAnonymousClass) { type = ((PsiAnonymousClass)refClass).getBaseClassType(); } PsiType deepComponentType = type.getDeepComponentType(); if (deepComponentType instanceof PsiCapturedWildcardType) { type = PsiTypesUtil.createArrayType(((PsiCapturedWildcardType)deepComponentType).getUpperBound(), type.getArrayDimensions()); } PsiType transformed = type.accept(new PsiTypeVisitor<PsiType>() { @Override public PsiType visitArrayType(@NotNull PsiArrayType arrayType) { PsiType componentType = arrayType.getComponentType(); PsiType type = componentType.accept(this); if (type == componentType) return arrayType; if (type instanceof PsiWildcardType) { type = ((PsiWildcardType)type).getBound(); } return type != null ? type.createArrayType().annotate(arrayType.getAnnotationProvider()) : arrayType; } @Override public PsiType visitType(@NotNull PsiType type) { return type; } @Override public PsiType visitWildcardType(@NotNull final PsiWildcardType wildcardType) { final PsiType bound = wildcardType.getBound(); PsiManager manager = wildcardType.getManager(); if (bound != null) { if (wildcardType.isSuper() && bound instanceof PsiIntersectionType) { return PsiWildcardType.createUnbounded(manager); } final PsiType acceptedBound = bound.accept(this); if (acceptedBound instanceof PsiWildcardType) { if (((PsiWildcardType)acceptedBound).isExtends() != wildcardType.isExtends()) return PsiWildcardType.createUnbounded(manager); return acceptedBound; } if (wildcardType.isExtends() && acceptedBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return PsiWildcardType.createUnbounded(manager); if (acceptedBound.equals(bound)) return wildcardType; return wildcardType.isExtends() ? PsiWildcardType.createExtends(manager, acceptedBound) : PsiWildcardType.createSuper(manager, acceptedBound); } return wildcardType; } @Override public PsiType visitCapturedWildcardType(@NotNull PsiCapturedWildcardType capturedWildcardType) { return openCaptured ? capturedWildcardType.getWildcard().accept(this) : capturedWildcardType; } @Override public PsiType visitClassType(@NotNull PsiClassType classType) { PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics(); PsiClass aClass = resolveResult.getElement(); if (aClass == null) return classType; boolean toExtend = false; PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; for (PsiTypeParameter typeParameter : PsiUtil.typeParametersIterable(aClass)) { PsiType typeArgument = resolveResult.getSubstitutor().substitute(typeParameter); if (typeArgument instanceof PsiCapturedWildcardType) toExtend = true; if (typeArgument instanceof PsiWildcardType && ((PsiWildcardType)typeArgument).getBound() instanceof PsiIntersectionType) { toExtend = true; } PsiType toPut; if (typeArgument == null) { toPut = null; } else { final PsiType accepted = typeArgument.accept(this); if (typeArgument instanceof PsiIntersectionType && !(accepted instanceof PsiWildcardType)) { toPut = PsiWildcardType.createExtends(typeParameter.getManager(), accepted); } else { toPut = accepted; } } LOG.assertTrue(toPut == null || toPut.isValid(), toPut); substitutor = substitutor.put(typeParameter, toPut); } PsiAnnotation[] applicableAnnotations = classType.getApplicableAnnotations(); if (substitutor == PsiSubstitutor.EMPTY && !toExtend && applicableAnnotations.length == 0 && !(aClass instanceof PsiTypeParameter)) { return classType; } PsiManager manager = aClass.getManager(); PsiType result = JavaPsiFacade.getElementFactory(manager.getProject()) .createType(aClass, substitutor, PsiUtil.getLanguageLevel(aClass)) .annotate(TypeAnnotationProvider.Static.create(applicableAnnotations)); if (toExtend) result = PsiWildcardType.createExtends(manager, result); return result; } }); PsiType componentType = transformed.getDeepComponentType(); if (componentType instanceof PsiWildcardType) { componentType = ((PsiWildcardType)componentType).getExtendsBound(); return PsiTypesUtil.createArrayType(componentType, transformed.getArrayDimensions()); } if (transformed instanceof PsiEllipsisType) { return ((PsiEllipsisType)transformed).toArrayType(); } return transformed; }