method refs: missed super class substitution (IDEA-126969)

This commit is contained in:
Anna Kozlova
2014-07-16 14:33:51 +02:00
parent f17f398f24
commit 7d19e0e85e
5 changed files with 47 additions and 5 deletions

View File

@@ -44,7 +44,15 @@ public class PsiMethodReferenceUtil {
public static String checkReturnType(PsiMethodReferenceExpression expression, JavaResolveResult result, PsiType functionalInterfaceType) {
final PsiElement resolve = result.getElement();
if (resolve instanceof PsiMethod) {
final PsiClass containingClass = ((PsiMethod)resolve).getContainingClass();
LOG.assertTrue(containingClass != null);
PsiSubstitutor subst = result.getSubstitutor();
PsiClass qContainingClass = getQualifierResolveResult(expression).getContainingClass();
if (qContainingClass != null && InheritanceUtil.isInheritorOrSelf(qContainingClass, containingClass, true)) {
subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst);
LOG.assertTrue(subst != null);
}
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
@@ -57,7 +65,7 @@ public class PsiMethodReferenceUtil {
PsiType methodReturnType = subst.substitute(returnType);
if (interfaceReturnType != null && interfaceReturnType != PsiType.VOID) {
if (methodReturnType == null) {
methodReturnType = JavaPsiFacade.getElementFactory(expression.getProject()).createType(((PsiMethod)resolve).getContainingClass(), subst);
methodReturnType = JavaPsiFacade.getElementFactory(expression.getProject()).createType(containingClass, subst);
}
if (!TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType, false)) {
return "Bad return type in method reference: cannot convert " + methodReturnType.getCanonicalText() + " to " + interfaceReturnType.getCanonicalText();

View File

@@ -21,6 +21,7 @@ import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfacePa
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -60,6 +61,10 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiType interfaceMethodReturnType = interfaceMethod.getReturnType();
final PsiType returnType = substitutor.substitute(interfaceMethodReturnType);
final PsiType[] typeParameters = myExpression.getTypeParameters();
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(myExpression);
PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
if (!myExpression.isExact()) {
for (PsiParameter parameter : targetParameters) {
if (!session.isProperType(substitutor.substitute(parameter.getType()))) {
@@ -70,11 +75,9 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiMember applicableMember = myExpression.getPotentiallyApplicableMember();
LOG.assertTrue(applicableMember != null);
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(myExpression);
final PsiClass applicableMemberContainingClass = applicableMember.getContainingClass();
final PsiClass containingClass = qualifierResolveResult.getContainingClass();
PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
psiSubstitutor = applicableMemberContainingClass == null || containingClass == null || myExpression.isConstructor()
? psiSubstitutor
: TypeConversionUtil.getSuperClassSubstitutor(applicableMemberContainingClass, containingClass, psiSubstitutor);
@@ -143,6 +146,13 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
final PsiType referencedMethodReturnType;
final PsiClass containingClass = method.getContainingClass();
LOG.assertTrue(containingClass != null, method);
PsiClass qContainingClass = qualifierResolveResult.getContainingClass();
if (qContainingClass != null && InheritanceUtil.isInheritorOrSelf(qContainingClass, containingClass, true)) {
psiSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, PsiSubstitutor.EMPTY);
LOG.assertTrue(psiSubstitutor != null);
}
if (method.isConstructor()) {
referencedMethodReturnType = JavaPsiFacade.getElementFactory(method.getProject()).createType(containingClass, PsiSubstitutor.EMPTY);
}
@@ -179,7 +189,6 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
}
int idx = 0;
PsiSubstitutor psiSubstitutor = PsiSubstitutor.EMPTY;
for (PsiTypeParameter param : method.getTypeParameters()) {
if (idx < typeParameters.length) {
psiSubstitutor = psiSubstitutor.put(param, typeParameters[idx++]);

View File

@@ -434,7 +434,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
return true;
}
final PsiSubstitutor subst = result.getSubstitutor();
PsiSubstitutor subst = result.getSubstitutor();
PsiType methodReturnType = null;
PsiClass containingClass = null;
@@ -451,6 +451,12 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
return false;
}
PsiClass qContainingClass = PsiMethodReferenceUtil.getQualifierResolveResult(this).getContainingClass();
if (qContainingClass != null && containingClass != null && InheritanceUtil.isInheritorOrSelf(qContainingClass, containingClass, true)) {
subst = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, subst);
LOG.assertTrue(subst != null);
}
methodReturnType = subst.substitute(returnType);
}
else if (resolve instanceof PsiClass) {

View File

@@ -0,0 +1,15 @@
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
class IDEA126969 {
void foo(final Stream<List<Integer>> stream) {
stream.flatMap(List::stream)
.forEach(i -> System.out.println(i.floatValue()));
stream.flatMap(Collection::stream)
.forEach(i -> System.out.println(i.floatValue()));
}
}

View File

@@ -273,6 +273,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testIDEA126969() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}