diff --git a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt index cb8b02d57d9..bf3883916b0 100644 --- a/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt +++ b/compiler/fir/lightTree/src/org/jetbrains/kotlin/fir/lightTree/converter/ExpressionsConverter.kt @@ -440,17 +440,29 @@ class ExpressionsConverter( val valueArguments = mutableListOf() var additionalArgument: FirExpression? = null var hasArguments = false - callSuffix.forEachChildren { - when (it.tokenType) { - REFERENCE_EXPRESSION -> name = it.asText - TYPE_ARGUMENT_LIST -> firTypeArguments += declarationsConverter.convertTypeArguments(it) - VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> { - hasArguments = true - valueArguments += it + callSuffix.forEachChildren { child -> + fun process(node: LighterASTNode) { + when (node.tokenType) { + REFERENCE_EXPRESSION -> { + name = node.asText + } + PARENTHESIZED -> node.getExpressionInParentheses()?.let { process(it) } ?: run { + additionalArgument = getAsFirExpression(node, "Incorrect invoke receiver") + } + TYPE_ARGUMENT_LIST -> { + firTypeArguments += declarationsConverter.convertTypeArguments(node) + } + VALUE_ARGUMENT_LIST, LAMBDA_ARGUMENT -> { + hasArguments = true + valueArguments += node + } + else -> if (node.tokenType != TokenType.ERROR_ELEMENT) { + additionalArgument = getAsFirExpression(node, "Incorrect invoke receiver") + } } - else -> if (it.tokenType != TokenType.ERROR_ELEMENT) additionalArgument = - getAsFirExpression(it, "Incorrect invoke receiver") } + + process(child) } val (calleeReference, explicitReceiver) = when { diff --git a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/LightTree2FirConverterTestCaseGenerated.java b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/LightTree2FirConverterTestCaseGenerated.java index 9b1990ba435..a70c195c4e0 100644 --- a/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/LightTree2FirConverterTestCaseGenerated.java +++ b/compiler/fir/lightTree/tests/org/jetbrains/kotlin/fir/lightTree/LightTree2FirConverterTestCaseGenerated.java @@ -213,6 +213,11 @@ public class LightTree2FirConverterTestCaseGenerated extends AbstractLightTree2F runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); } + @TestMetadata("inBrackets.kt") + public void testInBrackets() throws Exception { + runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt"); + } + @TestMetadata("init.kt") public void testInit() throws Exception { runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt"); diff --git a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 87274f22c7e..58cf21b8e11 100644 --- a/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.* import org.jetbrains.kotlin.fir.impl.FirAbstractAnnotatedElement import org.jetbrains.kotlin.fir.impl.FirLabelImpl +import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.impl.* import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.impl.* @@ -1253,23 +1254,29 @@ class RawFirBuilder(session: FirSession, val stubMode: Boolean) : BaseFirBuilder } } - override fun visitCallExpression(expression: KtCallExpression, data: Unit): FirElement { - val calleeExpression = expression.calleeExpression - val source = expression.toFirSourceElement() - - val (calleeReference, explicitReceiver) = when (calleeExpression) { + private fun splitToCalleeAndReceiver( + calleeExpression: KtExpression?, + defaultSource: FirPsiSourceElement + ): Pair { + return when (calleeExpression) { is KtSimpleNameExpression -> FirSimpleNamedReference( calleeExpression.toFirSourceElement(), calleeExpression.getReferencedNameAsName(), null ) to null + is KtParenthesizedExpression -> splitToCalleeAndReceiver(calleeExpression.expression, defaultSource) null -> FirErrorNamedReferenceImpl( null, FirSimpleDiagnostic("Call has no callee", DiagnosticKind.Syntax) ) to null else -> { FirSimpleNamedReference( - source, OperatorNameConventions.INVOKE, null + defaultSource, OperatorNameConventions.INVOKE, null ) to calleeExpression.toFirExpression("Incorrect invoke receiver") } } + } + + override fun visitCallExpression(expression: KtCallExpression, data: Unit): FirElement { + val source = expression.toFirSourceElement() + val (calleeReference, explicitReceiver) = splitToCalleeAndReceiver(expression.calleeExpression, source) val result = if (expression.valueArgumentList == null && expression.lambdaArguments.isEmpty()) { FirQualifiedAccessExpressionImpl(source).apply { diff --git a/compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt b/compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt new file mode 100644 index 00000000000..363c262ad17 --- /dev/null +++ b/compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt @@ -0,0 +1,4 @@ +fun test(e: Int.() -> String) { + val s = 3.e() + val ss = 3.(e)() +} \ No newline at end of file diff --git a/compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.txt b/compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.txt new file mode 100644 index 00000000000..b63c3afa853 --- /dev/null +++ b/compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.txt @@ -0,0 +1,5 @@ +FILE: inBrackets.kt + public? final? fun test(e: ( Int.() -> String )): R|kotlin/Unit| { + lval s: = IntegerLiteral(3).e#() + lval ss: = IntegerLiteral(3).e#() + } diff --git a/compiler/fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java b/compiler/fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java index 46f8c93e902..fa30d25cae7 100644 --- a/compiler/fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java +++ b/compiler/fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTestCaseGenerated.java @@ -213,6 +213,11 @@ public class RawFirBuilderTestCaseGenerated extends AbstractRawFirBuilderTestCas runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); } + @TestMetadata("inBrackets.kt") + public void testInBrackets() throws Exception { + runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt"); + } + @TestMetadata("init.kt") public void testInit() throws Exception { runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt"); diff --git a/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.kt b/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.kt new file mode 100644 index 00000000000..c0a6b401adb --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.kt @@ -0,0 +1,4 @@ +fun test(e: Int.() -> String) { + val s = 3.e() + val ss = 3.(e)() +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.txt b/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.txt new file mode 100644 index 00000000000..a70c058ed5a --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.txt @@ -0,0 +1,5 @@ +FILE: inBrackets.kt + public final fun test(e: R|kotlin/Int.() -> kotlin/String|): R|kotlin/Unit| { + lval s: = Int(3).#() + lval ss: = Int(3).#() + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 72929952d0f..c57824f70aa 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -679,6 +679,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt"); } + @TestMetadata("inBrackets.kt") + public void testInBrackets() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.kt"); + } + @TestMetadata("propertyFromParameter.kt") public void testPropertyFromParameter() throws Exception { runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyFromParameter.kt"); diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 4cd195cd088..09e69a60cca 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -679,6 +679,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt"); } + @TestMetadata("inBrackets.kt") + public void testInBrackets() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/inBrackets.kt"); + } + @TestMetadata("propertyFromParameter.kt") public void testPropertyFromParameter() throws Exception { runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/propertyFromParameter.kt"); diff --git a/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt b/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt index 6bfd3b74317..0546c14f2fb 100644 --- a/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt +++ b/compiler/testData/diagnostics/tests/declarationChecks/namedFunAsLastExpressionInBlock.fir.kt @@ -45,7 +45,7 @@ fun test() { x4 checkType { _>() } { y: Int -> fun named14(): Int {return 1} } - val b = (fun named15(): Boolean { return true })() + val b = (fun named15(): Boolean { return true })() baz(fun named16(){}) } diff --git a/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry_after.fir.kt b/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry_after.fir.kt index 867145131f6..6c4f3f5778a 100644 --- a/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry_after.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry_after.fir.kt @@ -10,7 +10,7 @@ enum class E { val foo: Any.() -> Unit = {} fun f1() = E.FIRST.foo() -fun f2() = E.FIRST.(foo)() +fun f2() = E.FIRST.(foo)() fun f3() = E.SECOND.foo() -fun f4() = E.SECOND.(foo)() +fun f4() = E.SECOND.(foo)() fun f5() = E.SECOND.A() diff --git a/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry_before.fir.kt b/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry_before.fir.kt index 8e7216c011a..97262b0cd34 100644 --- a/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry_before.fir.kt +++ b/compiler/testData/diagnostics/tests/enum/dontCreatePackageTypeForEnumEntry_before.fir.kt @@ -10,7 +10,7 @@ enum class E { val foo: Any.() -> Unit = {} fun f1() = E.FIRST.foo() -fun f2() = E.FIRST.(foo)() +fun f2() = E.FIRST.(foo)() fun f3() = E.SECOND.foo() -fun f4() = E.SECOND.(foo)() +fun f4() = E.SECOND.(foo)() fun f5() = E.SECOND.A() diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt index 027ba798f01..107f01d0c61 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt @@ -1,5 +1,5 @@ fun test1(f: String.() -> Unit) { - (f)() + (f)() f() } @@ -7,5 +7,5 @@ fun test1(f: String.() -> Unit) { fun test2(f: (Int) -> Int) { 1.f(2) - 2.(f)(2) + 2.(f)(2) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt index 3c2289bab4d..d616e9d6153 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt @@ -6,8 +6,8 @@ fun test1() { } fun test2(f: String.(Int) -> Unit) { - 11.(f)(1) - 11.(f)() + 11.(f)(1) + 11.(f)() } fun test3() { diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/implicitInvoke.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/implicitInvoke.fir.kt index 3f929db31fe..0956bf1e344 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/implicitInvoke.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/implicitInvoke.fir.kt @@ -25,9 +25,9 @@ fun test(c: () -> String, e: Int.() -> String) { (c)() 3.e() - 3.(e)() + 3.(e)() with(3) { e() - (e)() + (e)() } } diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt index 72dc0a20891..1bd97f6c098 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt @@ -15,7 +15,7 @@ fun test(a: A, b: B) { with(a) { b.foo() - b.(foo)() + b.(foo)() (b.foo)() @@ -25,7 +25,7 @@ fun test(a: A, b: B) { with(b) { a.foo() - a.(foo)() + a.(foo)() (a.foo)() @@ -36,7 +36,7 @@ fun test(a: A, b: B) { with(a) { with(b) { foo() - (foo)() + (foo)() } } } @@ -57,7 +57,7 @@ fun test(a: A, b: B) { with(a) { b.foo() - b.(foo)() + b.(foo)() (b.foo)() @@ -67,7 +67,7 @@ fun test(a: A, b: B) { with(b) { a.foo() - a.(foo)() + a.(foo)() (a.foo)() @@ -78,7 +78,7 @@ fun test(a: A, b: B) { with(a) { with(b) { foo() - (foo)() + (foo)() } } } diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt index cce60dc62a7..66a1244efff 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt @@ -9,10 +9,10 @@ val B.a: () -> Int get() = { 5 } fun test(a: A, b: B) { val x: Int = b.a() - b.(a)() + b.(a)() with(b) { val y: Int = a() - (a)() + (a)() } } diff --git a/compiler/visualizer/testData/rawBuilder/expressions/inBrackets.kt b/compiler/visualizer/testData/rawBuilder/expressions/inBrackets.kt new file mode 100644 index 00000000000..eee73cdc94e --- /dev/null +++ b/compiler/visualizer/testData/rawBuilder/expressions/inBrackets.kt @@ -0,0 +1,14 @@ +// FIR_IGNORE +fun test(e: Int.() -> String) { +// String +// │ Int +// │ │ fun Int.invoke(): String +// │ │ │ + val s = 3.e() +// String +// │ Int +// │ │ fun Int.invoke(): String +// │ │ │test.e: Int.() -> String +// │ │ ││ + val ss = 3.(e)() +} diff --git a/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/fir/FirVisualizerForRawFirDataGenerated.java b/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/fir/FirVisualizerForRawFirDataGenerated.java index 4c595aac3b0..f55e27df344 100644 --- a/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/fir/FirVisualizerForRawFirDataGenerated.java +++ b/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/fir/FirVisualizerForRawFirDataGenerated.java @@ -213,6 +213,11 @@ public class FirVisualizerForRawFirDataGenerated extends AbstractFirVisualizer { runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); } + @TestMetadata("inBrackets.kt") + public void testInBrackets() throws Exception { + runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt"); + } + @TestMetadata("init.kt") public void testInit() throws Exception { runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt"); diff --git a/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/psi/PsiVisualizerForRawFirDataGenerated.java b/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/psi/PsiVisualizerForRawFirDataGenerated.java index cb117308d17..0eb6b6c07b8 100644 --- a/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/psi/PsiVisualizerForRawFirDataGenerated.java +++ b/compiler/visualizer/tests/org/jetbrains/kotlin/visualizer/psi/PsiVisualizerForRawFirDataGenerated.java @@ -213,6 +213,11 @@ public class PsiVisualizerForRawFirDataGenerated extends AbstractPsiVisualizer { runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/in.kt"); } + @TestMetadata("inBrackets.kt") + public void testInBrackets() throws Exception { + runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/inBrackets.kt"); + } + @TestMetadata("init.kt") public void testInit() throws Exception { runTest("compiler/fir/psi2fir/testData/rawBuilder/expressions/init.kt");