From fa6672f721f0099fe99a343d1d477df314a2e7f3 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Thu, 27 Feb 2014 14:07:56 +0100 Subject: [PATCH] new inference: simplify target type calculation --- .../impl/source/resolve/JavaResolveUtil.java | 12 ++- .../graphInference/InferenceSession.java | 95 ++++--------------- ...eckedExceptionCompatibilityConstraint.java | 11 --- .../ExpressionCompatibilityConstraint.java | 16 ++-- 4 files changed, 33 insertions(+), 101 deletions(-) diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java index 5b76439ef406..3a0192705a19 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveUtil.java @@ -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); + } + }; } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java index abde4616fe77..775fa508d846 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceSession.java @@ -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() { - @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 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 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 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() { + @Override + public PsiSubstitutor compute() { + return result.getSubstitutor(); + } + })); } return null; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java index a67b64eea669..2d67b318d719 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/CheckedExceptionCompatibilityConstraint.java @@ -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; diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java index 30628e36beb6..26f041340347 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/ExpressionCompatibilityConstraint.java @@ -103,18 +103,18 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm session.addCapturedVariable(typeParam); } PsiSubstitutor substitutor = PsiSubstitutor.EMPTY; + //typeParams are already included + final Collection 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 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)