private static PsiType handleBoundComposition( PsiWildcardType wildcardType, PsiWildcardType bound) { if (bound.isExtends() == wildcardType.isExtends()) { final PsiType newBoundBound = bound.getBound(); if (newBoundBound != null) { return PsiWildcardType.changeBound(wildcardType, newBoundBound); } } return PsiWildcardType.createUnbounded(wildcardType.getManager()); }
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); } }
@Override public PsiType visitWildcardType(PsiWildcardType wildcardType) { final PsiType bound = wildcardType.getBound(); if (bound == null) { return wildcardType; } else { final PsiType newBound = bound.accept(this); if (newBound == null) { return null; } assert newBound.isValid() : newBound.getClass() + "; " + bound.isValid(); if (newBound instanceof PsiWildcardType) { final PsiType newBoundBound = ((PsiWildcardType) newBound).getBound(); return !((PsiWildcardType) newBound).isBounded() ? PsiWildcardType.createUnbounded(wildcardType.getManager()) : rebound(wildcardType, newBoundBound); } return newBound == PsiType.NULL ? newBound : rebound(wildcardType, newBound); } }
static void setupPatternMethods( PsiManager manager, GlobalSearchScope searchScope, List<PsiMethod> patternMethods, IntArrayList indices) { final JavaPsiFacade javaPsiFacade = JavaPsiFacade.getInstance(manager.getProject()); final PsiClass collectionClass = javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_COLLECTION, searchScope); PsiType[] javaLangObject = {PsiType.getJavaLangObject(manager, searchScope)}; MethodSignature removeSignature = MethodSignatureUtil.createMethodSignature( "remove", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); if (collectionClass != null) { PsiMethod remove = MethodSignatureUtil.findMethodBySignature(collectionClass, removeSignature, false); addMethod(remove, 0, patternMethods, indices); MethodSignature containsSignature = MethodSignatureUtil.createMethodSignature( "contains", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod contains = MethodSignatureUtil.findMethodBySignature(collectionClass, containsSignature, false); addMethod(contains, 0, patternMethods, indices); if (PsiUtil.isLanguageLevel5OrHigher(collectionClass)) { PsiClassType wildcardCollection = javaPsiFacade .getElementFactory() .createType(collectionClass, PsiWildcardType.createUnbounded(manager)); MethodSignature removeAllSignature = MethodSignatureUtil.createMethodSignature( "removeAll", new PsiType[] {wildcardCollection}, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod removeAll = MethodSignatureUtil.findMethodBySignature(collectionClass, removeAllSignature, false); addMethod(removeAll, 0, patternMethods, indices); } } final PsiClass listClass = javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_LIST, searchScope); if (listClass != null) { MethodSignature indexofSignature = MethodSignatureUtil.createMethodSignature( "indexOf", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod indexof = MethodSignatureUtil.findMethodBySignature(listClass, indexofSignature, false); addMethod(indexof, 0, patternMethods, indices); MethodSignature lastindexofSignature = MethodSignatureUtil.createMethodSignature( "lastIndexOf", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod lastindexof = MethodSignatureUtil.findMethodBySignature(listClass, lastindexofSignature, false); addMethod(lastindexof, 0, patternMethods, indices); } final PsiClass mapClass = javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_MAP, searchScope); if (mapClass != null) { PsiMethod remove = MethodSignatureUtil.findMethodBySignature(mapClass, removeSignature, false); addMethod(remove, 0, patternMethods, indices); MethodSignature getSignature = MethodSignatureUtil.createMethodSignature( "get", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod get = MethodSignatureUtil.findMethodBySignature(mapClass, getSignature, false); addMethod(get, 0, patternMethods, indices); MethodSignature containsKeySignature = MethodSignatureUtil.createMethodSignature( "containsKey", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod containsKey = MethodSignatureUtil.findMethodBySignature(mapClass, containsKeySignature, false); addMethod(containsKey, 0, patternMethods, indices); MethodSignature containsValueSignature = MethodSignatureUtil.createMethodSignature( "containsValue", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod containsValue = MethodSignatureUtil.findMethodBySignature(mapClass, containsValueSignature, false); addMethod(containsValue, 1, patternMethods, indices); } final PsiClass concurrentMapClass = javaPsiFacade.findClass(CommonClassNames.JAVA_UTIL_CONCURRENT_HASH_MAP, searchScope); if (concurrentMapClass != null) { MethodSignature containsSignature = MethodSignatureUtil.createMethodSignature( "contains", javaLangObject, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); PsiMethod contains = MethodSignatureUtil.findMethodBySignature(concurrentMapClass, containsSignature, false); addMethod(contains, 1, patternMethods, indices); } }
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); } }