From 924dde5961b9b0de469363e0cc6b7cc6273fbe6f Mon Sep 17 00:00:00 2001 From: peter Date: Tue, 28 Jun 2011 18:12:10 +0200 Subject: [PATCH] insert no method call explicit type arguments when there's no profit in it (IDEA-71128) --- .../completion/JavaMethodCallElement.java | 38 ++++++++++--------- ...erenceExpressionCompletionContributor.java | 2 +- .../completion/SmartCompletionDecorator.java | 11 +++++- ...itMethodTypeParametersOverZealous-out.java | 9 +++++ ...plicitMethodTypeParametersOverZealous.java | 9 +++++ .../completion/SmartTypeCompletionTest.java | 2 +- 6 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ExplicitMethodTypeParametersOverZealous-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/ExplicitMethodTypeParametersOverZealous.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index 65e9f578aee6..58a2a19db0d6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -98,7 +98,7 @@ public class JavaMethodCallElement extends LookupItem implements Type final int startOffset = context.getStartOffset(); final OffsetKey refStart = context.trackOffset(startOffset, true); - if (shouldInsertTypeParameters(context)) { + if (shouldInsertTypeParameters(context, startOffset)) { qualifyMethodCall(file, startOffset, document); insertExplicitTypeParameters(context, refStart); } @@ -129,7 +129,7 @@ public class JavaMethodCallElement extends LookupItem implements Type } - private boolean shouldInsertTypeParameters(InsertionContext context) { + private boolean shouldInsertTypeParameters(InsertionContext context, int offset) { final PsiElement leaf = context.getFile().findElementAt(context.getStartOffset()); if (PsiTreeUtil.getParentOfType(leaf, PsiExpressionList.class, true, PsiCodeBlock.class, PsiModifierListOwner.class) == null) { if (PsiTreeUtil.getParentOfType(leaf, PsiConditionalExpression.class, true, PsiCodeBlock.class, PsiModifierListOwner.class) == null) { @@ -143,31 +143,35 @@ public class JavaMethodCallElement extends LookupItem implements Type } } - return SmartCompletionDecorator.hasUnboundTypeParams(getObject()); + return SmartCompletionDecorator.hasUnboundTypeParams(getObject(), getExpectedTypeForExplicitTypeParameters(context, offset)); } - private boolean insertExplicitTypeParameters(InsertionContext context, OffsetKey refStart) { + @Nullable + private static PsiType getExpectedTypeForExplicitTypeParameters(InsertionContext context, final int offset) { context.commitDocument(); - PsiExpression expression = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), context.getOffset(refStart), PsiExpression.class, false); - if (expression == null) return true; + PsiExpression expression = PsiTreeUtil.findElementOfClassAtOffset(context.getFile(), offset, PsiExpression.class, false); + if (expression == null) return null; for (final ExpectedTypeInfo type : ExpectedTypesProvider.getExpectedTypes(expression, true)) { if (type.isInsertExplicitTypeParams()) { - final String typeParams = getTypeParamsText(type.getType()); - if (typeParams == null) { - return true; - } - - context.getDocument().insertString(context.getOffset(refStart), typeParams); - - JavaCompletionUtil.shortenReference(context.getFile(), context.getOffset(refStart)); - - break; + return type.getType(); } } + return null; + } - return true; + private void insertExplicitTypeParameters(InsertionContext context, OffsetKey refStart) { + context.commitDocument(); + + PsiType psiType = getExpectedTypeForExplicitTypeParameters(context, context.getOffset(refStart)); + if (psiType != null) { + final String typeParams = getTypeParamsText(psiType); + if (typeParams != null) { + context.getDocument().insertString(context.getOffset(refStart), typeParams); + JavaCompletionUtil.shortenReference(context.getFile(), context.getOffset(refStart)); + } + } } private void qualifyMethodCall(PsiFile file, final int startOffset, final Document document) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java index 7c206fa428ca..546d759033ef 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -170,7 +170,7 @@ public class ReferenceExpressionCompletionContributor { final JavaMethodCallElement item = lookupElement.as(JavaMethodCallElement.CLASS_CONDITION_KEY); assert item != null; final PsiMethod method = (PsiMethod)lookupElement.getObject(); - if (SmartCompletionDecorator.hasUnboundTypeParams(method)) { + if (SmartCompletionDecorator.hasUnboundTypeParams(method, parameters.getExpectedType())) { item.setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, parameters.getExpectedType())); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java index 60aaf504bf7d..3e030b775348 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SmartCompletionDecorator.java @@ -111,7 +111,7 @@ public class SmartCompletionDecorator extends TailTypeDecorator { super.handleInsert(context); } - public static boolean hasUnboundTypeParams(final PsiMethod method) { + public static boolean hasUnboundTypeParams(final PsiMethod method, PsiType expectedType) { final PsiTypeParameter[] typeParameters = method.getTypeParameters(); if (typeParameters.length == 0) return false; @@ -146,7 +146,14 @@ public class SmartCompletionDecorator extends TailTypeDecorator { if (!parameter.getType().accept(typeParamSearcher).booleanValue()) return false; } - return true; + PsiSubstitutor substitutor = calculateMethodReturnTypeSubstitutor(method, expectedType); + for (PsiTypeParameter parameter : typeParameters) { + if (!TypeConversionUtil.typeParameterErasure(parameter).equals(substitutor.substitute(parameter))) { + return true; + } + } + + return false; } public static PsiSubstitutor calculateMethodReturnTypeSubstitutor(PsiMethod method, final PsiType expected) { diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ExplicitMethodTypeParametersOverZealous-out.java b/java/java-tests/testData/codeInsight/completion/smartType/ExplicitMethodTypeParametersOverZealous-out.java new file mode 100644 index 000000000000..ff19c35166aa --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ExplicitMethodTypeParametersOverZealous-out.java @@ -0,0 +1,9 @@ +public class Foo { + { + bar(foo()); + } + + T foo() {} + + void bar(Object s) {} +} diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ExplicitMethodTypeParametersOverZealous.java b/java/java-tests/testData/codeInsight/completion/smartType/ExplicitMethodTypeParametersOverZealous.java new file mode 100644 index 000000000000..1867542fb525 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/ExplicitMethodTypeParametersOverZealous.java @@ -0,0 +1,9 @@ +public class Foo { + { + bar(fo) + } + + T foo() {} + + void bar(Object s) {} +} 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 98e1c6b98534..46773430ad7f 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -971,7 +971,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testFilterPrivateConstructors() throws Throwable { doTest(); } public void testExplicitMethodTypeParametersQualify() throws Throwable { doTest(); } - + public void testExplicitMethodTypeParametersOverZealous() throws Throwable { doTest(); } public void testExplicitMethodTypeParametersFromSuperClass() throws Throwable { doTest(); } public void testWildcardedInstanceof() throws Throwable { doTest(); }