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; }
public PsiType substitute(final PsiType t) { if (t instanceof PsiWildcardType) { final PsiWildcardType wcType = (PsiWildcardType) t; final PsiType bound = wcType.getBound(); if (bound == null) { return t; } final PsiManager manager = PsiManager.getInstance(myProject); final PsiType subst = substitute(bound); if (subst == null) return null; return subst instanceof PsiWildcardType ? subst : wcType.isExtends() ? PsiWildcardType.createExtends(manager, subst) : PsiWildcardType.createSuper(manager, subst); } else if (t instanceof PsiTypeVariable) { final PsiType b = apply(t); if (b instanceof Bottom || b instanceof PsiTypeVariable) { return null; } return substitute(b); } else if (t instanceof Bottom) { return null; } else if (t instanceof PsiArrayType) { return substitute(((PsiArrayType) t).getComponentType()).createArrayType(); } else if (t instanceof PsiClassType) { final PsiClassType.ClassResolveResult result = ((PsiClassType) t).resolveGenerics(); final PsiClass aClass = result.getElement(); final PsiSubstitutor aSubst = result.getSubstitutor(); if (aClass != null) { PsiSubstitutor theSubst = PsiSubstitutor.EMPTY; for (final PsiTypeParameter parm : aSubst.getSubstitutionMap().keySet()) { final PsiType type = aSubst.substitute(parm); theSubst = theSubst.put(parm, substitute(type)); } return JavaPsiFacade.getInstance(aClass.getProject()) .getElementFactory() .createType(aClass, theSubst); } } return t; }
private PsiWildcardType rebound(PsiWildcardType type, PsiType newBound) { LOG.assertTrue(type.getBound() != null); LOG.assertTrue(newBound.isValid()); if (type.isExtends()) { if (newBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { return PsiWildcardType.createUnbounded(type.getManager()); } else { return PsiWildcardType.createExtends(type.getManager(), newBound); } } else { return PsiWildcardType.createSuper(type.getManager(), newBound); } }
public PsiType apply(final PsiType type) { if (type instanceof PsiTypeVariable) { final PsiType t = myBindings.get(((PsiTypeVariable) type).getIndex()); return t == null ? type : t; } else if (type instanceof PsiArrayType) { return apply(((PsiArrayType) type).getComponentType()).createArrayType(); } else if (type instanceof PsiClassType) { final PsiClassType.ClassResolveResult result = Util.resolveType(type); final PsiClass theClass = result.getElement(); final PsiSubstitutor aSubst = result.getSubstitutor(); PsiSubstitutor theSubst = PsiSubstitutor.EMPTY; if (theClass != null) { for (final PsiTypeParameter aParm : aSubst.getSubstitutionMap().keySet()) { final PsiType aType = aSubst.substitute(aParm); theSubst = theSubst.put(aParm, apply(aType)); } return JavaPsiFacade.getInstance(theClass.getProject()) .getElementFactory() .createType(theClass, theSubst); } else { return type; } } else if (type instanceof PsiWildcardType) { final PsiWildcardType wcType = (PsiWildcardType) type; final PsiType bound = wcType.getBound(); if (bound != null) { final PsiType abound = apply(bound); if (abound instanceof PsiWildcardType) { return null; } return wcType.isExtends() ? PsiWildcardType.createExtends(PsiManager.getInstance(myProject), abound) : PsiWildcardType.createSuper(PsiManager.getInstance(myProject), abound); } return type; } else { return type; } }
public static boolean try2ProveTypeParameterDistinct(PsiType type, PsiClass typeParameter) { final PsiClassType[] types = typeParameter.getExtendsListTypes(); if (types.length == 0) return false; return provablyDistinct( PsiWildcardType.createExtends(typeParameter.getManager(), types[0]), type); }
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); } }