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 162d764df83a..fc22c6b89f59 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 @@ -18,13 +18,15 @@ package com.intellij.psi.impl.source.resolve.graphInference; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.Pair; import com.intellij.psi.*; +import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.impl.source.resolve.graphInference.constraints.ConstraintFormula; import com.intellij.psi.impl.source.resolve.graphInference.constraints.ExpressionCompatibilityConstraint; import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeCompatibilityConstraint; import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.ArrayUtilRt; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -75,12 +77,7 @@ public class InferenceSession { if (parameters.length > 0) { for (int i = 0; i < args.length; i++) { - PsiType parameterType = mySiteSubstitutor.substitute(parameters[i < parameters.length ? i : parameters.length - 1].getType()); - if (parameterType instanceof PsiEllipsisType) { - if (args.length != parameters.length || args[i] != null && !(args[i].getType() instanceof PsiArrayType)) { - parameterType = ((PsiEllipsisType)parameterType).getComponentType(); - } - } + PsiType parameterType = getParameterType(parameters, args, i, mySiteSubstitutor); if (args[i] != null) { myConstraints.add(new ExpressionCompatibilityConstraint(args[i], parameterType)); } @@ -98,6 +95,17 @@ public class InferenceSession { } } + private static PsiType getParameterType(PsiParameter[] parameters, PsiExpression[] args, int i, PsiSubstitutor substitutor) { + PsiType parameterType = substitutor.substitute(parameters[i < parameters.length ? i : parameters.length - 1].getType()); + if (parameterType instanceof PsiEllipsisType) { + if (args.length != parameters.length || PsiPolyExpressionUtil + .isPolyExpression(args[i]) || args[i] != null && !(args[i].getType() instanceof PsiArrayType)) { + parameterType = ((PsiEllipsisType)parameterType).getComponentType(); + } + } + return parameterType; + } + @NotNull public PsiSubstitutor infer() { repeatInferencePhases(); @@ -149,19 +157,45 @@ public class InferenceSession { context instanceof PsiNewExpression && PsiDiamondType.ourDiamondGuard.currentStack().contains(context)) { final PsiType returnType = method.getReturnType(); if (!PsiType.VOID.equals(returnType) && returnType != null) { - final PsiType targetType = PsiPolyExpressionUtil.getTargetType(context);//todo primitive type + PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context); + if (targetType == null) { + final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent()); + if (parent instanceof PsiExpressionList) { + final PsiElement gParent = parent.getParent(); + if (gParent instanceof PsiCallExpression) { + final PsiExpressionList argumentList = ((PsiCallExpression)gParent).getArgumentList(); + if (argumentList != null) { + final JavaResolveResult resolveResult = ((PsiCallExpression)gParent).resolveMethodGenerics(); + final PsiElement parentMethod = resolveResult.getElement(); + if (parentMethod instanceof PsiMethod) { + final PsiParameter[] parameters = ((PsiMethod)parentMethod).getParameterList().getParameters(); + PsiElement arg = context; + while (arg.getParent() instanceof PsiParenthesizedExpression) { + arg = parent.getParent(); + } + final PsiExpression[] args = argumentList.getExpressions(); + targetType = getParameterType(parameters, args, ArrayUtilRt.find(args, arg), resolveResult.getSubstitutor()); + } + } + } + } + } if (targetType != null) { - myConstraints.add(new TypeCompatibilityConstraint(targetType, returnType)); + myConstraints.add(new TypeCompatibilityConstraint(targetType, PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context))); } } } } public InferenceVariable getInferenceVariable(PsiType psiType) { + return getInferenceVariable(psiType, true); + } + + public InferenceVariable getInferenceVariable(PsiType psiType, boolean acceptCaptured) { final PsiClass psiClass = PsiUtil.resolveClassInClassTypeOnly(psiType); if (psiClass instanceof PsiTypeParameter) { final InferenceVariable inferenceVariable = myInferenceVariables.get(psiClass); - if (inferenceVariable != null) { + if (inferenceVariable != null && (acceptCaptured || !inferenceVariable.isCaptured())) { return inferenceVariable; } } @@ -169,10 +203,16 @@ public class InferenceSession { } public boolean isProperType(@Nullable PsiType type) { - return collectDependencies(type, null); + return isProperType(type, true); } - public boolean collectDependencies(@Nullable PsiType type, @Nullable final Set dependencies) { + public boolean isProperType(@Nullable PsiType type, boolean acceptCaptured) { + return collectDependencies(type, null, acceptCaptured); + } + + public boolean collectDependencies(@Nullable PsiType type, + @Nullable final Set dependencies, + final boolean acceptCaptured) { if (type == null) return true; final Boolean isProper = type.accept(new PsiTypeVisitor() { @Nullable @@ -198,7 +238,7 @@ public class InferenceSession { @Nullable @Override public Boolean visitClassType(PsiClassType classType) { - final InferenceVariable inferenceVariable = getInferenceVariable(classType); + final InferenceVariable inferenceVariable = getInferenceVariable(classType, acceptCaptured); if (inferenceVariable != null) { if (dependencies != null) { dependencies.add(inferenceVariable); @@ -271,7 +311,7 @@ public class InferenceSession { PsiType lub = null; for (PsiType lowerBound : lowerBounds) { lowerBound = acceptBoundsWithRecursiveDependencies(typeParameter, lowerBound); - if (isProperType(lowerBound)) { + if (isProperType(lowerBound, false)) { if (lub == null) { lub = lowerBound; } @@ -287,7 +327,7 @@ public class InferenceSession { PsiType glb = null; for (PsiType upperBound : upperBounds) { upperBound = acceptBoundsWithRecursiveDependencies(typeParameter, upperBound); - if (isProperType(upperBound)) { + if (isProperType(upperBound, false)) { if (glb == null) { glb = upperBound; } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java index 4a2c4126611e..c27ae4a53916 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariablesOrder.java @@ -41,7 +41,7 @@ public class InferenceVariablesOrder { for (InferenceBound inferenceBound : InferenceBound.values()) { for (PsiType bound : var.getBounds(inferenceBound)) { final HashSet dependencies = new HashSet(); - session.collectDependencies(bound, dependencies); + session.collectDependencies(bound, dependencies, true); for (InferenceVariable dependentVariable : dependencies) { final InferenceGraphNode dependency = nodes.get(dependentVariable); if (dependency != null) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java index 2e425e0fb436..709900569853 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiPolyExpressionUtil.java @@ -82,10 +82,6 @@ public class PsiPolyExpressionUtil { return false; } - public static PsiType getTargetType(@NotNull PsiCallExpression expression) { - return PsiTypesUtil.getExpectedTypeByParent(expression); - } - public static Boolean mentionsTypeParameters(@Nullable PsiType returnType, final Set typeParameters) { if (returnType == null) return false; return returnType.accept(new PsiTypeVisitor() { 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 676f046d5d6f..4e224ad39145 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 @@ -15,14 +15,17 @@ */ package com.intellij.psi.impl.source.resolve.graphInference.constraints; +import com.intellij.openapi.util.Pair; import com.intellij.psi.*; import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession; import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil; import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl; +import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.NotNull; import java.util.List; +import java.util.Map; /** * User: anna @@ -70,8 +73,10 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula { } if (myExpression instanceof PsiCallExpression) { - final JavaResolveResult resolveResult = ((PsiCallExpression)myExpression).resolveMethodGenerics(); - final PsiMethod method = (PsiMethod)resolveResult.getElement(); + final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList(); + final Map> map = MethodCandidateInfo.CURRENT_CANDIDATE.get(); + final Pair pair = map != null ? map.get(argumentList) : null; + final PsiMethod method = pair != null ? pair.first : ((PsiCallExpression)myExpression).resolveMethod(); if (method != null) { final PsiTypeParameter[] typeParameters = method.getTypeParameters(); if (typeParameters.length == 0) { @@ -80,7 +85,6 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula { constraints.add(new TypeCompatibilityConstraint(myT, exprType)); } } else { - final PsiExpressionList argumentList = ((PsiCallExpression)myExpression).getArgumentList(); PsiType returnType = method.getReturnType(); if (argumentList != null && returnType != null) { //todo constructor final InferenceSession callSession = new InferenceSession(typeParameters, method.getParameterList().getParameters(), diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA109875.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA109875.java index 39b92e87c332..d799ba286e09 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA109875.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA109875.java @@ -8,6 +8,6 @@ public class Test { } public static void main(String[] args) { - Test.>doTest(Collections.emptySet()); + Test.>doTest(Collections.emptySet()); } } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/InferenceWithUpperBoundPromotion.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/InferenceWithUpperBoundPromotion.java index 0c8796ceb5b1..8b2aabe285a7 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/InferenceWithUpperBoundPromotion.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/InferenceWithUpperBoundPromotion.java @@ -8,7 +8,7 @@ public class NestedGenericGoodCodeIsRed { Number num = null; satisfiesAllOf(isPositive(), isEqualTo(num)); - this.satisfiesAllOf(isPositive(), isEqualTo(10)); + this.satisfiesAllOf(isPositive(), isEqualTo(10)); }