diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java index a55d7d53b3d5..90203fc59f66 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiImplUtil.java @@ -414,7 +414,19 @@ public class PsiImplUtil { private static PsiType doNormalizeWildcardByPosition(final PsiType type, @NotNull PsiExpression expression, final PsiExpression toplevel) { if (type instanceof PsiCapturedWildcardType) { - return doNormalizeWildcardByPosition(((PsiCapturedWildcardType)type).getWildcard(), expression, toplevel); + final PsiWildcardType wildcardType = ((PsiCapturedWildcardType)type).getWildcard(); + + if (PsiUtil.isAccessedForWriting(toplevel)) { + return wildcardType.isSuper() ? wildcardType.getBound() : PsiCapturedWildcardType.create(wildcardType, expression); + } + else { + if (wildcardType.isExtends()) { + return wildcardType.getBound(); + } + else { + return ((PsiCapturedWildcardType)type).getUpperBound(); + } + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java index 96a4a29fb45f..839de2256816 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; +import java.util.List; import java.util.Map; import java.util.Set; @@ -358,16 +359,25 @@ public class PsiSubstitutorImpl implements PsiSubstitutor { } } } - } else if (substituted instanceof PsiWildcardType && ((PsiWildcardType)substituted).isSuper() && !(oldSubstituted instanceof PsiCapturedWildcardType)) { - final PsiType erasure = TypeConversionUtil.erasure(((PsiWildcardType)substituted).getBound()); - if (erasure != null) { - final PsiType[] boundTypes = typeParameter.getExtendsListTypes(); - for (PsiType boundType : boundTypes) { - if (TypeConversionUtil.isAssignable(erasure, boundType)) { - return boundType.accept(mySimpleSubstitutionVisitor); + } else if (substituted instanceof PsiWildcardType && ((PsiWildcardType)substituted).isSuper()) { + final PsiType[] boundTypes = typeParameter.getExtendsListTypes(); + PsiType glb = null; + for (PsiType boundType : boundTypes) { + final PsiType substitutedBound = boundType.accept(mySimpleSubstitutionVisitor); + if (substitutedBound != null) { + if (glb == null) { + glb = substitutedBound; + } + else { + glb = GenericsUtil.getGreatestLowerBound(glb, substitutedBound); } } } + if (glb != null && captureContext != null) { + final PsiCapturedWildcardType capturedWildcardType = PsiCapturedWildcardType.create((PsiWildcardType)substituted, captureContext, typeParameter); + capturedWildcardType.setUpperBound(glb); + return capturedWildcardType; + } } if (captureContext != null) { diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MakeUseOfUpperBoundOfCaptureWildcardDuringNormalization.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MakeUseOfUpperBoundOfCaptureWildcardDuringNormalization.java new file mode 100644 index 000000000000..08de193d52fd --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/MakeUseOfUpperBoundOfCaptureWildcardDuringNormalization.java @@ -0,0 +1,16 @@ +import java.util.List; + +class G & Runnable> { + T get() {return null;} +} + +interface I extends List, Runnable {} + +abstract class Test { + abstract G m(); + + { + m().get().run(); + String s = m().get().get(0); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeWithinItsWildcardBound.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeWithinItsWildcardBound.java index 052761440739..e85ae1288b9f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeWithinItsWildcardBound.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/TypeWithinItsWildcardBound.java @@ -311,7 +311,7 @@ class WithingBounds { AA>> a3; A a4; - A<? super A> a5; + A<? super A> a5; A<A[]> a7; } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/TypeWithinItsWildcardBound.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/TypeWithinItsWildcardBound.java index 052761440739..e85ae1288b9f 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/TypeWithinItsWildcardBound.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/TypeWithinItsWildcardBound.java @@ -311,7 +311,7 @@ class WithingBounds { AA>> a3; A a4; - A<? super A> a5; + A<? super A> a5; A<A[]> a7; } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 43712f70a119..16d145bd2c93 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -480,6 +480,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { } + public void testMakeUseOfUpperBoundOfCaptureWildcardDuringNormalization() 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);