method reference: exact reference check fixed for methods with the signatures without generics (IDEA-127765)

This commit is contained in:
Anna Kozlova
2014-08-05 16:11:14 +02:00
parent a1fbb53c78
commit 313125533c
4 changed files with 60 additions and 23 deletions

View File

@@ -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());
}
}

View File

@@ -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;
}
}
}

View File

@@ -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;
}
}

View File

@@ -106,6 +106,10 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
doTest();
}
public void testIDEA127765() throws Exception {
doTest();
}
private void doTest() {
doTest(false);
}