From 1c230c8f27ebeec027339cc2e50e2bc111ca43e3 Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Tue, 14 Nov 2023 12:24:10 +0000 Subject: [PATCH] [Wasm] Port WasmImport/WasmExport checker to K2 (KT-56849) --- .../diagnostics/FirWasmDiagnosticsList.kt | 16 ++++ .../diagnostics/wasm/FirWasmErrors.kt | 11 +++ .../wasm/FirWasmErrorsDefaultMessages.kt | 27 +++++++ .../wasm/checkers/WasmDeclarationCheckers.kt | 2 + .../FirWasmExportAnnotationChecker.kt | 44 +++++++++++ .../FirWasmImportAnnotationChecker.kt | 76 +++++++++++++++++++ .../wasmTests/wasmInterop/wasmExport.fir.kt | 58 -------------- .../wasmTests/wasmInterop/wasmExport.kt | 26 ++++--- .../wasmTests/wasmInterop/wasmImport.fir.kt | 49 ------------ .../wasmTests/wasmInterop/wasmImport.kt | 2 + .../kotlin/name/WasmStandardClassIds.kt | 3 + .../wasm/resolve/diagnostics/ErrorsWasm.java | 6 +- ...cker.kt => WasmExportAnnotationChecker.kt} | 12 +-- .../WasmImportAnnotationChecker.kt | 1 - 14 files changed, 205 insertions(+), 128 deletions(-) create mode 100644 compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmExportAnnotationChecker.kt create mode 100644 compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmImportAnnotationChecker.kt delete mode 100644 compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.fir.kt delete mode 100644 compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.fir.kt rename wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/{WasmInteropTypesChecker.kt => WasmExportAnnotationChecker.kt} (86%) diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirWasmDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirWasmDiagnosticsList.kt index 905a8e742b5..adeeded6342 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirWasmDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirWasmDiagnosticsList.kt @@ -28,4 +28,20 @@ object WASM_DIAGNOSTICS_LIST : DiagnosticList("FirWasmErrors") { parameter("type") } } + + val WASM_INTEROP by object : DiagnosticGroup("Wasm interop") { + val NESTED_WASM_EXPORT by error() + val WASM_EXPORT_ON_EXTERNAL_DECLARATION by error() + val JS_AND_WASM_EXPORTS_ON_SAME_DECLARATION by error() + val NESTED_WASM_IMPORT by error() + val WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION by error() + val WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE by error() + val WASM_IMPORT_EXPORT_VARARG_PARAMETER by error() + val WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE by error(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) { + parameter("type") + } + val WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE by error(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) { + parameter("type") + } + } } diff --git a/compiler/fir/checkers/checkers.wasm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrors.kt b/compiler/fir/checkers/checkers.wasm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrors.kt index c2550ff8cba..f267ac62124 100644 --- a/compiler/fir/checkers/checkers.wasm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrors.kt +++ b/compiler/fir/checkers/checkers.wasm/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrors.kt @@ -23,6 +23,17 @@ object FirWasmErrors { val CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION by error0() val WRONG_JS_INTEROP_TYPE by error2(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) + // Wasm interop + val NESTED_WASM_EXPORT by error0() + val WASM_EXPORT_ON_EXTERNAL_DECLARATION by error0() + val JS_AND_WASM_EXPORTS_ON_SAME_DECLARATION by error0() + val NESTED_WASM_IMPORT by error0() + val WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION by error0() + val WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE by error0() + val WASM_IMPORT_EXPORT_VARARG_PARAMETER by error0() + val WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE by error1(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) + val WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE by error1(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT) + init { RootDiagnosticRendererFactory.registerFactory(FirWasmErrorsDefaultMessages) } diff --git a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrorsDefaultMessages.kt b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrorsDefaultMessages.kt index 9dd4fec25f6..ddf4573e873 100644 --- a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/diagnostics/wasm/FirWasmErrorsDefaultMessages.kt @@ -12,7 +12,16 @@ import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.CALL_TO_DEFINED_EXTERNALLY_FROM_NON_EXTERNAL_DECLARATION import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.JS_AND_WASM_EXPORTS_ON_SAME_DECLARATION +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.NESTED_WASM_EXPORT +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.NESTED_WASM_IMPORT import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.NON_EXTERNAL_TYPE_EXTENDS_EXTERNAL_TYPE +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.WASM_EXPORT_ON_EXTERNAL_DECLARATION +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.WASM_IMPORT_EXPORT_VARARG_PARAMETER +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors.WRONG_JS_INTEROP_TYPE @Suppress("unused") @@ -34,5 +43,23 @@ object FirWasmErrorsDefaultMessages : BaseDiagnosticRendererFactory() { "Type ''{0}'' cannot be used in {1}. Only external, primitive, string and function types are supported in Kotlin/Wasm JS interop.", TO_STRING, FirDiagnosticRenderers.RENDER_TYPE, ) + + map.put(NESTED_WASM_EXPORT, "Only top-level functions can be exported with '@WasmExport'.") + map.put(WASM_EXPORT_ON_EXTERNAL_DECLARATION, "Functions annotated with '@WasmExport' must not be external.") + map.put(JS_AND_WASM_EXPORTS_ON_SAME_DECLARATION, "Cannot use '@WasmExport' and '@JsExport' for same function.") + map.put(NESTED_WASM_IMPORT, "Only top-level functions can be imported with '@WasmImport'.") + map.put(WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION, "Functions annotated with '@WasmImport' must be external.") + map.put(WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE, "Default parameter values are not supported with '@WasmImport' and '@WasmExport'.") + map.put(WASM_IMPORT_EXPORT_VARARG_PARAMETER, "Vararg parameters are not supported with '@WasmImport' and '@WasmExport'.") + map.put( + WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE, + "Unsupported ''@WasmImport'' and ''@WasmExport'' parameter type ''{0}''.", + FirDiagnosticRenderers.RENDER_TYPE + ) + map.put( + WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE, + "Unsupported ''@WasmImport'' and ''@WasmExport'' return type ''{0}''.", + FirDiagnosticRenderers.RENDER_TYPE + ) } } diff --git a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/WasmDeclarationCheckers.kt b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/WasmDeclarationCheckers.kt index 460c1fd587e..8483c3f7d0e 100644 --- a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/WasmDeclarationCheckers.kt +++ b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/WasmDeclarationCheckers.kt @@ -17,5 +17,7 @@ object WasmDeclarationCheckers : DeclarationCheckers() { override val basicDeclarationCheckers: Set get() = setOf( FirWasmJsInteropTypesChecker, + FirWasmImportAnnotationChecker, + FirWasmExportAnnotationChecker, ) } diff --git a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmExportAnnotationChecker.kt b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmExportAnnotationChecker.kt new file mode 100644 index 00000000000..8a95be0b61f --- /dev/null +++ b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmExportAnnotationChecker.kt @@ -0,0 +1,44 @@ +/* + * Copyright 2010-2023 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.fir.analysis.wasm.checkers.declaration + +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker +import org.jetbrains.kotlin.fir.analysis.checkers.isTopLevel +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors +import org.jetbrains.kotlin.fir.analysis.wasm.checkers.hasValidJsCodeBody +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId +import org.jetbrains.kotlin.fir.declarations.hasAnnotation +import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.name.WasmStandardClassIds + +object FirWasmExportAnnotationChecker : FirBasicDeclarationChecker() { + override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { + val annotation: FirAnnotation = + declaration.annotations.getAnnotationByClassId(WasmStandardClassIds.Annotations.WasmExport, context.session) ?: return + + if (!context.isTopLevel) { + reporter.reportOn(annotation.source, FirWasmErrors.NESTED_WASM_EXPORT, context) + } + + if (declaration.annotations.hasAnnotation(WasmStandardClassIds.Annotations.JsExport, context.session)) { + reporter.reportOn(declaration.source, FirWasmErrors.JS_AND_WASM_EXPORTS_ON_SAME_DECLARATION, context) + } + + if (declaration is FirSimpleFunction) { + if (declaration.symbol.isEffectivelyExternal(context.session) || declaration.hasValidJsCodeBody()) { + reporter.reportOn(annotation.source, FirWasmErrors.WASM_EXPORT_ON_EXTERNAL_DECLARATION, context) + } + + checkWasmInteropSignature(declaration, context, reporter) + } + } +} \ No newline at end of file diff --git a/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmImportAnnotationChecker.kt b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmImportAnnotationChecker.kt new file mode 100644 index 00000000000..d5fad008d56 --- /dev/null +++ b/compiler/fir/checkers/checkers.wasm/src/org/jetbrains/kotlin/fir/analysis/wasm/checkers/declaration/FirWasmImportAnnotationChecker.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2023 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.fir.analysis.wasm.checkers.declaration + +import org.jetbrains.kotlin.diagnostics.DiagnosticReporter +import org.jetbrains.kotlin.diagnostics.reportOn +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirBasicDeclarationChecker +import org.jetbrains.kotlin.fir.analysis.checkers.isTopLevel +import org.jetbrains.kotlin.fir.analysis.diagnostics.wasm.FirWasmErrors +import org.jetbrains.kotlin.fir.declarations.FirDeclaration +import org.jetbrains.kotlin.fir.declarations.FirFunction +import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId +import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.types.* +import org.jetbrains.kotlin.name.WasmStandardClassIds + +object FirWasmImportAnnotationChecker : FirBasicDeclarationChecker() { + override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) { + val annotation: FirAnnotation = + declaration.annotations.getAnnotationByClassId(WasmStandardClassIds.Annotations.WasmImport, context.session) ?: return + + if (!context.isTopLevel) { + reporter.reportOn(annotation.source, FirWasmErrors.NESTED_WASM_IMPORT, context) + } + + if (!declaration.symbol.isEffectivelyExternal(context.session)) { + reporter.reportOn(annotation.source, FirWasmErrors.WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION, context) + } + + if (declaration is FirFunction) { + checkWasmInteropSignature(declaration, context, reporter) + } + } +} + +fun checkWasmInteropSignature(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) { + for (parameter in declaration.valueParameters) { + val type = parameter.returnTypeRef.coneType + if (parameter.defaultValue != null) { + reporter.reportOn(parameter.source, FirWasmErrors.WASM_IMPORT_EXPORT_PARAMETER_DEFAULT_VALUE, context) + } + if (parameter.isVararg) { + reporter.reportOn(parameter.source, FirWasmErrors.WASM_IMPORT_EXPORT_VARARG_PARAMETER, context) + } + if (!isTypeSupportedInWasmInterop(type, false, context.session)) { + reporter.reportOn(parameter.source, FirWasmErrors.WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE, type, context) + } + } + + val returnType = declaration.returnTypeRef.coneType + if (!isTypeSupportedInWasmInterop(returnType, true, context.session)) { + reporter.reportOn(declaration.source, FirWasmErrors.WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE, returnType, context) + } +} + +private fun isTypeSupportedInWasmInterop( + unexpandedType: ConeKotlinType, + isInFunctionReturnPosition: Boolean, + session: FirSession, +): Boolean { + val type = unexpandedType.fullyExpandedType(session) + + if (type.isUnit) { + return isInFunctionReturnPosition + } + + // Primitive numbers and Boolean are supported + return type.isPrimitive && !type.isChar +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.fir.kt b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.fir.kt deleted file mode 100644 index bb5fe28cb74..00000000000 --- a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.fir.kt +++ /dev/null @@ -1,58 +0,0 @@ -import kotlin.wasm.WasmExport - -@WasmExport("a") -external fun foo0(): Unit - -@WasmExport("a") -fun foo1(): Int = js("42") - -class C() { - @WasmExport("a") - fun foo2(): Int = 42 -} - -@WasmExport("a") -fun foo3(): Int = 42 - -@WasmExport() -fun foo4(): Int = 42 - -@OptIn(kotlin.js.ExperimentalJsExport::class) -@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/wasmExport.kt b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.kt index 44c98621a6e..82b0b9db580 100644 --- a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.kt +++ b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmExport.kt @@ -1,14 +1,16 @@ +// FIR_IDENTICAL +// !DIAGNOSTICS: -UNUSED_PARAMETER import kotlin.wasm.WasmExport -@WasmExport("a") -external fun foo0(): Unit +@WasmExport("a") +external fun foo0(): Unit -@WasmExport("a") -fun foo1(): Int = js("42") +@WasmExport("a") +fun foo1(): Int = js("42") class C() { - @WasmExport("a") - fun foo2(): Int = 42 + @WasmExport("a") + fun foo2(): Int = 42 } @WasmExport("a") @@ -22,7 +24,7 @@ fun foo4(): Int = 42 @WasmExport() fun foo6(): Int = 42 -val p1 = (@WasmExport("a") fun () {}) +val p1 = (@WasmExport("a") fun () {}) @WasmExport("a") fun foo7( @@ -40,19 +42,19 @@ fun foo7( } @WasmExport("a") -fun returnNullableUnit(): Unit? { return null } +fun returnNullableUnit(): Unit? { return null } @WasmExport("a") -fun returnNullableBoolean(): Boolean? { return null } +fun returnNullableBoolean(): Boolean? { return null } @WasmExport("a") -fun returnNullableAny(): Any? { return null } +fun returnNullableAny(): Any? { return null } @WasmExport("a") -fun fooGeneric(x: T): T { return x } +fun fooGeneric(x: T): T { return x } @WasmExport("a") fun fooDeafultAndVararg( -a: Int = definedExternally, +a: Int = definedExternally, vararg b: Int ): Unit { b.toString() } diff --git a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.fir.kt b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.fir.kt deleted file mode 100644 index 28685c2b3db..00000000000 --- a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.fir.kt +++ /dev/null @@ -1,49 +0,0 @@ -import kotlin.wasm.WasmImport - -@WasmImport("a", "b") -external fun foo0(): Unit - -@WasmImport("a", "b") -fun foo1() { -} - -external class C { - @WasmImport("a", "b") - fun memberFunction() -} - -fun foo2() { - @WasmImport("a", "b") - fun localFun() { - } -} - -val p1 = (@WasmImport("a", "b") fun () {}) - -@WasmImport("a", "b") -external fun foo3( - p0: Unit, - p1: String, - p2: Any, - p3: Int?, - p4: Boolean? -): Unit - - -@WasmImport("a", "b") -external fun returnNullableUnit(): Unit? - -@WasmImport("a", "b") -external fun returnNullableBoolean(): Boolean? - -@WasmImport("a", "b") -external fun returnNullableAny(): Any? - -@WasmImport("a", "b") -external fun fooGeneric(x: T): T - -@WasmImport("a", "b") -external fun fooDeafultAndVararg( -a: Int = definedExternally, -vararg b: Int -): Unit diff --git a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.kt b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.kt index 2736e746c3b..c0fb49e18da 100644 --- a/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.kt +++ b/compiler/testData/diagnostics/wasmTests/wasmInterop/wasmImport.kt @@ -1,3 +1,5 @@ +// FIR_IDENTICAL + import kotlin.wasm.WasmImport @WasmImport("a", "b") diff --git a/core/compiler.common.wasm/src/org/jetbrains/kotlin/name/WasmStandardClassIds.kt b/core/compiler.common.wasm/src/org/jetbrains/kotlin/name/WasmStandardClassIds.kt index cda2b4aaf32..a19d7413b90 100644 --- a/core/compiler.common.wasm/src/org/jetbrains/kotlin/name/WasmStandardClassIds.kt +++ b/core/compiler.common.wasm/src/org/jetbrains/kotlin/name/WasmStandardClassIds.kt @@ -26,6 +26,9 @@ object WasmStandardClassIds { @JvmField val WasmImport = "WasmImport".wasmId() + + @JvmField + val WasmExport = "WasmExport".wasmId() } object Callables { 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 2a67bd381c9..23306b6a2eb 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 @@ -30,8 +30,10 @@ public interface ErrorsWasm { DiagnosticFactory0 WASM_IMPORT_ON_NON_EXTERNAL_DECLARATION = DiagnosticFactory0.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); + DiagnosticFactory1 WASM_IMPORT_EXPORT_UNSUPPORTED_PARAMETER_TYPE = + DiagnosticFactory1.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT); + DiagnosticFactory1 WASM_IMPORT_EXPORT_UNSUPPORTED_RETURN_TYPE = + DiagnosticFactory1.create(ERROR, PositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT); DiagnosticFactory0 WRONG_JS_FUN_TARGET = DiagnosticFactory0.create(ERROR); 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/WasmExportAnnotationChecker.kt similarity index 86% rename from wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmInteropTypesChecker.kt rename to wasm/wasm.frontend/src/org/jetbrains/kotlin/wasm/resolve/diagnostics/WasmExportAnnotationChecker.kt index b5f400fbdd4..ba1f765c896 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/WasmExportAnnotationChecker.kt @@ -14,16 +14,18 @@ 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.descriptorUtil.isEffectivelyExternal +import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.wasm.util.hasValidJsCodeBody -// TODO: Implement in K2: KT-56849 abstract class WasmExportAnnotationChecker(val checkJsInterop: Boolean) : 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(wasmExportFqName)) return + val wasmExport = descriptor.annotations.findAnnotation(wasmExportFqName) ?: return + + val wasmExportPsi = wasmExport.source.getPsi() ?: declaration val trace = context.trace val bindingContext = trace.bindingContext @@ -36,13 +38,11 @@ abstract class WasmExportAnnotationChecker(val checkJsInterop: Boolean) : Declar } if (descriptor.isEffectivelyExternal() || (checkJsInterop && descriptor.hasValidJsCodeBody(bindingContext))) { - val reportOn = descriptor.findPsi() ?: declaration - trace.report(ErrorsWasm.WASM_EXPORT_ON_EXTERNAL_DECLARATION.on(reportOn)) + trace.report(ErrorsWasm.WASM_EXPORT_ON_EXTERNAL_DECLARATION.on(wasmExportPsi)) } if (!DescriptorUtils.isTopLevelDeclaration(descriptor)) { - val reportOn = descriptor.findPsi() ?: declaration - trace.report(ErrorsWasm.NESTED_WASM_EXPORT.on(reportOn)) + trace.report(ErrorsWasm.NESTED_WASM_EXPORT.on(wasmExportPsi)) } WasmImportAnnotationChecker.checkSignatureIsPrimitive(descriptor, trace, declaration) 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 ab91c1e65bd..e96d3b768fa 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 @@ -32,7 +32,6 @@ import org.jetbrains.kotlin.types.typeUtil.isBoolean import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType import org.jetbrains.kotlin.types.typeUtil.isUnit -// TODO: Implement in K2: KT-56849 object WasmImportAnnotationChecker : DeclarationChecker { private val wasmImportFqName = FqName("kotlin.wasm.WasmImport")