better type inference for smart completing nested generic method call arguments (IDEA-74749)

This commit is contained in:
peter
2011-09-26 13:50:56 +02:00
parent 1bdf394db8
commit eb74d43139
4 changed files with 49 additions and 9 deletions
@@ -24,6 +24,7 @@ import com.intellij.openapi.util.RecursionManager;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.MethodProcessorSetupFailedException;
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
import com.intellij.psi.scope.processor.MethodResolverProcessor;
@@ -37,6 +38,9 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
public class PsiResolveHelperImpl implements PsiResolveHelper {
private static final RecursionGuard ourGuard = RecursionManager.createGuard("typeArgInference");
private final PsiManager myManager;
@@ -743,7 +747,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
try {
//can't call resolve() since it obtains full substitution, that may result in infinite recursion
PsiScopesUtil.setupAndRunProcessor(processor, contextCall, false);
int i = ArrayUtil.find(expressionList.getExpressions(), innerMethodCall);
PsiExpression[] expressions = expressionList.getExpressions();
int i = ArrayUtil.find(expressions, innerMethodCall);
assert i >= 0;
final JavaResolveResult[] results = processor.getResult();
PsiMethod owner = (PsiMethod)typeParameter.getOwner();
@@ -751,6 +756,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
final PsiType innerReturnType = owner.getReturnType();
for (final JavaResolveResult result : results) {
final PsiSubstitutor substitutor;
if (result instanceof MethodCandidateInfo) {
List<PsiExpression> leftArgs = Arrays.asList(expressions).subList(0, i);
substitutor = ((MethodCandidateInfo)result).inferTypeArguments(true, leftArgs.toArray(new PsiExpression[leftArgs.size()]));
} else {
substitutor = result.getSubstitutor();
}
final PsiElement element = result.getElement();
if (element instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)element;
@@ -764,15 +777,15 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
}
if (parameter != null) {
final PsiParameter finalParameter = parameter;
PsiType type = ourGuard
.doPreventingRecursion(innerMethodCall, true, new Computable<PsiType>() {
@Override
public PsiType compute() {
return result.getSubstitutor().substitute(finalParameter.getType());
}
}) ;
PsiType type = ourGuard.doPreventingRecursion(innerMethodCall, true, new Computable<PsiType>() {
@Override
public PsiType compute() {
return substitutor.substitute(finalParameter.getType());
}
});
final Pair<PsiType, ConstraintType> constraint =
getSubstitutionForTypeParameterConstraint(typeParameter, innerReturnType, type, false, PsiUtil.getLanguageLevel(innerMethodCall));
getSubstitutionForTypeParameterConstraint(typeParameter, innerReturnType, type, false,
PsiUtil.getLanguageLevel(innerMethodCall));
if (constraint != null) return constraint;
}
}
@@ -0,0 +1,13 @@
import java.util.List;
public class Zoo2 {
<T> void assertThat(T t, List<T> tt) { }
<T> List<T> wrap(T t) { }
public void main(String[] args) {
assertThat(args, wrap(args)<caret>);
}
}
@@ -0,0 +1,13 @@
import java.util.List;
public class Zoo2 {
<T> void assertThat(T t, List<T> tt) { }
<T> List<T> wrap(T t) { }
public void main(String[] args) {
assertThat(args, wrap(<caret>));
}
}
@@ -958,6 +958,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testPrimitiveArrayClassInMethod() throws Throwable { doTest(); }
public void testPrimitiveClassInAnno() throws Throwable { doTest(); }
public void testNewInnerClassOfSuper() throws Throwable { doTest(); }
public void testAssertThatMatcher() throws Throwable { doTest(); }
public void testInferFromCall() throws Throwable {
doTest();