mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
lambda: do not accept ? as type argument for return value (IDEA-91369)
This commit is contained in:
@@ -113,13 +113,43 @@ public class LambdaUtil {
|
||||
|
||||
@Nullable
|
||||
public static String checkInterfaceFunctional(PsiType functionalInterfaceType) {
|
||||
final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(functionalInterfaceType);
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
final PsiClass aClass = resolveResult.getElement();
|
||||
if (aClass != null) {
|
||||
if (checkReturnTypeApplicable(resolveResult, aClass)) {
|
||||
return "No instance of type " + functionalInterfaceType.getPresentableText() + " exists so that lambda expression can be type-checked";
|
||||
}
|
||||
return checkInterfaceFunctional(aClass);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static boolean checkReturnTypeApplicable(PsiClassType.ClassResolveResult resolveResult, final PsiClass aClass) {
|
||||
final MethodSignature methodSignature = getFunction(aClass);
|
||||
if (methodSignature == null) return false;
|
||||
|
||||
for (PsiTypeParameter parameter : aClass.getTypeParameters()) {
|
||||
if (parameter.getExtendsListTypes().length == 0) continue;
|
||||
boolean depends = false;
|
||||
final PsiType substitution = resolveResult.getSubstitutor().substitute(parameter);
|
||||
if (substitution instanceof PsiWildcardType && !((PsiWildcardType)substitution).isBounded()) {
|
||||
for (PsiType paramType : methodSignature.getParameterTypes()) {
|
||||
if (depends(paramType, parameter, new TypeParamsChecker((PsiMethod)null, aClass){
|
||||
@Override
|
||||
public boolean startedInference() {
|
||||
return true;
|
||||
}
|
||||
})) {
|
||||
depends = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!depends) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String checkInterfaceFunctional(@NotNull PsiClass psiClass) {
|
||||
if (psiClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
|
||||
|
||||
+22
@@ -40,4 +40,26 @@ class Test1 {
|
||||
}
|
||||
}</error>;
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
interface X<T extends Number> {
|
||||
T foo();
|
||||
}
|
||||
|
||||
{
|
||||
X<?> x = <error descr="No instance of type X<?> exists so that lambda expression can be type-checked">() -> 123</error>;
|
||||
X<? extends Number> x1 = () -> 123;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
interface X<T> {
|
||||
T foo();
|
||||
}
|
||||
|
||||
{
|
||||
X<?> x = () -> 123;
|
||||
}
|
||||
}
|
||||
+4
-1
@@ -173,7 +173,10 @@ public class ReplaceLambdaWithAnonymousIntention extends Intention {
|
||||
if (disabled[0]) return false;
|
||||
}
|
||||
final PsiType functionalInterfaceType = lambdaExpression.getFunctionalInterfaceType();
|
||||
return functionalInterfaceType != null && LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null && LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType);
|
||||
return functionalInterfaceType != null &&
|
||||
LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType) != null &&
|
||||
LambdaUtil.isLambdaFullyInferred(lambdaExpression, functionalInterfaceType) &&
|
||||
LambdaUtil.checkInterfaceFunctional(functionalInterfaceType) == null;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user