diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java index d4d8ae50edad..7637beb3e27e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java @@ -28,7 +28,10 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.PsiShortNamesCache; import com.intellij.psi.search.searches.DeepestSuperMethodsSearch; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.*; +import com.intellij.psi.util.PropertyUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.ArrayUtil; import com.intellij.util.NullableFunction; import com.intellij.util.Processor; @@ -581,7 +584,6 @@ public class ExpectedTypesProvider { } PsiExpression anotherExpr = op1.equals(myExpr) ? op2 : op1; PsiType anotherType = anotherExpr != null ? anotherExpr.getType() : null; - PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory(); IElementType i = expr.getOperationTokenType(); if (i == JavaTokenType.MINUS || i == JavaTokenType.ASTERISK || @@ -626,36 +628,8 @@ public class ExpectedTypesProvider { } } else if (i == JavaTokenType.EQEQ || i == JavaTokenType.NE) { - if (anotherType == null) { - myResult = ExpectedTypeInfo.EMPTY_ARRAY; - } - else { - ExpectedTypeInfoImpl info; - if (anotherType instanceof PsiPrimitiveType) { - if (PsiType.BOOLEAN.equals(anotherType)) { - info = createInfoImpl(anotherType, ExpectedTypeInfo.TYPE_STRICTLY, anotherType, TailType.NONE); - } - else if (PsiType.NULL.equals(anotherType)) { - PsiType objectType = factory.createTypeByFQClassName("java.lang.Object", myExpr.getResolveScope()); - info = createInfoImpl(objectType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, objectType, TailType.NONE); - } - else { - info = createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE); - } - } - else { - info = createInfoImpl(anotherType, ExpectedTypeInfo.TYPE_STRICTLY, anotherType, TailType.NONE); - } - - if (anotherExpr instanceof PsiReferenceExpression) { - PsiElement refElement = ((PsiReferenceExpression)anotherExpr).resolve(); - if (refElement instanceof PsiVariable) { - info.expectedName = getPropertyName((PsiVariable)refElement); - } - } - - myResult = new ExpectedTypeInfo[]{info}; - } + ExpectedTypeInfo info = getEqualsType(anotherExpr); + myResult = info == null ? ExpectedTypeInfo.EMPTY_ARRAY : new ExpectedTypeInfo[]{info}; } else if (i == JavaTokenType.LTLT || i == JavaTokenType.GTGT || i == JavaTokenType.GTGTGT) { if (anotherType == null) { @@ -687,6 +661,40 @@ public class ExpectedTypesProvider { } } + @Nullable + private static ExpectedTypeInfo getEqualsType(@Nullable PsiExpression anotherExpr) { + PsiType anotherType = anotherExpr != null ? anotherExpr.getType() : null; + if (anotherType == null) { + return null; + } + + ExpectedTypeInfoImpl info; + if (anotherType instanceof PsiPrimitiveType) { + if (PsiType.BOOLEAN.equals(anotherType)) { + info = createInfoImpl(anotherType, ExpectedTypeInfo.TYPE_STRICTLY, anotherType, TailType.NONE); + } + else if (PsiType.NULL.equals(anotherType)) { + PsiType objectType = PsiType.getJavaLangObject(anotherExpr.getManager(), anotherExpr.getResolveScope()); + info = createInfoImpl(objectType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, objectType, TailType.NONE); + } + else { + info = createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE); + } + } + else { + info = createInfoImpl(anotherType, ExpectedTypeInfo.TYPE_STRICTLY, anotherType, TailType.NONE); + } + + if (anotherExpr instanceof PsiReferenceExpression) { + PsiElement refElement = ((PsiReferenceExpression)anotherExpr).resolve(); + if (refElement instanceof PsiVariable) { + info.expectedName = getPropertyName((PsiVariable)refElement); + } + } + + return info; + } + @Override public void visitPrefixExpression(PsiPrefixExpression expr) { IElementType i = expr.getOperationTokenType(); final PsiType type = expr.getType(); @@ -984,7 +992,7 @@ public class ExpectedTypesProvider { PsiType parameterType = getParameterType(parameter, substitutor); TailType tailType = getMethodArgumentTailType(argument, index, method, substitutor, parameters); - PsiType defaultType = getDefaultType(method, substitutor, parameterType, argument); + PsiType defaultType = getDefaultType(method, substitutor, parameterType, argument, args); ExpectedTypeInfoImpl info = createInfoImpl(parameterType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, defaultType, tailType); info.setInsertExplicitTypeParams(true); @@ -1043,7 +1051,7 @@ public class ExpectedTypesProvider { @Nullable private static PsiType getDefaultType(final PsiMethod method, final PsiSubstitutor substitutor, final PsiType parameterType, - final PsiExpression argumentList) { + final PsiExpression argument, PsiExpression[] args) { final PsiClass containingClass = method.getContainingClass(); if (containingClass == null) return parameterType; @@ -1067,7 +1075,7 @@ public class ExpectedTypesProvider { if ("equals".equals(name)) { final PsiType type = checkMethod(method, CommonClassNames.JAVA_LANG_OBJECT, new NullableFunction() { public PsiType fun(final PsiClass psiClass) { - final PsiElement parent = argumentList.getParent().getParent(); + final PsiElement parent = argument.getParent().getParent(); if (parent instanceof PsiMethodCallExpression) { final PsiMethodCallExpression expression = (PsiMethodCallExpression)parent; final PsiExpression qualifierExpression = expression.getMethodExpression().getQualifierExpression(); @@ -1084,6 +1092,12 @@ public class ExpectedTypesProvider { }); if (type != null) return type; } + if (("assertEquals".equals(name) || "assertSame".equals(name)) && method.getParameterList().getParametersCount() == 2 && args.length == 2) { + ExpectedTypeInfo info = getEqualsType(args[0] == argument ? args[1] : args[0]); + if (info != null) { + return info.getDefaultType(); + } + } return parameterType; } diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/AssertEquals.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/AssertEquals.java new file mode 100644 index 000000000000..29224265ebb2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/AssertEquals.java @@ -0,0 +1,12 @@ +import junit.framework.Assert; +import java.io.File; + +public class Aaaaaaa extends Assert { + + { + File boo; + int bar; + assertEquals(new File("x"), b); + } + +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy index ee716a18cd19..b5a3e739a463 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy @@ -270,6 +270,11 @@ public class SmartTypeCompletionOrderingTest extends CompletionSortingTestCase { assertEquals("Bar", presentation.getItemText()); } + public void testAssertEquals() throws Throwable { + myFixture.addClass("package junit.framework; public class Assert { public static void assertEquals(Object a, Object b) {} }"); + checkPreferredItems(0, "boo", "bar") + } + @Override protected String getBasePath() { return JavaTestUtil.getRelativeJavaTestDataPath() + BASE_PATH;