From f4157021276d83d7ca32a354f8f2e75f82f1d9d9 Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Fri, 20 Sep 2013 19:54:07 +0400 Subject: [PATCH] new inference: default constructor as poly expression argument --- .../ExpressionCompatibilityConstraint.java | 67 ++++++++++++------- .../DefaultConstructorAsArgument.java | 21 ++++++ .../GraphInferenceHighlightingTest.java | 4 ++ 3 files changed, 66 insertions(+), 26 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/DefaultConstructorAsArgument.java 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 4e224ad39145..c0f923e1ee2e 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 @@ -74,36 +74,51 @@ public class ExpressionCompatibilityConstraint implements ConstraintFormula { if (myExpression instanceof PsiCallExpression) { 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) { - final PsiType exprType = myExpression.getType(); - if (exprType != null && !exprType.equals(PsiType.NULL)) { - constraints.add(new TypeCompatibilityConstraint(myT, exprType)); + if (argumentList != null) { + 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(); + PsiType returnType = null; + InferenceSession callSession = null; + if (method != null) { + returnType = method.getReturnType(); + final PsiParameter[] parameters = method.getParameterList().getParameters(); + if (returnType != null) { + callSession = new InferenceSession(method.getTypeParameters(), parameters, + argumentList.getExpressions(), + PsiSubstitutor.EMPTY, null, myExpression.getManager()); + } - } else { - PsiType returnType = method.getReturnType(); - if (argumentList != null && returnType != null) { //todo constructor - final InferenceSession callSession = new InferenceSession(typeParameters, method.getParameterList().getParameters(), - argumentList.getExpressions(), - PsiSubstitutor.EMPTY, null, myExpression.getManager()); - for (PsiTypeParameter typeParameter : session.getTypeParams()) { - callSession.addCapturedVariable(typeParameter); + } else if (myExpression instanceof PsiNewExpression) { //default constructor + final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)myExpression).getClassOrAnonymousClassReference(); + if (classReference != null) { + final PsiElement psiClass = classReference.resolve(); + if (psiClass instanceof PsiClass) { + returnType = JavaPsiFacade.getElementFactory(argumentList.getProject()).createType((PsiClass)psiClass, PsiSubstitutor.EMPTY); + callSession = new InferenceSession(((PsiClass)psiClass).getTypeParameters(), + PsiParameter.EMPTY_ARRAY, + argumentList.getExpressions(), + PsiSubstitutor.EMPTY, null, myExpression.getManager()); } - callSession.addConstraint(new TypeCompatibilityConstraint(myT, returnType)); - final PsiSubstitutor callSubstitutor = callSession.infer(); - if (myExpression instanceof PsiMethodCallExpression) { - returnType = - PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, callSubstitutor); - } else { - returnType = callSubstitutor.substitute(returnType); - } - constraints.add(new TypeCompatibilityConstraint(myT, returnType)); //todo primitive types } } + + if (callSession != null) { + + for (PsiTypeParameter typeParameter : session.getTypeParams()) { + callSession.addCapturedVariable(typeParameter); + } + callSession.addConstraint(new TypeCompatibilityConstraint(myT, returnType)); + final PsiSubstitutor callSubstitutor = callSession.infer(); + + if (myExpression instanceof PsiMethodCallExpression) { + returnType = PsiMethodCallExpressionImpl.captureReturnType((PsiMethodCallExpression)myExpression, method, returnType, callSubstitutor); + } + else { + returnType = callSubstitutor.substitute(returnType); + } + constraints.add(new TypeCompatibilityConstraint(myT, returnType)); //todo primitive types + } } return true; } diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/DefaultConstructorAsArgument.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/DefaultConstructorAsArgument.java new file mode 100644 index 000000000000..98462674376d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/DefaultConstructorAsArgument.java @@ -0,0 +1,21 @@ +class Main2 { + + void bar(Fun collector) { } + + Fun foo(D d) { return null; } + + public void test() { + bar(new Foo<>()); + } + + interface Fun { + R _(T t); + } + + class Foo implements Fun { + @Override + public Integer _(K k) { + return null; + } + } +} diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java index 84e60d5aa03f..e2bebcc97a02 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GraphInferenceHighlightingTest.java @@ -79,6 +79,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase doTest(); } + public void testDefaultConstructorAsArgument() throws Exception { + doTest(); + } + private void doTest() throws Exception { doTest(false); }