From 7d82c931a0d2ac6f14118a1d99a7a7a3f2e62aa7 Mon Sep 17 00:00:00 2001 From: Maxim Pestryakov Date: Wed, 19 Apr 2023 18:35:33 +0900 Subject: [PATCH] [Kotlin] Nullable constructors throw exception --- .github/workflows/kotlin-ci.yml | 4 ++-- .github/workflows/kotlin-sample-ci.yml | 4 ++-- codegen/lib/kotlin_helper.rb | 8 ++++---- codegen/lib/templates/kotlin/android_class.erb | 7 +++++++ codegen/lib/templates/kotlin/android_enum.erb | 8 ++++++++ codegen/lib/templates/kotlin/common_class.erb | 9 +++++++-- codegen/lib/templates/kotlin/common_enum.erb | 5 +++++ codegen/lib/templates/kotlin/ios_class.erb | 6 ++++++ codegen/lib/templates/kotlin/ios_enum.erb | 8 ++++++++ codegen/lib/templates/kotlin/js_accessors_class.erb | 6 ++++-- codegen/lib/templates/kotlin/js_accessors_enum.erb | 6 ++++-- codegen/lib/templates/kotlin/js_accessors_struct.erb | 2 +- codegen/lib/templates/kotlin/js_class.erb | 4 ++++ codegen/lib/templates/kotlin/js_enum.erb | 8 ++++++++ kotlin/build-logic/build.gradle.kts | 7 ++++--- kotlin/build.gradle.kts | 7 ++++--- kotlin/wallet-core-kotlin/build.gradle.kts | 4 ++-- .../wallet-core-kotlin/src/jsMain/kotlin/WalletCore.kt | 3 ++- 18 files changed, 82 insertions(+), 24 deletions(-) diff --git a/.github/workflows/kotlin-ci.yml b/.github/workflows/kotlin-ci.yml index 52127b9f9c9..7eeb8428054 100644 --- a/.github/workflows/kotlin-ci.yml +++ b/.github/workflows/kotlin-ci.yml @@ -17,10 +17,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Setup Gradle diff --git a/.github/workflows/kotlin-sample-ci.yml b/.github/workflows/kotlin-sample-ci.yml index 31ed23bceb6..86ff7d0a31f 100644 --- a/.github/workflows/kotlin-sample-ci.yml +++ b/.github/workflows/kotlin-sample-ci.yml @@ -17,10 +17,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up JDK 11 + - name: Set up JDK 17 uses: actions/setup-java@v3 with: - java-version: '11' + java-version: '17' distribution: 'temurin' - name: Install Kotlin Dependencies diff --git a/codegen/lib/kotlin_helper.rb b/codegen/lib/kotlin_helper.rb index cc465817ea6..515f4a94c20 100644 --- a/codegen/lib/kotlin_helper.rb +++ b/codegen/lib/kotlin_helper.rb @@ -222,8 +222,8 @@ def self.return_type(t) end end - def self.js_type(t, is_constructor = false) - nullable = "#{if t.is_nullable && !is_constructor then '?' else '' end}" + def self.js_type(t) + nullable = "#{if t.is_nullable then '?' else '' end}" case t.name when :void "" @@ -240,12 +240,12 @@ def self.js_type(t, is_constructor = false) end end - def self.js_return_type(t, is_constructor = false) + def self.js_return_type(t) case t.name when :void "" else - ": #{js_type(t, is_constructor)}" + ": #{js_type(t)}" end end diff --git a/codegen/lib/templates/kotlin/android_class.erb b/codegen/lib/templates/kotlin/android_class.erb index f3006d57526..3091b094ca7 100644 --- a/codegen/lib/templates/kotlin/android_class.erb +++ b/codegen/lib/templates/kotlin/android_class.erb @@ -6,9 +6,16 @@ actual class <%= entity.name %> private constructor( private val nativeHandle: Long, ) { + + init { + if (nativeHandle == 0L) throw IllegalArgumentException() + } <%# Constructors -%> <%- constructors.each do |constructor| -%> +<% if constructor.return_type.is_nullable -%> + @Throws(IllegalArgumentException::class) +<% end -%> actual constructor(<%= KotlinHelper.parameters(constructor.parameters) %>) : this(<%= KotlinHelper.format_name(constructor.name) %>(<%= KotlinHelper.calling_parameters_android(constructor.parameters) %>)) <% end -%> <%# Property declarations -%> diff --git a/codegen/lib/templates/kotlin/android_enum.erb b/codegen/lib/templates/kotlin/android_enum.erb index b749119c661..6231a663857 100644 --- a/codegen/lib/templates/kotlin/android_enum.erb +++ b/codegen/lib/templates/kotlin/android_enum.erb @@ -1,12 +1,20 @@ <%= render('kotlin/package.erb') %> +<% has_string = entity.cases.all? { |c| !c.string.nil? } -%> actual enum class <%= entity.name %>( @get:JvmName("value") val value: UInt, +<% if has_string -%> + actual val stringValue: String, +<% end -%> ) { <%# Cases -%> <% entity.cases.each_with_index do |c, i| -%> +<% if has_string -%> + <%= c.name %>(<%= c.value %>u, <%= c.string %>), +<% else -%> <%= c.name %>(<%= c.value %>u), +<% end -%> <% end -%> ; <%# Property declarations -%> diff --git a/codegen/lib/templates/kotlin/common_class.erb b/codegen/lib/templates/kotlin/common_class.erb index b47c1eb85f0..0cd6d4a506a 100644 --- a/codegen/lib/templates/kotlin/common_class.erb +++ b/codegen/lib/templates/kotlin/common_class.erb @@ -4,7 +4,11 @@ <% methods = entity.methods.select { |method| not method.name.start_with?('Delete') } -%> <% static_methods = entity.static_methods.select { |method| not method.name.start_with?('Create') } -%> <% if constructors.one? -%> +<% if constructors.first.return_type.is_nullable -%> +expect class <%= entity.name %> @Throws(IllegalArgumentException::class) constructor( +<% else -%> expect class <%= entity.name %>( +<% end -%> <%- constructors.first.parameters.each do |parameter| -%> <%= KotlinHelper.parameters([parameter]) %>, <%- end -%> @@ -12,10 +16,11 @@ expect class <%= entity.name %>( <%- else -%> expect class <%= entity.name %> { <%# Constructors -%> -<% if constructors.any? -%> +<%- constructors.each do |constructor| -%> +<% if constructor.return_type.is_nullable -%> + @Throws(IllegalArgumentException::class) <% end -%> -<%- constructors.each do |constructor| -%> constructor(<%= KotlinHelper.parameters(constructor.parameters) %>) <%- end -%> <% end -%> diff --git a/codegen/lib/templates/kotlin/common_enum.erb b/codegen/lib/templates/kotlin/common_enum.erb index 87f0d814598..39d85dca835 100644 --- a/codegen/lib/templates/kotlin/common_enum.erb +++ b/codegen/lib/templates/kotlin/common_enum.erb @@ -1,11 +1,16 @@ <%= render('kotlin/package.erb') %> +<% has_string = entity.cases.all? { |c| !c.string.nil? } -%> expect enum class <%= entity.name %> { <%# Cases -%> <% entity.cases.each_with_index do |c, i| -%> <%= c.name %>, <% end -%> ; + +<% if has_string -%> + val stringValue: String +<% end -%> <%# Property declarations -%> <%- entity.properties.each do |property| -%> val <%= KotlinHelper.format_name(property.name) %><%= KotlinHelper.return_type(property.return_type) %> diff --git a/codegen/lib/templates/kotlin/ios_class.erb b/codegen/lib/templates/kotlin/ios_class.erb index de3f758d91e..36bc94e8276 100644 --- a/codegen/lib/templates/kotlin/ios_class.erb +++ b/codegen/lib/templates/kotlin/ios_class.erb @@ -12,8 +12,14 @@ actual class <%= entity.name %> constructor( <%# Constructors -%> <%- constructors.each do |constructor| -%> +<% if constructor.return_type.is_nullable -%> + @Throws(IllegalArgumentException::class) + actual constructor(<%= KotlinHelper.parameters(constructor.parameters) %>) : this( + TW<%= entity.name %><%= constructor.name %>(<%= KotlinHelper.calling_parameters_ios(constructor.parameters) %>) ?: throw IllegalArgumentException() +<% else -%> actual constructor(<%= KotlinHelper.parameters(constructor.parameters) %>) : this( TW<%= entity.name %><%= constructor.name %>(<%= KotlinHelper.calling_parameters_ios(constructor.parameters) %>)!! +<% end -%> ) <% end -%> <%# Property declarations -%> diff --git a/codegen/lib/templates/kotlin/ios_enum.erb b/codegen/lib/templates/kotlin/ios_enum.erb index 3ddd115598b..0e4cbd10bbd 100644 --- a/codegen/lib/templates/kotlin/ios_enum.erb +++ b/codegen/lib/templates/kotlin/ios_enum.erb @@ -2,13 +2,21 @@ import com.trustwallet.core.<%= "TW#{entity.name}" %>.* +<% has_string = entity.cases.all? { |c| !c.string.nil? } -%> <% type = ": TW#{entity.name}" -%> actual enum class <%= entity.name %>( val value<%= type %>, +<% if has_string -%> + actual val stringValue: String, +<% end -%> ) { <%# Cases -%> <% entity.cases.each_with_index do |c, i| -%> +<% if has_string -%> + <%= c.name %>(TW<%= entity.name %><%= c.name %>, <%= c.string %>), +<% else -%> <%= c.name %>(TW<%= entity.name %><%= c.name %>), +<% end -%> <% end -%> ; <%# Property declarations -%> diff --git a/codegen/lib/templates/kotlin/js_accessors_class.erb b/codegen/lib/templates/kotlin/js_accessors_class.erb index 9930f021865..77645552c83 100644 --- a/codegen/lib/templates/kotlin/js_accessors_class.erb +++ b/codegen/lib/templates/kotlin/js_accessors_class.erb @@ -1,8 +1,10 @@ +@file:Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") + <%= render('kotlin/package.erb') %> @JsModule("@trustwallet/wallet-core") @JsName("<%= entity.name %>") -external class Js<%= entity.name %> { +external interface Js<%= entity.name %> { <%- entity.properties.each do |property| -%> fun <%= KotlinHelper.fix_name(WasmCppHelper.format_name(property.name)) %>()<%= KotlinHelper.js_return_type(property.return_type) %> <%- end -%> @@ -12,7 +14,7 @@ external class Js<%= entity.name %> { <% end -%> companion object { <% entity.static_methods.each do |method| -%> - fun <%= KotlinHelper.fix_name(WasmCppHelper.function_name(entity: entity, function: method)) %>(<%= KotlinHelper.js_parameters(method.parameters) %>)<%= KotlinHelper.js_return_type(method.return_type, method.name.start_with?("Create")) %> + fun <%= KotlinHelper.fix_name(WasmCppHelper.function_name(entity: entity, function: method)) %>(<%= KotlinHelper.js_parameters(method.parameters) %>)<%= KotlinHelper.js_return_type(method.return_type) %> <% end -%> } } diff --git a/codegen/lib/templates/kotlin/js_accessors_enum.erb b/codegen/lib/templates/kotlin/js_accessors_enum.erb index 34e44a7b352..feaa2e82caf 100644 --- a/codegen/lib/templates/kotlin/js_accessors_enum.erb +++ b/codegen/lib/templates/kotlin/js_accessors_enum.erb @@ -1,8 +1,10 @@ +@file:Suppress("NESTED_CLASS_IN_EXTERNAL_INTERFACE") + <%= render('kotlin/package.erb') %> @JsModule("@trustwallet/wallet-core") @JsName("<%= entity.name %>") -external class Js<%= entity.name %> { +external interface Js<%= entity.name %> { val value: Number companion object { <% entity.cases.each do |c| -%> @@ -17,7 +19,7 @@ inline val JsWalletCore.<%= entity.name %>: Js<%= entity.name %>.Companion <% if entity.properties.any? || entity.methods.any? -%> @JsModule("@trustwallet/wallet-core") @JsName("<%= entity.name %>Ext") -external object Js<%= entity.name %>Ext { +external interface Js<%= entity.name %>Ext { <%# Static method declarations -%> <%- entity.properties.each do |property| -%> fun <%= KotlinHelper.fix_name(WasmCppHelper.format_name(property.name)) %>(<%= KotlinHelper.js_parameters(property.parameters) %>)<%= KotlinHelper.js_return_type(property.return_type) %> diff --git a/codegen/lib/templates/kotlin/js_accessors_struct.erb b/codegen/lib/templates/kotlin/js_accessors_struct.erb index 671f438c880..911024dc9ee 100644 --- a/codegen/lib/templates/kotlin/js_accessors_struct.erb +++ b/codegen/lib/templates/kotlin/js_accessors_struct.erb @@ -2,7 +2,7 @@ @JsModule("@trustwallet/wallet-core") @JsName("<%= entity.name %>") -external object Js<%= entity.name %> { +external interface Js<%= entity.name %> { <%# Static method declarations -%> <% entity.static_methods.each do |method| -%> <% next if method.name.start_with?('Create') -%> diff --git a/codegen/lib/templates/kotlin/js_class.erb b/codegen/lib/templates/kotlin/js_class.erb index 5f6ad4809d7..14cd6ef5e40 100644 --- a/codegen/lib/templates/kotlin/js_class.erb +++ b/codegen/lib/templates/kotlin/js_class.erb @@ -10,8 +10,12 @@ actual class <%= entity.name %> constructor( <%- constructors.each do |constructor| -%> actual constructor(<%= KotlinHelper.parameters(constructor.parameters) %>) : +<% if constructor.return_type.is_nullable -%> + this(WalletCore.Instance.<%= entity.name %>.<%= WasmCppHelper.function_name(entity: entity, function: constructor) %>(<%= KotlinHelper.calling_parameters_js(constructor.parameters) %>) ?: throw IllegalArgumentException()) +<% else -%> this(WalletCore.Instance.<%= entity.name %>.<%= WasmCppHelper.function_name(entity: entity, function: constructor) %>(<%= KotlinHelper.calling_parameters_js(constructor.parameters) %>)) <% end -%> +<% end -%> <%# Property declarations -%> <% entity.properties.each do |property| -%> diff --git a/codegen/lib/templates/kotlin/js_enum.erb b/codegen/lib/templates/kotlin/js_enum.erb index 4ce79c684fc..18b723bbb86 100644 --- a/codegen/lib/templates/kotlin/js_enum.erb +++ b/codegen/lib/templates/kotlin/js_enum.erb @@ -1,11 +1,19 @@ <%= render('kotlin/package.erb') %> +<% has_string = entity.cases.all? { |c| !c.string.nil? } -%> actual enum class <%= entity.name %>( val jsValue: Js<%= entity.name %>, +<% if has_string -%> + actual val stringValue: String, +<% end -%> ) { <%# Cases -%> <% entity.cases.each_with_index do |c, i| -%> +<% if has_string -%> + <%= c.name %>(WalletCore.Instance.<%= entity.name %>.<%= KotlinHelper.fix_name(WasmCppHelper.format_name(c.name)) %>, <%= c.string %>), +<% else -%> <%= c.name %>(WalletCore.Instance.<%= entity.name %>.<%= KotlinHelper.fix_name(WasmCppHelper.format_name(c.name)) %>), +<% end -%> <% end -%> ; <%# Property declarations -%> diff --git a/kotlin/build-logic/build.gradle.kts b/kotlin/build-logic/build.gradle.kts index d6cda1875d1..83e8afc4707 100644 --- a/kotlin/build-logic/build.gradle.kts +++ b/kotlin/build-logic/build.gradle.kts @@ -1,3 +1,4 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -6,9 +7,9 @@ plugins { allprojects { tasks.withType { - kotlinOptions { - allWarningsAsErrors = true - jvmTarget = JavaVersion.VERSION_11.toString() + compilerOptions { + allWarningsAsErrors.set(true) + jvmTarget.set(JvmTarget.JVM_17) } } } diff --git a/kotlin/build.gradle.kts b/kotlin/build.gradle.kts index 87279b47a55..387b99278c9 100644 --- a/kotlin/build.gradle.kts +++ b/kotlin/build.gradle.kts @@ -1,6 +1,7 @@ // Workaround https://github.com/gradle/gradle/issues/22797 @file:Suppress("DSL_SCOPE_VIOLATION") +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -12,9 +13,9 @@ plugins { allprojects { tasks.withType { - kotlinOptions { - allWarningsAsErrors = true - jvmTarget = JavaVersion.VERSION_11.toString() + compilerOptions { + allWarningsAsErrors.set(true) + jvmTarget.set(JvmTarget.JVM_17) } } } diff --git a/kotlin/wallet-core-kotlin/build.gradle.kts b/kotlin/wallet-core-kotlin/build.gradle.kts index e82797fed7a..405f6c621e3 100644 --- a/kotlin/wallet-core-kotlin/build.gradle.kts +++ b/kotlin/wallet-core-kotlin/build.gradle.kts @@ -83,8 +83,8 @@ android { buildToolsVersion = libs.versions.android.sdk.tools.get() compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 } defaultConfig { diff --git a/kotlin/wallet-core-kotlin/src/jsMain/kotlin/WalletCore.kt b/kotlin/wallet-core-kotlin/src/jsMain/kotlin/WalletCore.kt index e71a5458a55..ba7c30845c5 100644 --- a/kotlin/wallet-core-kotlin/src/jsMain/kotlin/WalletCore.kt +++ b/kotlin/wallet-core-kotlin/src/jsMain/kotlin/WalletCore.kt @@ -11,7 +11,8 @@ import kotlin.js.Promise @JsName("WalletCoreKotlin") object WalletCore { - internal lateinit var Instance: JsWalletCore + lateinit var Instance: JsWalletCore + private set fun init(): Promise = if (::Instance.isInitialized) {