Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/IProject.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ object IProject : ProjectDetail() {

// Remember the libs.versions.toml!
val ktVersion = "2.0.20-Beta1"
val pluginVersion = "0.9.1"
val pluginVersion = "0.9.2"

override val version: String = "$ktVersion-$pluginVersion"

Expand Down Expand Up @@ -46,6 +46,6 @@ object IProject : ProjectDetail() {
fun Project.setupWith(ktVersion: String) {
group = IProject.GROUP
description = IProject.DESCRIPTION
val mergedVersion = ktVersion + "-" + IProject.pluginVersion.toString()
val mergedVersion = ktVersion + "-" + IProject.pluginVersion
version = if (IS_SNAPSHOT) "$mergedVersion-SNAPSHOT" else mergedVersion
}
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,29 @@ class SuspendTransformFirTransformer(
excludes.any { ex -> annotationClassId == ex }
}

addAll(notCompileAnnotationsCopied)
/*
* Create a new annotation based the annotation from the original function.
* It will be crashed with `IllegalArgumentException: Failed requirement`
* when using the `notCompileAnnotationsCopied` directly
* if there have some arguments with type `KClass`,
* e.g. `annotation class OneAnnotation(val target: KClass<*>)` or `kotlin.OptIn`.
*
* See https://github.com/ForteScarlet/kotlin-suspend-transform-compiler-plugin/issues/56
*/
val copied = notCompileAnnotationsCopied.map { a ->
buildAnnotation {
annotationTypeRef = buildResolvedTypeRef {
type = a.resolvedType
}
this.typeArguments.addAll(a.typeArguments)
this.argumentMapping = buildAnnotationArgumentMapping {
this.source = a.source
this.mapping.putAll(a.argumentMapping.mapping)
}
}
}

addAll(copied)
}

// try add @Generated(by = ...)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,10 @@ public void testOverride() {
public void testTypeAttr() {
runTest("src/testData/codegen/typeAttr.kt");
}

@Test
@TestMetadata("opt.kt")
public void testOpt() {
runTest("src/testData/codegen/opt.kt");
}
}
53 changes: 53 additions & 0 deletions compiler/suspend-transform-plugin/src/testData/codegen/opt.asm.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
public abstract interface OneOptAnno : java/lang/Object, java/lang/annotation/Annotation {

}

final class OptInTest$runAsync$1 : kotlin/coroutines/jvm/internal/SuspendLambda, kotlin/jvm/functions/Function1 {
int label

final OptInTest this$0

void <init>(OptInTest $receiver, kotlin.coroutines.Continuation $completion)

public final kotlin.coroutines.Continuation create(kotlin.coroutines.Continuation $completion)

public final java.lang.Object invoke(kotlin.coroutines.Continuation p1)

public java.lang.Object invoke(java.lang.Object p1)

public final java.lang.Object invokeSuspend(java.lang.Object $result)
}

final class OptInTest$runBlocking$1 : kotlin/coroutines/jvm/internal/SuspendLambda, kotlin/jvm/functions/Function1 {
int label

final OptInTest this$0

void <init>(OptInTest $receiver, kotlin.coroutines.Continuation $completion)

public final kotlin.coroutines.Continuation create(kotlin.coroutines.Continuation $completion)

public final java.lang.Object invoke(kotlin.coroutines.Continuation p1)

public java.lang.Object invoke(java.lang.Object p1)

public final java.lang.Object invokeSuspend(java.lang.Object $result)
}

public final class OptInTest : java/lang/Object {
public void <init>()

public final static java.lang.Object access$run0(OptInTest $this, kotlin.coroutines.Continuation $completion)

public final java.lang.Object run(kotlin.coroutines.Continuation $completion)

private final java.lang.Object run0(kotlin.coroutines.Continuation $completion)

public final java.util.concurrent.CompletableFuture runAsync()

public final int runBlocking()
}

