mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-20 13:31:28 +07:00
method reference: exact reference check fixed for methods with the signatures without generics (IDEA-127765)
This commit is contained in:
@@ -91,7 +91,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) {
|
||||
specialCase(session, constraints, substitutor, targetParameters);
|
||||
specialCase(session, constraints, substitutor, targetParameters, true);
|
||||
for (int i = 1; i < targetParameters.length; i++) {
|
||||
constraints.add(new TypeCompatibilityConstraint(psiSubstitutor.substitute(parameters[i - 1].getType()), substitutor.substitute(targetParameters[i].getType())));
|
||||
}
|
||||
@@ -198,7 +198,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (targetParameters.length == parameters.length + 1 && !method.isVarArgs() &&
|
||||
PsiPolyExpressionUtil.mentionsTypeParameters(referencedMethodReturnType, ContainerUtil.newHashSet(containingClass.getTypeParameters()))) { //todo specification bug?
|
||||
specialCase(session, constraints, substitutor, targetParameters);
|
||||
specialCase(session, constraints, substitutor, targetParameters, false);
|
||||
}
|
||||
constraints.add(new TypeCompatibilityConstraint(returnType, psiSubstitutor.substitute(referencedMethodReturnType)));
|
||||
}
|
||||
@@ -209,7 +209,8 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
private void specialCase(InferenceSession session,
|
||||
List<ConstraintFormula> constraints,
|
||||
PsiSubstitutor substitutor,
|
||||
PsiParameter[] targetParameters) {
|
||||
PsiParameter[] targetParameters,
|
||||
boolean ignoreRaw) {
|
||||
final PsiElement qualifier = myExpression.getQualifier();
|
||||
PsiType qualifierType = null;
|
||||
if (qualifier instanceof PsiTypeElement) {
|
||||
@@ -226,8 +227,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
final PsiElement res = resolveResult.getElement();
|
||||
if (res instanceof PsiClass) {
|
||||
PsiClass containingClass = (PsiClass)res;
|
||||
final boolean isRawSubst = !myExpression.isConstructor() &&
|
||||
PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
|
||||
final boolean isRawSubst = !ignoreRaw && !myExpression.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
|
||||
qualifierType = JavaPsiFacade.getElementFactory(res.getProject()).createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : resolveResult.getSubstitutor());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.psi.impl.PsiManagerEx;
|
||||
import com.intellij.psi.impl.source.resolve.ResolveCache;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
|
||||
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.ChildRole;
|
||||
import com.intellij.psi.impl.source.tree.FileElement;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
@@ -39,13 +40,12 @@ import com.intellij.psi.scope.util.PsiScopesUtil;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase implements PsiMethodReferenceExpression {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl");
|
||||
@@ -153,7 +153,8 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
if (arrayClass == containingClass) {
|
||||
final PsiType componentType = qualifierResolveResult.getSubstitutor().substitute(arrayClass.getTypeParameters()[0]);
|
||||
LOG.assertTrue(componentType != null, qualifierResolveResult.getSubstitutor());
|
||||
methods = new PsiMethod[] {factory.createMethodFromText("public " + componentType.createArrayType().getCanonicalText() + " __array__(int i) {return null;}", this)};
|
||||
//15.13.1 A method reference expression of the form ArrayType :: new is always exact.
|
||||
return factory.createMethodFromText("public " + componentType.createArrayType().getCanonicalText() + " __array__(int i) {return null;}", this);
|
||||
} else {
|
||||
methods = containingClass.getConstructors();
|
||||
}
|
||||
@@ -172,25 +173,38 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
if (psiMethod.getTypeParameters().length > 0) {
|
||||
final PsiReferenceParameterList parameterList = getParameterList();
|
||||
return parameterList != null && parameterList.getTypeParameterElements().length > 0 ? psiMethod : null;
|
||||
}
|
||||
}
|
||||
if (containingClass.isPhysical() && containingClass.hasTypeParameters()) {
|
||||
final PsiElement qualifier = getQualifier();
|
||||
if (qualifier instanceof PsiTypeElement) {
|
||||
final PsiJavaCodeReferenceElement referenceElement = ((PsiTypeElement)qualifier).getInnermostComponentReferenceElement();
|
||||
if (referenceElement != null) {
|
||||
final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
|
||||
if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
|
||||
return null;
|
||||
} else {
|
||||
final PsiSubstitutor classSubstitutor = TypeConversionUtil.getClassSubstitutor(psiMethod.getContainingClass(), containingClass, PsiSubstitutor.EMPTY);
|
||||
final Set<PsiType> signature = new HashSet<PsiType>(Arrays.asList(psiMethod.getSignature(PsiSubstitutor.EMPTY).getParameterTypes()));
|
||||
signature.add(psiMethod.getReturnType());
|
||||
boolean free = true;
|
||||
for (PsiType type : signature) {
|
||||
if (classSubstitutor != null) {
|
||||
type = classSubstitutor.substitute(type);
|
||||
}
|
||||
if (type != null && PsiPolyExpressionUtil.mentionsTypeParameters(type, ContainerUtil.newHashSet(containingClass.getTypeParameters()))) {
|
||||
free = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (free) return psiMethod;
|
||||
}
|
||||
}
|
||||
if (containingClass.hasTypeParameters()) {
|
||||
final PsiElement qualifier = getQualifier();
|
||||
PsiJavaCodeReferenceElement referenceElement = null;
|
||||
if (qualifier instanceof PsiTypeElement) {
|
||||
referenceElement = ((PsiTypeElement)qualifier).getInnermostComponentReferenceElement();
|
||||
} else if (qualifier instanceof PsiReferenceExpression) {
|
||||
final PsiReferenceExpression expression = (PsiReferenceExpression)qualifier;
|
||||
if (qualifierResolveResult.isReferenceTypeQualified()) {
|
||||
final PsiReferenceParameterList parameterList = expression.getParameterList();
|
||||
if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
|
||||
return null;
|
||||
}
|
||||
referenceElement = expression;
|
||||
}
|
||||
}
|
||||
if (referenceElement != null) {
|
||||
final PsiReferenceParameterList parameterList = referenceElement.getParameterList();
|
||||
if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
class IDEA127765 {
|
||||
void a(final Map<String, Optional<Double>> allValues, final Function<Optional<Double>, Double> get) {
|
||||
final Map<String, Double> presentValues = transformValues(filterValues(allValues, Optional::isPresent), get);
|
||||
}
|
||||
|
||||
public static <K, V1, V2> Map<K, V2> transformValues(Map<K, V1> fromMap, Function<? super V1, V2> function) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <K, V> Map<K, V> filterValues(Map<K, V> unfiltered, Predicate<? super V> valuePredicate) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -106,6 +106,10 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIDEA127765() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user