show method parameters: ensure inference results on wrong overloads not cached (IDEA-177725)

This commit is contained in:
Anna.Kozlova
2017-10-17 11:48:38 +02:00
parent bffca304b9
commit 3b40515140
3 changed files with 48 additions and 6 deletions
@@ -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);
@@ -0,0 +1,26 @@
import java.util.Collections;
import java.util.List;
public class Bug {
private static <TFrom, TTo> List<TTo> mapAsList(TFrom source, Class<TTo> toType) {
return Collections.singletonList((TTo) source);
}
private static <TFrom, TTo> List<TTo> mapAsList(TFrom source, Class<TTo> toType, boolean someOption) {
return Collections.singletonList((TTo) source);
}
private static class Foo {
public Foo(Long value, List<Long> values, List<Long> moreValues) {
}
}
public static void main(String[] args) {
new Foo(
1L,
mapAsList(2L, Long.class),
mapAsList(3L, Lo<caret>ng.class, true)
);
}
}
@@ -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();
}