@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; }
@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; }
private PsiType addBounds(PsiType substituted, final PsiTypeParameter typeParameter) { PsiElement captureContext = null; if (substituted instanceof PsiCapturedWildcardType) { final PsiCapturedWildcardType captured = (PsiCapturedWildcardType) substituted; substituted = captured.getWildcard(); captureContext = captured.getContext(); } if (substituted instanceof PsiWildcardType && !((PsiWildcardType) substituted).isSuper()) { PsiType originalBound = ((PsiWildcardType) substituted).getBound(); PsiManager manager = typeParameter.getManager(); final PsiType[] boundTypes = typeParameter.getExtendsListTypes(); for (PsiType boundType : boundTypes) { PsiType substitutedBoundType = boundType.accept(mySimpleSubstitutionVisitor); PsiWildcardType wildcardType = (PsiWildcardType) substituted; if (substitutedBoundType != null && !(substitutedBoundType instanceof PsiWildcardType) && !substitutedBoundType.equalsToText("java.lang.Object")) { if (originalBound == null || (!TypeConversionUtil.erasure(substitutedBoundType) .isAssignableFrom(TypeConversionUtil.erasure(originalBound)) && !TypeConversionUtil.erasure(substitutedBoundType) .isAssignableFrom( originalBound))) { // erasure is essential to avoid infinite recursion if (wildcardType.isExtends()) { final PsiType glb = GenericsUtil.getGreatestLowerBound(wildcardType.getBound(), substitutedBoundType); if (glb != null) { substituted = PsiWildcardType.createExtends(manager, glb); } } else { // unbounded substituted = PsiWildcardType.createExtends(manager, substitutedBoundType); } } } } } if (captureContext != null) { LOG.assertTrue(substituted instanceof PsiWildcardType); substituted = PsiCapturedWildcardType.create((PsiWildcardType) substituted, captureContext); } return substituted; }
@Override public PsiType visitCapturedWildcardType(PsiCapturedWildcardType capturedWildcardType) { return capturedWildcardType.getUpperBound().accept(this); }