From eb74d4313954c3436d4f0f49197efe3cf4660c55 Mon Sep 17 00:00:00 2001 From: peter Date: Mon, 26 Sep 2011 13:49:15 +0200 Subject: [PATCH] better type inference for smart completing nested generic method call arguments (IDEA-74749) --- .../source/resolve/PsiResolveHelperImpl.java | 31 +++++++++++++------ .../smartType/AssertThatMatcher-out.java | 13 ++++++++ .../smartType/AssertThatMatcher.java | 13 ++++++++ .../completion/SmartTypeCompletionTest.java | 1 + 4 files changed, 49 insertions(+), 9 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/AssertThatMatcher-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/smartType/AssertThatMatcher.java diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java index f0f9e54fbc9f..dc09609e6062 100644 --- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/PsiResolveHelperImpl.java @@ -24,6 +24,7 @@ import com.intellij.openapi.util.RecursionManager; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.*; import com.intellij.psi.infos.CandidateInfo; +import com.intellij.psi.infos.MethodCandidateInfo; import com.intellij.psi.scope.MethodProcessorSetupFailedException; import com.intellij.psi.scope.processor.MethodCandidatesProcessor; import com.intellij.psi.scope.processor.MethodResolverProcessor; @@ -37,6 +38,9 @@ import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; +import java.util.List; + public class PsiResolveHelperImpl implements PsiResolveHelper { private static final RecursionGuard ourGuard = RecursionManager.createGuard("typeArgInference"); private final PsiManager myManager; @@ -743,7 +747,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { try { //can't call resolve() since it obtains full substitution, that may result in infinite recursion PsiScopesUtil.setupAndRunProcessor(processor, contextCall, false); - int i = ArrayUtil.find(expressionList.getExpressions(), innerMethodCall); + PsiExpression[] expressions = expressionList.getExpressions(); + int i = ArrayUtil.find(expressions, innerMethodCall); assert i >= 0; final JavaResolveResult[] results = processor.getResult(); PsiMethod owner = (PsiMethod)typeParameter.getOwner(); @@ -751,6 +756,14 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { final PsiType innerReturnType = owner.getReturnType(); for (final JavaResolveResult result : results) { + final PsiSubstitutor substitutor; + if (result instanceof MethodCandidateInfo) { + List leftArgs = Arrays.asList(expressions).subList(0, i); + substitutor = ((MethodCandidateInfo)result).inferTypeArguments(true, leftArgs.toArray(new PsiExpression[leftArgs.size()])); + } else { + substitutor = result.getSubstitutor(); + } + final PsiElement element = result.getElement(); if (element instanceof PsiMethod) { final PsiMethod method = (PsiMethod)element; @@ -764,15 +777,15 @@ public class PsiResolveHelperImpl implements PsiResolveHelper { } if (parameter != null) { final PsiParameter finalParameter = parameter; - PsiType type = ourGuard - .doPreventingRecursion(innerMethodCall, true, new Computable() { - @Override - public PsiType compute() { - return result.getSubstitutor().substitute(finalParameter.getType()); - } - }) ; + PsiType type = ourGuard.doPreventingRecursion(innerMethodCall, true, new Computable() { + @Override + public PsiType compute() { + return substitutor.substitute(finalParameter.getType()); + } + }); final Pair constraint = - getSubstitutionForTypeParameterConstraint(typeParameter, innerReturnType, type, false, PsiUtil.getLanguageLevel(innerMethodCall)); + getSubstitutionForTypeParameterConstraint(typeParameter, innerReturnType, type, false, + PsiUtil.getLanguageLevel(innerMethodCall)); if (constraint != null) return constraint; } } diff --git a/java/java-tests/testData/codeInsight/completion/smartType/AssertThatMatcher-out.java b/java/java-tests/testData/codeInsight/completion/smartType/AssertThatMatcher-out.java new file mode 100644 index 000000000000..fe57795e7d1e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/AssertThatMatcher-out.java @@ -0,0 +1,13 @@ +import java.util.List; + +public class Zoo2 { + void assertThat(T t, List tt) { } + List wrap(T t) { } + + public void main(String[] args) { + assertThat(args, wrap(args)); + } + +} + + diff --git a/java/java-tests/testData/codeInsight/completion/smartType/AssertThatMatcher.java b/java/java-tests/testData/codeInsight/completion/smartType/AssertThatMatcher.java new file mode 100644 index 000000000000..149254e0a2ff --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/smartType/AssertThatMatcher.java @@ -0,0 +1,13 @@ +import java.util.List; + +public class Zoo2 { + void assertThat(T t, List tt) { } + List wrap(T t) { } + + public void main(String[] args) { + assertThat(args, wrap()); + } + +} + + diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java index 6503a6fcd151..578d1d29439b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java @@ -958,6 +958,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase { public void testPrimitiveArrayClassInMethod() throws Throwable { doTest(); } public void testPrimitiveClassInAnno() throws Throwable { doTest(); } public void testNewInnerClassOfSuper() throws Throwable { doTest(); } + public void testAssertThatMatcher() throws Throwable { doTest(); } public void testInferFromCall() throws Throwable { doTest();