From 8db104ef36df625c07f39d4cf84fcc132f4c6d07 Mon Sep 17 00:00:00 2001 From: Alexey Tsvetkov Date: Tue, 21 Apr 2015 15:09:57 +0300 Subject: [PATCH] JS: decomposition should preserve 'this' context with invocations #KT-7502 fixed --- .../kotlin/js/inline/ExpressionDecomposer.kt | 14 ++++++++++++-- .../InlineEvaluationOrderTestGenerated.java | 12 ++++++++++++ .../cases/methodCallQualifierWithSideEffect.kt | 14 ++++++++++++++ .../methodInlineCallQualifierWithSideEffect.kt | 15 +++++++++++++++ 4 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 js/js.translator/testData/inlineEvaluationOrder/cases/methodCallQualifierWithSideEffect.kt create mode 100644 js/js.translator/testData/inlineEvaluationOrder/cases/methodInlineCallQualifierWithSideEffect.kt diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt index 2572402670f..73a3bc5eb22 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/ExpressionDecomposer.kt @@ -25,6 +25,7 @@ import kotlin.platform.platformStatic import kotlin.properties.Delegates import com.intellij.util.SmartList +import org.jetbrains.kotlin.js.translate.context.Namer /** * If inline function consists of multiple statements, @@ -259,12 +260,21 @@ class ExpressionDecomposer private ( } private fun Callable.process() { - val matchedIndices = arguments.indicesOfExtractable + var matchedIndices = arguments.indicesOfExtractable if (!matchedIndices.hasNext()) return qualifier = accept(qualifier) if (qualifier in containsNodeWithSideEffect) { - qualifier = qualifier.extractToTemporary() + val callee = qualifier as? JsNameRef + val receiver = callee?.qualifier + + if (callee != null && receiver != null && receiver in containsNodeWithSideEffect) { + val receiverTmp = receiver.extractToTemporary() + callee.qualifier = receiverTmp + } + else { + qualifier = qualifier.extractToTemporary() + } } processByIndices(arguments, matchedIndices) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/InlineEvaluationOrderTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/InlineEvaluationOrderTestGenerated.java index 337fe2ba49c..40b7290f872 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/InlineEvaluationOrderTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/InlineEvaluationOrderTestGenerated.java @@ -197,6 +197,18 @@ public class InlineEvaluationOrderTestGenerated extends AbstractInlineEvaluation doTest(fileName); } + @TestMetadata("methodCallQualifierWithSideEffect.kt") + public void testMethodCallQualifierWithSideEffect() throws Exception { + String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/inlineEvaluationOrder/cases/methodCallQualifierWithSideEffect.kt"); + doTest(fileName); + } + + @TestMetadata("methodInlineCallQualifierWithSideEffect.kt") + public void testMethodInlineCallQualifierWithSideEffect() throws Exception { + String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/inlineEvaluationOrder/cases/methodInlineCallQualifierWithSideEffect.kt"); + doTest(fileName); + } + @TestMetadata("multiDeclaration.kt") public void testMultiDeclaration() throws Exception { String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/inlineEvaluationOrder/cases/multiDeclaration.kt"); diff --git a/js/js.translator/testData/inlineEvaluationOrder/cases/methodCallQualifierWithSideEffect.kt b/js/js.translator/testData/inlineEvaluationOrder/cases/methodCallQualifierWithSideEffect.kt new file mode 100644 index 00000000000..fa280e2c448 --- /dev/null +++ b/js/js.translator/testData/inlineEvaluationOrder/cases/methodCallQualifierWithSideEffect.kt @@ -0,0 +1,14 @@ +package foo + +// Test for KT-7502 + +class A(val value: Int) { + fun plus(num: Int): Int = this.value + num +} + +fun box(): String { + assertEquals(15, A(fizz(5)).plus(buzz(10))) + assertEquals("fizz(5);buzz(10);", pullLog()) + + return "OK" +} \ No newline at end of file diff --git a/js/js.translator/testData/inlineEvaluationOrder/cases/methodInlineCallQualifierWithSideEffect.kt b/js/js.translator/testData/inlineEvaluationOrder/cases/methodInlineCallQualifierWithSideEffect.kt new file mode 100644 index 00000000000..5f543bffed0 --- /dev/null +++ b/js/js.translator/testData/inlineEvaluationOrder/cases/methodInlineCallQualifierWithSideEffect.kt @@ -0,0 +1,15 @@ +package foo + +// Test for KT-7502 +// CHECK_NOT_CALLED: plus + +class A(val value: Int) { + inline fun plus(num: Int): Int = this.value + num +} + +fun box(): String { + assertEquals(15, A(fizz(5)).plus(buzz(10))) + assertEquals("fizz(5);buzz(10);", pullLog()) + + return "OK" +} \ No newline at end of file