mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 13:02:30 +07:00
method refs: add constraint P1->ReferenceType for inexact method references despite of spec (IDEA-117311)
This commit is contained in:
@@ -37,7 +37,7 @@ public class PsiMethodReferenceUtil {
|
||||
|
||||
public static boolean hasReceiver(PsiType[] parameterTypes, QualifierResolveResult qualifierResolveResult, PsiMethodReferenceExpression methodRef) {
|
||||
if (parameterTypes.length > 0 &&
|
||||
isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()) &&
|
||||
isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()) &&
|
||||
isStaticallyReferenced(methodRef)) {
|
||||
return true;
|
||||
}
|
||||
@@ -257,7 +257,6 @@ public class PsiMethodReferenceUtil {
|
||||
}
|
||||
|
||||
public static boolean isReceiverType(PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) {
|
||||
boolean arrayType = receiverType instanceof PsiArrayType;
|
||||
if (containingClass != null) {
|
||||
receiverType = getExpandedType(receiverType, containingClass);
|
||||
}
|
||||
@@ -265,17 +264,15 @@ public class PsiMethodReferenceUtil {
|
||||
final PsiClass receiverClass = resolveResult.getElement();
|
||||
if (receiverClass != null && isReceiverType(receiverClass, containingClass)) {
|
||||
LOG.assertTrue(containingClass != null);
|
||||
return arrayType ||
|
||||
resolveResult.getSubstitutor().equals(psiSubstitutor) ||
|
||||
emptyOrRaw(containingClass, psiSubstitutor) ||
|
||||
emptyOrRaw(receiverClass, resolveResult.getSubstitutor());
|
||||
return emptyOrRaw(containingClass, psiSubstitutor) ||
|
||||
TypeConversionUtil.isAssignable(JavaPsiFacade.getElementFactory(containingClass.getProject()).createType(containingClass, psiSubstitutor), GenericsUtil.eliminateWildcards(receiverType));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean emptyOrRaw(PsiClass containingClass, PsiSubstitutor psiSubstitutor) {
|
||||
return PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor) ||
|
||||
(!containingClass.hasTypeParameters() && psiSubstitutor.getSubstitutionMap().isEmpty());
|
||||
psiSubstitutor.getSubstitutionMap().isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isReceiverType(PsiType functionalInterfaceType, PsiClass containingClass, @Nullable PsiMethod referencedMethod) {
|
||||
|
||||
@@ -20,8 +20,8 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
|
||||
import com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
@@ -81,25 +81,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
}
|
||||
final PsiParameter[] parameters = applicableMember instanceof PsiMethod ? ((PsiMethod)applicableMember).getParameterList().getParameters() : PsiParameter.EMPTY_ARRAY;
|
||||
if (targetParameters.length == parameters.length + 1) {
|
||||
final PsiTypeElement qualifierTypeElement = myExpression.getQualifierType();
|
||||
final PsiExpression qualifierExpression = myExpression.getQualifierExpression();
|
||||
PsiType qualifierType;
|
||||
if (qualifierTypeElement != null) {
|
||||
qualifierType = qualifierTypeElement.getType();
|
||||
}
|
||||
else {
|
||||
LOG.assertTrue(qualifierExpression != null);
|
||||
qualifierType = qualifierExpression.getType();
|
||||
if (qualifierType == null && qualifierExpression instanceof PsiReferenceExpression) {
|
||||
final JavaResolveResult resolveResult = ((PsiReferenceExpression)qualifierExpression).advancedResolve(false);
|
||||
final PsiElement resolve = resolveResult.getElement();
|
||||
if (resolve instanceof PsiClass) {
|
||||
qualifierType = JavaPsiFacade.getElementFactory(resolve.getProject()).createType((PsiClass)resolve, resolveResult.getSubstitutor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constraints.add(new SubtypingConstraint(qualifierType, GenericsUtil.eliminateWildcards(substitutor.substitute(targetParameters[0].getType())), true));
|
||||
specialCase(session, constraints, substitutor, targetParameters);
|
||||
for (int i = 1; i < targetParameters.length; i++) {
|
||||
constraints.add(new TypeCompatibilityConstraint(psiSubstitutor.substitute(parameters[i - 1].getType()), GenericsUtil.eliminateWildcards(substitutor.substitute(targetParameters[i].getType()))));
|
||||
}
|
||||
@@ -184,12 +166,50 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
|
||||
session.initBounds(method.getTypeParameters());
|
||||
session.initBounds(containingClass.getTypeParameters());
|
||||
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (targetParameters.length == parameters.length + 1) {
|
||||
specialCase(session, constraints, substitutor, targetParameters);
|
||||
}
|
||||
constraints.add(new TypeCompatibilityConstraint(returnType, referencedMethodReturnType));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void specialCase(InferenceSession session,
|
||||
List<ConstraintFormula> constraints,
|
||||
PsiSubstitutor substitutor,
|
||||
PsiParameter[] targetParameters) {
|
||||
final PsiTypeElement qualifierTypeElement = myExpression.getQualifierType();
|
||||
final PsiExpression qualifierExpression = myExpression.getQualifierExpression();
|
||||
PsiType qualifierType;
|
||||
if (qualifierTypeElement != null) {
|
||||
qualifierType = qualifierTypeElement.getType();
|
||||
}
|
||||
else {
|
||||
LOG.assertTrue(qualifierExpression != null);
|
||||
qualifierType = qualifierExpression.getType();
|
||||
if (qualifierType == null && qualifierExpression instanceof PsiReferenceExpression) {
|
||||
final JavaResolveResult resolveResult = ((PsiReferenceExpression)qualifierExpression).advancedResolve(false);
|
||||
final PsiElement res = resolveResult.getElement();
|
||||
if (res instanceof PsiClass) {
|
||||
PsiClass containingClass = (PsiClass)res;
|
||||
final boolean isRawSubst = !myExpression.isConstructor() &&
|
||||
PsiTreeUtil.isAncestor(containingClass, myExpression, true) &&
|
||||
PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
|
||||
qualifierType = JavaPsiFacade.getElementFactory(res.getProject()).createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : resolveResult.getSubstitutor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType);
|
||||
if (qualifierClass != null) {
|
||||
session.initBounds(qualifierClass.getTypeParameters());
|
||||
constraints.add(new SubtypingConstraint(qualifierType, GenericsUtil.eliminateWildcards(substitutor.substitute(targetParameters[0].getType())), true));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(PsiSubstitutor substitutor) {
|
||||
myT = substitutor.substitute(myT);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class Box<TBox>
|
||||
{
|
||||
|
||||
public TBox getValue()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
void foo(Stream<Box<String>> stream){
|
||||
List<String> l1 = stream.map(Box<String>::getValue).collect(Collectors.toList());
|
||||
List<String> l2 = stream.map(Box::getValue).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA117311() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user