From 990ee849e262b332ef66d4a5d67b800583dc8514 Mon Sep 17 00:00:00 2001 From: Anton Bannykh Date: Mon, 4 Feb 2019 17:30:19 +0300 Subject: [PATCH] JS: test local declaration deduplication with name clash; fix the test --- .../kotlin/js/inline/InliningScope.kt | 16 +++++++ .../kotlin/js/inline/util/collectUtils.kt | 1 + .../js/test/semantics/BoxJsTestGenerated.java | 5 +++ .../test/semantics/IrBoxJsTestGenerated.java | 5 +++ .../box/inline/localDeclarationsClash.kt | 43 +++++++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 js/js.translator/testData/box/inline/localDeclarationsClash.kt diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InliningScope.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InliningScope.kt index d3229f713a2..ad26b484af6 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InliningScope.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/InliningScope.kt @@ -29,6 +29,8 @@ sealed class InliningScope { abstract fun addImport(tag: String, vars: JsVars) + open fun addLocalDeclarationBinding(inlineFunctionTag: String, name: JsName, index: Int) {} + open fun preprocess(statement: JsStatement) {} abstract fun update() @@ -82,16 +84,26 @@ sealed class InliningScope { } } + val localDeclarations = mutableListOf() + copiedStatements.asSequence() .flatMap { node -> collectDefinedNamesInAllScopes(node).asSequence() } .filter { name -> !newReplacements.containsKey(name) } .forEach { name -> val alias = JsScope.declareTemporaryName(name.ident) alias.copyMetadataFrom(name) + localDeclarations += alias val replacement = JsAstUtils.pureFqn(alias, null) newReplacements[name] = replacement } + // Add local declarations to the nae bindings in order to correctly rename usages of the same imported local declaraions + definition.tag?.let { tag -> + localDeclarations.forEachIndexed { index, name -> + addLocalDeclarationBinding(tag, name, index) + } + } + // Apply renaming and restore the static ref links JsBlock(copiedStatements).let { replaceNames(it, newReplacements) @@ -190,6 +202,10 @@ class ProgramFragmentInliningScope( addNameBinding(name, tag) } + override fun addLocalDeclarationBinding(inlineFunctionTag: String, name: JsName, index: Int) { + addNameBinding(name, "\$local:$inlineFunctionTag:$index") + } + override fun addInlinedDeclaration(tag: String?, declaration: JsStatement) { if (tag != null) { fragment.inlinedLocalDeclarations.computeIfAbsent(tag) { JsGlobalBlock() }.statements.add(declaration) diff --git a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/collectUtils.kt b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/collectUtils.kt index a033c01352d..46524a4095a 100644 --- a/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/collectUtils.kt +++ b/js/js.inliner/src/org/jetbrains/kotlin/js/inline/util/collectUtils.kt @@ -125,6 +125,7 @@ fun collectDefinedNames(scope: JsNode): Set { } fun collectDefinedNamesInAllScopes(scope: JsNode): Set { + // Order is important for the local declaration deduplication val names = mutableSetOf() object : RecursiveJsVisitor() { diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java index 68078bd2f2a..e6a83f6d6e1 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/BoxJsTestGenerated.java @@ -4060,6 +4060,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/inline/lambdaReassignmentWithCapture.kt"); } + @TestMetadata("localDeclarationsClash.kt") + public void testLocalDeclarationsClash() throws Exception { + runTest("js/js.translator/testData/box/inline/localDeclarationsClash.kt"); + } + @TestMetadata("localInlineExtensionFunction.kt") public void testLocalInlineExtensionFunction() throws Exception { runTest("js/js.translator/testData/box/inline/localInlineExtensionFunction.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java index b7051ddb64b..0a051ba4126 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/IrBoxJsTestGenerated.java @@ -4060,6 +4060,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/inline/lambdaReassignmentWithCapture.kt"); } + @TestMetadata("localDeclarationsClash.kt") + public void testLocalDeclarationsClash() throws Exception { + runTest("js/js.translator/testData/box/inline/localDeclarationsClash.kt"); + } + @TestMetadata("localInlineExtensionFunction.kt") public void testLocalInlineExtensionFunction() throws Exception { runTest("js/js.translator/testData/box/inline/localInlineExtensionFunction.kt"); diff --git a/js/js.translator/testData/box/inline/localDeclarationsClash.kt b/js/js.translator/testData/box/inline/localDeclarationsClash.kt new file mode 100644 index 00000000000..8a02f5b2d50 --- /dev/null +++ b/js/js.translator/testData/box/inline/localDeclarationsClash.kt @@ -0,0 +1,43 @@ +// EXPECTED_REACHABLE_NODES: 1281 +// FILE: 1.kt + +package o + +import I + +inline fun run(): String { + return object : I { + override fun run() = "O" + }.run() +} + + +// FILE: 2.kt + +package k + +import I + +inline fun run(): String { + return object : I { + override fun run() = "K" + }.run() +} + +// FILE: 3.kt + +fun ok() = o.run() + k.run() + +// FILE: main.kt + +interface I { + fun run(): String +} + +fun box(): String { + + if (ok() != "OK") return "fail" + + + return o.run() + k.run() +} \ No newline at end of file