new inference: avoid current type calculation during conflict resolution for target type detection (IDEA-121052)

This commit is contained in:
Anna Kozlova
2014-02-21 12:42:22 +01:00
parent edf1d19ecc
commit 6a38fbafaf
4 changed files with 56 additions and 19 deletions
@@ -24,6 +24,8 @@ import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.*;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.MethodProcessorSetupFailedException;
import com.intellij.psi.scope.PsiConflictResolver;
import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
import com.intellij.psi.scope.processor.MethodResolverProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
@@ -500,26 +502,17 @@ public class InferenceSession {
final PsiExpressionList argumentList = ((PsiCallExpression)gParent).getArgumentList();
if (argumentList != null) {
final Pair<PsiMethod, PsiSubstitutor> pair = MethodCandidateInfo.getCurrentMethod(argumentList);
final MethodCandidatesProcessor processor = new MethodResolverProcessor((PsiCallExpression)gParent, argumentList, context.getContainingFile()) {
final PsiFile placeFile = context.getContainingFile();
final JavaMethodsConflictResolver conflictResolver = new JavaMethodsConflictResolver(argumentList, PsiUtil.getLanguageLevel(placeFile)){
@Override
protected PsiType[] getArgumentTypes() {
return InferenceSession.getArgumentTypes(argumentList, context);
}
};
final MethodCandidatesProcessor processor = new MethodResolverProcessor((PsiCallExpression)gParent, placeFile, new PsiConflictResolver[]{conflictResolver}) {
@Override
protected PsiType[] getExpressionTypes(PsiExpressionList argumentList) {
if (argumentList != null) {
final PsiExpression[] expressions = argumentList.getExpressions();
final int idx = LambdaUtil.getLambdaIdx(argumentList, context);
final PsiType[] types = PsiType.createArray(expressions.length);
for (int i = 0; i < expressions.length; i++) {
if (i != idx) {
types[i] = expressions[i].getType();
}
else {
types[i] = PsiType.NULL;
}
}
return types;
}
else {
return null;
}
return getArgumentTypes(argumentList, context);
}
};
try {
@@ -549,6 +542,26 @@ public class InferenceSession {
return null;
}
private static PsiType[] getArgumentTypes(PsiExpressionList argumentList, PsiExpression context) {
if (argumentList != null) {
final PsiExpression[] expressions = argumentList.getExpressions();
final int idx = LambdaUtil.getLambdaIdx(argumentList, context);
final PsiType[] types = PsiType.createArray(expressions.length);
for (int i = 0; i < expressions.length; i++) {
if (i != idx) {
types[i] = expressions[i].getType();
}
else {
types[i] = PsiType.NULL;
}
}
return types;
}
else {
return null;
}
}
private PsiType getTypeByMethod(PsiExpression context,
PsiExpressionList argumentList,
Pair<PsiMethod, PsiSubstitutor> pair,
@@ -415,11 +415,15 @@ public class JavaMethodsConflictResolver implements PsiConflictResolver{
private PsiType[] getActualParameterTypes() {
if (myActualParameterTypes == null) {
LOG.assertTrue(myArgumentsList instanceof PsiExpressionList, myArgumentsList);
myActualParameterTypes = ((PsiExpressionList)myArgumentsList).getExpressionTypes();
myActualParameterTypes = getArgumentTypes();
}
return myActualParameterTypes;
}
protected PsiType[] getArgumentTypes() {
return ((PsiExpressionList)myArgumentsList).getExpressionTypes();
}
private enum Specifics {
FIRST,
SECOND,
@@ -0,0 +1,16 @@
import java.util.Comparator;
import java.util.function.Function;
import java.util.stream.Stream;
class TypeDetectionTest {
void main(Stream<Integer> of) {
of.sorted(comparing(n -> n.doubleValue()));
}
public static <T, U extends Comparable<? super U>> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor){
return null;
}
}
@@ -122,6 +122,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testTargetTypeConflictResolverShouldNotTryToEvaluateCurrentArgumentType() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}