From 27c2a4f6a8c017cc572b1e6b7c69f5d1f5b223d3 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Tue, 27 Dec 2016 14:23:04 +0300 Subject: [PATCH] JS: disable mangling for PublishedApi. Export declarations marked with PublishedApi. See KT-15442 --- .../codegen/box/publishedApi/simple.kt | 6 ++- .../codegen/box/publishedApi/topLevel.kt | 10 ++++ .../light-analysis/publishedApi/simple.txt | 2 +- .../light-analysis/publishedApi/topLevel.txt | 8 +++ .../ir/IrBlackBoxCodegenTestGenerated.java | 6 +++ .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ ...LightAnalysisModeCodegenTestGenerated.java | 6 +++ .../kotlin/js/naming/NameSuggestion.kt | 15 ++++-- .../js/test/semantics/BoxJsTestGenerated.java | 6 +++ .../semantics/JsCodegenBoxTestGenerated.java | 6 +++ .../translate/context/DeclarationExporter.kt | 2 +- .../box/multiModule/publishedApiMangling.kt | 54 +++++++++++++++++++ 12 files changed, 120 insertions(+), 7 deletions(-) create mode 100644 compiler/testData/codegen/box/publishedApi/topLevel.kt create mode 100644 compiler/testData/codegen/light-analysis/publishedApi/topLevel.txt create mode 100644 js/js.translator/testData/box/multiModule/publishedApiMangling.kt diff --git a/compiler/testData/codegen/box/publishedApi/simple.kt b/compiler/testData/codegen/box/publishedApi/simple.kt index f21d948cf2a..4ad78979fd4 100644 --- a/compiler/testData/codegen/box/publishedApi/simple.kt +++ b/compiler/testData/codegen/box/publishedApi/simple.kt @@ -1,3 +1,5 @@ +// MODULE: lib +// FILE: lib.kt class A { @PublishedApi @@ -7,6 +9,8 @@ class A { } -fun box() : String { +// MODULE: main(lib) +// FILE: main.kt +fun box(): String { return A().test() } \ No newline at end of file diff --git a/compiler/testData/codegen/box/publishedApi/topLevel.kt b/compiler/testData/codegen/box/publishedApi/topLevel.kt new file mode 100644 index 00000000000..e2a33400e7d --- /dev/null +++ b/compiler/testData/codegen/box/publishedApi/topLevel.kt @@ -0,0 +1,10 @@ +// MODULE: lib +// FILE: lib.kt +@PublishedApi +internal fun published() = "OK" + +inline fun test() = published() + +// MODULE: main(lib) +// FILE: main.kt +fun box() = test() \ No newline at end of file diff --git a/compiler/testData/codegen/light-analysis/publishedApi/simple.txt b/compiler/testData/codegen/light-analysis/publishedApi/simple.txt index b6fcb534916..c5986574bd5 100644 --- a/compiler/testData/codegen/light-analysis/publishedApi/simple.txt +++ b/compiler/testData/codegen/light-analysis/publishedApi/simple.txt @@ -6,6 +6,6 @@ public final class A { } @kotlin.Metadata -public final class SimpleKt { +public final class MainKt { public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String } diff --git a/compiler/testData/codegen/light-analysis/publishedApi/topLevel.txt b/compiler/testData/codegen/light-analysis/publishedApi/topLevel.txt new file mode 100644 index 00000000000..d3b9de697b9 --- /dev/null +++ b/compiler/testData/codegen/light-analysis/publishedApi/topLevel.txt @@ -0,0 +1,8 @@ +public final class LibKt { + public final static @kotlin.PublishedApi @org.jetbrains.annotations.NotNull method published(): java.lang.String + public final static @org.jetbrains.annotations.NotNull method test(): java.lang.String +} + +public final class MainKt { + public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String +} diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 529e9548710..fdf967a488a 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -11899,6 +11899,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/publishedApi/simple.kt"); doTest(fileName); } + + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/publishedApi/topLevel.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 9bea324e0e6..8f6084a0af5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11899,6 +11899,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/publishedApi/simple.kt"); doTest(fileName); } + + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/publishedApi/topLevel.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges") diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java index 5f4e459859e..c7b7e86f6b5 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeCodegenTestGenerated.java @@ -11899,6 +11899,12 @@ public class LightAnalysisModeCodegenTestGenerated extends AbstractLightAnalysis String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/publishedApi/simple.kt"); doTest(fileName); } + + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/publishedApi/topLevel.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges") diff --git a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt index f9b2d9aa8ac..703a42a888f 100644 --- a/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt +++ b/js/js.frontend/src/org/jetbrains/kotlin/js/naming/NameSuggestion.kt @@ -120,7 +120,7 @@ class NameSuggestion { var liftedName = ownName var hasInline = false while (container is FunctionDescriptor) { - if (container.isInline && container.visibility.isPublicAPI) { + if (container.isInline && container.ownEffectiveVisibility.isPublicAPI) { hasInline = true } liftedName = getSuggestedName(container) + "$" + liftedName @@ -257,20 +257,24 @@ class NameSuggestion { fun mangledAndStable() = NameAndStability(getStableMangledName(baseName, getArgumentTypesAsString(descriptor)), true) fun mangledPrivate() = NameAndStability(getPrivateMangledName(baseName, descriptor), false) + val effectiveVisibility = descriptor.ownEffectiveVisibility + val containingDeclaration = descriptor.containingDeclaration return when (containingDeclaration) { - is PackageFragmentDescriptor -> if (descriptor.visibility.isPublicAPI) mangledAndStable() else regularAndUnstable() + is PackageFragmentDescriptor -> if (effectiveVisibility.isPublicAPI) mangledAndStable() else regularAndUnstable() is ClassDescriptor -> { // valueOf() is created in the library with a mangled name for every enum class if (descriptor is FunctionDescriptor && descriptor.isEnumValueOfMethod()) return mangledAndStable() // Make all public declarations stable - if (descriptor.visibility == Visibilities.PUBLIC) return mangledAndStable() + if (effectiveVisibility == Visibilities.PUBLIC) { + return mangledAndStable() + } if (descriptor is CallableMemberDescriptor && descriptor.isOverridableOrOverrides) return mangledAndStable() // Make all protected declarations of non-final public classes stable - if (descriptor.visibility == Visibilities.PROTECTED && + if (effectiveVisibility == Visibilities.PROTECTED && !containingDeclaration.isFinalClass && containingDeclaration.visibility.isPublicAPI ) { @@ -323,5 +327,8 @@ class NameSuggestion { val absHashCode = Math.abs(forCalculateId.hashCode()) return if (absHashCode != 0) Integer.toString(absHashCode, Character.MAX_RADIX) else "" } + + private val DeclarationDescriptorWithVisibility.ownEffectiveVisibility + get() = visibility.effectiveVisibility(this, checkPublishedApi = true).toVisibility() } } 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 cab15223639..333648c4ba5 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 @@ -5330,6 +5330,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { doTest(fileName); } + @TestMetadata("publishedApiMangling.kt") + public void testPublishedApiMangling() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/multiModule/publishedApiMangling.kt"); + doTest(fileName); + } + @TestMetadata("useElementsFromDefaultPackageInAnotherModule.kt") public void testUseElementsFromDefaultPackageInAnotherModule() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/multiModule/useElementsFromDefaultPackageInAnotherModule.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index b7bd89d40cb..77021e01aad 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -14006,6 +14006,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/publishedApi/simple.kt"); doTest(fileName); } + + @TestMetadata("topLevel.kt") + public void testTopLevel() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/publishedApi/topLevel.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/codegen/box/ranges") diff --git a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DeclarationExporter.kt b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DeclarationExporter.kt index 2fe833ee060..ba678752147 100644 --- a/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DeclarationExporter.kt +++ b/js/js.translator/src/org/jetbrains/kotlin/js/translate/context/DeclarationExporter.kt @@ -142,4 +142,4 @@ internal class DeclarationExporter(val context: StaticContext) { } private fun MemberDescriptor.shouldBeExported(force: Boolean) = - force || isEffectivelyPublicApi || AnnotationsUtils.getJsNameAnnotation(this) != null + force || effectiveVisibility(checkPublishedApi = true).publicApi || AnnotationsUtils.getJsNameAnnotation(this) != null diff --git a/js/js.translator/testData/box/multiModule/publishedApiMangling.kt b/js/js.translator/testData/box/multiModule/publishedApiMangling.kt new file mode 100644 index 00000000000..1436a8db8cf --- /dev/null +++ b/js/js.translator/testData/box/multiModule/publishedApiMangling.kt @@ -0,0 +1,54 @@ +// MODULE: lib +// FILE: lib.kt +class A { + @PublishedApi + internal fun published(x: String) = "${x}K" + + fun template(x: String): String = TODO("") +} + +@PublishedApi +internal fun publishedTopLevel(x: String) = "${x}K" + +fun templateTopLevel(x: String): String = TODO("") + +interface I { + fun test(): String +} + +@PublishedApi +internal class B(val x: String) : I { + override fun test() = x + "K" +} + +// MODULE: main(lib) +// FILE: main.kt +import kotlin.text.Regex + +inline fun templates() { + A().template("X") + templateTopLevel("X") +} + +fun box(): String { + val testFunctionName = "published" + extractSuffix("template") + val a = A() + var result = a.asDynamic()[testFunctionName].call(a, "O") + if (result != "OK") return "fail1: $result" + + val topLevelName = "publishedTopLevel" + extractSuffix("templateTopLevel") + result = js("lib")[topLevelName]("O") + if (result != "OK") return "fail2: $result" + + val b: I = js("new lib.B('O')") + result = b.test() + if (result != "OK") return "fail3: $result" + + return "OK" +} + +private fun extractSuffix(prefix: String): String { + val functionBody: String = js("_").templates.toString() + val regex = Regex(prefix + "(_[\\\$a-zA-Z0-9]+)") + return regex.find(functionBody)!!.groupValues[1] +} \ No newline at end of file