Kotlin suspend transform compiler plugin
Summary
Kotlin compiler plugin for generating platform-compatible functions for suspend functions.
JVM
class Foo {
@JvmBlocking
@JvmAsync
suspend fun waitAndGet(): String {
delay(5)
return "Hello"
}
}
compiled
class Foo {
// Hide from Java
@JvmSynthetic
suspend fun waitAndGet(): String {
delay(5)
return "Hello"
}
@Api4J // RequiresOptIn annotation, provide warnings to Kotlin
fun waitAndGetBlocking(): String = runInBlocking { waitAndGet() } // 'runInBlocking' from the runtime provided by the plugin
@Api4J // RequiresOptIn annotation, provide warnings to Kotlin
fun waitAndGetAsync(): CompletableFuture<out String> = runInAsync { waitAndGet() } // 'runInAsync' from the runtime provided by the plugin
}
JS
class Foo {
@JsPromise
suspend fun waitAndGet(): String {
delay(5)
return "Hello"
}
}
compiled
class Foo {
suspend fun waitAndGet(): String {
delay(5)
return "Hello"
}
@Api4Js // RequiresOptIn annotation, provide warnings to Kotlin
fun waitAndGetBlocking(): Promise<String> = runInAsync { waitAndGet() } // 'runInBlocking' from the runtime provided by the plugin
}
JS platform target not supported yet. see: KT-53993
Usage
Gradle
Way 1:
build.gradle.kts
plugins {
kotlin("jvm") // or..?
id("love.forte.plugin.suspend-transform") version "$PLUGIN_VERSION"
// other...
}
// other...
// config it.
suspendTransform {
enabled = true // default: true
}
Way 2:
build.gradle.kts
buildscript {
repositories {
mavenCentral()
gradlePluginPortal()
}
dependencies {
classpath("love.forte.plugin.suspend-transform:suspend-transform-plugin-gradle:$GRADLE_PLUGIN_VERSION")
}
}
plugins {
kotlin("jvm") // or..?
id("love.forte.plugin.suspend-transform")
// other...
}
// other...
// config it.
suspendTransform {
enabled = true // default: true
}
Maven
Not supported yet.
Effect
source:
import love.forte.plugin.suspendtrans.annotation.JvmAsync
import love.forte.plugin.suspendtrans.annotation.JvmBlocking
@JvmBlocking
@JvmAsync
interface Foo {
suspend fun name(): String
suspend fun age(def: Int = 5): Int
@JvmBlocking(asProperty = true)
suspend fun self(): Foo
}
@JvmBlocking
@JvmAsync
class FooImpl : Foo {
suspend fun size(): Long = 666
override suspend fun name(): String = "forte"
override suspend fun age(def: Int): Int = def
@JvmBlocking(asProperty = true) // must be 'asProperty=true'
override suspend fun self(): FooImpl = this
}
class Bar {
@JvmBlocking
@JvmAsync
suspend fun bar(): String = ""
suspend fun noTrans(): Int = 1
}
compiled:
Simplified from decompiled results.
import love.forte.plugin.suspendtrans.annotation.JvmAsync
import love.forte.plugin.suspendtrans.annotation.JvmBlocking
import love.forte.plugin.suspendtrans.annotation.Generated
import love.forte.plugin.suspendtrans.annotation.Api4J
import kotlin.jvm.JvmSynthetic
@JvmBlocking
@JvmAsync
interface Foo {
@love.forte.plugin.suspendtrans.annotation.Generated
@love.forte.plugin.suspendtrans.annotation.Api4J
val selfBlocking: Foo /* compiled code */
suspend fun age(def: Int /* = compiled code */): Int
@Generated
@Api4J
fun ageAsync(def: Int /* = compiled code */): java.util.concurrent.CompletableFuture<Int> { /* compiled code */ }
@Generated
@Api4J
fun ageBlocking(def: Int /* = compiled code */): Int { /* compiled code */ }
suspend fun name(): String
@Generated
@Api4J
fun nameAsync(): java.util.concurrent.CompletableFuture<out String> { /* compiled code */ }
@Generated
@Api4J
fun nameBlocking(): String { /* compiled code */ }
@JvmBlocking
suspend fun self(): Foo
@Generated
@Api4J
fun selfAsync(): java.util.concurrent.CompletableFuture<out Foo> { /* compiled code */ }
}
@JvmBlocking
@JvmAsync
class FooImpl : Foo {
@Generated
@Api4J
open val selfBlocking: FooImpl /* compiled code */
@JvmSynthetic
open suspend fun age(def: Int): Int { /* compiled code */ }
@Generated
@Api4J
open fun ageAsync(def: Int): java.util.concurrent.CompletableFuture<Int> { /* compiled code */ }
@Generated
@Api4J
open fun ageBlocking(def: Int): Int { /* compiled code */ }
@JvmSynthetic
open suspend fun name(): String { /* compiled code */ }
@Generated
@Api4J
open fun nameAsync(): java.util.concurrent.CompletableFuture<out String> { /* compiled code */ }
@Generated
@Api4J
open fun nameBlocking(): String { /* compiled code */ }
@JvmSynthetic
@JvmBlocking
suspend fun self(): FooImpl { /* compiled code */ }
@Generated
@Api4J
fun selfAsync(): java.util.concurrent.CompletableFuture<out FooImpl> { /* compiled code */ }
@JvmSynthetic
suspend fun size(): Long { /* compiled code */ }
@Generated
@Api4J
fun sizeAsync(): java.util.concurrent.CompletableFuture<Long> { /* compiled code */ }
@Generated
@Api4J
fun sizeBlocking(): Long { /* compiled code */ }
}
class Bar {
@JvmSynthetic
@JvmBlocking
@JvmAsync
suspend fun bar(): String { /* compiled code */ }
@Generated
@Api4J
fun barAsync(): java.util.concurrent.CompletableFuture<out String> { /* compiled code */ }
@Generated
@Api4J
fun barBlocking(): String { /* compiled code */ }
fun noTrans(): Int { /* compiled code */ }
}