mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 03:21:12 +07:00
java 8: intersection type casts (IDEA-98843)
This commit is contained in:
@@ -116,6 +116,12 @@ public class LambdaUtil {
|
||||
}
|
||||
|
||||
public static boolean isAcceptable(PsiLambdaExpression lambdaExpression, final PsiType leftType, boolean checkReturnType) {
|
||||
if (leftType instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunctType : ((PsiIntersectionType)leftType).getConjuncts()) {
|
||||
if (isAcceptable(lambdaExpression, conjunctType, checkReturnType)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(leftType);
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
if (psiClass instanceof PsiAnonymousClass) {
|
||||
@@ -462,17 +468,16 @@ public class LambdaUtil {
|
||||
if (type == null) {
|
||||
type = getFunctionalInterfaceType(lambdaExpression, false);
|
||||
}
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type);
|
||||
if (resolveResult != null) {
|
||||
final PsiMethod method = getFunctionalInterfaceMethod(type);
|
||||
if (method != null) {
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (parameterIndex < parameters.length) {
|
||||
final PsiType psiType = getSubstitutor(method, resolveResult).substitute(parameters[parameterIndex].getType());
|
||||
if (!dependsOnTypeParams(psiType, type, lambdaExpression, null)) {
|
||||
return GenericsUtil.eliminateWildcards(psiType);
|
||||
}
|
||||
}
|
||||
if (type instanceof PsiIntersectionType) {
|
||||
final PsiType[] conjuncts = ((PsiIntersectionType)type).getConjuncts();
|
||||
for (PsiType conjunct : conjuncts) {
|
||||
final PsiType lambdaParameterFromType = getLambdaParameterFromType(parameterIndex, lambdaExpression, conjunct);
|
||||
if (lambdaParameterFromType != null) return lambdaParameterFromType;
|
||||
}
|
||||
} else {
|
||||
final PsiType lambdaParameterFromType = getLambdaParameterFromType(parameterIndex, lambdaExpression, type);
|
||||
if (lambdaParameterFromType != null) {
|
||||
return lambdaParameterFromType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -485,6 +490,23 @@ public class LambdaUtil {
|
||||
return new PsiLambdaParameterType(param);
|
||||
}
|
||||
|
||||
private static PsiType getLambdaParameterFromType(int parameterIndex, PsiLambdaExpression lambdaExpression, PsiType conjunct) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(conjunct);
|
||||
if (resolveResult != null) {
|
||||
final PsiMethod method = getFunctionalInterfaceMethod(conjunct);
|
||||
if (method != null) {
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (parameterIndex < parameters.length) {
|
||||
final PsiType psiType = getSubstitutor(method, resolveResult).substitute(parameters[parameterIndex].getType());
|
||||
if (!dependsOnTypeParams(psiType, conjunct, lambdaExpression, null)) {
|
||||
return GenericsUtil.eliminateWildcards(psiType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PsiSubstitutor inferFromReturnType(final PsiTypeParameter[] typeParameters,
|
||||
final PsiType returnType,
|
||||
@Nullable final PsiType interfaceMethodReturnType,
|
||||
|
||||
@@ -116,6 +116,12 @@ public class PsiMethodReferenceUtil {
|
||||
|
||||
public static boolean isAcceptable(@Nullable final PsiMethodReferenceExpression methodReferenceExpression, PsiType left) {
|
||||
if (methodReferenceExpression == null) return false;
|
||||
if (left instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType)left).getConjuncts()) {
|
||||
if (isAcceptable(methodReferenceExpression, conjunct)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Map<PsiMethodReferenceExpression, PsiType> map = ourRefs.get();
|
||||
if (map == null) {
|
||||
map = new HashMap<PsiMethodReferenceExpression, PsiType>();
|
||||
|
||||
@@ -667,9 +667,7 @@ public class TypeConversionUtil {
|
||||
|
||||
if (right instanceof PsiMethodReferenceType) {
|
||||
final PsiMethodReferenceExpression methodReferenceExpression = ((PsiMethodReferenceType)right).getExpression();
|
||||
if (left instanceof PsiClassType) {
|
||||
return PsiMethodReferenceUtil.isAcceptable(methodReferenceExpression, (PsiClassType)left);
|
||||
} else if (left instanceof PsiLambdaExpressionType) {
|
||||
if (left instanceof PsiLambdaExpressionType) {
|
||||
final PsiType rType = methodReferenceExpression.getFunctionalInterfaceType();
|
||||
final PsiType lType = ((PsiLambdaExpressionType)left).getExpression().getFunctionalInterfaceType();
|
||||
return Comparing.equal(rType, lType);
|
||||
@@ -678,18 +676,17 @@ public class TypeConversionUtil {
|
||||
final PsiType lType = ((PsiMethodReferenceType)left).getExpression().getFunctionalInterfaceType();
|
||||
return Comparing.equal(rType, lType);
|
||||
}
|
||||
return PsiMethodReferenceUtil.isAcceptable(methodReferenceExpression, left);
|
||||
}
|
||||
if (right instanceof PsiLambdaExpressionType) {
|
||||
final PsiLambdaExpression rLambdaExpression = ((PsiLambdaExpressionType)right).getExpression();
|
||||
if (left instanceof PsiClassType) {
|
||||
return LambdaUtil.isAcceptable(rLambdaExpression, left, false);
|
||||
}
|
||||
if (left instanceof PsiLambdaExpressionType) {
|
||||
final PsiLambdaExpression lLambdaExpression = ((PsiLambdaExpressionType)left).getExpression();
|
||||
final PsiType rType = rLambdaExpression.getFunctionalInterfaceType();
|
||||
final PsiType lType = lLambdaExpression.getFunctionalInterfaceType();
|
||||
return Comparing.equal(rType, lType);
|
||||
}
|
||||
return LambdaUtil.isAcceptable(rLambdaExpression, left, false);
|
||||
}
|
||||
|
||||
if (left instanceof PsiIntersectionType) {
|
||||
|
||||
@@ -105,11 +105,14 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
|
||||
cachedType = componentType.createArrayType();
|
||||
}
|
||||
else {
|
||||
final PsiElement opElement = PsiTreeUtil.skipSiblingsForward(element.getPsi(), PsiWhiteSpace.class);
|
||||
final List<PsiTypeElement> typeElements = PsiTreeUtil.getChildrenOfTypeAsList(this, PsiTypeElement.class);
|
||||
final List<PsiType> types = ContainerUtil.map(typeElements, new Function<PsiTypeElement, PsiType>() {
|
||||
@Override public PsiType fun(final PsiTypeElement psiTypeElement) { return psiTypeElement.getType(); }
|
||||
});
|
||||
cachedType = new PsiDisjunctionType(types, getManager());
|
||||
cachedType = opElement instanceof PsiJavaToken && ((PsiJavaToken)opElement).getTokenType() == JavaTokenType.AND
|
||||
? PsiIntersectionType.createIntersection(types.toArray(new PsiType[types.size()]))
|
||||
: new PsiDisjunctionType(types, getManager());
|
||||
}
|
||||
}
|
||||
else if (elementType == JavaElementType.JAVA_CODE_REFERENCE) {
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
class Test {
|
||||
public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K, V>> foo() {
|
||||
return (Comparator<Map.Entry<K, V>> & Serializable)(c1, c2) -> c1.getKey().compareTo(c2.getKey());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import java.io.Serializable;
|
||||
class Test {
|
||||
{
|
||||
Runnable r = (Runnable & Serializable)Test::new;
|
||||
}
|
||||
}
|
||||
@@ -177,6 +177,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testIntersectionTypeInCast() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
|
||||
}
|
||||
|
||||
@@ -153,6 +153,10 @@ public class MethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
public void testIntersectionTypeInCast() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
private void doTest() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user