mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java] [inference]: avoid recursion guards in clients as they may prevent engine code to complete normally (IDEA-268120)
here highlighting got guarded and inference was unable to walk up to the containing call and failed because of that. Guard is needed for the case when the same code may be invoked *during* inference itself, corresponding guard exists already and mentioned in javadoc GitOrigin-RevId: bdb8ba5056884d1b6869bd0d31c8482f77adb3a7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f379784ad1
commit
e287fd7576
+1
-1
@@ -1625,7 +1625,7 @@ public final class HighlightUtil {
|
||||
PsiType switchExpressionType = switchExpression.getType();
|
||||
if (switchExpressionType != null) {
|
||||
for (PsiExpression expression : PsiUtil.getSwitchResultExpressions(switchExpression)) {
|
||||
final PsiType expressionType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, true, expression::getType);
|
||||
final PsiType expressionType = expression.getType();
|
||||
if (expressionType != null && !switchExpressionType.isAssignableFrom(expressionType)) {
|
||||
String text = JavaErrorBundle
|
||||
.message("bad.type.in.switch.expression", expressionType.getCanonicalText(), switchExpressionType.getCanonicalText());
|
||||
|
||||
+1
-1
@@ -116,7 +116,7 @@ public class AdjustFunctionContextFix extends LocalQuickFixAndIntentionActionOnP
|
||||
PsiMethodReferenceExpression methodRef = (PsiMethodReferenceExpression)expression;
|
||||
actualReturnType = PsiMethodReferenceUtil.getMethodReferenceReturnType(methodRef);
|
||||
} else {
|
||||
actualReturnType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, true, () -> expression.getType());
|
||||
actualReturnType = expression.getType();
|
||||
}
|
||||
String targetMethodName = remapper.apply(actualReturnType);
|
||||
if (targetMethodName == null) return null;
|
||||
|
||||
@@ -640,6 +640,14 @@ public final class LambdaUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If called to check applicability or anything which may be required to determine type, outer caching prevention is required
|
||||
* For example, {@link com.intellij.psi.impl.source.tree.java.PsiLambdaExpressionImpl#isAcceptable(PsiType, PsiMethod)}:
|
||||
* {@code return LambdaUtil.performWithTargetType(this, leftType, () ->
|
||||
* LambdaUtil.checkReturnTypeCompatible(this, substitutor.substitute(methodReturnType)) == null);}
|
||||
*
|
||||
* otherwise calls to {@code expr#getType()} inside the method may lead to infinite recursion
|
||||
*/
|
||||
public static Map<PsiElement, @Nls String> checkReturnTypeCompatible(PsiLambdaExpression lambdaExpression, PsiType functionalInterfaceReturnType) {
|
||||
Map<PsiElement, @Nls String> errors = new LinkedHashMap<>();
|
||||
if (PsiType.VOID.equals(functionalInterfaceReturnType)) {
|
||||
@@ -669,7 +677,7 @@ public final class LambdaUtil {
|
||||
else if (functionalInterfaceReturnType != null) {
|
||||
final List<PsiExpression> returnExpressions = getReturnExpressions(lambdaExpression);
|
||||
for (final PsiExpression expression : returnExpressions) {
|
||||
final PsiType expressionType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(expression, true, expression::getType);
|
||||
final PsiType expressionType = expression.getType();
|
||||
if (expressionType != null && !functionalInterfaceReturnType.isAssignableFrom(expressionType)) {
|
||||
errors.put(expression, JavaPsiBundle.message("bad.return.type.in.lambda.expression", expressionType.getPresentableText(),
|
||||
functionalInterfaceReturnType.getPresentableText()));
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import java.util.function.Function;
|
||||
|
||||
|
||||
class MyTest {
|
||||
void m(Try<String> t) {
|
||||
t.andThen(v -> fa<caret>il());
|
||||
}
|
||||
|
||||
private static <V> V fail() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
interface Try<K> {
|
||||
<U> void andThen(Function<K, Try<U>> function);
|
||||
}
|
||||
+22
@@ -24,9 +24,14 @@ import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.infos.MethodCandidateInfo;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
|
||||
@NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/expressions";
|
||||
|
||||
@@ -38,6 +43,23 @@ public class Java8ExpressionsCheckTest extends LightDaemonAnalyzerTestCase {
|
||||
doTestAllMethodCallExpressions();
|
||||
}
|
||||
|
||||
public void testNestedLambdaReturnTypeCheck() {
|
||||
configure();
|
||||
PsiMethodCallExpression
|
||||
call = PsiTreeUtil.getParentOfType(getFile().findElementAt(getEditor().getCaretModel().getOffset()), PsiMethodCallExpression.class);
|
||||
@Nullable PsiLambdaExpression lambda = PsiTreeUtil.getParentOfType(call, PsiLambdaExpression.class);
|
||||
|
||||
PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(lambda.getFunctionalInterfaceType());
|
||||
Map<PsiElement, @Nls String> errors = LambdaUtil.checkReturnTypeCompatible(lambda, interfaceReturnType);
|
||||
if (errors != null) {
|
||||
fail(StreamEx.of(errors.values()).joining(", "));
|
||||
}
|
||||
|
||||
PsiType type = call.getType();
|
||||
assertNotNull(type);
|
||||
assertFalse(type.getPresentableText(), type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT));
|
||||
}
|
||||
|
||||
public void testForbidCachingForAllQualifiersWhenDependOnThreadLocalTypes() {
|
||||
configure();
|
||||
PsiMethodCallExpression getKeyCall =
|
||||
|
||||
Reference in New Issue
Block a user