diamonds: allow in invocation context in java 8

This commit is contained in:
anna
2012-07-18 17:26:34 +02:00
parent 6d84287e33
commit 28230348a2
6 changed files with 122 additions and 77 deletions
@@ -17,88 +17,18 @@ package com.intellij.psi.impl.source.resolve;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.MethodProcessorSetupFailedException;
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ArrayUtil;
import java.util.Arrays;
import java.util.List;
/**
* @author yole
*/
public class CompletionParameterTypeInferencePolicy extends ParameterTypeInferencePolicy {
public class CompletionParameterTypeInferencePolicy extends ProcessCandidateParameterTypeInferencePolicy {
public static final CompletionParameterTypeInferencePolicy INSTANCE = new CompletionParameterTypeInferencePolicy();
private CompletionParameterTypeInferencePolicy() {
}
@Override
public Pair<PsiType, ConstraintType> inferTypeConstraintFromCallContext(PsiCallExpression innerMethodCall,
PsiExpressionList expressionList,
PsiCallExpression contextCall,
PsiTypeParameter typeParameter) {
final MethodCandidatesProcessor processor = new MethodCandidatesProcessor(contextCall);
try {
//can't call resolve() since it obtains full substitution, that may result in infinite recursion
PsiScopesUtil.setupAndRunProcessor(processor, contextCall, false);
PsiExpression[] expressions = expressionList.getExpressions();
int i = ArrayUtil.find(expressions, innerMethodCall);
assert i >= 0;
final JavaResolveResult[] results = processor.getResult();
PsiMethod owner = (PsiMethod)typeParameter.getOwner();
if (owner == null) return null;
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(this, leftArgs.toArray(new PsiExpression[leftArgs.size()]));
} else {
substitutor = result.getSubstitutor();
}
final PsiElement element = result.getElement();
if (element instanceof PsiMethod) {
final PsiMethod method = (PsiMethod)element;
final PsiParameter[] parameters = method.getParameterList().getParameters();
PsiParameter parameter = null;
if (parameters.length > i) {
parameter = parameters[i];
}
else if (method.isVarArgs()) {
parameter = parameters[parameters.length - 1];
}
if (parameter != null) {
final PsiParameter finalParameter = parameter;
PsiType type = PsiResolveHelperImpl.ourGuard.doPreventingRecursion(innerMethodCall, true, new Computable<PsiType>() {
@Override
public PsiType compute() {
return substitutor.substitute(finalParameter.getType());
}
});
final Pair<PsiType, ConstraintType> constraint =
PsiResolveHelperImpl.getSubstitutionForTypeParameterConstraint(typeParameter, innerReturnType, type, false,
PsiUtil.getLanguageLevel(innerMethodCall));
if (constraint != null) return constraint;
}
}
}
}
catch (MethodProcessorSetupFailedException ev) {
return null;
}
return null;
}
@Override
public PsiType getDefaultExpectedType(PsiCallExpression methodCall) {
ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(methodCall, true);