diff --git a/compiler/testData/codegen/boxWasmJsInterop/wasmExport.kt b/compiler/testData/codegen/boxWasmJsInterop/wasmExport.kt index ed42c007418..3bf7db3b0bf 100644 --- a/compiler/testData/codegen/boxWasmJsInterop/wasmExport.kt +++ b/compiler/testData/codegen/boxWasmJsInterop/wasmExport.kt @@ -3,17 +3,17 @@ import kotlin.wasm.WasmExport @WasmExport -fun exportDefaultName(): String = "some string" +fun exportDefaultName(): Boolean = true -fun checkDefaultName(): Int = js("typeof wasmExports.exportDefaultName() === 'object'") +fun checkDefaultName(): Boolean = js("typeof wasmExports.exportDefaultName() !== 'object'") @WasmExport("exportOverriddenName") -fun exportWithName(): String = "some string" +fun exportWithName(): Boolean = true -fun checkOverriddenName(): Int = js("typeof wasmExports.exportOverriddenName() === 'object'") +fun checkOverriddenName(): Boolean = js("typeof wasmExports.exportOverriddenName() !== 'object'") fun box(): String { - if (checkDefaultName() != 1) return "checkDefaultName fail" - if (checkOverriddenName() != 1) return "checkOverriddenName fail" + if (!checkDefaultName()) return "checkDefaultName fail" + if (!checkOverriddenName()) return "checkOverriddenName fail" return "OK" } \ No newline at end of file diff --git a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.kt b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.kt index f1ae75722cb..44c98621a6e 100644 --- a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.kt +++ b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.kt @@ -21,3 +21,38 @@ fun foo4(): Int = 42 @JsExport() @WasmExport() fun foo6(): Int = 42 + +val p1 = (@WasmExport("a") fun () {}) + +@WasmExport("a") +fun foo7( +p0: Unit, +p1: String, +p2: Any, +p3: Int?, +p4: Boolean? +): Unit { + p0.toString() + p1.toString() + p2.toString() + p3.toString() + p4.toString() +} + +@WasmExport("a") +fun returnNullableUnit(): Unit? { return null } + +@WasmExport("a") +fun returnNullableBoolean(): Boolean? { return null } + +@WasmExport("a") +fun returnNullableAny(): Any? { return null } + +@WasmExport("a") +fun fooGeneric(x: T): T { return x } + +@WasmExport("a") +fun fooDeafultAndVararg( +a: Int = definedExternally, +vararg b: Int +): Unit { b.toString() } diff --git a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.kt b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.kt index e436de2b3e2..2736e746c3b 100644 --- a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.kt +++ b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.kt @@ -22,28 +22,28 @@ val p1 = (@WasmIm @WasmImport("a", "b") external fun foo3( - p0: Unit, - p1: String, - p2: Any, - p3: Int?, - p4: Boolean? + p0: Unit, + p1: String, + p2: Any, + p3: Int?, + p4: Boolean? ): Unit -@WasmImport("a", "b") +@WasmImport("a", "b") external fun returnNullableUnit(): Unit? -@WasmImport("a", "b") +@WasmImport("a", "b") external fun returnNullableBoolean(): Boolean? -@WasmImport("a", "b") +@WasmImport("a", "b") external fun returnNullableAny(): Any? -@WasmImport("a", "b") -external fun fooGeneric(x: T): T +@WasmImport("a", "b") +external fun fooGeneric(x: T): T @WasmImport("a", "b") external fun fooDeafultAndVararg( - a: Int = definedExternally, -vararg b: Int -): Unit \ No newline at end of file +a: Int = definedExternally, +vararg b: Int +): Unit diff --git a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/WasmPlatformConfigurator.kt b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/WasmPlatformConfigurator.kt index 08ff838b3e4..ca8b7b3cb13 100644 --- a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/WasmPlatformConfigurator.kt +++ b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/WasmPlatformConfigurator.kt @@ -30,9 +30,9 @@ object WasmPlatformConfigurator : PlatformConfiguratorBase( JsExportDeclarationChecker, WasmExternalDeclarationChecker, WasmImportAnnotationChecker, + WasmExportAnnotationChecker, WasmJsFunAnnotationChecker, WasmJsInteropTypesChecker, - WasmInteropTypesChecker, ), additionalCallCheckers = listOf( JsModuleCallChecker, diff --git a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/DefaultErrorMessagesWasm.kt b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/DefaultErrorMessagesWasm.kt index 3475302332d..7d39be949cd 100644 --- a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/DefaultErrorMessagesWasm.kt +++ b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/DefaultErrorMessagesWasm.kt @@ -31,10 +31,10 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy { put(ErrorsWasm.NESTED_WASM_IMPORT, "Only top-level functions can be imported with @WasmImport") put(ErrorsWasm.WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION, "Functions annotated with @WasmImport must be external") - put(ErrorsWasm.WASM_IMPORT_PARAMETER_DEFAULT_VALUE, "Default parameter values are not supported with @WasmImport") - put(ErrorsWasm.WASM_IMPORT_VARARG_PARAMETER, "Vararg parameters are not supported with @WasmImport") - put(ErrorsWasm.WASM_IMPORT_UNSUPPORTED_PARAMETER_TYPE, "Unsupported @WasmImport parameter type {0}", Renderers.RENDER_TYPE) - put(ErrorsWasm.WASM_IMPORT_UNSUPPORTED_RETURN_TYPE, "Unsupported @WasmImport return type {0}", Renderers.RENDER_TYPE) + put(ErrorsWasm.WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE, "Default parameter values are not supported with @WasmImport and @WasmExport") + put(ErrorsWasm.WASM_IMPORT_EXPORT_VARARG_PARAMETER, "Vararg parameters are not supported with @WasmImport and @WasmExport") + put(ErrorsWasm.WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE, "Unsupported @WasmImport and @WasmExport parameter type {0}", Renderers.RENDER_TYPE) + put(ErrorsWasm.WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE, "Unsupported @WasmImport and @WasmExport return type {0}", Renderers.RENDER_TYPE) put(ErrorsWasm.WRONG_JS_FUN_TARGET, "Only top-level external functions can be implemented using @JsFun") diff --git a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/ErrorsWasm.java b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/ErrorsWasm.java index 60a4746518f..631c7651a84 100644 --- a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/ErrorsWasm.java +++ b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/ErrorsWasm.java @@ -25,10 +25,10 @@ public interface ErrorsWasm { DiagnosticFactory0 NESTED_WASM_IMPORT = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 WASM_IMPORT_PARAMETER_DEFAULT_VALUE = DiagnosticFactory0.create(ERROR); - DiagnosticFactory0 WASM_IMPORT_VARARG_PARAMETER = DiagnosticFactory0.create(ERROR); - DiagnosticFactory1 WASM_IMPORT_UNSUPPORTED_PARAMETER_TYPE = DiagnosticFactory1.create(ERROR); - DiagnosticFactory1 WASM_IMPORT_UNSUPPORTED_RETURN_TYPE = DiagnosticFactory1.create(ERROR); + DiagnosticFactory0 WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 WASM_IMPORT_EXPORT_VARARG_PARAMETER = DiagnosticFactory0.create(ERROR); + DiagnosticFactory1 WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE = DiagnosticFactory1.create(ERROR); DiagnosticFactory0 WRONG_JS_FUN_TARGET = DiagnosticFactory0.create(ERROR); diff --git a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmImportAnnotationChecker.kt b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmImportAnnotationChecker.kt index af5bd3b92f2..ab91c1e65bd 100644 --- a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmImportAnnotationChecker.kt +++ b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmImportAnnotationChecker.kt @@ -19,6 +19,7 @@ package org.jetbrains.kotlin.wasm.resolve.diagnostics import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.calls.components.isVararg @@ -44,26 +45,12 @@ object WasmImportAnnotationChecker : DeclarationChecker { if (!DescriptorUtils.isTopLevelDeclaration(descriptor)) { trace.report(ErrorsWasm.NESTED_WASM_IMPORT.on(wasmImportPsi)) } + if (descriptor is FunctionDescriptor) { if (!descriptor.isEffectivelyExternal()) { trace.report(ErrorsWasm.WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION.on(wasmImportPsi)) } - for (parameter: ValueParameterDescriptor in descriptor.valueParameters) { - val valueParameterDeclaration by lazy { DescriptorToSourceUtils.descriptorToDeclaration(parameter)!! } - if (parameter.declaresDefaultValue()) { - trace.report(ErrorsWasm.WASM_IMPORT_PARAMETER_DEFAULT_VALUE.on(valueParameterDeclaration)) - } - if (parameter.isVararg) { - trace.report(ErrorsWasm.WASM_IMPORT_VARARG_PARAMETER.on(valueParameterDeclaration)) - } - if (!isParameterTypeSupported(parameter.type)) { - trace.report(ErrorsWasm.WASM_IMPORT_UNSUPPORTED_PARAMETER_TYPE.on(valueParameterDeclaration, parameter.type)) - } - } - val returnType = descriptor.returnType - if (returnType != null && !isReturnTypeSupported(returnType)) { - trace.report(ErrorsWasm.WASM_IMPORT_UNSUPPORTED_RETURN_TYPE.on(declaration, returnType)) - } + checkSignatureIsPrimitive(descriptor, trace, declaration) } } @@ -72,5 +59,23 @@ object WasmImportAnnotationChecker : DeclarationChecker { private fun isReturnTypeSupported(type: KotlinType): Boolean = isParameterTypeSupported(type) || type.isUnit() -} + fun checkSignatureIsPrimitive(descriptor: FunctionDescriptor, trace: BindingTrace, declaration: KtDeclaration) { + for (parameter: ValueParameterDescriptor in descriptor.valueParameters) { + val valueParameterDeclaration by lazy { DescriptorToSourceUtils.descriptorToDeclaration(parameter)!! } + if (parameter.declaresDefaultValue()) { + trace.report(ErrorsWasm.WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE.on(valueParameterDeclaration)) + } + if (parameter.isVararg) { + trace.report(ErrorsWasm.WASM_IMPORT_EXPORT_VARARG_PARAMETER.on(valueParameterDeclaration)) + } + if (!isParameterTypeSupported(parameter.type)) { + trace.report(ErrorsWasm.WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE.on(valueParameterDeclaration, parameter.type)) + } + } + val returnType = descriptor.returnType + if (returnType != null && !isReturnTypeSupported(returnType)) { + trace.report(ErrorsWasm.WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE.on(declaration, returnType)) + } + } +} \ No newline at end of file diff --git a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmInteropTypesChecker.kt b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmInteropTypesChecker.kt index db78b450d6b..b17886a14cc 100644 --- a/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmInteropTypesChecker.kt +++ b/wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmInteropTypesChecker.kt @@ -17,16 +17,18 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal import org.jetbrains.kotlin.wasm.util.hasValidJsCodeBody // TODO: Implement in K2: KT-56849 -object WasmInteropTypesChecker : DeclarationChecker { +object WasmExportAnnotationChecker : DeclarationChecker { + private val wasmExportFqName = FqName("kotlin.wasm.WasmExport") + private val jsExportFqName = FqName("kotlin.js.JsExport") + override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { if (descriptor !is FunctionDescriptor) return - - if (!descriptor.annotations.hasAnnotation(FqName("kotlin.wasm.WasmExport"))) return + if (!descriptor.annotations.hasAnnotation(wasmExportFqName)) return val trace = context.trace val bindingContext = trace.bindingContext - if (descriptor.annotations.hasAnnotation(FqName("kotlin.js.JsExport"))) { + if (descriptor.annotations.hasAnnotation(jsExportFqName)) { val reportOn = descriptor.findPsi() ?: declaration trace.report(ErrorsWasm.JS_AND_WASM_EXPORTS_ON_SAME_DECLARATION.on(reportOn)) } @@ -40,5 +42,7 @@ object WasmInteropTypesChecker : DeclarationChecker { val reportOn = descriptor.findPsi() ?: declaration trace.report(ErrorsWasm.NESTED_WASM_EXPORT.on(reportOn)) } + + WasmImportAnnotationChecker.checkSignatureIsPrimitive(descriptor, trace, declaration) } } \ No newline at end of file