mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-06 05:10:22 +07:00
capture conversion: ensure captured wildcards are not replaced after creation, so substitution is consistent; at the same time ensure that "?" with upper bound Runnable is equivalent to "? extends Runnable"
This commit is contained in:
@@ -509,7 +509,7 @@ public class GenericsUtil {
|
||||
final PsiType bound = ((PsiWildcardType)type).getBound();
|
||||
return eliminateWildcards(bound != null ? bound : ((PsiWildcardType)type).getExtendsBound(), false);//object
|
||||
} else if (type instanceof PsiCapturedWildcardType && !eliminateInTypeArguments) {
|
||||
return eliminateWildcards(((PsiCapturedWildcardType)type).getWildcard(), eliminateInTypeArguments);
|
||||
return ((PsiCapturedWildcardType)type).getUpperBound();
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
package com.intellij.psi;
|
||||
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.RecursionGuard;
|
||||
import com.intellij.openapi.util.RecursionManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -49,8 +52,11 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
|
||||
myExistential = existential;
|
||||
myContext = context;
|
||||
myParameter = parameter;
|
||||
myUpperBound = PsiType.getJavaLangObject(myContext.getManager(), getResolveScope());
|
||||
}
|
||||
|
||||
private static RecursionGuard guard = RecursionManager.createGuard("captureGuard");
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof PsiCapturedWildcardType)) {
|
||||
@@ -58,7 +64,7 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
|
||||
}
|
||||
|
||||
final PsiCapturedWildcardType captured = (PsiCapturedWildcardType)o;
|
||||
if (!myContext.equals(captured.myContext) || !myExistential.equals(captured.myExistential)) {
|
||||
if (!myContext.equals(captured.myContext) || myExistential.isSuper() && !myExistential.equals(captured.myExistential)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -66,12 +72,24 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if (myParameter != null) {
|
||||
final Boolean sameUpperBounds = guard.doPreventingRecursion(myContext, true, new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return Comparing.equal(myUpperBound, captured.myUpperBound);
|
||||
}
|
||||
});
|
||||
|
||||
if (sameUpperBounds != null && sameUpperBounds) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return myExistential.equals(captured.myExistential);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return myExistential.hashCode() + 31 * myContext.hashCode();
|
||||
return myUpperBound.hashCode() + 31 * myContext.hashCode();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -125,14 +143,14 @@ public class PsiCapturedWildcardType extends PsiType.Stub {
|
||||
|
||||
public PsiType getUpperBound () {
|
||||
final PsiType bound = myExistential.getBound();
|
||||
if (myExistential.isExtends()) {
|
||||
if (myExistential.isExtends() && myParameter == null) {
|
||||
return bound;
|
||||
}
|
||||
else if (bound instanceof PsiCapturedWildcardType) {
|
||||
return PsiWildcardType.createSuper(myContext.getManager(), ((PsiCapturedWildcardType)bound).getUpperBound());
|
||||
}
|
||||
else {
|
||||
return myUpperBound != null ? myUpperBound : PsiType.getJavaLangObject(myContext.getManager(), getResolveScope());
|
||||
return myUpperBound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -763,10 +763,11 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
captureContext = captured.getContext();
|
||||
}
|
||||
PsiType glb = null;
|
||||
PsiType originalBound = PsiType.NULL;
|
||||
if (substituted instanceof PsiWildcardType) {
|
||||
final PsiType[] boundTypes = typeParameter.getExtendsListTypes();
|
||||
PsiManager manager = typeParameter.getManager();
|
||||
PsiType originalBound = !((PsiWildcardType)substituted).isSuper() ? ((PsiWildcardType)substituted).getBound() : null;
|
||||
originalBound = !((PsiWildcardType)substituted).isSuper() ? ((PsiWildcardType)substituted).getBound() : null;
|
||||
glb = originalBound;
|
||||
for (PsiType boundType : boundTypes) {
|
||||
PsiType substitutedBoundType = captureSubstitutor.substitute(boundType);
|
||||
@@ -813,9 +814,11 @@ public final class PsiUtil extends PsiUtilCore {
|
||||
|
||||
if (captureContext != null) {
|
||||
LOG.assertTrue(substituted instanceof PsiWildcardType, substituted);
|
||||
substituted = oldSubstituted instanceof PsiCapturedWildcardType && substituted.equals(((PsiCapturedWildcardType)oldSubstituted).getWildcard())
|
||||
? oldSubstituted
|
||||
: PsiCapturedWildcardType.create((PsiWildcardType)substituted, captureContext, typeParameter);
|
||||
substituted =
|
||||
oldSubstituted instanceof PsiCapturedWildcardType && substituted.equals(((PsiCapturedWildcardType)oldSubstituted).getWildcard())
|
||||
? oldSubstituted
|
||||
: captureSubstitutor.substitute(typeParameter);
|
||||
LOG.assertTrue(substituted instanceof PsiCapturedWildcardType);
|
||||
if (glb != null) {
|
||||
((PsiCapturedWildcardType)substituted).setUpperBound(glb);
|
||||
}
|
||||
|
||||
@@ -257,8 +257,10 @@ public class PsiSubstitutorImpl implements PsiSubstitutor {
|
||||
} else {
|
||||
PsiType substituted = substituteInternal(original);
|
||||
if (original instanceof PsiWildcardType && substituted instanceof PsiCapturedWildcardType) {
|
||||
substituted = PsiCapturedWildcardType.create(((PsiCapturedWildcardType)substituted).getWildcard(),
|
||||
((PsiCapturedWildcardType)substituted).getContext(), param);
|
||||
final PsiCapturedWildcardType capturedWildcardType = PsiCapturedWildcardType.create(((PsiCapturedWildcardType)substituted).getWildcard(),
|
||||
((PsiCapturedWildcardType)substituted).getContext(), param);
|
||||
capturedWildcardType.setUpperBound(((PsiCapturedWildcardType)substituted).getUpperBound());
|
||||
substituted = capturedWildcardType;
|
||||
}
|
||||
//if (substituted == null) return false;
|
||||
substMap.put(param, substituted);
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
interface A<T extends String, K extends T> {
|
||||
K get();
|
||||
}
|
||||
|
||||
class Test {
|
||||
void f(A<?, ?> a) {
|
||||
String s = a.get();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
class C<T extends C<? extends C<? extends T>>>{
|
||||
void foo(C<?> x){
|
||||
<error descr="Inferred type 'capture<? extends C<? extends C<capture<?>>>>' for type parameter 'T' is not within its bound; should extend 'C<capture<? extends C<? extends C<capture<?>>>>>'">bar(x)</error>;
|
||||
<error descr="Inferred type 'capture<?>' for type parameter 'T' is not within its bound; should extend 'C<capture<?>>'">bar(x)</error>;
|
||||
}
|
||||
<T extends C<? extends T>> void bar(C<T> x){}
|
||||
}
|
||||
@@ -6,6 +6,6 @@ interface B<T extends Cloneable> {
|
||||
|
||||
class D {
|
||||
void bar(B<?> x, List<?> y) {
|
||||
x.foo<error descr="'foo(java.util.List<? super capture<? extends java.lang.Cloneable>>)' in 'B' cannot be applied to '(java.util.List<capture<?>>)'">(y)</error>;
|
||||
x.foo<error descr="'foo(java.util.List<? super capture<?>>)' in 'B' cannot be applied to '(java.util.List<capture<?>>)'">(y)</error>;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,6 @@ class Test2 {}
|
||||
|
||||
class Test {
|
||||
public void test(TestIF<?> testIF) {
|
||||
testIF.run<error descr="'run(capture<? extends TestIF2<? extends Test2>>)' in 'TestIF' cannot be applied to '()'">()</error>;
|
||||
testIF.run<error descr="'run(capture<?>)' in 'TestIF' cannot be applied to '()'">()</error>;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ class SortTest<R extends Comparable<R>> implements Comparable<SortTest<R>> {
|
||||
SortTest<?> t2 = new SortTest<Integer>(0);
|
||||
list.add(t2);
|
||||
<error descr="Inferred type 'SortTest<?>' for type parameter 'T' is not within its bound; should implement 'java.lang.Comparable<? super SortTest<?>>'">Collections.sort(list)</error>;
|
||||
t1.compareTo<error descr="'compareTo(SortTest<capture<? extends java.lang.Comparable<capture<?>>>>)' in 'SortTest' cannot be applied to '(SortTest<capture<? extends java.lang.Comparable<capture<?>>>>)'">(t2)</error>;
|
||||
t1.compareTo<error descr="'compareTo(SortTest<capture<?>>)' in 'SortTest' cannot be applied to '(SortTest<capture<?>>)'">(t2)</error>;
|
||||
|
||||
//this should be OK
|
||||
SortTest<?>[] arr = new SortTest<?>[0];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class C<T extends C<? extends C<? extends T>>>{
|
||||
void foo(C<?> x){
|
||||
<error descr="Inferred type 'capture<? extends C<? extends C<capture<?>>>>' for type parameter 'T' is not within its bound; should extend 'C<capture<? extends C<? extends C<capture<?>>>>>'">bar(x)</error>;
|
||||
<error descr="Inferred type 'capture<?>' for type parameter 'T' is not within its bound; should extend 'C<capture<?>>'">bar(x)</error>;
|
||||
}
|
||||
<T extends C<? extends T>> void bar(C<T> x){}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ interface B<T extends Cloneable> {
|
||||
|
||||
class D {
|
||||
void bar(B<?> x, List<?> y) {
|
||||
x.foo<error descr="'foo(java.util.List<? super capture<? extends java.lang.Cloneable>>)' in 'B' cannot be applied to '(java.util.List<capture<?>>)'">(y)</error>;
|
||||
x.foo<error descr="'foo(java.util.List<? super capture<?>>)' in 'B' cannot be applied to '(java.util.List<capture<?>>)'">(y)</error>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ class Test2 {}
|
||||
|
||||
class Test {
|
||||
public void test(TestIF<?> testIF) {
|
||||
testIF.run<error descr="'run(capture<? extends TestIF2<? extends Test2>>)' in 'TestIF' cannot be applied to '()'">()</error>;
|
||||
testIF.run<error descr="'run(capture<?>)' in 'TestIF' cannot be applied to '()'">()</error>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class SortTest<R extends Comparable<R>> implements Comparable<SortTest<R>> {
|
||||
SortTest<?> t2 = new SortTest<Integer>(0);
|
||||
list.add(t2);
|
||||
Collections.sort<error descr="'sort(java.util.List<T>)' in 'java.util.Collections' cannot be applied to '(java.util.ArrayList<SortTest<?>>)'">(list)</error>;
|
||||
t1.compareTo<error descr="'compareTo(SortTest<capture<? extends java.lang.Comparable<capture<?>>>>)' in 'SortTest' cannot be applied to '(SortTest<capture<? extends java.lang.Comparable<capture<?>>>>)'">(t2)</error>;
|
||||
t1.compareTo<error descr="'compareTo(SortTest<capture<?>>)' in 'SortTest' cannot be applied to '(SortTest<capture<?>>)'">(t2)</error>;
|
||||
|
||||
//this should be OK
|
||||
SortTest<?>[] arr = new SortTest<?>[0];
|
||||
|
||||
@@ -508,6 +508,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false);
|
||||
}
|
||||
|
||||
public void testCapturedBoundOfCapture() 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