java 8: accept diamonds in method calls

(cherry picked from commit 08397e08d34121af89e37901453ea786b3c8612e)
This commit is contained in:
Anna Kozlova
2014-03-12 10:16:46 +01:00
parent 4112118f42
commit 144684ba22
5 changed files with 63 additions and 15 deletions
@@ -18,14 +18,15 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightClassUtil;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.filters.getters.ExpectedTypesGetter;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.statistics.JavaStatisticsManager;
import com.intellij.psi.statistics.StatisticsInfo;
import com.intellij.psi.statistics.StatisticsManager;
@@ -169,7 +170,7 @@ public class JavaInheritorsGetter extends CompletionProvider<CompletionParameter
final PsiDiamondTypeImpl.DiamondInferenceResult inferenceResult = PsiDiamondTypeImpl.resolveInferredTypes(initializer);
if (inferenceResult.getErrorMessage() == null &&
!psiClass.hasModifierProperty(PsiModifier.ABSTRACT) &&
areInferredTypesApplicable(inferenceResult.getTypes(), parameters.getOriginalPosition())) {
areInferredTypesApplicable(inferenceResult.getTypes(), parameters.getPosition())) {
psiType = initializer.getType();
}
}
@@ -186,18 +187,36 @@ public class JavaInheritorsGetter extends CompletionProvider<CompletionParameter
return LookupElementDecorator.withInsertHandler(item, myConstructorInsertHandler);
}
private static boolean areInferredTypesApplicable(@NotNull PsiType[] types, PsiElement originalPosition) {
final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(originalPosition, PsiMethodCallExpression.class);
private static boolean areInferredTypesApplicable(@NotNull PsiType[] types, PsiElement position) {
final PsiMethodCallExpression methodCallExpression = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class);
if (methodCallExpression != null) {
final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(originalPosition, PsiNewExpression.class);
if (newExpression != null && ArrayUtil.find(methodCallExpression.getArgumentList().getExpressions(), newExpression) > -1 ||
Comparing.equal(originalPosition.getParent(), methodCallExpression.getArgumentList())) {
final JavaResolveResult resolveResult = methodCallExpression.resolveMethodGenerics();
final PsiMethod method = (PsiMethod)resolveResult.getElement();
return method == null ||
PsiUtil.getApplicabilityLevel(method, resolveResult.getSubstitutor(), types, PsiUtil.getLanguageLevel(originalPosition))
!= MethodCandidateInfo.ApplicabilityLevel.NOT_APPLICABLE;
if (PsiUtil.isLanguageLevel8OrHigher(methodCallExpression)) {
final PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(position, PsiNewExpression.class, false);
if (newExpression != null) {
PsiElement parent = newExpression;
while (parent.getParent() instanceof PsiParenthesizedExpression) {
parent = parent.getParent();
}
final int idx = ArrayUtil.find(methodCallExpression.getArgumentList().getExpressions(), parent);
if (idx > -1) {
final JavaResolveResult resolveResult = methodCallExpression.resolveMethodGenerics();
final PsiMethod method = (PsiMethod)resolveResult.getElement();
if (method != null) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (idx < parameters.length) {
final PsiType expectedType = resolveResult.getSubstitutor().substitute(parameters[idx].getType());
final PsiClass aClass = PsiUtil.resolveClassInType(expectedType);
if (aClass != null) {
final PsiClassType inferredArg = JavaPsiFacade.getElementFactory(method.getProject()).createType(aClass, types);
LOG.assertTrue(expectedType != null);
return TypeConversionUtil.isAssignable(expectedType, inferredArg);
}
}
}
}
}
}
return false;
}
return true;
}
@@ -0,0 +1,12 @@
class A<T> {
A(T... t) {
}
{
bar(new A<>(<caret>) );
}
<T> void bar(A<T> s) {}
}
@@ -0,0 +1,12 @@
class A<T> {
A(T... t) {
}
{
bar(new <caret> );
}
<T> void bar(A<T> s) {}
}
@@ -35,7 +35,7 @@ public class SmartType17CompletionTest extends LightFixtureCompletionTestCase {
@NotNull
@Override
protected LightProjectDescriptor getProjectDescriptor() {
return JAVA_LATEST;
return JAVA_1_7;
}
public void testDiamondCollapsed() throws Exception {
@@ -96,6 +96,11 @@ public class SmartType18CompletionTest extends LightFixtureCompletionTestCase {
}
}
public void testDiamondsInsideMethodCall() throws Exception {
configureByFile("/" + getTestName(false) + ".java");
checkResultByFile("/" + getTestName(false) + "-out.java");
}
private void doTest() {
configureByFile("/" + getTestName(false) + ".java");
assertNotNull(myItems);