fix intersection types in receiver position (IDEA-144472)

This commit is contained in:
Anna Kozlova
2015-08-31 16:20:21 +03:00
parent b73923096d
commit 2df4481722
4 changed files with 51 additions and 15 deletions

View File

@@ -1290,10 +1290,9 @@ public class InferenceSession {
// the type to search is the result of capture conversion (5.1.10) applied to T;
// otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference.
if (PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor)) {
final PsiClassType.ClassResolveResult pResult = PsiUtil.resolveGenericsClassInType(PsiImplUtil.normalizeWildcardTypeByPosition(pType, (PsiExpression)myContext));
final PsiClass pClass = pResult.getElement();
final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil
.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null;
PsiType normalizedPType = PsiImplUtil.normalizeWildcardTypeByPosition(pType, (PsiExpression)myContext);
final PsiSubstitutor receiverSubstitutor = PsiMethodReferenceCompatibilityConstraint
.getParameterizedTypeSubstitutor(containingClass, normalizedPType);
if (receiverSubstitutor != null) {
if (!method.hasTypeParameters()) {
if (signature.getParameterTypes().length == 1 || PsiUtil.isRawSubstitutor(containingClass, receiverSubstitutor)) {

View File

@@ -22,10 +22,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.MethodSignature;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.util.*;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
@@ -219,13 +216,8 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
// otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference.
if ( PsiUtil.isRawSubstitutor(qContainingClass, psiSubstitutor)) {
if (member instanceof PsiMethod && PsiMethodReferenceUtil.isSecondSearchPossible(signature.getParameterTypes(), qualifierResolveResult, myExpression)) {
final PsiType pType = signature.getParameterTypes()[0];
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(
PsiImplUtil.normalizeWildcardTypeByPosition(pType, myExpression));
PsiClass paramClass = resolveResult.getElement();
LOG.assertTrue(paramClass != null);
psiSubstitutor = TypeConversionUtil.getClassSubstitutor(qContainingClass, paramClass, resolveResult.getSubstitutor());
LOG.assertTrue(psiSubstitutor != null);
final PsiType pType = PsiImplUtil.normalizeWildcardTypeByPosition(signature.getParameterTypes()[0], myExpression);
psiSubstitutor = getParameterizedTypeSubstitutor(qContainingClass, pType);
}
else if (member instanceof PsiMethod && ((PsiMethod)member).isConstructor() || member instanceof PsiClass) {
//15.13.1
@@ -253,6 +245,24 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
return psiSubstitutor;
}
public static PsiSubstitutor getParameterizedTypeSubstitutor(PsiClass qContainingClass, PsiType pType) {
if (pType instanceof PsiIntersectionType) {
for (PsiType type : ((PsiIntersectionType)pType).getConjuncts()) {
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type);
if (InheritanceUtil.isInheritorOrSelf(resolveResult.getElement(), qContainingClass, true)) {
return getParameterizedTypeSubstitutor(qContainingClass, type);
}
}
}
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(pType);
PsiClass paramClass = resolveResult.getElement();
LOG.assertTrue(paramClass != null);
PsiSubstitutor psiSubstitutor = TypeConversionUtil.getClassSubstitutor(qContainingClass, paramClass, resolveResult.getSubstitutor());
LOG.assertTrue(psiSubstitutor != null);
return psiSubstitutor;
}
@Override
public void apply(PsiSubstitutor substitutor, boolean cache) {
myT = substitutor.substitute(myT);

View File

@@ -0,0 +1,23 @@
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
abstract class Constraint<ConstraintType extends Constraint<ConstraintType>> {
protected abstract Stream<Event> evStream();
private void foo(final Set<CConstraint> ctrlSTCs,
final Set<BConstraint> probCstrs) {
ArrayList<Event> a = new ArrayList<Event>(Stream
.concat(ctrlSTCs.stream(), probCstrs.stream())
.flatMap(Constraint::evStream)
.collect(Collectors.toSet()));
}
private abstract class CConstraint extends Constraint<CConstraint> implements I {}
private abstract class BConstraint extends Constraint<BConstraint> implements I {}
interface I {}
interface Event {}
}

View File

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