diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java index 43890225a21c..d770f131a608 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java @@ -184,4 +184,59 @@ public class PsiTypesUtil { } return null; } + + @Nullable + public static PsiType getExpectedTypeByParent(PsiExpression methodCall) { + final PsiElement parent = PsiUtil.skipParenthesizedExprUp(methodCall.getParent()); + if (parent instanceof PsiVariable) { + if (checkSameExpression(methodCall, ((PsiVariable)parent).getInitializer())) { + return ((PsiVariable)parent).getType(); + } + } + else if (parent instanceof PsiAssignmentExpression) { + if (checkSameExpression(methodCall, ((PsiAssignmentExpression)parent).getRExpression())) { + return ((PsiAssignmentExpression)parent).getLExpression().getType(); + } + } + else if (parent instanceof PsiIfStatement) { + if (checkSameExpression(methodCall, ((PsiIfStatement)parent).getCondition())) { + return PsiType.BOOLEAN.getBoxedType(parent); + } + } + else if (parent instanceof PsiWhileStatement) { + if (checkSameExpression(methodCall, ((PsiWhileStatement)parent).getCondition())) { + return PsiType.BOOLEAN.getBoxedType(parent); + } + } + else if (parent instanceof PsiForStatement) { + if (checkSameExpression(methodCall, ((PsiForStatement)parent).getCondition())) { + return PsiType.BOOLEAN.getBoxedType(parent); + } + } + else if (parent instanceof PsiDoWhileStatement) { + if (checkSameExpression(methodCall, ((PsiDoWhileStatement)parent).getCondition())) { + return PsiType.BOOLEAN.getBoxedType(parent); + } + } + else if (parent instanceof PsiTypeCastExpression) { + return ((PsiTypeCastExpression)parent).getType(); + } + else if (parent instanceof PsiReturnStatement) { + final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class); + if (lambdaExpression != null) { + return LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression.getFunctionalInterfaceType()); + } + else { + PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class); + if (method != null) { + return method.getReturnType(); + } + } + } + return null; + } + + private static boolean checkSameExpression(PsiExpression templateExpr, final PsiExpression expression) { + return templateExpr.equals(PsiUtil.skipParenthesizedExprDown(expression)); + } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index 1cf2d419d97b..c9fbfbf60ded 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -34,10 +34,7 @@ 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.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.psi.util.*; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.HashMap; @@ -1015,88 +1012,50 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { PsiSubstitutor substitutor, ParameterTypeInferencePolicy policy) { Pair constraint = null; - PsiType expectedType = null; + PsiType expectedType = PsiTypesUtil.getExpectedTypeByParent(methodCall); - if (parent instanceof PsiVariable) { - if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(((PsiVariable)parent).getInitializer()))) { - expectedType = ((PsiVariable)parent).getType(); - } - } - else if (parent instanceof PsiAssignmentExpression) { - if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(((PsiAssignmentExpression)parent).getRExpression()))) { - expectedType = ((PsiAssignmentExpression)parent).getLExpression().getType(); - } - } - else if (parent instanceof PsiIfStatement) { - if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(((PsiIfStatement)parent).getCondition()))) { - expectedType = PsiType.BOOLEAN.getBoxedType(parent); - } - } - else if (parent instanceof PsiWhileStatement) { - if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(((PsiWhileStatement)parent).getCondition()))) { - expectedType = PsiType.BOOLEAN.getBoxedType(parent); - } - } - else if (parent instanceof PsiForStatement) { - if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(((PsiForStatement)parent).getCondition()))) { - expectedType = PsiType.BOOLEAN.getBoxedType(parent); - } - } - else if (parent instanceof PsiDoWhileStatement) { - if (methodCall.equals(PsiUtil.skipParenthesizedExprDown(((PsiDoWhileStatement)parent).getCondition()))) { - expectedType = PsiType.BOOLEAN.getBoxedType(parent); - } - } - else if (parent instanceof PsiReturnStatement) { - final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class); - if (lambdaExpression != null) { - expectedType = LambdaUtil.getFunctionalInterfaceReturnType(lambdaExpression.getFunctionalInterfaceType()); - if (expectedType == null) { + if (expectedType == null) { + if (parent instanceof PsiReturnStatement) { + final PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(parent, PsiLambdaExpression.class); + if (lambdaExpression != null) { return getFailedInferenceConstraint(typeParameter); } - } else { - PsiMethod method = PsiTreeUtil.getParentOfType(parent, PsiMethod.class); - if (method != null) { - expectedType = method.getReturnType(); - } } - } - else if (parent instanceof PsiExpressionList) { - final PsiElement pParent = parent.getParent(); - if (pParent instanceof PsiCallExpression && parent.equals(((PsiCallExpression)pParent).getArgumentList())) { - constraint = policy.inferTypeConstraintFromCallContext(methodCall, (PsiExpressionList)parent, (PsiCallExpression)pParent, typeParameter); - if (constraint == null && PsiUtil.isLanguageLevel8OrHigher(methodCall)) { - constraint = graphInferenceFromCallContext(methodCall, typeParameter, (PsiCallExpression)pParent); - if (constraint != null) { - final PsiType constraintFirst = constraint.getFirst(); - if (constraintFirst == null || constraintFirst.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { - constraint = null; + else if (parent instanceof PsiExpressionList) { + final PsiElement pParent = parent.getParent(); + if (pParent instanceof PsiCallExpression && parent.equals(((PsiCallExpression)pParent).getArgumentList())) { + constraint = policy.inferTypeConstraintFromCallContext(methodCall, (PsiExpressionList)parent, (PsiCallExpression)pParent, typeParameter); + if (constraint == null && PsiUtil.isLanguageLevel8OrHigher(methodCall)) { + constraint = graphInferenceFromCallContext(methodCall, typeParameter, (PsiCallExpression)pParent); + if (constraint != null) { + final PsiType constraintFirst = constraint.getFirst(); + if (constraintFirst == null || constraintFirst.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) { + constraint = null; + } } } } - } - } else if (parent instanceof PsiLambdaExpression) { - expectedType = ourGraphGuard.doPreventingRecursion(methodCall, true, new Computable() { - @Override - public PsiType compute() { - return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType()); - } - }); - if (expectedType == null) { - return null; - } - } else if (parent instanceof PsiTypeCastExpression) { - expectedType = ((PsiTypeCastExpression)parent).getType(); - } else if (parent instanceof PsiConditionalExpression) { - if (PsiUtil.isLanguageLevel8OrHigher(parent)) { - try { - final Pair pair = inferFromConditionalExpression(parent, methodCall, typeParameter, substitutor, policy); - if (pair != null) { - return pair; + } else if (parent instanceof PsiLambdaExpression) { + expectedType = ourGraphGuard.doPreventingRecursion(methodCall, true, new Computable() { + @Override + public PsiType compute() { + return LambdaUtil.getFunctionalInterfaceReturnType(((PsiLambdaExpression)parent).getFunctionalInterfaceType()); } + }); + if (expectedType == null) { + return null; } - finally { - GraphInferencePolicy.forget(parent); + } else if (parent instanceof PsiConditionalExpression) { + if (PsiUtil.isLanguageLevel8OrHigher(parent)) { + try { + final Pair pair = inferFromConditionalExpression(parent, methodCall, typeParameter, substitutor, policy); + if (pair != null) { + return pair; + } + } + finally { + GraphInferencePolicy.forget(parent); + } } } } @@ -1196,6 +1155,10 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { return result; } + private static boolean checkSameExpression(PsiExpression templateExpr, final PsiExpression expression) { + return templateExpr.equals(PsiUtil.skipParenthesizedExprDown(expression)); + } + private static Pair inferExceptionConstrains(PsiTypeParameter typeParameter, PsiExpression expression, PsiMethod method,