From 3a36a786d4ef87751d86b1a50e98c188df18be1c Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Mon, 15 Jan 2024 12:57:27 +0200 Subject: [PATCH] [FIR] Properly generate implicit invoke calls for `a.(b)()` ^KT-64891 Fixed --- .../LightTreeRawFirExpressionBuilder.kt | 24 ++++++------- .../kotlin/fir/builder/PsiRawFirBuilder.kt | 34 +++++++++++++------ .../rawBuilder/expressions/inBrackets.txt | 2 +- .../tests/fixExpressionsInQaSelectors.fir.kt | 16 --------- .../tests/fixExpressionsInQaSelectors.kt | 1 + .../receiverPresenceErrorForInvoke.fir.kt | 2 +- .../wrongReceiverForInvokeOnExpression.fir.kt | 2 +- ...OnVariableWithExtensionFunctionType.fir.kt | 4 +-- .../invoke/wrongInvokeExtension.fir.kt | 4 +-- 9 files changed, 44 insertions(+), 45 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/fixExpressionsInQaSelectors.fir.kt diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt index dbc7cadd633..6e13819d30d 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt @@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.lightTree.fir.ValueParameter import org.jetbrains.kotlin.fir.lightTree.fir.WhenEntry import org.jetbrains.kotlin.fir.lightTree.fir.addDestructuringStatements import org.jetbrains.kotlin.fir.references.FirNamedReference +import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference import org.jetbrains.kotlin.fir.references.builder.buildExplicitThisReference @@ -651,8 +652,8 @@ class LightTreeRawFirExpressionBuilder( SUPER_EXPRESSION -> { superNode = node } - PARENTHESIZED -> node.getExpressionInParentheses()?.let { process(it) } ?: run { - additionalArgument = getAsFirExpression(node, "Incorrect invoke receiver") + PARENTHESIZED -> if (node.tokenType != TokenType.ERROR_ELEMENT) { + additionalArgument = getAsFirExpression(node.getExpressionInParentheses(), "Incorrect invoke receiver") } TYPE_ARGUMENT_LIST -> { firTypeArguments += declarationBuilder.convertTypeArguments(node, allowedUnderscoredTypeArgument = true) @@ -680,6 +681,15 @@ class LightTreeRawFirExpressionBuilder( } ) + superNode != null || additionalArgument?.calleeReference is FirSuperReference -> { + CalleeAndReceiver( + buildErrorNamedReference { + this.source = superNode?.toFirSourceElement() ?: additionalArgument?.calleeReference?.source + diagnostic = ConeSimpleDiagnostic("Super cannot be a callee", DiagnosticKind.SuperNotAllowed) + } + ) + } + additionalArgument != null -> { CalleeAndReceiver( buildSimpleNamedReference { @@ -691,16 +701,6 @@ class LightTreeRawFirExpressionBuilder( ) } - superNode != null -> { - CalleeAndReceiver( - buildErrorNamedReference { - val node = superNode!! - this.source = node.toFirSourceElement() - diagnostic = ConeSimpleDiagnostic("Super cannot be a callee", DiagnosticKind.SuperNotAllowed) - } - ) - } - else -> CalleeAndReceiver( buildErrorNamedReference { this.source = source diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt index bb249911cb1..01a8b3b44b2 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.impl.FirContractCallBlock import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock import org.jetbrains.kotlin.fir.extensions.extensionService +import org.jetbrains.kotlin.fir.references.FirSuperReference import org.jetbrains.kotlin.fir.references.builder.* import org.jetbrains.kotlin.fir.scopes.FirScopeProvider import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -2948,8 +2949,11 @@ open class PsiRawFirBuilder( calleeExpression: KtExpression?, defaultSource: KtPsiSourceElement, ): CalleeAndReceiver { - return when (calleeExpression) { - is KtSimpleNameExpression -> + val parenthesizedArgument = (calleeExpression as? KtParenthesizedExpression)?.expression + ?.toFirExpression("Incorrect invoke receiver") + + return when { + calleeExpression is KtSimpleNameExpression -> CalleeAndReceiver( buildSimpleNamedReference { source = calleeExpression.toFirSourceElement() @@ -2957,22 +2961,32 @@ open class PsiRawFirBuilder( } ) - is KtParenthesizedExpression -> splitToCalleeAndReceiver(calleeExpression.expression, defaultSource) - - null -> { + calleeExpression is KtSuperExpression || parenthesizedArgument?.calleeReference is FirSuperReference -> { CalleeAndReceiver( buildErrorNamedReference { - source = defaultSource - diagnostic = ConeSyntaxDiagnostic("Call has no callee") + source = (calleeExpression as? KtSuperExpression)?.toFirSourceElement() + ?: parenthesizedArgument?.calleeReference?.source + diagnostic = ConeSimpleDiagnostic("Super cannot be a callee", DiagnosticKind.SuperNotAllowed) } ) } - is KtSuperExpression -> { + parenthesizedArgument != null -> { + CalleeAndReceiver( + buildSimpleNamedReference { + source = defaultSource.fakeElement(KtFakeSourceElementKind.ImplicitInvokeCall) + name = OperatorNameConventions.INVOKE + }, + receiverExpression = parenthesizedArgument, + isImplicitInvoke = true + ) + } + + calleeExpression == null -> { CalleeAndReceiver( buildErrorNamedReference { - source = calleeExpression.toFirSourceElement() - diagnostic = ConeSimpleDiagnostic("Super cannot be a callee", DiagnosticKind.SuperNotAllowed) + source = defaultSource + diagnostic = ConeSyntaxDiagnostic("Call has no callee") } ) } diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/inBrackets.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/inBrackets.txt index b63c3afa853..e1a99da8887 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/inBrackets.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/expressions/inBrackets.txt @@ -1,5 +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#() + lval ss: = e#.invoke#(IntegerLiteral(3)) } diff --git a/compiler/testData/diagnostics/tests/fixExpressionsInQaSelectors.fir.kt b/compiler/testData/diagnostics/tests/fixExpressionsInQaSelectors.fir.kt deleted file mode 100644 index deecf65de6d..00000000000 --- a/compiler/testData/diagnostics/tests/fixExpressionsInQaSelectors.fir.kt +++ /dev/null @@ -1,16 +0,0 @@ -// ISSUE: KT-64891 - -val b: Int.() -> Int = { 10 } -val Int.b: () -> String get() = { "B" } - -fun main() { - 5.(b)().inv() // should be Int - 5.b().length // should be String -} - -fun id(it: T) = it - -fun rain() { - 5.(b)().inv() - 5.(id(b))().inv() // should be consistent -} diff --git a/compiler/testData/diagnostics/tests/fixExpressionsInQaSelectors.kt b/compiler/testData/diagnostics/tests/fixExpressionsInQaSelectors.kt index fa51561d28e..b46e805efe3 100644 --- a/compiler/testData/diagnostics/tests/fixExpressionsInQaSelectors.kt +++ b/compiler/testData/diagnostics/tests/fixExpressionsInQaSelectors.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // ISSUE: KT-64891 val b: Int.() -> Int = { 10 } 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 df552565076..7b5de563481 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/errors/receiverPresenceErrorForInvoke.fir.kt @@ -7,5 +7,5 @@ fun test1(f: String.() -> Unit) { fun test2(f: (Int) -> Int) { 1.f(2) - 2.(f)(2) + 2.(f)(2) } 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 2bac50b07f5..270b89f4d68 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/errors/wrongReceiverForInvokeOnExpression.fir.kt @@ -5,7 +5,7 @@ fun test1() { } fun test2(f: String.(Int) -> Unit) { - 11.(f)(1) + 11.(f)(1) 11.(f)() } diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt index 069fda35cf2..acbbfa50cf8 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/invokeOnVariableWithExtensionFunctionType.fir.kt @@ -24,7 +24,7 @@ fun test(a: A, b: B) { with(b) { a.foo() - a.(foo)() + a.(foo)() (a.foo)() @@ -66,7 +66,7 @@ fun test(a: A, b: B) { with(b) { a.foo() - a.(foo)() + a.(foo)() (a.foo)() diff --git a/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt b/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt index ece2c87afc2..cff7fd9cb15 100644 --- a/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt +++ b/compiler/testData/diagnostics/tests/resolve/invoke/wrongInvokeExtension.fir.kt @@ -10,10 +10,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)() } }