mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
captured wildcards: refactor to extract same parts for extends/super wildcards, ensure upper bound is not lost for extends wildcard (IDEA-57292)
This commit is contained in:
@@ -297,7 +297,7 @@ public class GenericsUtil {
|
||||
}
|
||||
else if (substituted instanceof PsiCapturedWildcardType) {
|
||||
final PsiType extendsBound = ((PsiCapturedWildcardType)substituted).getUpperBound();
|
||||
if (acceptExtendsBound(extendsType, extendsBound) || extendsType.equals(substitutor.substitute(extendsBound))) {
|
||||
if (acceptExtendsBound(extendsType, extendsBound) || extendsType.equals(extendsBound)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,21 +49,6 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
|
||||
myExistential = existential;
|
||||
myContext = context;
|
||||
myParameter = parameter;
|
||||
if (parameter != null) {
|
||||
final PsiClassType[] boundTypes = parameter.getExtendsListTypes();
|
||||
if (boundTypes.length > 0) {
|
||||
PsiType result = null;
|
||||
for (PsiType type : boundTypes) {
|
||||
if (result == null) {
|
||||
result = type;
|
||||
}
|
||||
else {
|
||||
result = GenericsUtil.getGreatestLowerBound(result, type);
|
||||
}
|
||||
}
|
||||
myUpperBound = result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -719,16 +719,22 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
final PsiClass aClass = result.getElement();
|
||||
if (aClass != null) {
|
||||
final PsiSubstitutor substitutor = result.getSubstitutor();
|
||||
|
||||
PsiSubstitutor captureSubstitutor = substitutor;
|
||||
for (PsiTypeParameter typeParameter : typeParametersIterable(aClass)) {
|
||||
final PsiType substituted = substitutor.substitute(typeParameter);
|
||||
if (substituted instanceof PsiWildcardType) {
|
||||
captureSubstitutor = captureSubstitutor.put(typeParameter, PsiCapturedWildcardType.create((PsiWildcardType)substituted, context, typeParameter));
|
||||
}
|
||||
}
|
||||
|
||||
Map<PsiTypeParameter, PsiType> substitutionMap = null;
|
||||
for (PsiTypeParameter typeParameter : typeParametersIterable(aClass)) {
|
||||
final PsiType substituted = substitutor.substitute(typeParameter);
|
||||
if (substituted instanceof PsiWildcardType) {
|
||||
if (substitutionMap == null) substitutionMap = new HashMap<PsiTypeParameter, PsiType>(substitutor.getSubstitutionMap());
|
||||
substitutionMap.put(typeParameter,
|
||||
captureTypeParameterBounds(typeParameter, substituted, context,
|
||||
substitutor.put(typeParameter,
|
||||
PsiCapturedWildcardType
|
||||
.create((PsiWildcardType)substituted, context, typeParameter))));
|
||||
captureTypeParameterBounds(typeParameter, substituted, context, captureSubstitutor));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -748,7 +754,7 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
|
||||
public static PsiType captureTypeParameterBounds(@NotNull PsiTypeParameter typeParameter, PsiType substituted,
|
||||
PsiElement context,
|
||||
PsiSubstitutor substitutor) {
|
||||
PsiSubstitutor captureSubstitutor) {
|
||||
PsiType oldSubstituted = substituted;
|
||||
PsiElement captureContext = context;
|
||||
if (substituted instanceof PsiCapturedWildcardType) {
|
||||
@@ -756,66 +762,63 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
substituted = captured.getWildcard();
|
||||
captureContext = captured.getContext();
|
||||
}
|
||||
if (substituted instanceof PsiWildcardType && !((PsiWildcardType)substituted).isSuper()) {
|
||||
PsiType originalBound = ((PsiWildcardType)substituted).getBound();
|
||||
PsiManager manager = typeParameter.getManager();
|
||||
PsiType glb = null;
|
||||
if (substituted instanceof PsiWildcardType) {
|
||||
final PsiType[] boundTypes = typeParameter.getExtendsListTypes();
|
||||
PsiManager manager = typeParameter.getManager();
|
||||
PsiType originalBound = !((PsiWildcardType)substituted).isSuper() ? ((PsiWildcardType)substituted).getBound() : null;
|
||||
glb = originalBound;
|
||||
for (PsiType boundType : boundTypes) {
|
||||
PsiType substitutedBoundType = substitutor.substitute(boundType);
|
||||
PsiWildcardType wildcardType = (PsiWildcardType)substituted;
|
||||
PsiType substitutedBoundType = captureSubstitutor.substitute(boundType);
|
||||
if (substitutedBoundType != null && !(substitutedBoundType instanceof PsiWildcardType) &&
|
||||
!substitutedBoundType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
|
||||
if (originalBound instanceof PsiArrayType &&
|
||||
substitutedBoundType instanceof PsiArrayType &&
|
||||
!originalBound.isAssignableFrom(substitutedBoundType) &&
|
||||
!substitutedBoundType.isAssignableFrom(originalBound)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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 bound = wildcardType.getBound();
|
||||
if (bound instanceof PsiArrayType && substitutedBoundType instanceof PsiArrayType &&
|
||||
!bound.isAssignableFrom(substitutedBoundType) && !substitutedBoundType.isAssignableFrom(bound)) {
|
||||
continue;
|
||||
}
|
||||
final PsiType glb = GenericsUtil.getGreatestLowerBound(bound, substitutedBoundType);
|
||||
if (glb != null) {
|
||||
substituted = PsiWildcardType.createExtends(manager, glb);
|
||||
}
|
||||
|
||||
if (glb == null) {
|
||||
glb = substitutedBoundType;
|
||||
}
|
||||
else {
|
||||
//unbounded
|
||||
substituted = substitutedBoundType instanceof PsiCapturedWildcardType
|
||||
? ((PsiCapturedWildcardType)substitutedBoundType).getWildcard()
|
||||
: PsiWildcardType.createExtends(manager, substitutedBoundType);
|
||||
glb = GenericsUtil.getGreatestLowerBound(glb, substitutedBoundType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (substituted instanceof PsiWildcardType && ((PsiWildcardType)substituted).isSuper()) {
|
||||
final PsiType[] boundTypes = typeParameter.getExtendsListTypes();
|
||||
PsiType glb = null;
|
||||
for (PsiType boundType : boundTypes) {
|
||||
final PsiType substitutedBound = substitutor.substitute(boundType);
|
||||
if (substitutedBound != null) {
|
||||
if (glb == null) {
|
||||
glb = substitutedBound;
|
||||
}
|
||||
else {
|
||||
glb = GenericsUtil.getGreatestLowerBound(glb, substitutedBound);
|
||||
|
||||
if (glb != null) {
|
||||
if (!((PsiWildcardType)substituted).isSuper()) {
|
||||
substituted = glb instanceof PsiCapturedWildcardType ? ((PsiCapturedWildcardType)glb).getWildcard()
|
||||
: PsiWildcardType.createExtends(manager, glb);
|
||||
}
|
||||
else {
|
||||
if (captureContext != null) {
|
||||
final PsiCapturedWildcardType capturedWildcardType = oldSubstituted instanceof PsiCapturedWildcardType
|
||||
? (PsiCapturedWildcardType)oldSubstituted
|
||||
: (PsiCapturedWildcardType)captureSubstitutor.substitute(typeParameter);
|
||||
LOG.assertTrue(capturedWildcardType != null);
|
||||
capturedWildcardType.setUpperBound(glb);
|
||||
return capturedWildcardType;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (glb != null && captureContext != null) {
|
||||
final PsiCapturedWildcardType capturedWildcardType = oldSubstituted instanceof PsiCapturedWildcardType
|
||||
? (PsiCapturedWildcardType)oldSubstituted
|
||||
: PsiCapturedWildcardType.create((PsiWildcardType)substituted, captureContext, typeParameter);
|
||||
capturedWildcardType.setUpperBound(glb);
|
||||
return capturedWildcardType;
|
||||
}
|
||||
}
|
||||
|
||||
if (captureContext != null) {
|
||||
LOG.assertTrue(substituted instanceof PsiWildcardType, substituted);
|
||||
substituted = oldSubstituted instanceof PsiCapturedWildcardType && substituted == ((PsiCapturedWildcardType)oldSubstituted).getWildcard()
|
||||
substituted = oldSubstituted instanceof PsiCapturedWildcardType && substituted.equals(((PsiCapturedWildcardType)oldSubstituted).getWildcard())
|
||||
? oldSubstituted
|
||||
: PsiCapturedWildcardType.create((PsiWildcardType)substituted, captureContext, typeParameter);
|
||||
if (glb != null) {
|
||||
((PsiCapturedWildcardType)substituted).setUpperBound(glb);
|
||||
}
|
||||
}
|
||||
return substituted;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,14 @@ public abstract class PsiTypeMapper extends PsiTypeVisitorEx<PsiType> {
|
||||
@Override
|
||||
public PsiType visitCapturedWildcardType(final PsiCapturedWildcardType type) {
|
||||
PsiWildcardType mapped = mapType(type.getWildcard());
|
||||
return mapped == null ? null : PsiCapturedWildcardType.create(mapped, type.getContext(), type.getTypeParameter());
|
||||
if (mapped == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
final PsiCapturedWildcardType capturedWildcardType = PsiCapturedWildcardType.create(mapped, type.getContext(), type.getTypeParameter());
|
||||
capturedWildcardType.setUpperBound(mapType(type.getUpperBound()));
|
||||
return capturedWildcardType;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -423,12 +423,7 @@ public class PsiImplUtil {
|
||||
return wildcardType.isSuper() ? wildcardType.getBound() : PsiCapturedWildcardType.create(wildcardType, expression);
|
||||
}
|
||||
else {
|
||||
if (wildcardType.isExtends()) {
|
||||
return wildcardType.getBound();
|
||||
}
|
||||
else {
|
||||
return ((PsiCapturedWildcardType)type).getUpperBound();
|
||||
}
|
||||
return ((PsiCapturedWildcardType)type).getUpperBound();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
|
||||
class C56 {
|
||||
|
||||
class A<T,S extends T> {}
|
||||
|
||||
class C {
|
||||
void foo(A<?,?> x){
|
||||
bar(x);
|
||||
}
|
||||
<T,S extends T> void bar(A<T,S> x){}
|
||||
}
|
||||
}
|
||||
|
||||
class C57 {
|
||||
class B<T,S> {}
|
||||
class A<T,S extends T> extends B<T,S> {}
|
||||
|
||||
class C {
|
||||
void foo(A<?,?> x){
|
||||
bar(x);
|
||||
}
|
||||
<T,S extends T> void bar(B<T,S> x){}
|
||||
}
|
||||
}
|
||||
@@ -496,6 +496,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest(LanguageLevel.JDK_1_8, JavaSdkVersion.JDK_1_8, true);
|
||||
}
|
||||
|
||||
public void testPreserveCaptureWildcardsInUpperBounds() throws Exception {
|
||||
doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
|
||||
}
|
||||
|
||||
public void testJavaUtilCollections_NoVerify() throws Exception {
|
||||
PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule()));
|
||||
assertNotNull(collectionsClass);
|
||||
|
||||
Reference in New Issue
Block a user