diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java index 68893c6c973b..d33eab4e0fad 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java @@ -92,7 +92,7 @@ class CollectionsUtilityMethodsProvider { final PsiMethod method = methods[0]; final JavaMethodCallElement item = new JavaMethodCallElement(method, false, false); item.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE); - item.setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, expectedType), myElement); + item.setInferenceSubstitutorFromExpectedType(myElement, expectedType); myResult.consume(item); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java index 97f00f85661b..36db8a10ec7c 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java @@ -475,7 +475,7 @@ public class JavaCompletionContributor extends CompletionContributor { ? null : ContainerUtil.find(expectedTypes, type -> type.isAssignableFrom(returned)); if (matchingExpectation != null) { - call.setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, matchingExpectation), position); + call.setInferenceSubstitutorFromExpectedType(position, matchingExpectation); } } } 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 c1d0cef8866e..9a4b89bbc365 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -69,7 +69,7 @@ public class JavaMethodCallElement extends LookupItem implements Type private final MemberLookupHelper myHelper; private PsiSubstitutor myQualifierSubstitutor = PsiSubstitutor.EMPTY; private PsiSubstitutor myInferenceSubstitutor = PsiSubstitutor.EMPTY; - private boolean myMayNeedExplicitTypeParameters; + private boolean myNeedExplicitTypeParameters; private String myForcedQualifier = ""; @Nullable private String myPresentableTypeArgs; @@ -109,10 +109,10 @@ public class JavaMethodCallElement extends LookupItem implements Type return getSubstitutor().substitute(getInferenceSubstitutor().substitute(getObject().getReturnType())); } - public void setInferenceSubstitutor(@NotNull final PsiSubstitutor substitutor, PsiElement place) { - myInferenceSubstitutor = substitutor; - myMayNeedExplicitTypeParameters = mayNeedTypeParameters(place); - myPresentableTypeArgs = shouldInsertTypeParameters() ? getTypeParamsText(true, myMethod, substitutor) : null; + public void setInferenceSubstitutorFromExpectedType(@NotNull PsiElement place, @NotNull PsiType expectedType) { + myInferenceSubstitutor = SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(myMethod, expectedType); + myNeedExplicitTypeParameters = mayNeedTypeParameters(place) && !myInferenceSubstitutor.equals(PsiSubstitutor.EMPTY) && SmartCompletionDecorator.hasUnboundTypeParams(myMethod, expectedType); + myPresentableTypeArgs = myNeedExplicitTypeParameters ? getTypeParamsText(true, myMethod, myInferenceSubstitutor) : null; if (myPresentableTypeArgs != null && myPresentableTypeArgs.length() > 10) { myPresentableTypeArgs = myPresentableTypeArgs.substring(0, 10) + "...>"; } @@ -179,7 +179,7 @@ public class JavaMethodCallElement extends LookupItem implements Type final int startOffset = context.getStartOffset(); final OffsetKey refStart = context.trackOffset(startOffset, true); - if (shouldInsertTypeParameters() && mayNeedTypeParameters(context.getFile().findElementAt(context.getStartOffset()))) { + if (myNeedExplicitTypeParameters) { qualifyMethodCall(file, startOffset, document); insertExplicitTypeParameters(context, refStart); } @@ -387,11 +387,7 @@ public class JavaMethodCallElement extends LookupItem implements Type }); } - private boolean shouldInsertTypeParameters() { - return myMayNeedExplicitTypeParameters && !getInferenceSubstitutor().equals(PsiSubstitutor.EMPTY) && myMethod.getParameterList().getParametersCount() == 0; - } - - public static boolean mayNeedTypeParameters(@Nullable final PsiElement leaf) { + private static boolean mayNeedTypeParameters(@NotNull final PsiElement leaf) { if (PsiTreeUtil.getParentOfType(leaf, PsiExpressionList.class, true, PsiCodeBlock.class, PsiModifierListOwner.class) == null) { if (PsiTreeUtil.getParentOfType(leaf, PsiConditionalExpression.class, true, PsiCodeBlock.class, PsiModifierListOwner.class) == null) { return false; 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 59757c88b1e2..6316eed5e758 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java @@ -166,10 +166,7 @@ public class ReferenceExpressionCompletionContributor { if (lookupElement.getObject() instanceof PsiMethod) { final JavaMethodCallElement item = lookupElement.as(JavaMethodCallElement.CLASS_CONDITION_KEY); if (item != null) { - final PsiMethod method = (PsiMethod)lookupElement.getObject(); - if (SmartCompletionDecorator.hasUnboundTypeParams(method, parameters.getExpectedType())) { - item.setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, parameters.getExpectedType()), element); - } + item.setInferenceSubstitutorFromExpectedType(element, parameters.getExpectedType()); } } } diff --git a/java/java-impl/src/com/intellij/psi/filters/getters/JavaMembersGetter.java b/java/java-impl/src/com/intellij/psi/filters/getters/JavaMembersGetter.java index 48b1ec7de472..84ee160d2ed3 100644 --- a/java/java-impl/src/com/intellij/psi/filters/getters/JavaMembersGetter.java +++ b/java/java-impl/src/com/intellij/psi/filters/getters/JavaMembersGetter.java @@ -150,15 +150,13 @@ public class JavaMembersGetter extends MembersGetter { @Override @Nullable protected LookupElement createMethodElement(PsiMethod method) { - PsiSubstitutor substitutor = SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, myExpectedType); - PsiType type = substitutor.substitute(method.getReturnType()); + JavaMethodCallElement item = new JavaMethodCallElement(method, false, false); + item.setInferenceSubstitutorFromExpectedType(myPlace, myExpectedType); + PsiType type = item.getType(); if (type == null || !myExpectedType.isAssignableFrom(type)) { return null; } - - JavaMethodCallElement item = new JavaMethodCallElement(method, false, false); - item.setInferenceSubstitutor(substitutor, myPlace); return item; } } diff --git a/java/java-tests/testData/codeInsight/completion/normal/ExplicitTypeArgumentsWhenParameterTypesDoNotDependOnTypeParameters.java b/java/java-tests/testData/codeInsight/completion/normal/ExplicitTypeArgumentsWhenParameterTypesDoNotDependOnTypeParameters.java new file mode 100644 index 000000000000..31b22f6e5ae5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ExplicitTypeArgumentsWhenParameterTypesDoNotDependOnTypeParameters.java @@ -0,0 +1,19 @@ +import java.util.*; + +class Foo { + final R to(Function, R> converter) { + + } + + static { + new Foo().to(Bar.metho) + } +} + +class Bar { + static Function, ?> method(List scope) { + } + +} + +interface Function {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/ExplicitTypeArgumentsWhenParameterTypesDoNotDependOnTypeParameters_after.java b/java/java-tests/testData/codeInsight/completion/normal/ExplicitTypeArgumentsWhenParameterTypesDoNotDependOnTypeParameters_after.java new file mode 100644 index 000000000000..2a433a9c0c0a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/ExplicitTypeArgumentsWhenParameterTypesDoNotDependOnTypeParameters_after.java @@ -0,0 +1,19 @@ +import java.util.*; + +class Foo { + final R to(Function, R> converter) { + + } + + static { + new Foo().to(Bar.method()) + } +} + +class Bar { + static Function, ?> method(List scope) { + } + +} + +interface Function {} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/smartType/generics/after6.java b/java/java-tests/testData/codeInsight/completion/smartType/generics/after6.java index d3dad3c95f3d..d1e457f5ad0c 100644 --- a/java/java-tests/testData/codeInsight/completion/smartType/generics/after6.java +++ b/java/java-tests/testData/codeInsight/completion/smartType/generics/after6.java @@ -4,6 +4,6 @@ class C{ public X foo(T sdhg);' { - X dsd = foo() + X dsd = foo(); } } \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.groovy index de50be614956..f831a1232236 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/NormalCompletionTest.groovy @@ -1482,6 +1482,8 @@ class XInternalError {} checkResult() } + void testExplicitTypeArgumentsWhenParameterTypesDoNotDependOnTypeParameters() { doTest() } + void testNoFinalInAnonymousConstructor() { doTest() } void testListArrayListCast() { doTest('\n') }