From 3b40515140c9000dc886b247a5f6b445a34302d9 Mon Sep 17 00:00:00 2001 From: "Anna.Kozlova" Date: Tue, 17 Oct 2017 11:44:10 +0200 Subject: [PATCH] show method parameters: ensure inference results on wrong overloads not cached (IDEA-177725) --- .../api/impls/MethodParameterInfoHandler.java | 14 +++++----- .../OverloadWithErrorOnTheTopLevel.java | 26 +++++++++++++++++++ .../java/codeInsight/ParameterInfoTest.java | 14 ++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/parameterInfo/OverloadWithErrorOnTheTopLevel.java diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java index 3a0ac51aab11..b6954f2b5de2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/MethodParameterInfoHandler.java @@ -35,6 +35,7 @@ import com.intellij.psi.scope.util.PsiScopesUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.MethodSignatureUtil; import com.intellij.util.ArrayUtil; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -242,7 +243,7 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc CandidateInfo candidate = (CandidateInfo)candidates[i]; PsiMethod method = (PsiMethod)candidate.getElement(); if (!method.isValid()) continue; - PsiSubstitutor substitutor = getCandidateInfoSubstitutor(candidate); + PsiSubstitutor substitutor = getCandidateInfoSubstitutor(o, candidate); assert substitutor != null; if (!method.isValid() || !substitutor.isValid()) { @@ -377,10 +378,11 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc } } - private static PsiSubstitutor getCandidateInfoSubstitutor(CandidateInfo candidate) { - return candidate instanceof MethodCandidateInfo && ((MethodCandidateInfo)candidate).isInferencePossible() - ? ((MethodCandidateInfo)candidate).inferTypeArguments(CompletionParameterTypeInferencePolicy.INSTANCE, true) - : candidate.getSubstitutor(); + private static PsiSubstitutor getCandidateInfoSubstitutor(PsiElement argList, CandidateInfo candidate) { + return MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(ObjectUtils.notNull(argList, candidate.getElement()), false, + () -> candidate instanceof MethodCandidateInfo && ((MethodCandidateInfo)candidate).isInferencePossible() + ? ((MethodCandidateInfo)candidate).inferTypeArguments(CompletionParameterTypeInferencePolicy.INSTANCE, true) + : candidate.getSubstitutor()); } private static boolean isAssignableParametersBeforeGivenIndex(final PsiParameter[] parms, @@ -689,7 +691,7 @@ public class MethodParameterInfoHandler implements ParameterInfoHandlerWithTabAc return; } - updateMethodPresentation(method, getCandidateInfoSubstitutor(info), context); + updateMethodPresentation(method, getCandidateInfoSubstitutor(context.getParameterOwner(), info), context); } else { updateMethodPresentation((PsiMethod)p, null, context); diff --git a/java/java-tests/testData/codeInsight/parameterInfo/OverloadWithErrorOnTheTopLevel.java b/java/java-tests/testData/codeInsight/parameterInfo/OverloadWithErrorOnTheTopLevel.java new file mode 100644 index 000000000000..ca0c78497489 --- /dev/null +++ b/java/java-tests/testData/codeInsight/parameterInfo/OverloadWithErrorOnTheTopLevel.java @@ -0,0 +1,26 @@ + +import java.util.Collections; +import java.util.List; + +public class Bug { + private static List mapAsList(TFrom source, Class toType) { + return Collections.singletonList((TTo) source); + } + + private static List mapAsList(TFrom source, Class toType, boolean someOption) { + return Collections.singletonList((TTo) source); + } + + private static class Foo { + public Foo(Long value, List values, List moreValues) { + } + } + + public static void main(String[] args) { + new Foo( + 1L, + mapAsList(2L, Long.class), + mapAsList(3L, Long.class, true) + ); + } +} diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/ParameterInfoTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/ParameterInfoTest.java index 3377da923afc..4ada8b302b44 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/ParameterInfoTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/ParameterInfoTest.java @@ -91,6 +91,20 @@ public class ParameterInfoTest extends LightCodeInsightFixtureTestCase { doTest2CandidatesWithPreselection(); } + public void testOverloadWithErrorOnTheTopLevel() { + doTest2CandidatesWithPreselection(); + PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()); + PsiCall call = LambdaUtil.treeWalkUp(elementAtCaret); + assertNotNull(call); + //cache the type of first argument: if type is calculated by cached session of first (wrong) overload, then applicability check would fail + //applicability check itself takes into account only child constraints and thus won't see cached elements on top level, thus explicit type calculation + PsiType type = call.getArgumentList().getExpressions()[1].getType(); + assertNotNull(type); + JavaResolveResult result = call.resolveMethodGenerics(); + assertTrue(result instanceof MethodCandidateInfo); + assertTrue(((MethodCandidateInfo)result).isApplicable()); + } + public void testOverloadWithVarargsArray() { doTest2CandidatesWithPreselection(); }