mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
lambda/method refs: more specific according to 15.12.2.5 - prefer private when private type is given/reference when reference type is given
This commit is contained in:
@@ -652,7 +652,7 @@ public class LambdaUtil {
|
||||
final PsiType interfaceReturnType1 = getReturnType(functionalInterfaceIdx, conflict);
|
||||
if (actualParameterTypes[functionalInterfaceIdx] instanceof PsiLambdaExpressionType || actualParameterTypes[functionalInterfaceIdx] instanceof PsiMethodReferenceType) {
|
||||
if (interfaceReturnType != null && interfaceReturnType1 != null && !Comparing.equal(interfaceReturnType, interfaceReturnType1)) {
|
||||
int moreSpecific1 = isMoreSpecific(interfaceReturnType, interfaceReturnType1);
|
||||
int moreSpecific1 = isMoreSpecific(interfaceReturnType, interfaceReturnType1, actualParameterTypes[functionalInterfaceIdx]);
|
||||
if (moreSpecific < 0 && moreSpecific1 > 0 || moreSpecific > 0 && moreSpecific1 < 0) {
|
||||
moreSpecific = 0;
|
||||
break;
|
||||
@@ -676,17 +676,33 @@ public class LambdaUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static int isMoreSpecific(PsiType returnType, PsiType returnType1) {
|
||||
enum TypeKind {
|
||||
PRIMITIVE, REFERENCE, NONE_DETERMINED
|
||||
}
|
||||
|
||||
private static int isMoreSpecific(PsiType returnType, PsiType returnType1, PsiType lambdaType) {
|
||||
if (returnType == PsiType.VOID || returnType1 == PsiType.VOID) return 0;
|
||||
if (returnType instanceof PsiPrimitiveType) {
|
||||
if (!(returnType1 instanceof PsiPrimitiveType)) {
|
||||
return -1;
|
||||
} else {
|
||||
return TypeConversionUtil.isAssignable(returnType, returnType1) ? 1 : -1;
|
||||
TypeKind typeKind = TypeKind.PRIMITIVE;
|
||||
if (lambdaType instanceof PsiLambdaExpressionType) {
|
||||
typeKind = areLambdaReturnExpressionsPrimitive((PsiLambdaExpressionType)lambdaType);
|
||||
} else if (lambdaType instanceof PsiMethodReferenceType) {
|
||||
final PsiElement referencedElement = ((PsiMethodReferenceType)lambdaType).getExpression().resolve();
|
||||
if (referencedElement instanceof PsiMethod && !(((PsiMethod)referencedElement).getReturnType() instanceof PsiPrimitiveType)) {
|
||||
typeKind = TypeKind.REFERENCE;
|
||||
}
|
||||
}
|
||||
if (returnType1 instanceof PsiPrimitiveType) {
|
||||
return 1;
|
||||
if (typeKind != TypeKind.NONE_DETERMINED) {
|
||||
if (returnType instanceof PsiPrimitiveType) {
|
||||
final int moreSpecific = typeKind == TypeKind.PRIMITIVE ? 1 : -1;
|
||||
if (!(returnType1 instanceof PsiPrimitiveType)) {
|
||||
return -moreSpecific;
|
||||
} else {
|
||||
return TypeConversionUtil.isAssignable(returnType, returnType1) ? moreSpecific : -moreSpecific;
|
||||
}
|
||||
}
|
||||
if (returnType1 instanceof PsiPrimitiveType) {
|
||||
return typeKind == TypeKind.PRIMITIVE ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
final PsiClassType.ClassResolveResult r = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(returnType));
|
||||
@@ -728,6 +744,28 @@ public class LambdaUtil {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static TypeKind areLambdaReturnExpressionsPrimitive(PsiLambdaExpressionType lambdaType) {
|
||||
final List<PsiExpression> returnExpressions = getReturnExpressions(lambdaType.getExpression());
|
||||
TypeKind typeKind = TypeKind.NONE_DETERMINED;
|
||||
for (PsiExpression expression : returnExpressions) {
|
||||
final PsiType returnExprType = expression.getType();
|
||||
if (returnExprType instanceof PsiPrimitiveType) {
|
||||
if (typeKind == TypeKind.REFERENCE) {
|
||||
typeKind = TypeKind.NONE_DETERMINED;
|
||||
break;
|
||||
}
|
||||
typeKind = TypeKind.PRIMITIVE;
|
||||
} else {
|
||||
if (typeKind == TypeKind.PRIMITIVE) {
|
||||
typeKind = TypeKind.NONE_DETERMINED;
|
||||
break;
|
||||
}
|
||||
typeKind = TypeKind.REFERENCE;
|
||||
}
|
||||
}
|
||||
return typeKind;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiType getReturnType(int functionalTypeIdx, CandidateInfo method) {
|
||||
final PsiParameter[] methodParameters = ((PsiMethod)method.getElement()).getParameterList().getParameters();
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
class Test {
|
||||
static class Inner {
|
||||
int foo() { return 0; }
|
||||
Integer fooBoxed() { return 0; }
|
||||
}
|
||||
|
||||
void test(Stream<Inner> sp) {
|
||||
IntStream mi = sp.map(Inner::foo);
|
||||
Stream<Integer> mI = sp.map(Inner::fooBoxed);
|
||||
|
||||
IntStream li = sp.map(inner->inner.foo());
|
||||
Stream<Integer> lI = sp.map(inner -> inner.fooBoxed());
|
||||
}
|
||||
|
||||
interface Stream<T> {
|
||||
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
|
||||
IntStream map(IntFunction<? super T> mapper);
|
||||
}
|
||||
|
||||
interface Function<T, R> {
|
||||
public R _(T t);
|
||||
}
|
||||
|
||||
interface IntFunction<T> {
|
||||
public int _(T t);
|
||||
}
|
||||
|
||||
interface IntStream {}
|
||||
}
|
||||
+4
@@ -216,6 +216,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
public void testAmbiguityReturnValueResolution3() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLambdaOnVarargsPlace1() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user