mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
lambda & raw types
This commit is contained in:
@@ -76,6 +76,7 @@ public class LambdaUtil {
|
||||
|
||||
public static boolean isLambdaFullyInferred(PsiLambdaExpression expression, PsiType functionalInterfaceType) {
|
||||
if (expression.getParameterList().getParametersCount() > 0 || getFunctionalInterfaceReturnType(functionalInterfaceType) != PsiType.VOID) { //todo check that void lambdas without params check
|
||||
if (functionalInterfaceType instanceof PsiClassType && ((PsiClassType)functionalInterfaceType).isRaw()) return false;
|
||||
return !dependsOnTypeParams(functionalInterfaceType, expression);
|
||||
}
|
||||
return true;
|
||||
@@ -144,8 +145,8 @@ public class LambdaUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!lambdaFormalType
|
||||
.isAssignableFrom(GenericsUtil.eliminateWildcards(resolveResult.getSubstitutor().substitute(methodSignature.getSubstitutor().substitute(methodParameterType))))) {
|
||||
if (!TypeConversionUtil.erasure(lambdaFormalType)
|
||||
.isAssignableFrom(TypeConversionUtil.erasure(GenericsUtil.eliminateWildcards(resolveResult.getSubstitutor().substitute(methodSignature.getSubstitutor().substitute(methodParameterType)))))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -433,6 +434,9 @@ public class LambdaUtil {
|
||||
final PsiElement gParent = parent.getParent();
|
||||
if (gParent instanceof PsiCallExpression) {
|
||||
myMethod = ((PsiCallExpression)gParent).resolveMethod();
|
||||
if (myMethod != null && PsiTreeUtil.isAncestor(myMethod, expression, false)) {
|
||||
myMethod = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-4
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.source.resolve;
|
||||
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
@@ -186,6 +185,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
PsiType upperBound = PsiType.NULL;
|
||||
if (paramTypes.length > 0) {
|
||||
sortLambdaExpressionsLast(paramTypes, argTypes);
|
||||
boolean rawType = false;
|
||||
boolean nullPassed = false;
|
||||
for (int j = 0; j < argTypes.length; j++) {
|
||||
PsiType argumentType = argTypes[j];
|
||||
if (argumentType == null) continue;
|
||||
@@ -193,6 +194,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
|
||||
PsiType parameterType = paramTypes[j];
|
||||
if (parameterType == null) break;
|
||||
rawType |= parameterType instanceof PsiClassType && ((PsiClassType)parameterType).isRaw();
|
||||
nullPassed |= argumentType == PsiType.NULL;
|
||||
|
||||
if (parameterType instanceof PsiEllipsisType) {
|
||||
parameterType = ((PsiEllipsisType)parameterType).getComponentType();
|
||||
@@ -203,6 +206,7 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
final Pair<PsiType,ConstraintType> currentSubstitution;
|
||||
if (argumentType instanceof PsiLambdaExpressionType) {
|
||||
currentSubstitution = inferSubstitutionFromLambda(typeParameter, (PsiLambdaExpressionType)argumentType, lowerBound);
|
||||
if (rawType && currentSubstitution == FAILED_INFERENCE || nullPassed && currentSubstitution == null) return new Pair<PsiType, ConstraintType>(null, ConstraintType.EQUALS);
|
||||
} else {
|
||||
currentSubstitution = getSubstitutionForTypeParameterConstraint(typeParameter, parameterType,
|
||||
argumentType, true, PsiUtil.getLanguageLevel(typeParameter));
|
||||
@@ -592,7 +596,8 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
if (constraintFromFormalParams != null) return constraintFromFormalParams;
|
||||
|
||||
final PsiParameter[] methodParameters = method.getParameterList().getParameters();
|
||||
final PsiSubstitutor subst = resolveResult.getSubstitutor();
|
||||
final PsiSubstitutor subst =
|
||||
TypeConversionUtil.getSuperClassSubstitutor(method.getContainingClass(), resolveResult.getElement(), resolveResult.getSubstitutor());
|
||||
final boolean methodParamsDependOnTypeParams = methodParamsDependOnTypeParams(lambdaExpression, methodParameters, subst, typeParam);
|
||||
final PsiType returnType = subst.substitute(method.getReturnType());
|
||||
if (returnType != null && returnType != PsiType.VOID) {
|
||||
@@ -891,8 +896,10 @@ public class PsiResolveHelperImpl implements PsiResolveHelper {
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
}
|
||||
final PsiMethod method = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
|
||||
if (method == null || methodParamsDependOnTypeParams((PsiLambdaExpression)expression, method.getParameterList().getParameters(),
|
||||
PsiUtil.resolveGenericsClassInType(functionalInterfaceType).getSubstitutor(), typeParameter)) {
|
||||
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
|
||||
if (method == null || methodParamsDependOnTypeParams((PsiLambdaExpression)expression, method.getParameterList().getParameters(),
|
||||
TypeConversionUtil.getSuperClassSubstitutor(method.getContainingClass(), resolveResult.getElement(), resolveResult.getSubstitutor()), typeParameter)) {
|
||||
return getFailedInferenceConstraint(typeParameter);
|
||||
}
|
||||
}
|
||||
|
||||
+15
-8
@@ -1,14 +1,21 @@
|
||||
class Test <T, U> {
|
||||
class TestData<K> {}
|
||||
interface TerminalOp<L, M> extends IntermediateOp<L, M> {}
|
||||
interface IntermediateOp<L1, M1> { boolean _(L1 l, M1 m);}
|
||||
|
||||
class Test<T, U> {
|
||||
protected U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp<T, U>... ops) {
|
||||
return exerciseOps(data, terminal, (u, v) -> u.equals(v));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class TestData<K> {}
|
||||
interface TerminalOp<L, M> extends IntermediateOp<L, M> {
|
||||
|
||||
class Test1 {
|
||||
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp... ops) {
|
||||
return exerciseOps(data, terminal, (u, v) -> u.equals(v));
|
||||
}
|
||||
interface IntermediateOp<L1, M1> { boolean _(L1 l, M1 m);}
|
||||
}
|
||||
|
||||
}
|
||||
class Test2 {
|
||||
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp<T, U>... ops) {
|
||||
return exerciseOps(data, terminal, (u, v) -> u.equals(v));
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import java.util.*;
|
||||
class TestData<K> {}
|
||||
interface TerminalOp<L, M> extends IntermediateOp<L, M> {}
|
||||
interface IntermediateOp<L1, M1> { boolean _(L1 l, M1 m);}
|
||||
|
||||
|
||||
class Test1 {
|
||||
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp<T, U>... ops) {
|
||||
return exerciseOps(data, (u, v) -> u.equals(v), terminal);
|
||||
}
|
||||
}
|
||||
|
||||
class Test2 {
|
||||
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp... ops) {
|
||||
return exerciseOps(data, <error descr="Cyclic inference">(u, v) -> u.equals(v)</error>, terminal);
|
||||
}
|
||||
}
|
||||
|
||||
class Test3 {
|
||||
interface I<Y> {
|
||||
void m(Y y);
|
||||
}
|
||||
|
||||
static <T> void bar(I<T> i, List<T> l){
|
||||
bar(x -> {}, l);
|
||||
bar(<error descr="Cyclic inference">x -> {}</error>, null);
|
||||
bar((I<T>)x -> {}, null);
|
||||
bar((T x) -> {}, null);
|
||||
bar(x -> {}, new ArrayList<T>());
|
||||
bar(<error descr="Cyclic inference">x -> {}</error>, new ArrayList());
|
||||
}
|
||||
|
||||
static {
|
||||
bar(<error descr="Cyclic inference">x->{}</error>, new ArrayList());
|
||||
}
|
||||
}
|
||||
+4
@@ -92,6 +92,10 @@ public class LambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testLambdaOnVarargPlace() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLambdaRawOrNot() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNoInferenceResult() throws Exception {
|
||||
doTest();
|
||||
|
||||
Reference in New Issue
Block a user