ensure assignability for standalone expressions during applicability check (IDEA-159086)

This commit is contained in:
Anna.Kozlova
2017-02-13 18:01:21 +01:00
parent d720d1fd0d
commit 770bd344ea
4 changed files with 41 additions and 5 deletions

View File

@@ -25,7 +25,9 @@ import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ThreeState;
import com.intellij.util.containers.ContainerUtil;
@@ -127,15 +129,27 @@ public class MethodCandidateInfo extends CandidateInfo{
final PsiMethod method = getElement();
if (isToInferApplicability()) {
if (!isOverloadCheck()) {
//ensure applicability check is performed
getSubstitutor(false);
}
//ensure applicability check
PsiSubstitutor applicabilitySubstitutor = getSubstitutor(false);
//already performed checks, so if inference failed, error message should be saved
if (myInferenceError != null || isPotentiallyCompatible() != ThreeState.YES) {
return ApplicabilityLevel.NOT_APPLICABLE;
}
if (myArgumentList instanceof PsiExpressionList) {
PsiParameter[] parameters = getElement().getParameterList().getParameters();
PsiExpression[] expressions = ((PsiExpressionList)myArgumentList).getExpressions();
for (int i = 0; i < expressions.length; i++) {
if (!PsiPolyExpressionUtil.isPolyExpression(expressions[i])) {
PsiType expressionType = expressions[i].getType();
PsiType parameterType = applicabilitySubstitutor.substitute(PsiTypesUtil.getParameterType(parameters, i, isVarargs()));
if (expressionType != null && parameterType != null && !parameterType.isAssignableFrom(expressionType)) {
return ApplicabilityLevel.NOT_APPLICABLE;
}
}
}
}
return isVarargs() ? ApplicabilityLevel.VARARGS : ApplicabilityLevel.FIXED_ARITY;
}

View File

@@ -0,0 +1,18 @@
import java.util.*;
class Test {
interface Q<K> {
}
void f(List list, Set<List<Object>> q) {
assertThat1(list, <error descr="'assertThat1(java.util.List, java.util.Set<? super java.util.List>)' in 'Test' cannot be applied to '(java.util.List, java.util.Set<java.util.List<java.lang.Object>>)'">q</error>);
assertThat2(list, q);
assertThat<error descr="Cannot resolve method 'assertThat(java.util.List, java.util.Set<java.util.List<java.lang.Object>>)'">(list, q)</error>;
}
private static <T> void assertThat1(T actual, Set<? super T> matcher) {}
private static <T> void assertThat2(T actual, Set<? extends T> matcher) {}
private static <T> void assertThat(T actual, Set<? super T> matcher) {}
private static <T> void assertThat(T actual, List<? super T> matcher) {}
}

View File

@@ -9,6 +9,6 @@ class Calls {
void foo(Function<String, Optional> computable) {}
{
<error descr="Not a statement">((x) -> a(b(c(x))));</error>
((x) -> a(b(c<error descr="'c(C)' in 'Calls' cannot be applied to '(<lambda parameter>)'">(x)</error>)));
}
}

View File

@@ -495,6 +495,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
doTest();
}
public void testAssignabilityOfStandaloneExpressionsDuringApplicabilityCheck() throws Exception {
doTest();
}
public void testRecursiveTypeWithCapture() throws Exception {
doTest();
}