[JS] JsExport diagnostics and legacy support
Account for JsExport in legacy backend namer. It means we catch overloaded exported function conflicts for free! Add error diagnostics: * NESTED_JS_EXPORT (Fixes KT-36798) * WRONG_EXPORTED_DECLARATION (Part of the fix for KT-37752) * NON_EXPORTABLE_TYPE (Fixes KT-37771)
This commit is contained in:
+26
@@ -0,0 +1,26 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
package foo
|
||||
|
||||
open class NonExportedClass
|
||||
|
||||
@JsExport
|
||||
class <!NON_EXPORTABLE_TYPE("super", "NonExportedClass")!>ExportedClass<!> : NonExportedClass()
|
||||
|
||||
interface NonExportedInterface
|
||||
|
||||
@JsExport
|
||||
class <!NON_EXPORTABLE_TYPE("super", "NonExportedInterface")!>ExportedClass2<!> : NonExportedInterface
|
||||
|
||||
@JsExport
|
||||
open class ExportedGenericClass<T>
|
||||
|
||||
@JsExport
|
||||
class <!NON_EXPORTABLE_TYPE("super", "ExportedGenericClass<NonExportedClass>")!>ExportedClass3<!> : ExportedGenericClass<NonExportedClass>()
|
||||
|
||||
@JsExport
|
||||
interface ExportedGenericInterface<T>
|
||||
|
||||
@JsExport
|
||||
class <!NON_EXPORTABLE_TYPE("super", "ExportedGenericInterface<NonExportedClass>")!>ExportedClass4<!> : ExportedGenericInterface<NonExportedClass>
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package
|
||||
|
||||
package foo {
|
||||
|
||||
@kotlin.js.JsExport public final class ExportedClass : foo.NonExportedClass {
|
||||
public constructor ExportedClass()
|
||||
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 ExportedClass2 : foo.NonExportedInterface {
|
||||
public constructor ExportedClass2()
|
||||
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 ExportedClass3 : foo.ExportedGenericClass<foo.NonExportedClass> {
|
||||
public constructor ExportedClass3()
|
||||
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 ExportedClass4 : foo.ExportedGenericInterface<foo.NonExportedClass> {
|
||||
public constructor ExportedClass4()
|
||||
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 open class ExportedGenericClass</*0*/ T> {
|
||||
public constructor ExportedGenericClass</*0*/ T>()
|
||||
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 interface ExportedGenericInterface</*0*/ T> {
|
||||
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
|
||||
}
|
||||
|
||||
public open class NonExportedClass {
|
||||
public constructor NonExportedClass()
|
||||
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
|
||||
}
|
||||
|
||||
public interface NonExportedInterface {
|
||||
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
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.js.ExperimentalJsExport
|
||||
|
||||
package foo
|
||||
|
||||
class C1 {
|
||||
<!NESTED_JS_EXPORT!>@JsExport<!>
|
||||
fun f1() {}
|
||||
|
||||
<!NESTED_JS_EXPORT!>@JsExport<!>
|
||||
val p: Int = 10
|
||||
|
||||
<!NESTED_JS_EXPORT!>@JsExport<!>
|
||||
object O
|
||||
}
|
||||
|
||||
fun f2() {
|
||||
<!NESTED_JS_EXPORT!>@JsExport<!>
|
||||
fun f3() {}
|
||||
|
||||
<!NESTED_JS_EXPORT!>@JsExport<!>
|
||||
class C2
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
package
|
||||
|
||||
package foo {
|
||||
public fun f2(): kotlin.Unit
|
||||
|
||||
public final class C1 {
|
||||
public constructor C1()
|
||||
@kotlin.js.JsExport public final val p: kotlin.Int = 10
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
@kotlin.js.JsExport public final fun f1(): kotlin.Unit
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
@kotlin.js.JsExport public object O {
|
||||
private constructor O()
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+15
@@ -0,0 +1,15 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
package foo
|
||||
|
||||
@JsExport
|
||||
class C(val x: String) {
|
||||
<!WRONG_EXPORTED_DECLARATION("secondary constructor without @JsName")!>constructor(x: Int)<!>: this(x.toString())
|
||||
}
|
||||
|
||||
@JsExport
|
||||
class C2(val x: String) {
|
||||
@JsName("JsNameProvided")
|
||||
constructor(x: Int): this(x.toString())
|
||||
}
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
package
|
||||
|
||||
package foo {
|
||||
|
||||
@kotlin.js.JsExport public final class C {
|
||||
public constructor C(/*0*/ x: kotlin.Int)
|
||||
public constructor C(/*0*/ x: 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 C2 {
|
||||
@kotlin.js.JsName(name = "JsNameProvided") public constructor C2(/*0*/ x: kotlin.Int)
|
||||
public constructor C2(/*0*/ x: 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
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.js.ExperimentalJsExport
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
package foo
|
||||
|
||||
class C
|
||||
|
||||
@JsExport
|
||||
fun foo(<!NON_EXPORTABLE_TYPE("parameter", "C")!>x: C<!>) {
|
||||
}
|
||||
|
||||
<!NON_EXPORTABLE_TYPE("return", "C")!>@JsExport
|
||||
fun bar()<!> = C()
|
||||
|
||||
<!NON_EXPORTABLE_TYPE("property", "C")!>@JsExport
|
||||
val x: C<!> = C()
|
||||
|
||||
<!NON_EXPORTABLE_TYPE("property", "C")!>@JsExport
|
||||
var x2: C<!>
|
||||
get() = C()
|
||||
set(value) { }
|
||||
|
||||
@JsExport
|
||||
class A(
|
||||
<!NON_EXPORTABLE_TYPE("parameter", "C"), NON_EXPORTABLE_TYPE("property", "C")!>val x: C<!>,
|
||||
<!NON_EXPORTABLE_TYPE("parameter", "C")!>y: C<!>
|
||||
) {
|
||||
<!NON_EXPORTABLE_TYPE("return", "C")!>fun foo(<!NON_EXPORTABLE_TYPE("parameter", "C")!>x: C<!>)<!> = x
|
||||
|
||||
<!NON_EXPORTABLE_TYPE("property", "C")!>val x2: C<!> = C()
|
||||
|
||||
<!NON_EXPORTABLE_TYPE("property", "C")!>var x3: C<!>
|
||||
get() = C()
|
||||
set(value) { }
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun foo2() {
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun foo3(<!NON_EXPORTABLE_TYPE("parameter", "Unit")!>x: Unit<!>) {
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun foo4(x: () -> Unit) {
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun foo5(<!NON_EXPORTABLE_TYPE("parameter", "(Unit) -> Unit")!>x: (Unit) -> Unit<!>) {
|
||||
}
|
||||
|
||||
@JsExport
|
||||
fun foo6(x: (A) -> A) {
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
package
|
||||
|
||||
package foo {
|
||||
@kotlin.js.JsExport public val x: foo.C
|
||||
@kotlin.js.JsExport public var x2: foo.C
|
||||
@kotlin.js.JsExport public fun bar(): foo.C
|
||||
@kotlin.js.JsExport public fun foo(/*0*/ x: foo.C): kotlin.Unit
|
||||
@kotlin.js.JsExport public fun foo2(): kotlin.Unit
|
||||
@kotlin.js.JsExport public fun foo3(/*0*/ x: kotlin.Unit): kotlin.Unit
|
||||
@kotlin.js.JsExport public fun foo4(/*0*/ x: () -> kotlin.Unit): kotlin.Unit
|
||||
@kotlin.js.JsExport public fun foo5(/*0*/ x: (kotlin.Unit) -> kotlin.Unit): kotlin.Unit
|
||||
@kotlin.js.JsExport public fun foo6(/*0*/ x: (foo.A) -> foo.A): kotlin.Unit
|
||||
|
||||
@kotlin.js.JsExport public final class A {
|
||||
public constructor A(/*0*/ x: foo.C, /*1*/ y: foo.C)
|
||||
public final val x: foo.C
|
||||
public final val x2: foo.C
|
||||
public final var x3: foo.C
|
||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final fun foo(/*0*/ x: foo.C): foo.C
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public final class C {
|
||||
public constructor C()
|
||||
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
|
||||
}
|
||||
}
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.js.ExperimentalJsExport
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
package foo
|
||||
|
||||
abstract class C
|
||||
interface I
|
||||
|
||||
@JsExport
|
||||
fun <<!NON_EXPORTABLE_TYPE("upper bound", "C")!>T : C<!>>foo() { }
|
||||
|
||||
@JsExport
|
||||
class A<<!NON_EXPORTABLE_TYPE("upper bound", "C")!>T : C<!>, <!NON_EXPORTABLE_TYPE("upper bound", "I")!>S: I<!>>
|
||||
|
||||
@JsExport
|
||||
interface I2<<!NON_EXPORTABLE_TYPE("upper bound", "C"), NON_EXPORTABLE_TYPE("upper bound", "I")!>T<!>> where T : C, T : I
|
||||
Vendored
+31
@@ -0,0 +1,31 @@
|
||||
package
|
||||
|
||||
package foo {
|
||||
@kotlin.js.JsExport public fun </*0*/ T : foo.C> foo(): kotlin.Unit
|
||||
|
||||
@kotlin.js.JsExport public final class A</*0*/ T : foo.C, /*1*/ S : foo.I> {
|
||||
public constructor A</*0*/ T : foo.C, /*1*/ S : foo.I>()
|
||||
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
|
||||
}
|
||||
|
||||
public abstract class C {
|
||||
public constructor C()
|
||||
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
|
||||
}
|
||||
|
||||
public interface I {
|
||||
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 interface I2</*0*/ T : foo.C> where T : foo.I {
|
||||
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
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
package foo
|
||||
|
||||
<!WRONG_EXPORTED_DECLARATION("inline function with reified type parameters")!>@JsExport
|
||||
inline fun <reified T> inlineReifiedFun(x: Any)<!> = x is T
|
||||
|
||||
<!WRONG_EXPORTED_DECLARATION("suspend function")!>@JsExport
|
||||
suspend fun suspendFun()<!> { }
|
||||
|
||||
<!WRONG_EXPORTED_DECLARATION("extension property")!>@JsExport
|
||||
val String.extensionProperty<!>
|
||||
get() = this.length
|
||||
|
||||
@JsExport
|
||||
enum class <!WRONG_EXPORTED_DECLARATION("enum class")!>EnumClass<!> { ENTRY1, ENTRY2 }
|
||||
|
||||
@JsExport
|
||||
annotation class <!WRONG_EXPORTED_DECLARATION("annotation class")!>AnnotationClass<!>
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package
|
||||
|
||||
package foo {
|
||||
@kotlin.js.JsExport public val kotlin.String.extensionProperty: kotlin.Int
|
||||
@kotlin.js.JsExport public inline fun </*0*/ reified T> inlineReifiedFun(/*0*/ x: kotlin.Any): kotlin.Boolean
|
||||
@kotlin.js.JsExport public suspend fun suspendFun(): kotlin.Unit
|
||||
|
||||
@kotlin.js.JsExport public final annotation class AnnotationClass : kotlin.Annotation {
|
||||
public constructor AnnotationClass()
|
||||
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 enum class EnumClass : kotlin.Enum<foo.EnumClass> {
|
||||
enum entry ENTRY1
|
||||
|
||||
enum entry ENTRY2
|
||||
|
||||
private constructor EnumClass()
|
||||
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: foo.EnumClass): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): foo.EnumClass
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<foo.EnumClass>
|
||||
}
|
||||
}
|
||||
Vendored
+17
@@ -0,0 +1,17 @@
|
||||
// !USE_EXPERIMENTAL: kotlin.js.ExperimentalJsExport
|
||||
// !RENDER_DIAGNOSTICS_MESSAGES
|
||||
|
||||
@file:JsExport
|
||||
|
||||
package foo
|
||||
|
||||
<!WRONG_EXPORTED_DECLARATION("inline function with reified type parameters")!>inline fun <reified T> inlineReifiedFun(x: Any)<!> = x is T
|
||||
|
||||
<!WRONG_EXPORTED_DECLARATION("suspend function")!>suspend fun suspendFun()<!> { }
|
||||
|
||||
<!WRONG_EXPORTED_DECLARATION("extension property")!>val String.extensionProperty<!>
|
||||
get() = this.length
|
||||
|
||||
enum class <!WRONG_EXPORTED_DECLARATION("enum class")!>EnumClass<!> { ENTRY1, ENTRY2 }
|
||||
|
||||
annotation class <!WRONG_EXPORTED_DECLARATION("annotation class")!>AnnotationClass<!>
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
package
|
||||
|
||||
package foo {
|
||||
public val kotlin.String.extensionProperty: kotlin.Int
|
||||
public inline fun </*0*/ reified T> inlineReifiedFun(/*0*/ x: kotlin.Any): kotlin.Boolean
|
||||
public suspend fun suspendFun(): kotlin.Unit
|
||||
|
||||
public final annotation class AnnotationClass : kotlin.Annotation {
|
||||
public constructor AnnotationClass()
|
||||
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
|
||||
}
|
||||
|
||||
public final enum class EnumClass : kotlin.Enum<foo.EnumClass> {
|
||||
enum entry ENTRY1
|
||||
|
||||
enum entry ENTRY2
|
||||
|
||||
private constructor EnumClass()
|
||||
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: foo.EnumClass): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): foo.EnumClass
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<foo.EnumClass>
|
||||
}
|
||||
}
|
||||
+48
@@ -334,6 +334,54 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/export")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Export extends AbstractDiagnosticsTestWithJsStdLib {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInExport() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib/export"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@TestMetadata("extendingNonExportedType.kt")
|
||||
public void testExtendingNonExportedType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/export/extendingNonExportedType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jsExportOnNestedDeclarations.kt")
|
||||
public void testJsExportOnNestedDeclarations() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/export/jsExportOnNestedDeclarations.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("secondaryConstructorWithoutJsName.kt")
|
||||
public void testSecondaryConstructorWithoutJsName() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/export/secondaryConstructorWithoutJsName.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unexportableTypesInSignature.kt")
|
||||
public void testUnexportableTypesInSignature() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/export/unexportableTypesInSignature.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("unexportableTypesInTypeParameters.kt")
|
||||
public void testUnexportableTypesInTypeParameters() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/export/unexportableTypesInTypeParameters.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("wrongExportedDeclaration.kt")
|
||||
public void testWrongExportedDeclaration() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/export/wrongExportedDeclaration.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("wrongExportedDeclarationInExportedFile.kt")
|
||||
public void testWrongExportedDeclarationInExportedFile() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithJsStdLib/export/wrongExportedDeclarationInExportedFile.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/testsWithJsStdLib/inline")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.getNameForAnnotatedObject
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils.isNativeObject
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||
@@ -40,7 +41,7 @@ import kotlin.math.abs
|
||||
* A new instance of this class can be created for each request, however, it's recommended to use stable instance, since
|
||||
* [NameSuggestion] supports caching.
|
||||
*/
|
||||
class NameSuggestion {
|
||||
class NameSuggestion(val bindingContext: BindingContext) {
|
||||
private val cache: MutableMap<DeclarationDescriptor, SuggestedName?> = Collections.synchronizedMap(WeakHashMap())
|
||||
|
||||
/**
|
||||
@@ -112,7 +113,7 @@ class NameSuggestion {
|
||||
// Local functions and variables are always private with their own names as suggested names
|
||||
is CallableDescriptor ->
|
||||
if (DescriptorUtils.isDescriptorWithLocalVisibility(descriptor)) {
|
||||
val ownName = getNameForAnnotatedObject(descriptor) ?: getSuggestedName(descriptor)
|
||||
val ownName = getNameForAnnotatedObject(descriptor, bindingContext) ?: getSuggestedName(descriptor)
|
||||
var name = ownName
|
||||
var scope = descriptor.containingDeclaration
|
||||
|
||||
@@ -195,7 +196,7 @@ class NameSuggestion {
|
||||
|
||||
parts.reverse()
|
||||
val unmangledName = parts.joinToString("$")
|
||||
val (id, stable) = mangleNameIfNecessary(unmangledName, fixedDescriptor)
|
||||
val (id, stable) = mangleNameIfNecessary(unmangledName, fixedDescriptor, bindingContext)
|
||||
return SuggestedName(listOf(id), stable, fixedDescriptor, current)
|
||||
}
|
||||
|
||||
@@ -217,7 +218,7 @@ class NameSuggestion {
|
||||
}
|
||||
|
||||
companion object {
|
||||
private fun mangleNameIfNecessary(baseName: String, descriptor: DeclarationDescriptor): NameAndStability {
|
||||
private fun mangleNameIfNecessary(baseName: String, descriptor: DeclarationDescriptor, bindingContext: BindingContext): NameAndStability {
|
||||
// If we have a callable descriptor (property or method) it can override method in a parent class.
|
||||
// Traverse to the topmost overridden method.
|
||||
// It does not matter which path to choose during traversal, since front-end must ensure
|
||||
@@ -230,7 +231,7 @@ class NameSuggestion {
|
||||
}
|
||||
|
||||
// If declaration is marked with either external, @native, @library or @JsName, return its stable name as is.
|
||||
val nativeName = getNameForAnnotatedObject(overriddenDescriptor)
|
||||
val nativeName = getNameForAnnotatedObject(overriddenDescriptor, bindingContext)
|
||||
if (nativeName != null) return NameAndStability(nativeName, true)
|
||||
|
||||
if (overriddenDescriptor is FunctionDescriptor) {
|
||||
|
||||
@@ -31,11 +31,13 @@ import org.jetbrains.kotlin.types.DynamicTypesAllowed
|
||||
object JsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
DynamicTypesAllowed(),
|
||||
additionalDeclarationCheckers = listOf(
|
||||
NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(),
|
||||
JsNameChecker, JsModuleChecker, JsExternalFileChecker,
|
||||
JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker
|
||||
NativeInvokeChecker(), NativeGetterChecker(), NativeSetterChecker(),
|
||||
JsNameChecker, JsModuleChecker, JsExternalFileChecker,
|
||||
JsExternalChecker, JsInheritanceChecker, JsMultipleInheritanceChecker,
|
||||
JsRuntimeAnnotationChecker,
|
||||
JsDynamicDeclarationChecker,
|
||||
JsExportAnnotationChecker,
|
||||
JsExportDeclarationChecker
|
||||
),
|
||||
additionalCallCheckers = listOf(
|
||||
JsModuleCallChecker,
|
||||
@@ -46,7 +48,6 @@ object JsPlatformConfigurator : PlatformConfiguratorBase(
|
||||
identifierChecker = JsIdentifierChecker
|
||||
) {
|
||||
override fun configureModuleComponents(container: StorageComponentContainer) {
|
||||
container.useInstance(NameSuggestion())
|
||||
container.useImpl<JsCallChecker>()
|
||||
container.useImpl<JsTypeSpecificityComparator>()
|
||||
container.useImpl<JsNameClashChecker>()
|
||||
|
||||
+4
@@ -100,6 +100,10 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
"Can't apply multiple inheritance here, since it's impossible to generate bridge for system function {0}",
|
||||
Renderers.DECLARATION_NAME_WITH_KIND)
|
||||
|
||||
put(ErrorsJs.NESTED_JS_EXPORT, "@JsExport is only allowed on files and top-level declarations")
|
||||
put(ErrorsJs.WRONG_EXPORTED_DECLARATION, "Declaration of such kind ({0}) can't be exported to JS", Renderers.STRING)
|
||||
put(ErrorsJs.NON_EXPORTABLE_TYPE, "Exported declaration uses non-exportable {0} type: {1}", Renderers.STRING, RENDER_TYPE)
|
||||
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,10 @@ public interface ErrorsJs {
|
||||
DiagnosticFactory1<PsiElement, CallableMemberDescriptor> WRONG_MULTIPLE_INHERITANCE =
|
||||
DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
DiagnosticFactory0<PsiElement> NESTED_JS_EXPORT = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory1<KtExpression, String> WRONG_EXPORTED_DECLARATION = DiagnosticFactory1.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
DiagnosticFactory2<PsiElement, String, KotlinType> NON_EXPORTABLE_TYPE = DiagnosticFactory2.create(ERROR, DECLARATION_SIGNATURE_OR_DEFAULT);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
{
|
||||
|
||||
+2
-1
@@ -25,8 +25,9 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
|
||||
class JsBuiltinNameClashChecker(private val nameSuggestion: NameSuggestion) : DeclarationChecker {
|
||||
class JsBuiltinNameClashChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val nameSuggestion = NameSuggestion(context.trace.bindingContext)
|
||||
if (AnnotationsUtils.isNativeObject(descriptor)) return
|
||||
if (descriptor.containingDeclaration !is ClassDescriptor) return
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||
|
||||
object JsExportAnnotationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val trace = context.trace
|
||||
|
||||
val jsExport = AnnotationsUtils.getJsExportAnnotation(descriptor) ?: return
|
||||
val jsExportPsi = jsExport.source.getPsi() ?: declaration
|
||||
|
||||
if (descriptor !is PackageFragmentDescriptor && !DescriptorUtils.isTopLevelDeclaration(descriptor)) {
|
||||
trace.report(ErrorsJs.NESTED_JS_EXPORT.on(jsExportPsi))
|
||||
}
|
||||
}
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind.*
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||
import org.jetbrains.kotlin.resolve.inline.isInlineWithReified
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
|
||||
object JsExportDeclarationChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val trace = context.trace
|
||||
val bindingContext = trace.bindingContext
|
||||
|
||||
fun checkTypeParameter(descriptor: TypeParameterDescriptor) {
|
||||
for (upperBound in descriptor.upperBounds) {
|
||||
if (!isTypeExportable(upperBound, bindingContext)) {
|
||||
val typeParameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)!!
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(typeParameterDeclaration, "upper bound", upperBound))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun checkValueParameter(descriptor: ValueParameterDescriptor) {
|
||||
if (!isTypeExportable(descriptor.type, bindingContext)) {
|
||||
val valueParameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)!!
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(valueParameterDeclaration, "parameter", descriptor.type))
|
||||
}
|
||||
}
|
||||
|
||||
if (!AnnotationsUtils.isExportedObject(descriptor, bindingContext)) return
|
||||
if (descriptor !is MemberDescriptor)
|
||||
return
|
||||
|
||||
val hasJsName = AnnotationsUtils.getJsNameAnnotation(descriptor) != null
|
||||
|
||||
fun reportWrongExportedDeclaration(kind: String) {
|
||||
trace.report(ErrorsJs.WRONG_EXPORTED_DECLARATION.on(declaration, kind))
|
||||
}
|
||||
|
||||
if (descriptor.isExpect) {
|
||||
reportWrongExportedDeclaration("expect")
|
||||
}
|
||||
|
||||
when (descriptor) {
|
||||
is FunctionDescriptor -> {
|
||||
for (typeParameter in descriptor.typeParameters) {
|
||||
checkTypeParameter(typeParameter)
|
||||
}
|
||||
|
||||
if (descriptor.isInlineWithReified()) {
|
||||
reportWrongExportedDeclaration("inline function with reified type parameters")
|
||||
return
|
||||
}
|
||||
|
||||
if (descriptor.isSuspend) {
|
||||
reportWrongExportedDeclaration("suspend function")
|
||||
return
|
||||
}
|
||||
|
||||
if (descriptor is ConstructorDescriptor) {
|
||||
if (!descriptor.isPrimary && !hasJsName)
|
||||
reportWrongExportedDeclaration("secondary constructor without @JsName")
|
||||
}
|
||||
|
||||
// Properties are checked instead of property accessors
|
||||
if (descriptor !is PropertyAccessorDescriptor) {
|
||||
for (parameter in descriptor.valueParameters) {
|
||||
checkValueParameter(parameter)
|
||||
}
|
||||
|
||||
descriptor.returnType?.let { returnType ->
|
||||
if (!isTypeExportable(returnType, bindingContext, true)) {
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(declaration, "return", returnType))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is PropertyDescriptor -> {
|
||||
if (descriptor.isExtensionProperty) {
|
||||
reportWrongExportedDeclaration("extension property")
|
||||
return
|
||||
}
|
||||
if (!isTypeExportable(descriptor.type, bindingContext)) {
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(declaration, "property", descriptor.type))
|
||||
}
|
||||
}
|
||||
|
||||
is ClassDescriptor -> {
|
||||
for (typeParameter in descriptor.declaredTypeParameters) {
|
||||
checkTypeParameter(typeParameter)
|
||||
}
|
||||
|
||||
if (descriptor.kind == ENUM_CLASS) {
|
||||
reportWrongExportedDeclaration("enum class")
|
||||
return
|
||||
}
|
||||
if (descriptor.kind == ANNOTATION_CLASS) {
|
||||
reportWrongExportedDeclaration("annotation class")
|
||||
return
|
||||
}
|
||||
if (descriptor.kind == ENUM_ENTRY) {
|
||||
// Covered by ENUM_CLASS
|
||||
return
|
||||
}
|
||||
|
||||
for (superType in descriptor.defaultType.supertypes()) {
|
||||
if (!isTypeExportable(superType, bindingContext)) {
|
||||
trace.report(ErrorsJs.NON_EXPORTABLE_TYPE.on(declaration, "super", superType))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun isTypeExportable(type: KotlinType, bindingContext: BindingContext, isReturnType: Boolean = false): Boolean {
|
||||
if (isReturnType && type.isUnit())
|
||||
return true
|
||||
|
||||
if (type.isFunctionType) {
|
||||
val arguments = type.arguments
|
||||
val argumentsSize = type.arguments.size - 1
|
||||
for (i in 0 until argumentsSize) {
|
||||
if (!isTypeExportable(arguments[i].type, bindingContext))
|
||||
return false
|
||||
}
|
||||
if (!isTypeExportable(arguments.last().type, bindingContext, isReturnType = true))
|
||||
return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
for (argument: TypeProjection in type.arguments) {
|
||||
if (!isTypeExportable(argument.type, bindingContext))
|
||||
return false
|
||||
}
|
||||
|
||||
val nonNullable = type.makeNotNullable()
|
||||
|
||||
// Is primitive exportable type
|
||||
if (nonNullable.isAnyOrNullableAny() ||
|
||||
nonNullable.isDynamic() ||
|
||||
nonNullable.isBoolean() ||
|
||||
KotlinBuiltIns.isThrowableOrNullableThrowable(nonNullable) ||
|
||||
KotlinBuiltIns.isString(nonNullable) ||
|
||||
(nonNullable.isPrimitiveNumberOrNullableType() && !nonNullable.isLong()) ||
|
||||
nonNullable.isNothingOrNullableNothing() ||
|
||||
(KotlinBuiltIns.isArray(type)) ||
|
||||
KotlinBuiltIns.isPrimitiveArray(type)
|
||||
) return true
|
||||
|
||||
val descriptor: ClassifierDescriptor = type.constructor.declarationDescriptor ?: return false
|
||||
return descriptor.isEffectivelyExternal() || AnnotationsUtils.isExportedObject(descriptor, bindingContext)
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -5,18 +5,29 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.resolve.diagnostics
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion
|
||||
import org.jetbrains.kotlin.js.translate.utils.AnnotationsUtils
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
|
||||
|
||||
class JsNameCharsChecker(private val suggestion: NameSuggestion) : DeclarationChecker {
|
||||
class JsNameCharsChecker : DeclarationChecker {
|
||||
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
|
||||
val bindingContext = context.trace.bindingContext
|
||||
|
||||
if (descriptor is PropertyAccessorDescriptor && AnnotationsUtils.getJsName(descriptor) == null) return
|
||||
|
||||
// This case will be reported as WRONG_EXPORTED_DECLARATION for
|
||||
// secondary constructor with missing JsName. Skipping it here to simplify further logic.
|
||||
if (descriptor is ConstructorDescriptor &&
|
||||
AnnotationsUtils.getJsName(descriptor) == null &&
|
||||
AnnotationsUtils.isExportedObject(descriptor, bindingContext)
|
||||
) return
|
||||
|
||||
val suggestion = NameSuggestion(bindingContext)
|
||||
val suggestedName = suggestion.suggest(descriptor) ?: return
|
||||
if (suggestedName.stable && suggestedName.names.any { NameSuggestion.sanitizeName(it) != it }) {
|
||||
context.trace.report(ErrorsJs.NAME_CONTAINS_ILLEGAL_CHARS.on(declaration))
|
||||
|
||||
+3
-1
@@ -35,7 +35,6 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isExtensionProperty
|
||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||
|
||||
class JsNameClashChecker(
|
||||
private val nameSuggestion: NameSuggestion,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) : DeclarationChecker {
|
||||
companion object {
|
||||
@@ -45,6 +44,7 @@ class JsNameClashChecker(
|
||||
Errors.PACKAGE_OR_CLASSIFIER_REDECLARATION)
|
||||
}
|
||||
|
||||
lateinit var nameSuggestion: NameSuggestion
|
||||
private val scopes = mutableMapOf<DeclarationDescriptor, MutableMap<String, DeclarationDescriptor>>()
|
||||
private val clashedFakeOverrides = mutableMapOf<DeclarationDescriptor, Pair<DeclarationDescriptor, DeclarationDescriptor>>()
|
||||
private val clashedDescriptors = mutableSetOf<Pair<DeclarationDescriptor, String>>()
|
||||
@@ -62,6 +62,8 @@ class JsNameClashChecker(
|
||||
diagnosticHolder: DiagnosticSink, bindingContext: BindingContext
|
||||
) {
|
||||
if (descriptor is ConstructorDescriptor && descriptor.isPrimary) return
|
||||
if (!this::nameSuggestion.isInitialized || nameSuggestion.bindingContext !== bindingContext)
|
||||
nameSuggestion = NameSuggestion(bindingContext)
|
||||
|
||||
for (suggested in nameSuggestion.suggestAllPossibleNames(descriptor)) {
|
||||
if (suggested.stable && suggested.scope is ClassOrPackageFragmentDescriptor && presentsInGeneratedCode(suggested.descriptor)) {
|
||||
|
||||
@@ -40,6 +40,7 @@ import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt.isEf
|
||||
|
||||
public final class AnnotationsUtils {
|
||||
private static final String JS_NAME = "kotlin.js.JsName";
|
||||
private static final FqName JS_EXPORT = new FqName("kotlin.js.JsExport");
|
||||
public static final FqName JS_MODULE_ANNOTATION = new FqName("kotlin.js.JsModule");
|
||||
private static final FqName JS_NON_MODULE_ANNOTATION = new FqName("kotlin.js.JsNonModule");
|
||||
public static final FqName JS_QUALIFIER_ANNOTATION = new FqName("kotlin.js.JsQualifier");
|
||||
@@ -83,7 +84,10 @@ public final class AnnotationsUtils {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getNameForAnnotatedObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
public static String getNameForAnnotatedObject(
|
||||
@NotNull DeclarationDescriptor descriptor,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
String defaultJsName = getJsName(descriptor);
|
||||
|
||||
for (PredefinedAnnotation annotation : PredefinedAnnotation.Companion.getWITH_CUSTOM_NAME()) {
|
||||
@@ -97,7 +101,7 @@ public final class AnnotationsUtils {
|
||||
return name != null ? name : descriptor.getName().asString();
|
||||
}
|
||||
|
||||
if (defaultJsName == null && isEffectivelyExternalMember(descriptor)) {
|
||||
if (defaultJsName == null && (isEffectivelyExternalMember(descriptor) || isExportedObject(descriptor, bindingContext))) {
|
||||
return descriptor.getName().asString();
|
||||
}
|
||||
|
||||
@@ -112,6 +116,23 @@ public final class AnnotationsUtils {
|
||||
return descriptor.getAnnotations().findAnnotation(annotation.getFqName());
|
||||
}
|
||||
|
||||
public static boolean isExportedObject(@NotNull DeclarationDescriptor descriptor, @NotNull BindingContext bindingContext) {
|
||||
if (descriptor instanceof MemberDescriptor) {
|
||||
MemberDescriptor memberDescriptor = (MemberDescriptor) descriptor;
|
||||
if (memberDescriptor.getVisibility() != Visibilities.PUBLIC) return false;
|
||||
}
|
||||
|
||||
if (hasAnnotationOrInsideAnnotatedClass(descriptor, JS_EXPORT)) return true;
|
||||
|
||||
if (CollectionsKt.any(getContainingFileAnnotations(bindingContext, descriptor), annotation ->
|
||||
JS_EXPORT.equals(annotation.getFqName())
|
||||
)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isNativeObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
if (hasAnnotationOrInsideAnnotatedClass(descriptor, PredefinedAnnotation.NATIVE) || isEffectivelyExternalMember(descriptor)) return true;
|
||||
|
||||
@@ -154,6 +175,11 @@ public final class AnnotationsUtils {
|
||||
return descriptor.getAnnotations().findAnnotation(new FqName(JS_NAME));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AnnotationDescriptor getJsExportAnnotation(@NotNull DeclarationDescriptor descriptor) {
|
||||
return descriptor.getAnnotations().findAnnotation(JS_EXPORT);
|
||||
}
|
||||
|
||||
public static boolean isPredefinedObject(@NotNull DeclarationDescriptor descriptor) {
|
||||
if (descriptor instanceof MemberDescriptor && ((MemberDescriptor) descriptor).isExpect()) return true;
|
||||
if (isEffectivelyExternalMember(descriptor)) return true;
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.js.translate.context.Namer
|
||||
import org.jetbrains.kotlin.js.translate.expression.InlineMetadata
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils.getModuleName
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||
import org.jetbrains.kotlin.utils.JsLibraryUtils
|
||||
import java.io.File
|
||||
@@ -55,7 +56,8 @@ private val SPECIAL_FUNCTION_PATTERN = Regex("var\\s+($JS_IDENTIFIER)\\s*=\\s*($
|
||||
|
||||
class FunctionReader(
|
||||
private val reporter: JsConfig.Reporter,
|
||||
private val config: JsConfig
|
||||
private val config: JsConfig,
|
||||
private val bindingContext: BindingContext
|
||||
) {
|
||||
/**
|
||||
* fileContent: .js file content, that contains this module definition.
|
||||
@@ -205,7 +207,7 @@ class FunctionReader(
|
||||
info: ModuleInfo,
|
||||
fragment: JsProgramFragment
|
||||
): FunctionWithWrapper {
|
||||
val tag = Namer.getFunctionTag(descriptor, config)
|
||||
val tag = Namer.getFunctionTag(descriptor, config, bindingContext)
|
||||
val moduleReference = fragment.inlineModuleMap[tag]?.deepCopy() ?: fragment.scope.declareName("_").makeRef()
|
||||
val allDefinedNames = collectDefinedNamesInAllScopes(fn.function)
|
||||
val replacements = hashMapOf(
|
||||
@@ -234,7 +236,7 @@ class FunctionReader(
|
||||
|
||||
private fun readFunctionFromSource(descriptor: CallableDescriptor, info: ModuleInfo): FunctionWithWrapper? {
|
||||
val source = info.fileContent
|
||||
var tag = Namer.getFunctionTag(descriptor, config)
|
||||
var tag = Namer.getFunctionTag(descriptor, config, bindingContext)
|
||||
var index = source.indexOf(tag)
|
||||
|
||||
// Hack for compatibility with old versions of stdlib
|
||||
|
||||
@@ -13,11 +13,13 @@ import org.jetbrains.kotlin.js.inline.context.FunctionDefinitionLoader
|
||||
import org.jetbrains.kotlin.js.inline.context.InliningContext
|
||||
|
||||
import org.jetbrains.kotlin.js.translate.general.AstGenerationResult
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class JsInliner(
|
||||
val reporter: JsConfig.Reporter,
|
||||
val config: JsConfig,
|
||||
val trace: DiagnosticSink,
|
||||
val bindingContext: BindingContext,
|
||||
val translationResult: AstGenerationResult
|
||||
) {
|
||||
|
||||
|
||||
+3
-3
@@ -75,7 +75,7 @@ class FunctionDefinitionLoader(
|
||||
return lookUpFunctionDirect(call, scope) ?: lookUpFunctionIndirect(call, scope) ?: lookUpFunctionExternal(call, scope.fragment)
|
||||
}
|
||||
|
||||
private val functionReader = FunctionReader(inliner.reporter, inliner.config)
|
||||
private val functionReader = FunctionReader(inliner.reporter, inliner.config, inliner.bindingContext)
|
||||
|
||||
private data class FragmentInfo(
|
||||
val functions: Map<JsName, FunctionWithWrapper>,
|
||||
@@ -160,7 +160,7 @@ class FunctionDefinitionLoader(
|
||||
private fun lookUpFunctionDirect(call: JsInvocation, callsiteScope: InliningScope): InlineFunctionDefinition? {
|
||||
val descriptor = call.descriptor ?: return null
|
||||
|
||||
val tag = Namer.getFunctionTag(descriptor, inliner.config)
|
||||
val tag = Namer.getFunctionTag(descriptor, inliner.config, inliner.bindingContext)
|
||||
|
||||
val definitionFragment = fragmentByTag(tag) ?: return null
|
||||
|
||||
@@ -178,7 +178,7 @@ class FunctionDefinitionLoader(
|
||||
private fun lookUpFunctionExternal(call: JsInvocation, fragment: JsProgramFragment): InlineFunctionDefinition? =
|
||||
call.descriptor?.let { descriptor ->
|
||||
functionReader[descriptor, fragment]?.let {
|
||||
InlineFunctionDefinition(it, Namer.getFunctionTag(descriptor, inliner.config))
|
||||
InlineFunctionDefinition(it, Namer.getFunctionTag(descriptor, inliner.config, inliner.bindingContext))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,6 +32,11 @@ fun main(args: Array<String>) {
|
||||
model("typescript-export/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS_IR)
|
||||
}
|
||||
|
||||
testClass<AbstractLegacyJsTypeScriptExportTest> {
|
||||
model("typescript-export/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS)
|
||||
}
|
||||
|
||||
|
||||
testClass<AbstractSourceMapGenerationSmokeTest> {
|
||||
model("sourcemap/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS)
|
||||
}
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test.semantics
|
||||
|
||||
import org.jetbrains.kotlin.js.test.BasicBoxTest
|
||||
|
||||
abstract class AbstractLegacyJsTypeScriptExportTest : BasicBoxTest(
|
||||
pathToTestDir = TEST_DATA_DIR_PATH + "typescript-export/",
|
||||
testGroupOutputDirPrefix = "legacy-typescript-export/",
|
||||
pathToRootOutputDir = TEST_DATA_DIR_PATH
|
||||
)
|
||||
Generated
+139
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.test.semantics;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils;
|
||||
import org.jetbrains.kotlin.test.TargetBackend;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("js/js.translator/testData/typescript-export")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public class LegacyJsTypeScriptExportTestGenerated extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInTypescript_export() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/declarations")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Declarations extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInDeclarations() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/declarations"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("declarations.kt")
|
||||
public void testDeclarations() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/declarations/declarations.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/inheritance")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Inheritance extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInInheritance() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/inheritance"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("inheritance.kt")
|
||||
public void testInheritance() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/inheritance/inheritance.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/namespaces")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Namespaces extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInNamespaces() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/namespaces"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("namespaces.kt")
|
||||
public void testNamespaces() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/namespaces/namespaces.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/primitives")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Primitives extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInPrimitives() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/primitives"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("primitives.kt")
|
||||
public void testPrimitives() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/primitives/primitives.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/selectiveExport")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SelectiveExport extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSelectiveExport() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/selectiveExport"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("selectiveExport.kt")
|
||||
public void testSelectiveExport() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/selectiveExport/selectiveExport.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("js/js.translator/testData/typescript-export/visibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Visibility extends AbstractLegacyJsTypeScriptExportTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInVisibility() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("js/js.translator/testData/typescript-export/visibility"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.JS, true);
|
||||
}
|
||||
|
||||
@TestMetadata("visibility.kt")
|
||||
public void testVisibility() throws Exception {
|
||||
runTest("js/js.translator/testData/typescript-export/visibility/visibility.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -167,6 +167,7 @@ class K2JSTranslator @JvmOverloads constructor(
|
||||
reporter,
|
||||
config,
|
||||
analysisResult.bindingTrace,
|
||||
bindingTrace.bindingContext,
|
||||
translationResult
|
||||
).process()
|
||||
if (hasError(diagnostics)) return TranslationResult.Fail(diagnostics)
|
||||
|
||||
@@ -34,12 +34,12 @@ import org.jetbrains.kotlin.js.backend.ast.metadata.TypeCheck;
|
||||
import org.jetbrains.kotlin.js.config.JsConfig;
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion;
|
||||
import org.jetbrains.kotlin.js.naming.SuggestedName;
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatformAnalyzerServices;
|
||||
import org.jetbrains.kotlin.js.translate.intrinsic.functions.factories.ArrayFIF;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsAstUtils;
|
||||
import org.jetbrains.kotlin.js.translate.utils.JsDescriptorUtils;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -57,8 +57,8 @@ public final class Namer {
|
||||
public static final String KOTLIN_NAME = KotlinLanguage.NAME;
|
||||
public static final String KOTLIN_LOWER_NAME = KOTLIN_NAME.toLowerCase();
|
||||
|
||||
public static final String EQUALS_METHOD_NAME = getStableMangledNameForDescriptor(JsPlatformAnalyzerServices.INSTANCE.getBuiltIns().getAny(), "equals");
|
||||
public static final String COMPARE_TO_METHOD_NAME = getStableMangledNameForDescriptor(JsPlatformAnalyzerServices.INSTANCE.getBuiltIns().getComparable(), "compareTo");
|
||||
public static final String EQUALS_METHOD_NAME = "equals";
|
||||
public static final String COMPARE_TO_METHOD_NAME = "compareTo_11rb$";
|
||||
public static final String LONG_FROM_NUMBER = "fromNumber";
|
||||
public static final String LONG_TO_NUMBER = "toNumber";
|
||||
public static final String LONG_FROM_INT = "fromInt";
|
||||
@@ -134,7 +134,11 @@ public final class Namer {
|
||||
public static final String SAM_FIELD_NAME = "function$";
|
||||
|
||||
@NotNull
|
||||
public static String getFunctionTag(@NotNull CallableDescriptor functionDescriptor, @NotNull JsConfig config) {
|
||||
public static String getFunctionTag(
|
||||
@NotNull CallableDescriptor functionDescriptor,
|
||||
@NotNull JsConfig config,
|
||||
@NotNull BindingContext bindingContext
|
||||
) {
|
||||
String intrinsicTag = ArrayFIF.INSTANCE.getTag(functionDescriptor, config);
|
||||
if (intrinsicTag != null) return intrinsicTag;
|
||||
|
||||
@@ -147,7 +151,7 @@ public final class Namer {
|
||||
qualifier = fqNameParent.asString();
|
||||
}
|
||||
|
||||
SuggestedName suggestedName = new NameSuggestion().suggest(functionDescriptor);
|
||||
SuggestedName suggestedName = new NameSuggestion(bindingContext).suggest(functionDescriptor);
|
||||
assert suggestedName != null : "Suggested name can be null only for module descriptors: " + functionDescriptor;
|
||||
String mangledName = suggestedName.getNames().get(0);
|
||||
return StringUtil.join(Arrays.asList(moduleName, qualifier, mangledName), ".");
|
||||
@@ -225,18 +229,6 @@ public final class Namer {
|
||||
callSetProperty = kotlin("callSetter");
|
||||
}
|
||||
|
||||
// TODO: get rid of this function
|
||||
@NotNull
|
||||
private static String getStableMangledNameForDescriptor(@NotNull ClassDescriptor descriptor, @NotNull String functionName) {
|
||||
Collection<? extends SimpleFunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getContributedFunctions(
|
||||
Name.identifier(functionName), NoLookupLocation.FROM_BACKEND
|
||||
);
|
||||
assert functions.size() == 1 : "Can't select a single function: " + functionName + " in " + descriptor;
|
||||
SuggestedName suggested = new NameSuggestion().suggest(functions.iterator().next());
|
||||
assert suggested != null : "Suggested name for class members is always non-null: " + functions.iterator().next();
|
||||
return suggested.getNames().get(0);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JsNameRef kotlin(@NotNull JsName name) {
|
||||
return pureFqn(name, kotlinObject());
|
||||
|
||||
@@ -111,7 +111,7 @@ public final class StaticContext {
|
||||
private final JsImportedModule currentModuleAsImported;
|
||||
|
||||
@NotNull
|
||||
private final NameSuggestion nameSuggestion = new NameSuggestion();
|
||||
private final NameSuggestion nameSuggestion;
|
||||
|
||||
@NotNull
|
||||
private final Map<DeclarationDescriptor, JsName> nameCache = new HashMap<>();
|
||||
@@ -169,6 +169,7 @@ public final class StaticContext {
|
||||
fragment = new JsProgramFragment(rootFunction.getScope(), packageFqn);
|
||||
|
||||
this.bindingTrace = bindingTrace;
|
||||
this.nameSuggestion = new NameSuggestion(bindingTrace.getBindingContext());
|
||||
this.namer = Namer.newInstance(program.getRootScope());
|
||||
this.intrinsics = new Intrinsics();
|
||||
this.rootScope = fragment.getScope();
|
||||
@@ -801,7 +802,7 @@ public final class StaticContext {
|
||||
|
||||
public void addInlineCall(@NotNull CallableDescriptor descriptor) {
|
||||
descriptor = (CallableDescriptor) JsDescriptorUtils.findRealInlineDeclaration(descriptor);
|
||||
String tag = Namer.getFunctionTag(descriptor, config);
|
||||
String tag = Namer.getFunctionTag(descriptor, config, getBindingContext());
|
||||
JsExpression moduleExpression = exportModuleForInline(DescriptorUtils.getContainingModule(descriptor));
|
||||
if (moduleExpression == null) {
|
||||
moduleExpression = getModuleExpressionFor(descriptor);
|
||||
|
||||
+2
-2
@@ -179,13 +179,13 @@ public class TranslationContext {
|
||||
@NotNull
|
||||
public TranslationContext newFunctionBodyWithUsageTracker(@NotNull JsFunction fun, @NotNull MemberDescriptor descriptor) {
|
||||
DynamicContext dynamicContext = DynamicContext.newContext(fun.getScope(), fun.getBody());
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor);
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, bindingContext());
|
||||
return new TranslationContext(this, this.staticContext, dynamicContext, this.aliasingContext.inner(), usageTracker, descriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TranslationContext innerWithUsageTracker(@NotNull MemberDescriptor descriptor) {
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor);
|
||||
UsageTracker usageTracker = new UsageTracker(this.usageTracker, descriptor, bindingContext());
|
||||
return new TranslationContext(this, staticContext, dynamicContext, aliasingContext.inner(), usageTracker, descriptor);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsScope
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.descriptor
|
||||
import org.jetbrains.kotlin.js.descriptorUtils.isCoroutineLambda
|
||||
import org.jetbrains.kotlin.js.naming.NameSuggestion
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.*
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
@@ -30,7 +31,8 @@ private val CAPTURED_RECEIVER_NAME_PREFIX : String = "this$"
|
||||
|
||||
class UsageTracker(
|
||||
private val parent: UsageTracker?,
|
||||
val containingDescriptor: MemberDescriptor
|
||||
val containingDescriptor: MemberDescriptor,
|
||||
val bindingContext: BindingContext
|
||||
) {
|
||||
|
||||
private val captured = linkedMapOf<DeclarationDescriptor, JsName>()
|
||||
@@ -175,7 +177,7 @@ class UsageTracker(
|
||||
|
||||
// Append 'closure$' prefix to avoid name clash between closure and member fields in case of local classes
|
||||
else -> {
|
||||
val mangled = NameSuggestion.sanitizeName(NameSuggestion().suggest(this)!!.names.last())
|
||||
val mangled = NameSuggestion.sanitizeName(NameSuggestion(bindingContext).suggest(this)!!.names.last())
|
||||
"closure\$$mangled"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ class InlineMetadata(val tag: JsStringLiteral, val function: FunctionWithWrapper
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun compose(function: JsFunction, descriptor: CallableDescriptor, context: TranslationContext): InlineMetadata {
|
||||
val tag = JsStringLiteral(Namer.getFunctionTag(descriptor, context.config))
|
||||
val tag = JsStringLiteral(Namer.getFunctionTag(descriptor, context.config, context.bindingContext()))
|
||||
val inliningContext = context.inlineFunctionContext!!
|
||||
val block = JsBlock(inliningContext.importBlock.statements + inliningContext.prototypeBlock.statements +
|
||||
inliningContext.declarationsBlock.statements + JsReturn(function))
|
||||
|
||||
+3
-4
@@ -1,16 +1,15 @@
|
||||
// SKIP_MINIFICATION
|
||||
|
||||
// Exported declaration uses non-exportable return type: Char
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
@JsName("foo")
|
||||
@JsExport
|
||||
fun foo(): Char = '1'
|
||||
|
||||
@JsExport
|
||||
val p1: Char = '2'
|
||||
|
||||
@JsExport
|
||||
var p2: Char = '3'
|
||||
|
||||
@JsExport
|
||||
var p3: Char = '4'
|
||||
get() = field + 1
|
||||
set(value) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1276
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
@JsExport
|
||||
class A(val x: Char)
|
||||
|
||||
fun typeOf(x: dynamic): String = js("typeof x")
|
||||
|
||||
@@ -4,7 +4,6 @@ interface I {
|
||||
val a: Char
|
||||
}
|
||||
|
||||
@JsExport
|
||||
object X : I {
|
||||
override var a = '#'
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1289
|
||||
// IGNORE_BACKEND: JS_IR
|
||||
|
||||
@JsExport
|
||||
open class A {
|
||||
val foo: Char
|
||||
get() = 'X'
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1282
|
||||
|
||||
@JsExport
|
||||
interface I {
|
||||
fun ok(): String
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ class A {
|
||||
}
|
||||
}
|
||||
|
||||
@JsExport
|
||||
val A.z: Int
|
||||
@JsName("getZ_") get() = 42
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
@file:JsExport
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
@file:JsExport
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// FILE: file1.kt
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ declare namespace JS_TESTS {
|
||||
type Nullable<T> = T | null | undefined
|
||||
namespace foo {
|
||||
const _any: any;
|
||||
const _unit: void;
|
||||
function _nothing(): never
|
||||
const _throwable: Error;
|
||||
const _string: string;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
@file:JsExport
|
||||
|
||||
@@ -8,8 +9,6 @@ package foo
|
||||
|
||||
val _any: Any = Any()
|
||||
|
||||
val _unit: Unit = Unit
|
||||
|
||||
fun _nothing(): Nothing { throw Throwable() }
|
||||
|
||||
val _throwable: Throwable = Throwable()
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// FILE: file1.kt
|
||||
package foo
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// TARGET_BACKEND: JS_IR
|
||||
// CHECK_TYPESCRIPT_DECLARATIONS
|
||||
// RUN_PLAIN_BOX_FUNCTION
|
||||
// SKIP_MINIFICATION
|
||||
// SKIP_NODE_JS
|
||||
|
||||
// TODO fix statics export in DCE-driven mode
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
@@ -32,12 +32,33 @@ public expect annotation class JsName(val name: String)
|
||||
public annotation class ExperimentalJsExport
|
||||
|
||||
/**
|
||||
* Exports top-level declaration.
|
||||
* Exports top-level declaration on JS platform.
|
||||
*
|
||||
* Compiler exports from the module those top-level declarations that are marked with this annotation.
|
||||
* There is no effect if this annotation is applied to a non-top-level declaration.
|
||||
* Compiled module exposes declarations that are marked with this annotation without name mangling.
|
||||
*
|
||||
* This annotation has effect only on top-level declarations and only in IR-based JS backend.
|
||||
* This annotation can be applied to either files or top-level declarations.
|
||||
*
|
||||
* It is currently prohibited to export the following kinds of declarations:
|
||||
*
|
||||
* * `expect` declarations
|
||||
* * inline functions with reified type parameters
|
||||
* * suspend functions
|
||||
* * secondary constructors without `@JsName`
|
||||
* * extension properties
|
||||
* * enum classes
|
||||
* * annotation classes
|
||||
*
|
||||
* Signatures of exported declarations must only contain "exportable" types:
|
||||
*
|
||||
* * `dynamic`, `Any`, `String`, `Boolean`, `Byte`, `Short`, `Int`, `Float`, `Double`
|
||||
* * `BooleanArray`, `ByteArray`, `ShortArray`, `IntArray`, `FloatArray`, `DoubleArray`
|
||||
* * `Array<exportable-type>`
|
||||
* * Function types with exportable parameters and return types
|
||||
* * `external` or `@JsExport` classes and interfaces
|
||||
* * Nullable counterparts of types above
|
||||
* * Unit return type. Must not be nullable
|
||||
*
|
||||
* This annotation is experimental, meaning that restrictions mentioned above are subject to change.
|
||||
*/
|
||||
@ExperimentalJsExport
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
|
||||
@@ -162,12 +162,33 @@ public annotation class JsNonModule
|
||||
public annotation class JsQualifier(val value: String)
|
||||
|
||||
/**
|
||||
* Exports top-level declaration.
|
||||
* Exports top-level declaration on JS platform.
|
||||
*
|
||||
* Compiler exports from the module those top-level declarations that are marked with this annotation.
|
||||
* There is no effect if this annotation is applied to a non-top-level declaration.
|
||||
* Compiled module exposes declarations that are marked with this annotation without name mangling.
|
||||
*
|
||||
* This annotation has effect only on top-level declarations and only in IR-based JS backend.
|
||||
* This annotation can be applied to either files or top-level declarations.
|
||||
*
|
||||
* It is currently prohibited to export the following kinds of declarations:
|
||||
*
|
||||
* * `expect` declarations
|
||||
* * inline functions with reified type parameters
|
||||
* * suspend functions
|
||||
* * secondary constructors without `@JsName`
|
||||
* * extension properties
|
||||
* * enum classes
|
||||
* * annotation classes
|
||||
*
|
||||
* Signatures of exported declarations must only contain "exportable" types:
|
||||
*
|
||||
* * `dynamic`, `Any`, `String`, `Boolean`, `Byte`, `Short`, `Int`, `Float`, `Double`
|
||||
* * `BooleanArray`, `ByteArray`, `ShortArray`, `IntArray`, `FloatArray`, `DoubleArray`
|
||||
* * `Array<exportable-type>`
|
||||
* * Function types with exportable parameters and return types
|
||||
* * `external` or `@JsExport` classes and interfaces
|
||||
* * Nullable counterparts of types above
|
||||
* * Unit return type. Must not be nullable
|
||||
*
|
||||
* This annotation is experimental, meaning that restrictions mentioned above are subject to change.
|
||||
*/
|
||||
@ExperimentalJsExport
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
|
||||
Reference in New Issue
Block a user