diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index 8fbbff13fd10..bedf539dbc3d 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -550,15 +550,8 @@ public class JavaCompletionUtil { return Collections.singletonList(JavaClassNameCompletionContributor.createClassLookupItem((PsiClass)completion, true).setSubstitutor(substitutor)); } if (completion instanceof PsiMethod) { - PsiMethod method = (PsiMethod)completion; - JavaMethodCallElement item = new JavaMethodCallElement(method).setQualifierSubstitutor(substitutor); - if (processor.shouldQualifyMethodCall(method)) { - PsiClass containingClass = method.getContainingClass(); - String className = containingClass == null ? null : containingClass.getName(); - if (className != null) { - item.setForcedQualifier(className + (method.hasModifierProperty(PsiModifier.STATIC) ? "." : ".this.")); - } - } + JavaMethodCallElement item = new JavaMethodCallElement((PsiMethod)completion).setQualifierSubstitutor(substitutor); + item.setForcedQualifier(completionElement.getQualifierText()); return Collections.singletonList(item); } if (completion instanceof PsiVariable) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java index c09b1b71d316..742ba05d2ec9 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java @@ -61,7 +61,6 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme private final Set myShadowedNames = ContainerUtil.newHashSet(); private final Set myCurrentScopeMethodNames = ContainerUtil.newHashSet(); private final Set myFinishedScopesMethodNames = ContainerUtil.newHashSet(); - private final Set myMethodsToQualify = ContainerUtil.newHashSet(); private final PsiElement myElement; private final PsiElement myScope; private final ElementFilter myFilter; @@ -245,33 +244,39 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme } } + if (element instanceof PsiMethod) { + myCurrentScopeMethodNames.add(((PsiMethod)element).getName()); + } + if (!satisfies(element, state) || !isAccessible(element)) return true; StaticProblem sp = myElement.getParent() instanceof PsiMethodReferenceExpression ? StaticProblem.none : getStaticProblem(element); if (sp == StaticProblem.instanceAfterStatic) return true; - CompletionElement completion = new CompletionElement(element, state.get(PsiSubstitutor.KEY)); + CompletionElement completion = new CompletionElement(element, state.get(PsiSubstitutor.KEY), getCallQualifierText(element)); CompletionElement prev = myResults.get(completion); if (prev == null || completion.isMoreSpecificThan(prev)) { myResults.put(completion, completion); if (sp == StaticProblem.staticAfterInstance) { mySecondRateResults.add(completion); } - - if (element instanceof PsiMethod) { - String name = ((PsiMethod)element).getName(); - myCurrentScopeMethodNames.add(name); - if (myFinishedScopesMethodNames.contains(name)) { - myMethodsToQualify.add((PsiMethod)element); - } - } } return true; } - public boolean shouldQualifyMethodCall(@NotNull PsiMethod method) { - return myMethodsToQualify.contains(method); + @NotNull + private String getCallQualifierText(@NotNull PsiElement element) { + if (element instanceof PsiMethod) { + PsiMethod method = (PsiMethod)element; + if (myFinishedScopesMethodNames.contains(method.getName())) { + String className = myDeclarationHolder instanceof PsiClass ? ((PsiClass)myDeclarationHolder).getName() : null; + if (className != null) { + return className + (method.hasModifierProperty(PsiModifier.STATIC) ? "." : ".this."); + } + } + } + return ""; } private boolean isQualifiedContext() { diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/completion/scope/CompletionElement.java b/java/java-psi-impl/src/com/intellij/codeInsight/completion/scope/CompletionElement.java index df758ceb8523..86bf81d7d69f 100644 --- a/java/java-psi-impl/src/com/intellij/codeInsight/completion/scope/CompletionElement.java +++ b/java/java-psi-impl/src/com/intellij/codeInsight/completion/scope/CompletionElement.java @@ -16,6 +16,7 @@ package com.intellij.codeInsight.completion.scope; import com.intellij.openapi.util.Comparing; +import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; @@ -33,13 +34,24 @@ public class CompletionElement{ private final Object myElement; private final PsiSubstitutor mySubstitutor; private final Object myEqualityObject; + private final String myQualifierText; public CompletionElement(Object element, PsiSubstitutor substitutor) { + this(element, substitutor, ""); + } + + public CompletionElement(Object element, PsiSubstitutor substitutor, @NotNull String qualifierText) { myElement = element; mySubstitutor = substitutor; + myQualifierText = qualifierText; myEqualityObject = getUniqueId(); } + @NotNull + public String getQualifierText() { + return myQualifierText; + } + public PsiSubstitutor getSubstitutor(){ return mySubstitutor; } @@ -58,7 +70,7 @@ public class CompletionElement{ return ((PsiPackage)myElement).getQualifiedName(); } if(myElement instanceof PsiMethod){ - return ((PsiMethod)myElement).getSignature(mySubstitutor); + return Pair.create(((PsiMethod)myElement).getSignature(mySubstitutor), myQualifierText); } if (myElement instanceof PsiVariable) { return "#" + ((PsiVariable)myElement).getName(); diff --git a/java/java-tests/testData/codeInsight/completion/smartType/QualifyOuterClassCall-out.java b/java/java-tests/testData/codeInsight/completion/smartType/QualifyOuterClassCall-out.java new file mode 100644 index 000000000000..c0e2633fb278 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/QualifyOuterClassCall-out.java @@ -0,0 +1,13 @@ +interface I { + int getFoo(); +} +class Outer { + private final I myInner = new I() { + @Override + public int getFoo() { + return Outer.this.getFoo(); + } + }; + + int getFoo() { return 0; } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/QualifyOuterClassCall.java b/java/java-tests/testData/codeInsight/completion/smartType/QualifyOuterClassCall.java new file mode 100644 index 000000000000..e31798cb9e31 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/QualifyOuterClassCall.java @@ -0,0 +1,13 @@ +interface I { + int getFoo(); +} +class Outer { + private final I myInner = new I() { + @Override + public int getFoo() { + return getF + } + }; + + int getFoo() { return 0; } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 4daca42f2236..4937a7d44e60 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -1166,7 +1166,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testLocalClassInExpectedTypeArguments() { doTest(); } - private void doActionTest() throws Exception { + private void doActionTest() { configureByTestName(); checkResultByTestName(); } @@ -1237,4 +1237,6 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { configureByTestName(); assertOrderedEquals(myFixture.getLookupElementStrings(), "get2"); } + + public void testQualifyOuterClassCall() { doActionTest(); } }