diff --git a/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java b/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java index 5606d343ccab..48faf39370bc 100644 --- a/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java +++ b/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java @@ -25,6 +25,7 @@ import com.intellij.codeInsight.lookup.LookupItemUtil; import com.intellij.psi.*; import com.intellij.psi.filters.TrueFilter; import com.intellij.psi.scope.processor.FilterScopeProcessor; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.Nullable; @@ -40,31 +41,35 @@ public class MembersGetter { public static void addMembers(PsiElement position, PsiType expectedType, CompletionResultSet results) { final PsiClass psiClass = PsiUtil.resolveClassInType(expectedType); - if (psiClass != null) { - processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, expectedType); - } + processMembers(position, results, psiClass, PsiTreeUtil.getParentOfType(position, PsiAnnotation.class) != null, expectedType); if (expectedType instanceof PsiPrimitiveType && PsiType.DOUBLE.isAssignableFrom(expectedType)) { - final PsiElement parent = position.getParent(); - if (parent instanceof PsiReferenceExpression) { - final PsiElement refParent = parent.getParent(); - if (refParent instanceof PsiExpressionList) { - final PsiClass aClass = getCalledClass(refParent.getParent()); - if (aClass != null) { - processMembers(position, results, aClass, false, expectedType); - } - } - else if (refParent instanceof PsiBinaryExpression) { - final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)refParent; - if (parent == binaryExpression.getROperand() && - JavaTokenType.EQEQ == binaryExpression.getOperationSign().getTokenType()) { - final PsiClass aClass = getCalledClass(binaryExpression.getLOperand()); - if (aClass != null) { - processMembers(position, results, aClass, false, expectedType); - } - } + addConstantsFromTargetClass(position, expectedType, results); + } + } + + private static void addConstantsFromTargetClass(PsiElement position, PsiType expectedType, CompletionResultSet results) { + PsiElement parent = position.getParent(); + if (!(parent instanceof PsiReferenceExpression)) { + return; + } + + PsiElement prev = parent; + parent = parent.getParent(); + while (parent instanceof PsiBinaryExpression) { + final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)parent; + final IElementType op = binaryExpression.getOperationSign().getTokenType(); + if (JavaTokenType.EQEQ == op || JavaTokenType.NE == op) { + if (prev == binaryExpression.getROperand()) { + processMembers(position, results, getCalledClass(binaryExpression.getLOperand()), false, expectedType); } + return; } + prev = parent; + parent = parent.getParent(); + } + if (parent instanceof PsiExpressionList) { + processMembers(position, results, getCalledClass(parent.getParent()), false, expectedType); } } @@ -95,8 +100,10 @@ public class MembersGetter { return null; } - private static void processMembers(final PsiElement context, final CompletionResultSet results, final PsiClass where, + private static void processMembers(final PsiElement context, final CompletionResultSet results, @Nullable final PsiClass where, final boolean acceptMethods, PsiType expectedType) { + if (where == null) return; + final FilterScopeProcessor processor = new FilterScopeProcessor(TrueFilter.INSTANCE); where.processDeclarations(processor, ResolveState.initial(), null, context); @@ -113,7 +120,9 @@ public class MembersGetter { item.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); JavaCompletionUtil.qualify(item); if (member instanceof PsiMethod) { - ((JavaMethodCallElement) item).setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor((PsiMethod) member, expectedType)); + final PsiMethod method = (PsiMethod)member; + final PsiSubstitutor substitutor = SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, expectedType); + ((JavaMethodCallElement) item).setInferenceSubstitutor(substitutor); } results.addElement(item); } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr-out.java b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr-out.java new file mode 100644 index 000000000000..2c6d84a06d75 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr-out.java @@ -0,0 +1,15 @@ +class Foo { + public static final int FOO_FOO; + public static final int FOO_BAR; + + Foo(int a) {} + + void foo(int x); +} + +public class Bar { + + { + new Foo(2 | Foo.FOO_BAR) + } +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr.java b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr.java new file mode 100644 index 000000000000..7c4d822b11ca --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInOr.java @@ -0,0 +1,15 @@ +class Foo { + public static final int FOO_FOO; + public static final int FOO_BAR; + + Foo(int a) {} + + void foo(int x); +} + +public class Bar { + + { + new Foo(2 | FB) + } +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus-out.java b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus-out.java new file mode 100644 index 000000000000..8122f1052be4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus-out.java @@ -0,0 +1,15 @@ +class Foo { + public static final int FOO_FOO; + public static final int FOO_BAR; + + Foo(int a) {} + + void foo(int x); +} + +public class Bar { + + { + new Foo(2 + Foo.FOO_BAR) + } +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus.java b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus.java new file mode 100644 index 000000000000..88d89a73a2b4 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/UseIntConstantsInPlus.java @@ -0,0 +1,15 @@ +class Foo { + public static final int FOO_FOO; + public static final int FOO_BAR; + + Foo(int a) {} + + void foo(int x); +} + +public class Bar { + + { + new Foo(2 + FB) + } +} 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 d194054d0279..c76e9cfb2c18 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -636,6 +636,8 @@ public class SmartTypeCompletionTest extends LightCompletionTestCase { public void testUseIntConstantsFromTargetClass() throws Throwable { doTest(); } public void testUseIntConstantsFromTargetClassReturnValue() throws Throwable { doTest(); } public void testUseIntConstantsFromConstructedClass() throws Throwable { doTest(); } + public void testUseIntConstantsInPlus() throws Throwable { doTest(); } + public void testUseIntConstantsInOr() throws Throwable { doTest(); } public void testExtraSemicolonAfterMethodParam() throws Throwable { CodeStyleSettings styleSettings = CodeStyleSettingsManager.getSettings(getProject());