From 3dd4a0d86856f6eff304a5953fba0b9350b2b7d3 Mon Sep 17 00:00:00 2001 From: Alexander Korepanov Date: Mon, 15 Jan 2024 15:45:43 +0100 Subject: [PATCH] [JS FIR] Add JS_NAME_CLASH tests for constructors ^KT-64867 Related --- .../name/constructorsWithSameJsName.fir.kt | 49 +++++++++++++++ .../name/constructorsWithSameJsName.kt | 49 +++++++++++++++ .../name/constructorsWithSameJsName.txt | 29 +++++++++ .../js/test/fir/FirJsES6BoxTestGenerated.java | 6 ++ .../fir/FirLightTreeJsBoxTestGenerated.java | 6 ++ ...JsOldFrontendDiagnosticsTestGenerated.java | 6 ++ .../js/test/fir/FirPsiJsBoxTestGenerated.java | 6 ++ ...JsOldFrontendDiagnosticsTestGenerated.java | 6 ++ .../DiagnosticsWithJsStdLibTestGenerated.java | 6 ++ .../js/test/ir/IrBoxJsES6TestGenerated.java | 6 ++ .../js/test/ir/IrBoxJsTestGenerated.java | 6 ++ .../export/topLevelAndClassCtrNameClash.kt | 62 +++++++++++++++++++ 12 files changed, 237 insertions(+) create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.fir.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.kt create mode 100644 compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.txt create mode 100644 js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.fir.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.fir.kt new file mode 100644 index 00000000000..03c260cb80c --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.fir.kt @@ -0,0 +1,49 @@ +// FIR_DIFFERENCE +// K1 doesn't detect a clash between constructors in one class. +// It doesn't seem correct (KT-64976) because it leads to a clash in the generated JS code. K2 works correctly. +// !DIAGNOSTICS: -OPT_IN_USAGE + +@JsExport +class ClassA { + val x: String + + @JsName("constructorA") + constructor(y: String) { + x = "fromString:$y" + } + + @JsName("constructorOther") + constructor(y: Int) { + x = "fromInt:$y" + } +} + +@JsExport +class ClassB { + val x: String + + @JsName("constructorB") + constructor(y: String) { + x = "fromString:$y" + } + + @JsName("constructorOther") + constructor(y: Int) { + x = "fromInt:$y" + } +} + +@JsExport +class ClassC { + val x: String + + @JsName("constructorC") + constructor(y: String) { + x = "fromString:$y" + } + + @JsName("constructorC") + constructor(y: Int) { + x = "fromInt:$y" + } +} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.kt b/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.kt new file mode 100644 index 00000000000..4754dd8c043 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.kt @@ -0,0 +1,49 @@ +// FIR_DIFFERENCE +// K1 doesn't detect a clash between constructors in one class. +// It doesn't seem correct (KT-64976) because it leads to a clash in the generated JS code. K2 works correctly. +// !DIAGNOSTICS: -OPT_IN_USAGE + +@JsExport +class ClassA { + val x: String + + @JsName("constructorA") + constructor(y: String) { + x = "fromString:$y" + } + + @JsName("constructorOther") + constructor(y: Int) { + x = "fromInt:$y" + } +} + +@JsExport +class ClassB { + val x: String + + @JsName("constructorB") + constructor(y: String) { + x = "fromString:$y" + } + + @JsName("constructorOther") + constructor(y: Int) { + x = "fromInt:$y" + } +} + +@JsExport +class ClassC { + val x: String + + @JsName("constructorC") + constructor(y: String) { + x = "fromString:$y" + } + + @JsName("constructorC") + constructor(y: Int) { + x = "fromInt:$y" + } +} diff --git a/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.txt b/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.txt new file mode 100644 index 00000000000..b4ed17863c2 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.txt @@ -0,0 +1,29 @@ +package + +@kotlin.js.JsExport public final class ClassA { + @kotlin.js.JsName(name = "constructorOther") public constructor ClassA(/*0*/ y: kotlin.Int) + @kotlin.js.JsName(name = "constructorA") public constructor ClassA(/*0*/ y: kotlin.String) + public final val x: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.js.JsExport public final class ClassB { + @kotlin.js.JsName(name = "constructorOther") public constructor ClassB(/*0*/ y: kotlin.Int) + @kotlin.js.JsName(name = "constructorB") public constructor ClassB(/*0*/ y: kotlin.String) + public final val x: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.js.JsExport public final class ClassC { + @kotlin.js.JsName(name = "constructorC") public constructor ClassC(/*0*/ y: kotlin.Int) + @kotlin.js.JsName(name = "constructorC") public constructor ClassC(/*0*/ y: kotlin.String) + public final val x: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsES6BoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsES6BoxTestGenerated.java index b25c26114e2..63fa5e3af79 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsES6BoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsES6BoxTestGenerated.java @@ -3250,6 +3250,12 @@ public class FirJsES6BoxTestGenerated extends AbstractFirJsES6BoxTest { runTest("js/js.translator/testData/box/export/reservedModuleNameInExportedFile.kt"); } + @Test + @TestMetadata("topLevelAndClassCtrNameClash.kt") + public void testTopLevelAndClassCtrNameClash() throws Exception { + runTest("js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt"); + } + @Test @TestMetadata("vararg.kt") public void testVararg() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirLightTreeJsBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirLightTreeJsBoxTestGenerated.java index 13af2b748b9..b5844e41989 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirLightTreeJsBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirLightTreeJsBoxTestGenerated.java @@ -3144,6 +3144,12 @@ public class FirLightTreeJsBoxTestGenerated extends AbstractFirLightTreeJsBoxTes runTest("js/js.translator/testData/box/export/reservedModuleNameInExportedFile.kt"); } + @Test + @TestMetadata("topLevelAndClassCtrNameClash.kt") + public void testTopLevelAndClassCtrNameClash() throws Exception { + runTest("js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt"); + } + @Test @TestMetadata("vararg.kt") public void testVararg() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirLightTreeJsOldFrontendDiagnosticsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirLightTreeJsOldFrontendDiagnosticsTestGenerated.java index d6338e4ade3..34fd50f6da7 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirLightTreeJsOldFrontendDiagnosticsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirLightTreeJsOldFrontendDiagnosticsTestGenerated.java @@ -700,6 +700,12 @@ public class FirLightTreeJsOldFrontendDiagnosticsTestGenerated extends AbstractF runTest("compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.kt"); } + @Test + @TestMetadata("constructorsWithSameJsName.kt") + public void testConstructorsWithSameJsName() throws Exception { + runTest("compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.kt"); + } + @Test @TestMetadata("declarationClash.kt") public void testDeclarationClash() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirPsiJsBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirPsiJsBoxTestGenerated.java index b0e4f14f9a4..225ba71ff26 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirPsiJsBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirPsiJsBoxTestGenerated.java @@ -3144,6 +3144,12 @@ public class FirPsiJsBoxTestGenerated extends AbstractFirPsiJsBoxTest { runTest("js/js.translator/testData/box/export/reservedModuleNameInExportedFile.kt"); } + @Test + @TestMetadata("topLevelAndClassCtrNameClash.kt") + public void testTopLevelAndClassCtrNameClash() throws Exception { + runTest("js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt"); + } + @Test @TestMetadata("vararg.kt") public void testVararg() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirPsiJsOldFrontendDiagnosticsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirPsiJsOldFrontendDiagnosticsTestGenerated.java index 70f1f8a2016..6a623b76447 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirPsiJsOldFrontendDiagnosticsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirPsiJsOldFrontendDiagnosticsTestGenerated.java @@ -700,6 +700,12 @@ public class FirPsiJsOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiJ runTest("compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.kt"); } + @Test + @TestMetadata("constructorsWithSameJsName.kt") + public void testConstructorsWithSameJsName() throws Exception { + runTest("compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.kt"); + } + @Test @TestMetadata("declarationClash.kt") public void testDeclarationClash() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/DiagnosticsWithJsStdLibTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/DiagnosticsWithJsStdLibTestGenerated.java index 4730d8d45b0..65bab7ce858 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/DiagnosticsWithJsStdLibTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/DiagnosticsWithJsStdLibTestGenerated.java @@ -700,6 +700,12 @@ public class DiagnosticsWithJsStdLibTestGenerated extends AbstractDiagnosticsTes runTest("compiler/testData/diagnostics/testsWithJsStdLib/name/conflictingNamesFromSuperclass.kt"); } + @Test + @TestMetadata("constructorsWithSameJsName.kt") + public void testConstructorsWithSameJsName() throws Exception { + runTest("compiler/testData/diagnostics/testsWithJsStdLib/name/constructorsWithSameJsName.kt"); + } + @Test @TestMetadata("declarationClash.kt") public void testDeclarationClash() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java index 04e1559bac0..daade41ac03 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsES6TestGenerated.java @@ -3250,6 +3250,12 @@ public class IrBoxJsES6TestGenerated extends AbstractIrBoxJsES6Test { runTest("js/js.translator/testData/box/export/reservedModuleNameInExportedFile.kt"); } + @Test + @TestMetadata("topLevelAndClassCtrNameClash.kt") + public void testTopLevelAndClassCtrNameClash() throws Exception { + runTest("js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt"); + } + @Test @TestMetadata("vararg.kt") public void testVararg() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java index 715554bb923..1818035bcc6 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java @@ -3144,6 +3144,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/export/reservedModuleNameInExportedFile.kt"); } + @Test + @TestMetadata("topLevelAndClassCtrNameClash.kt") + public void testTopLevelAndClassCtrNameClash() throws Exception { + runTest("js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt"); + } + @Test @TestMetadata("vararg.kt") public void testVararg() throws Exception { diff --git a/js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt b/js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt new file mode 100644 index 00000000000..a32c1406a5a --- /dev/null +++ b/js/js.translator/testData/box/export/topLevelAndClassCtrNameClash.kt @@ -0,0 +1,62 @@ +// IGNORE_BACKEND_K1: JS_IR, JS_IR_ES6 +// K1 reports a name clash error between top-level declarations and constructors. It seems relevant for legacy JS BE; +// however, this is not applicable to JS IR BE because in the generated JS code, there is no name clash. +// K2 doesn't report anything and works correctly with JS IR BE. + +// RUN_PLAIN_BOX_FUNCTION +// MODULE: lib +// FILE: lib.kt +@JsExport +class ClassA { + val a: String + + @JsName("createFromString") + constructor(y: String) { + a = "ClassA:fromString:$y" + } + + @JsName("createFromInt") + constructor(y: Int) { + a = "ClassA:fromInt:$y" + } +} + +@JsExport +class ClassB { + val b: String + + @JsName("createFromString") + constructor(y: String) { + b = "ClassB:fromString:$y" + } + + @JsName("createFromInt") + constructor(y: Int) { + b = "ClassB:fromInt:$y" + } +} + +@JsExport +fun createFromString(y: String) = "fromString:$y"; + +@JsExport +fun createFromInt(y: Int) = "fromInt:$y"; + +// FILE: main.js +function box() { + var a1 = this.lib.ClassA.createFromString("A1"); + var a2 = this.lib.ClassA.createFromInt(2); + var b3 = this.lib.ClassB.createFromString("B3"); + var b4 = this.lib.ClassB.createFromInt(4); + var x5 = this.lib.createFromString("X5"); + var x6 = this.lib.createFromInt(6); + + if (a1.a !== "ClassA:fromString:A1") return "Error: '" + a1.a + "' !== 'ClassA:fromString:A1'" + if (a2.a !== "ClassA:fromInt:2") return "Error: '" + a2.a + "' !== 'ClassA:fromInt:2'" + if (b3.b !== "ClassB:fromString:B3") return "Error: '" + b3.b + "' !== 'ClassB:fromString:B3'" + if (b4.b !== "ClassB:fromInt:4") return "Error: '" + b4.b + "' !== 'ClassB:fromInt:4'" + if (x5 !== "fromString:X5") return "Error: '" + x5 + "' !== 'fromString:X5'" + if (x6 !== "fromInt:6") return "Error: '" + x6 + "' !== 'fromInt:6'" + + return "OK" +}