diff --git a/java/java-psi-api/src/com/intellij/psi/infos/CandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/CandidateInfo.java index c76541dd91f5..ea8e40180198 100644 --- a/java/java-psi-api/src/com/intellij/psi/infos/CandidateInfo.java +++ b/java/java-psi-api/src/com/intellij/psi/infos/CandidateInfo.java @@ -15,6 +15,8 @@ */ package com.intellij.psi.infos; +import com.intellij.openapi.projectRoots.JavaSdkVersion; +import com.intellij.openapi.projectRoots.JavaVersionService; import com.intellij.psi.*; /** @@ -99,12 +101,31 @@ public class CandidateInfo implements JavaResolveResult { final PsiMember member = (PsiMember)myCandidate; accessProblem = !JavaPsiFacade.getInstance(myPlace.getProject()).getResolveHelper() .isAccessible(member, member.getModifierList(), myPlace, myAccessClass, myCurrentFileResolveContext); + if (!accessProblem && member.hasModifierProperty(PsiModifier.PRIVATE) && myPlace instanceof PsiReferenceExpression && JavaVersionService.getInstance().isAtLeast(myPlace, JavaSdkVersion.JDK_1_7)) { + accessProblem = isAccessedThroughTypeParameterBound(); + } } myAccessProblem = accessProblem ? Boolean.TRUE : Boolean.FALSE; } return !myAccessProblem.booleanValue(); } + private boolean isAccessedThroughTypeParameterBound() { + final PsiExpression qualifierExpression = ((PsiReferenceExpression)myPlace).getQualifierExpression(); + if (qualifierExpression instanceof PsiMethodCallExpression) { + final JavaResolveResult resolveResult = ((PsiMethodCallExpression)qualifierExpression).resolveMethodGenerics(); + final PsiElement element = resolveResult.getElement(); + if (element instanceof PsiMethod) { + final PsiType returnType = ((PsiMethod)element).getReturnType(); + final PsiType substitutedReturnType = resolveResult.getSubstitutor().substitute(returnType); + if (substitutedReturnType instanceof PsiCapturedWildcardType) { + return true; + } + } + } + return false; + } + @Override public boolean isStaticsScopeCorrect(){ return !myStaticsProblem; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA88895.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA88895.java new file mode 100644 index 000000000000..e3482d7f55ed --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/IDEA88895.java @@ -0,0 +1,26 @@ +import java.util.Iterator; + +public class WildcardGenericAndPrivateField { + + private Object field; + + public Iterator iterator() { + return null; + } + + public void methodDoesNotCompile() { + Iterator iterator = iterator(); + while ( iterator.hasNext() ) { + Object o = iterator.next().field; + } + } + + public void methodCompiles() { + Iterator iterator = iterator(); + while ( iterator.hasNext() ) { + WildcardGenericAndPrivateField next = iterator.next(); + Object o = next.field; + } + } + +} \ No newline at end of file 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 02151ec4bbb5..9142b65b3ba1 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -127,6 +127,7 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { public void testIDEA80386() throws Exception { doTest(false);} public void testIDEA66311() throws Exception { doTest17Incompatibility();} + public void testIDEA88895() throws Exception { doTest17Incompatibility();} public void testIDEA66311_16() throws Exception { doTest(false);} public void testIDEA76283() throws Exception {doTest(false);} public void testIDEA74899() throws Exception {doTest(false);}