diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java index 8c02a544804be..b3cd57eb2306b 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java @@ -27,6 +27,7 @@ import javax.swing.*; import java.util.Arrays; +import java.util.List; public class PsiParameterImpl extends JavaStubPsiElement implements PsiParameter { private volatile PsiType myCachedType; @@ -51,29 +52,44 @@ private static PsiType getLambdaParameterType(@NotNull PsiParameter param) { if (parameterIndex > -1) { PsiLambdaExpression lambdaExpression = PsiTreeUtil.getParentOfType(param, PsiLambdaExpression.class); if (lambdaExpression != null) { - PsiType functionalInterfaceType = MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(param, false, - () -> LambdaUtil.getFunctionalInterfaceType(lambdaExpression, true)); - if (functionalInterfaceType == null) { - Ref typeRef = Ref.create(); - // Probably there are several candidates for the functional expression type but all of them have the same parameter type - LambdaUtil.processParentOverloads(lambdaExpression, t -> { - PsiType candidate = getTypeForFunctionalInterfaceType(lambdaExpression, t, parameterIndex); - PsiType prevType = typeRef.get(); - if (prevType == null) { - typeRef.set(candidate); + PsiType type = MethodCandidateInfo.ourOverloadGuard.doPreventingRecursion(param, false, () -> { + PsiElement parent = lambdaExpression.getParent(); + if (parent instanceof PsiExpressionList) { + PsiElement gParent = parent.getParent(); + if (gParent instanceof PsiAnonymousClass) { + gParent = gParent.getParent(); } - else { - if (!(prevType instanceof PsiLambdaParameterType) && !prevType.equals(candidate)) { - typeRef.set(new PsiLambdaParameterType(param)); + List overloadStack = MethodCandidateInfo.ourOverloadGuard.currentStack(); + if (gParent instanceof PsiCall && + (overloadStack.contains(gParent) || overloadStack.contains(lambdaExpression)) + ) { + return null; + } + } + + PsiType functionalInterfaceType = LambdaUtil.getFunctionalInterfaceType(lambdaExpression, true); + if (functionalInterfaceType == null) { + Ref typeRef = Ref.create(); + // Probably there are several candidates for the functional expression type but all of them have the same parameter type + LambdaUtil.processParentOverloads(lambdaExpression, t -> { + PsiType candidate = getTypeForFunctionalInterfaceType(lambdaExpression, t, parameterIndex); + PsiType prevType = typeRef.get(); + if (prevType == null) { + typeRef.set(candidate); } + else { + if (!(prevType instanceof PsiLambdaParameterType) && !prevType.equals(candidate)) { + typeRef.set(new PsiLambdaParameterType(param)); + } + } + }); + if (!typeRef.isNull()) { + return typeRef.get(); } - }); - if (!typeRef.isNull()) { - return typeRef.get(); } - } - PsiType lambdaParameterFromType = getTypeForFunctionalInterfaceType(lambdaExpression, functionalInterfaceType, parameterIndex); - if (lambdaParameterFromType != null) return lambdaParameterFromType; + return getTypeForFunctionalInterfaceType(lambdaExpression, functionalInterfaceType, parameterIndex); + }); + if (type != null) return type; } } } diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java index 348d55b01c3cf..f3e4ff54c66eb 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiNewExpressionImpl.java @@ -209,7 +209,8 @@ public boolean equals(Object obj) { @Override public JavaResolveResult @NotNull [] multiResolve(boolean incompleteCode) { - return (JavaResolveResult[])getConstructorFakeReference().multiResolve(incompleteCode); + ResolveResult[] results = getConstructorFakeReference().multiResolve(incompleteCode); + return results instanceof JavaResolveResult[] ? (JavaResolveResult[])results : JavaResolveResult.EMPTY_ARRAY; } @Override diff --git a/uast/uast-tests/test/org/jetbrains/uast/test/java/JavaUastApiTest.kt b/uast/uast-tests/test/org/jetbrains/uast/test/java/JavaUastApiTest.kt index 42a6a2f6b8fe7..2b69685c5f62b 100644 --- a/uast/uast-tests/test/org/jetbrains/uast/test/java/JavaUastApiTest.kt +++ b/uast/uast-tests/test/org/jetbrains/uast/test/java/JavaUastApiTest.kt @@ -325,4 +325,57 @@ class JavaUastApiTest : AbstractJavaUastTest() { // IDEA-336319: TYPE_USE should not be applicable to UMethod TestCase.assertEquals(0, count) } + + @Test + fun testLambdaFunctionalInterfaceType() { + // IDEA-383770 + val file = myFixture.configureByText( + "MyClass.java", + """ + package com.example + + public class Message { + public int what; + } + + class Looper {} + + class Handler { + public interface Callback { + boolean handleMessage(Message msg); + } + + public Handler() {} + + public Handler(Callback callback) {} + + public Handler(Looper looper) {} + } + + final class MyClass { + public static void foo() { + Handler handler = + new Handler( + msg -> { + switch (msg.what) { + case 1: + return true; + default: + return false; + } + }); + } + } + """.trimIndent() + ) + val uFile = file.toUElementOfType()!! + uFile.accept( + object : AbstractUastVisitor() { + override fun visitLambdaExpression(node: ULambdaExpression): Boolean { + TestCase.assertEquals("com.example.Handler.Callback", node.functionalInterfaceType?.canonicalText) + return super.visitLambdaExpression(node) + } + } + ) + } }