isPertinentToApplicability: check class type parameters if constructor is called with diamonds (IDEA-147619)

This commit is contained in:
Anna Kozlova
2015-11-09 13:46:30 +01:00
parent fc40c1d5ea
commit 289aea179d
3 changed files with 53 additions and 4 deletions

View File

@@ -182,12 +182,13 @@ public class InferenceSession {
private static boolean isPertinentToApplicability(PsiExpression expr, PsiMethod method, PsiType expectedReturnType) {
if (expr instanceof PsiLambdaExpression && ((PsiLambdaExpression)expr).hasFormalParameterTypes() ||
expr instanceof PsiMethodReferenceExpression && ((PsiMethodReferenceExpression)expr).isExact()) {
if (method != null && method.getTypeParameters().length > 0) {
if (method != null) {
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(expr.getParent());
PsiType paramType = null;
if (parent instanceof PsiExpressionList) {
final PsiElement gParent = parent.getParent();
if (gParent instanceof PsiCallExpression && ((PsiCallExpression)gParent).getTypeArgumentList().getTypeParameterElements().length == 0) {
PsiTypeParameterListOwner owner = getTypeParameterOwner(method, gParent);
if (owner != null) {
final int idx = LambdaUtil.getLambdaIdx(((PsiExpressionList)parent), expr);
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (idx > parameters.length - 1) {
@@ -197,7 +198,7 @@ public class InferenceSession {
else {
paramType = parameters[idx].getType();
}
if (isTypeParameterType(method, paramType)) return false;
if (isTypeParameterType(owner, paramType)) return false;
}
}
else if (expectedReturnType != null && parent instanceof PsiLambdaExpression) {
@@ -231,7 +232,30 @@ public class InferenceSession {
return true;
}
private static boolean isTypeParameterType(PsiMethod method, PsiType paramType) {
private static PsiTypeParameterListOwner getTypeParameterOwner(@NotNull PsiMethod method, PsiElement gParent) {
PsiTypeParameterListOwner owner = null;
if (method.getTypeParameters().length > 0 && gParent instanceof PsiCallExpression && ((PsiCallExpression)gParent).getTypeArgumentList().getTypeParameterElements().length == 0) {
owner = method;
}
else if (method.isConstructor() && gParent instanceof PsiNewExpression) {
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null && containingClass.hasTypeParameters()) {
final PsiJavaCodeReferenceElement classReference = ((PsiNewExpression)gParent).getClassOrAnonymousClassReference();
if (classReference != null) {
final PsiReferenceParameterList parameterList = classReference.getParameterList();
if (parameterList != null) {
final PsiTypeElement[] typeElements = parameterList.getTypeParameterElements();
if (typeElements.length == 1 && typeElements[0].getType() instanceof PsiDiamondType) {
owner = containingClass;
}
}
}
}
}
return owner;
}
private static boolean isTypeParameterType(PsiTypeParameterListOwner method, PsiType paramType) {
final PsiClass psiClass = PsiUtil.resolveClassInType(paramType); //accept ellipsis here
if (psiClass instanceof PsiTypeParameter && ((PsiTypeParameter)psiClass).getOwner() == method) return true;
return false;

View File

@@ -0,0 +1,21 @@
import java.util.*;
import java.util.function.UnaryOperator;
class Test {
public static Optional<String> bar(Optional<String> o) {
return null;
}
public <T> D<T> foo(D<T> entries) {
return null;
}
{
D<UnaryOperator<Optional<String>>> registry = foo(new D<>(Test::bar));
}
static class D<V> {
public D(V value) {}
}
}

View File

@@ -315,6 +315,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
doTest();
}
public void testDiamondWithExactMethodReferenceInside() throws Exception {
doTest();
}
private void doTest() throws Exception {
doTest(false);
}