public abstract interface Values : java/lang/Object, java/lang/annotation/Annotation {
public abstract java.lang.Class target()
}
125 changes: 125 additions & 0 deletions compiler/suspend-transform-plugin/src/testData/codegen/opt.fir.ir.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
FILE fqName:<root> fileName:/Main.kt
CLASS ANNOTATION_CLASS name:OneOptAnno modality:OPEN visibility:public superTypes:[kotlin.Annotation]
annotations:
RequiresOptIn(message = <null>, level = GET_ENUM 'ENUM_ENTRY IR_EXTERNAL_DECLARATION_STUB name:ERROR' type=kotlin.RequiresOptIn.Level)
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.OneOptAnno
CONSTRUCTOR visibility:public <> () returnType:<root>.OneOptAnno [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ANNOTATION_CLASS name:OneOptAnno modality:OPEN visibility:public superTypes:[kotlin.Annotation]'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS ANNOTATION_CLASS name:Values modality:OPEN visibility:public superTypes:[kotlin.Annotation]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.Values
PROPERTY name:target visibility:public modality:FINAL [val]
FIELD PROPERTY_BACKING_FIELD name:target type:kotlin.reflect.KClass<*> visibility:private [final]
EXPRESSION_BODY
GET_VAR 'target: kotlin.reflect.KClass<*> declared in <root>.Values.<init>' type=kotlin.reflect.KClass<*> origin=INITIALIZE_PROPERTY_FROM_PARAMETER
FUN DEFAULT_PROPERTY_ACCESSOR name:<get-target> visibility:public modality:FINAL <> ($this:<root>.Values) returnType:kotlin.reflect.KClass<*>
correspondingProperty: PROPERTY name:target visibility:public modality:FINAL [val]
$this: VALUE_PARAMETER name:<this> type:<root>.Values
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun <get-target> (): kotlin.reflect.KClass<*> declared in <root>.Values'
GET_FIELD 'FIELD PROPERTY_BACKING_FIELD name:target type:kotlin.reflect.KClass<*> visibility:private [final]' type=kotlin.reflect.KClass<*> origin=null
receiver: GET_VAR '<this>: <root>.Values declared in <root>.Values.<get-target>' type=<root>.Values origin=null
CONSTRUCTOR visibility:public <> (target:kotlin.reflect.KClass<*>) returnType:<root>.Values [primary]
VALUE_PARAMETER name:target index:0 type:kotlin.reflect.KClass<*>
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS ANNOTATION_CLASS name:Values modality:OPEN visibility:public superTypes:[kotlin.Annotation]'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Annotation
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
CLASS CLASS name:OptInTest modality:FINAL visibility:public superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.OptInTest
CONSTRUCTOR visibility:public <> () returnType:<root>.OptInTest [primary]
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'public constructor <init> () declared in kotlin.Any'
INSTANCE_INITIALIZER_CALL classDescriptor='CLASS CLASS name:OptInTest modality:FINAL visibility:public superTypes:[kotlin.Any]'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean [fake_override,operator]
overridden:
public open fun equals (other: kotlin.Any?): kotlin.Boolean declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
VALUE_PARAMETER name:other index:0 type:kotlin.Any?
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int [fake_override]
overridden:
public open fun hashCode (): kotlin.Int declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String [fake_override]
overridden:
public open fun toString (): kotlin.String declared in kotlin.Any
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
FUN GENERATED[love.forte.plugin.suspendtrans.fir.SuspendTransformPluginKey] name:runAsync visibility:public modality:FINAL <> ($this:<root>.OptInTest) returnType:java.util.concurrent.CompletableFuture
annotations:
OptIn(markerClass = [CLASS_REFERENCE 'CLASS ANNOTATION_CLASS name:OneOptAnno modality:OPEN visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<<root>.OneOptAnno>])
Values(target = CLASS_REFERENCE 'CLASS CLASS name:OptInTest modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<<root>.OptInTest>)
JvmBlocking(baseName = <null>, suffix = <null>, asProperty = <null>)
Api4J
$this: VALUE_PARAMETER name:<this> type:<root>.OptInTest
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun runAsync (): java.util.concurrent.CompletableFuture declared in <root>.OptInTest'
CALL 'public final fun $runInAsync$ <T> (block: kotlin.coroutines.SuspendFunction0<T of love.forte.plugin.suspendtrans.runtime.$runInAsync$>, scope: kotlinx.coroutines.CoroutineScope?): java.util.concurrent.CompletableFuture declared in love.forte.plugin.suspendtrans.runtime' type=java.util.concurrent.CompletableFuture origin=null
<T>: <none>
block: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<java.util.concurrent.CompletableFuture> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<no name provided> visibility:local modality:FINAL <> () returnType:java.util.concurrent.CompletableFuture [suspend]
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <no name provided> (): java.util.concurrent.CompletableFuture declared in <root>.OptInTest.runAsync'
CALL 'public final fun run (): kotlin.Int declared in <root>.OptInTest' type=kotlin.Int origin=null
$this: GET_VAR '<this>: <root>.OptInTest declared in <root>.OptInTest.runAsync' type=<root>.OptInTest origin=null
FUN GENERATED[love.forte.plugin.suspendtrans.fir.SuspendTransformPluginKey] name:runBlocking visibility:public modality:FINAL <> ($this:<root>.OptInTest) returnType:kotlin.Int
annotations:
OptIn(markerClass = [CLASS_REFERENCE 'CLASS ANNOTATION_CLASS name:OneOptAnno modality:OPEN visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<<root>.OneOptAnno>])
Values(target = CLASS_REFERENCE 'CLASS CLASS name:OptInTest modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<<root>.OptInTest>)
JvmAsync(baseName = <null>, suffix = <null>, asProperty = <null>)
Api4J
$this: VALUE_PARAMETER name:<this> type:<root>.OptInTest
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun runBlocking (): kotlin.Int declared in <root>.OptInTest'
CALL 'public final fun $runInBlocking$ <T> (block: kotlin.coroutines.SuspendFunction0<T of love.forte.plugin.suspendtrans.runtime.$runInBlocking$>): T of love.forte.plugin.suspendtrans.runtime.$runInBlocking$ declared in love.forte.plugin.suspendtrans.runtime' type=T of love.forte.plugin.suspendtrans.runtime.$runInBlocking$ origin=null
<T>: <none>
block: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.Int> origin=LAMBDA
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Int [suspend]
BLOCK_BODY
RETURN type=kotlin.Nothing from='local final fun <no name provided> (): kotlin.Int declared in <root>.OptInTest.runBlocking'
CALL 'public final fun run (): kotlin.Int declared in <root>.OptInTest' type=kotlin.Int origin=null
$this: GET_VAR '<this>: <root>.OptInTest declared in <root>.OptInTest.runBlocking' type=<root>.OptInTest origin=null
FUN name:run visibility:public modality:FINAL <> ($this:<root>.OptInTest) returnType:kotlin.Int [suspend]
annotations:
OptIn(markerClass = [CLASS_REFERENCE 'CLASS ANNOTATION_CLASS name:OneOptAnno modality:OPEN visibility:public superTypes:[kotlin.Annotation]' type=kotlin.reflect.KClass<<root>.OneOptAnno>])
Values(target = CLASS_REFERENCE 'CLASS CLASS name:OptInTest modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.reflect.KClass<<root>.OptInTest>)
JvmBlocking(baseName = <null>, suffix = <null>, asProperty = <null>)
JvmAsync(baseName = <null>, suffix = <null>, asProperty = <null>)
JvmSynthetic
$this: VALUE_PARAMETER name:<this> type:<root>.OptInTest
BLOCK_BODY
RETURN type=kotlin.Nothing from='public final fun run (): kotlin.Int declared in <root>.OptInTest'
CALL 'private final fun run0 (): kotlin.Int declared in <root>.OptInTest' type=kotlin.Int origin=null
$this: GET_VAR '<this>: <root>.OptInTest declared in <root>.OptInTest.run' type=<root>.OptInTest origin=null
FUN name:run0 visibility:private modality:FINAL <> ($this:<root>.OptInTest) returnType:kotlin.Int [suspend]
annotations:
OneOptAnno
$this: VALUE_PARAMETER name:<this> type:<root>.OptInTest
BLOCK_BODY
RETURN type=kotlin.Nothing from='private final fun run0 (): kotlin.Int declared in <root>.OptInTest'
CONST Int type=kotlin.Int value=1
34 changes: 34 additions & 0 deletions compiler/suspend-transform-plugin/src/testData/codegen/opt.fir.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
FILE: Main.kt
@R|kotlin/RequiresOptIn|(level = Q|kotlin/RequiresOptIn.Level|.R|kotlin/RequiresOptIn.Level.ERROR|) public final annotation class OneOptAnno : R|kotlin/Annotation| {
public constructor(): R|OneOptAnno| {
super<R|kotlin/Any|>()
}

}
public final annotation class Values : R|kotlin/Annotation| {
public constructor(target: R|kotlin/reflect/KClass<*>|): R|Values| {
super<R|kotlin/Any|>()
}

public final val target: R|kotlin/reflect/KClass<*>| = R|<local>/target|
public get(): R|kotlin/reflect/KClass<*>|

}
public final class OptInTest : R|kotlin/Any| {
public constructor(): R|OptInTest| {
super<R|kotlin/Any|>()
}

@R|OneOptAnno|() private final suspend fun run0(): R|kotlin/Int| {
^run0 Int(1)
}

@R|kotlin/OptIn|(markerClass = vararg(<getClass>(Q|OneOptAnno|))) @R|Values|(target = <getClass>(Q|OptInTest|)) @R|love/forte/plugin/suspendtrans/annotation/JvmBlocking|() @R|love/forte/plugin/suspendtrans/annotation/JvmAsync|() public final suspend fun run(): R|kotlin/Int| {
^run this@R|/OptInTest|.R|/OptInTest.run0|()
}

@R|kotlin/OptIn|(markerClass = vararg(<getClass>(Q|OneOptAnno|))) @R|Values|(target = <getClass>(Q|OptInTest|)) @R|love/forte/plugin/suspendtrans/annotation/JvmBlocking|() @R|love/forte/plugin/suspendtrans/annotation/Api4J|() public final fun runAsync(): R|java/util/concurrent/CompletableFuture<out kotlin/Int>|

@R|kotlin/OptIn|(markerClass = vararg(<getClass>(Q|OneOptAnno|))) @R|Values|(target = <getClass>(Q|OptInTest|)) @R|love/forte/plugin/suspendtrans/annotation/JvmAsync|() @R|love/forte/plugin/suspendtrans/annotation/Api4J|() public final fun runBlocking(): R|kotlin/Int|

}
27 changes: 27 additions & 0 deletions compiler/suspend-transform-plugin/src/testData/codegen/opt.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// FIR_DUMP
// DUMP_IR
// SOURCE
// FILE: Main.kt [MainKt#main]

import kotlinx.coroutines.suspendCancellableCoroutine
import love.forte.plugin.suspendtrans.annotation.JvmAsync
import love.forte.plugin.suspendtrans.annotation.JvmBlocking
import kotlin.annotation.AnnotationRetention.SOURCE
import kotlin.coroutines.resume
import kotlin.reflect.KClass

@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
annotation class OneOptAnno

annotation class Values(val target: KClass<*>)

class OptInTest {
@OneOptAnno
private suspend fun run0() = 1

@OptIn(OneOptAnno::class)
@Values(OptInTest::class)
@JvmBlocking
@JvmAsync
suspend fun run(): Int = run0()
}
31 changes: 8 additions & 23 deletions samples/sample-js/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,55 +25,40 @@ repositories {

apply(plugin = "love.forte.plugin.suspend-transform")

//tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
// kotlinOptions {
// useK2
// languageVersion = "2.0"
// }
//}



@OptIn(ExperimentalKotlinGradlePluginApi::class)
kotlin {
compilerOptions {
freeCompilerArgs.addAll(
"-Xexpect-actual-classes"
)
}

js(IR) {
nodejs()
useEsModules()
generateTypeScriptDefinitions()
binaries.executable()

@OptIn(ExperimentalKotlinGradlePluginApi::class)
compilerOptions {
target = "es2015"
useEsClasses = true
freeCompilerArgs.addAll(
// https://kotlinlang.org/docs/whatsnew20.html#per-file-compilation-for-kotlin-js-projects
"-Xir-per-file"
"-Xir-per-file",
)
}

// compilations.all {
// kotlinOptions {
// useEsClasses = true
// }
// }
}

sourceSets {
named("jsMain") {
dependencies {
implementation(kotlin("stdlib"))
// val pluginVersion = "0.4.0"
// api("love.forte.plugin.suspend-transform:suspend-transform-runtime:$pluginVersion")
// api("love.forte.plugin.suspend-transform:suspend-transform-annotation:$pluginVersion")
// implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
api(libs.kotlinx.coroutines.core)
}
}
}
}



extensions.getByType<SuspendTransformGradleExtension>().apply {
transformers[TargetPlatform.JS] = mutableListOf(
SuspendTransformConfiguration.jsPromiseTransformer.copy(
Expand Down
17 changes: 17 additions & 0 deletions samples/sample-js/src/commonMain/kotlin/Key.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@file:OptIn(ExperimentalJsExport::class)

import love.forte.plugin.suspendtrans.annotation.JsPromise


/**
*
* @author ForteScarlet
*/
@JsExport
abstract class Key {

@JsPromise
@JsExport.Ignore
abstract suspend fun run(): Any

}
10 changes: 10 additions & 0 deletions samples/sample-js/src/commonMain/kotlin/KeyImpl.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import love.forte.plugin.suspendtrans.annotation.JsPromise

/**
*
* @author ForteScarlet
*/
expect class KeyImpl : Key {
@JsPromise
override suspend fun run(): ByteArray
}
Loading