new inference: simplify target type calculation

This commit is contained in:
Anna Kozlova
2014-02-27 18:32:38 +01:00
parent cbe62cc24d
commit fa6672f721
4 changed files with 33 additions and 101 deletions
@@ -227,13 +227,19 @@ public class JavaResolveUtil {
public static void substituteResults(@NotNull PsiJavaCodeReferenceElement ref, @NotNull JavaResolveResult[] result) {
if (result.length > 0 && result[0].getElement() instanceof PsiClass) {
PsiType[] parameters = ref.getTypeParameters();
for (int i = 0; i < result.length; i++) {
CandidateInfo resolveResult = (CandidateInfo)result[i];
PsiElement resultElement = resolveResult.getElement();
if (resultElement instanceof PsiClass && ((PsiClass)resultElement).hasTypeParameters()) {
PsiSubstitutor substitutor = resolveResult.getSubstitutor().putAll((PsiClass)resultElement, parameters);
result[i] = new CandidateInfo(resolveResult, substitutor);
PsiSubstitutor substitutor = resolveResult.getSubstitutor();
result[i] = new CandidateInfo(resolveResult, substitutor) {
@NotNull
@Override
public PsiSubstitutor getSubstitutor() {
final PsiType[] parameters = ref.getTypeParameters();
return super.getSubstitutor().putAll((PsiClass)resultElement, parameters);
}
};
}
}
}
@@ -23,12 +23,6 @@ import com.intellij.psi.*;
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;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiTypesUtil;
@@ -174,7 +168,8 @@ public class InferenceSession {
return true;
}
private static PsiType getParameterType(PsiParameter[] parameters, PsiExpression[] args, int i, PsiSubstitutor substitutor) {
private static PsiType getParameterType(PsiParameter[] parameters, PsiExpression[] args, int i, @Nullable PsiSubstitutor substitutor) {
if (substitutor == null) return null;
PsiType parameterType = substitutor.substitute(parameters[i < parameters.length ? i : parameters.length - 1].getType());
if (parameterType instanceof PsiEllipsisType) {
final PsiExpression arg = args[i];
@@ -366,19 +361,13 @@ public class InferenceSession {
}
private void initReturnTypeConstraint(PsiMethod method, final PsiCallExpression context) {
if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method) ||
context instanceof PsiNewExpression && PsiDiamondType.ourDiamondGuard.currentStack().contains(context)) {
if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method)) {
PsiType returnType = method.getReturnType();
if (!PsiType.VOID.equals(returnType) && returnType != null) {
returnType = PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context);
PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context);
if (targetType == null) {
targetType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(context, false, new Computable<PsiType>() {
@Override
public PsiType compute() {
return getTargetType(context);
}
});
targetType = getTargetType(context);
}
if (targetType != null) {
registerConstraints(returnType, targetType);
@@ -495,7 +484,7 @@ public class InferenceSession {
return false;
}
private PsiType getTargetType(final PsiExpression context) {
private static PsiType getTargetType(final PsiExpression context) {
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent());
if (parent instanceof PsiExpressionList) {
PsiElement gParent = parent.getParent();
@@ -505,28 +494,8 @@ public class InferenceSession {
if (gParent instanceof PsiCallExpression) {
final PsiExpressionList argumentList = ((PsiCallExpression)gParent).getArgumentList();
if (argumentList != null) {
final Pair<PsiMethod, PsiSubstitutor> pair = MethodCandidateInfo.getCurrentMethod(argumentList);
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) {
return getArgumentTypes(argumentList, context);
}
};
try {
PsiScopesUtil.setupAndRunProcessor(processor, (PsiCallExpression)gParent, false);
}
catch (MethodProcessorSetupFailedException e) {
return null;
}
final JavaResolveResult[] results = processor.getResult();
return results.length == 1 ? getTypeByMethod(context, argumentList, pair, results[0], results[0].getElement()) : null;
final JavaResolveResult result = ((PsiCallExpression)gParent).resolveMethodGenerics();
return getTypeByMethod(context, argumentList, result, result.getElement());
}
}
} else if (parent instanceof PsiConditionalExpression) {
@@ -546,30 +515,9 @@ 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,
JavaResolveResult result, PsiElement parentMethod) {
private static PsiType getTypeByMethod(PsiExpression context,
PsiExpressionList argumentList,
final JavaResolveResult result, PsiElement parentMethod) {
if (parentMethod instanceof PsiMethod) {
final PsiParameter[] parameters = ((PsiMethod)parentMethod).getParameterList().getParameters();
if (parameters.length == 0) return null;
@@ -581,23 +529,12 @@ public class InferenceSession {
}
final int i = ArrayUtilRt.find(args, arg);
if (i < 0) return null;
final PsiCallExpression callExpression = PsiTreeUtil.getParentOfType(argumentList, PsiCallExpression.class);
if (callExpression != null && callExpression.getTypeArguments().length > 0) {
return getParameterType(parameters, args, i, ((MethodCandidateInfo)result).typeArgumentsSubstitutor());
}
final PsiType parameterType = getParameterType(parameters, args, i, pair != null ? pair.second : PsiSubstitutor.EMPTY);
args[i] = null;
final PsiTypeParameter[] typeParameters = ((PsiMethod)parentMethod).getTypeParameters();
final InferenceSession session = new InferenceSession(typeParameters, ((MethodCandidateInfo)result).getSiteSubstitutor(), myManager, argumentList);
session.initExpressionConstraints(parameters, args, argumentList, (PsiMethod)parentMethod);
if (session.tryToInfer(parameters, args, callExpression, (PsiMethod)parentMethod) != null) {
return null;
}
final Collection<PsiTypeParameter> params = session.getTypeParams();
initBounds(params.toArray(new PsiTypeParameter[params.size()]));
liftBounds(session.getInferenceVariables());
final PsiSubstitutor substitutor = ((MethodCandidateInfo)result).getSiteSubstitutor();
return substitutor.substitute(parameterType);
return getParameterType(parameters, args, i, PsiResolveHelper.ourGraphGuard.doPreventingRecursion(argumentList.getParent(), false, new Computable<PsiSubstitutor>() {
@Override
public PsiSubstitutor compute() {
return result.getSubstitutor();
}
}));
}
return null;
}
@@ -48,17 +48,6 @@ public class CheckedExceptionCompatibilityConstraint extends InputOutputConstrai
if (!PsiPolyExpressionUtil.isPolyExpression(myExpression)) {
return true;
}
if (myExpression instanceof PsiCallExpression) {
final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList();
if (argumentList != null) {
for (PsiExpression expression : argumentList.getExpressions()) {
if (PsiPolyExpressionUtil.isPolyExpression(expression)) {
//todo additional constraints [JDK-8033488]
}
}
}
return true;
}
if (myExpression instanceof PsiParenthesizedExpression) {
constraints.add(new CheckedExceptionCompatibilityConstraint(((PsiParenthesizedExpression)myExpression).getExpression(), myT));
return true;
@@ -103,18 +103,18 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
session.addCapturedVariable(typeParam);
}
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
//typeParams are already included
final Collection<PsiTypeParameter> params = session.getTypeParams();
InferenceSession callSession = new InferenceSession(params.toArray(new PsiTypeParameter[params.size()]), resolveResult instanceof MethodCandidateInfo ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor()
: PsiSubstitutor.EMPTY, myExpression.getManager(), myExpression);
if (method != null) {
//typeParams are already included
final Collection<PsiTypeParameter> params = session.getTypeParams();
InferenceSession callSession = new InferenceSession(params.toArray(new PsiTypeParameter[params.size()]), resolveResult instanceof MethodCandidateInfo ? ((MethodCandidateInfo)resolveResult).getSiteSubstitutor()
: PsiSubstitutor.EMPTY, myExpression.getManager(), myExpression);
final PsiExpression[] args = argumentList.getExpressions();
final PsiParameter[] parameters = method.getParameterList().getParameters();
callSession.initExpressionConstraints(parameters, args, myExpression, method);
callSession.registerConstraints(returnType, myT);
if (callSession.repeatInferencePhases(true)) {
session.liftBounds(callSession.getInferenceVariables());
}
}
callSession.registerConstraints(returnType, myT);
if (callSession.repeatInferencePhases(true)) {
session.liftBounds(callSession.getInferenceVariables());
}
final PsiType capturedReturnType = myExpression instanceof PsiMethodCallExpression
? PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, substitutor)