From 6aff53204f0654df4d2dd8bcd9cd9216ba00dfc8 Mon Sep 17 00:00:00 2001 From: Dmitry Petrov Date: Wed, 13 Feb 2019 16:08:03 +0300 Subject: [PATCH] psi2ir: support dynamic infix calls ('foo bar 42' is 'foo.bar(42)') --- .../kotlin/psi2ir/generators/DynamicCalls.kt | 2 +- .../generators/OperatorExpressionGenerator.kt | 15 +++++++++------ .../nonLocalReturns/tryFinally/kt26384_2.kt | 2 +- .../ir/irJsText/dynamic/dynamicInfixCall.kt | 3 +++ .../ir/irJsText/dynamic/dynamicInfixCall.txt | 17 +++++++++++++++++ .../kotlin/ir/IrJsTextTestCaseGenerated.java | 5 +++++ 6 files changed, 36 insertions(+), 8 deletions(-) create mode 100644 compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.kt create mode 100644 compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.txt diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DynamicCalls.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DynamicCalls.kt index 9c918dd7cf4..c0eec70e85b 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DynamicCalls.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DynamicCalls.kt @@ -13,7 +13,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions internal fun ResolvedCall<*>.isImplicitInvoke(): Boolean { if (resultingDescriptor.name != OperatorNameConventions.INVOKE) return false - val callExpression = call.callElement as? KtCallExpression ?: return true + val callExpression = call.callElement as? KtCallExpression ?: return false val calleeExpression = callExpression.calleeExpression as? KtSimpleNameExpression ?: return true return calleeExpression.getReferencedName() != OperatorNameConventions.INVOKE.asString() } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index 01d7338220f..89d00dac42e 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -177,14 +177,17 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat val kotlinType = context.bindingContext.getType(ktExpression) ?: throw AssertionError("No type for ${ktExpression.text}") + val startOffset = ktExpression.startOffsetSkippingComments + val endOffset = ktExpression.endOffset + val irType = kotlinType.toIrType() + + if (ktExpression.operationToken == KtTokens.IDENTIFIER) { + return generateCall(getResolvedCall(ktExpression)!!, ktExpression, null) + } + val operator = ktExpression.getDynamicOperator() - return IrDynamicOperatorExpressionImpl( - ktExpression.startOffsetSkippingComments, - ktExpression.endOffset, - kotlinType.toIrType(), - operator - ).apply { + return IrDynamicOperatorExpressionImpl(startOffset, endOffset, irType, operator).apply { left = ktLeft.genExpr() right = ktRight.genExpr() } diff --git a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt index 586a0bb5ba2..079a47863d9 100644 --- a/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt +++ b/compiler/testData/codegen/boxInline/nonLocalReturns/tryFinally/kt26384_2.kt @@ -1,4 +1,4 @@ -// IGNORE_BACKEND: JVM_IR +// IGNORE_BACKEND: JVM_IR, JS_IR // NO_CHECK_LAMBDA_INLINING // FILE: 1.kt diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.kt b/compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.kt new file mode 100644 index 00000000000..89d8f86d5cc --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.kt @@ -0,0 +1,3 @@ +fun test1(d: dynamic) = d foo 123 + +fun test2(d: dynamic) = d invoke 123 \ No newline at end of file diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.txt b/compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.txt new file mode 100644 index 00000000000..d95dcf1dbc8 --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.txt @@ -0,0 +1,17 @@ +FILE fqName: fileName:/dynamicInfixCall.kt + FUN name:test1 visibility:public modality:FINAL <> (d:dynamic) returnType:dynamic flags: + VALUE_PARAMETER name:d index:0 type:dynamic flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='test1(dynamic): dynamic' + DYN_OP operator=INVOKE type=dynamic + receiver: DYN_MEMBER memberName='foo' type=dynamic + GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST Int type=kotlin.Int value=123 + FUN name:test2 visibility:public modality:FINAL <> (d:dynamic) returnType:dynamic flags: + VALUE_PARAMETER name:d index:0 type:dynamic flags: + BLOCK_BODY + RETURN type=kotlin.Nothing from='test2(dynamic): dynamic' + DYN_OP operator=INVOKE type=dynamic + receiver: DYN_MEMBER memberName='invoke' type=dynamic + GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null + 0: CONST Int type=kotlin.Int value=123 diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java index 454bd29ff6f..0c8aba31743 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java @@ -101,6 +101,11 @@ public class IrJsTextTestCaseGenerated extends AbstractIrJsTextTestCase { runTest("compiler/testData/ir/irJsText/dynamic/dynamicExclExclOperator.kt"); } + @TestMetadata("dynamicInfixCall.kt") + public void testDynamicInfixCall() throws Exception { + runTest("compiler/testData/ir/irJsText/dynamic/dynamicInfixCall.kt"); + } + @TestMetadata("dynamicMemberAccess.kt") public void testDynamicMemberAccess() throws Exception { runTest("compiler/testData/ir/irJsText/dynamic/dynamicMemberAccess.kt");