From 868006e50ba7fb403c472681c81835e3e40db3d9 Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Wed, 5 Jul 2023 16:35:36 +0800 Subject: [PATCH 1/4] =?UTF-8?q?WIP:=20=E5=B0=9D=E8=AF=95=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=AF=B9=20CoroutineScope=20=E7=9A=84=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E8=BD=AC=E5=8C=96=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ir/SuspendTransformTransformer.kt | 43 +++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt b/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt index d2474a0..8e97c82 100644 --- a/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt +++ b/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt @@ -1,6 +1,9 @@ package love.forte.plugin.suspendtrans.ir -import love.forte.plugin.suspendtrans.* +import love.forte.plugin.suspendtrans.SuspendTransformConfiguration +import love.forte.plugin.suspendtrans.SuspendTransformUserData +import love.forte.plugin.suspendtrans.SuspendTransformUserDataKey +import love.forte.plugin.suspendtrans.fqn import love.forte.plugin.suspendtrans.utils.* import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI @@ -9,16 +12,20 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI -import org.jetbrains.kotlin.ir.builders.irBlockBody -import org.jetbrains.kotlin.ir.builders.irCall -import org.jetbrains.kotlin.ir.builders.irGet -import org.jetbrains.kotlin.ir.builders.irReturn -import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.IrTypeOperator +import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.isSubtypeOfClass import org.jetbrains.kotlin.ir.types.typeWith -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.isAnnotationWithEqualFqName +import org.jetbrains.kotlin.ir.util.primaryConstructor import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -92,7 +99,8 @@ class SuspendTransformTransformer( private fun resolveFunctionBodyByDescriptor(declaration: IrFunction, descriptor: CallableDescriptor): IrFunction? { val userData = descriptor.getUserData(SuspendTransformUserDataKey) ?: return null - val callableFunction = pluginContext.referenceFunctions(userData.transformer.transformFunctionInfo.toCallableId()).firstOrNull() + val callableFunction = + pluginContext.referenceFunctions(userData.transformer.transformFunctionInfo.toCallableId()).firstOrNull() ?: throw IllegalStateException("Transform function ${userData.transformer.transformFunctionInfo} not found") val generatedOriginFunction = resolveFunctionBody(declaration, userData.originFunction, callableFunction) @@ -112,7 +120,7 @@ class SuspendTransformTransformer( currentAnnotations.any { a -> a.isAnnotationWithEqualFqName(name) } addAll(currentAnnotations) - val syntheticFunctionIncludes = userData.transformer.originFunctionIncludeAnnotations + val syntheticFunctionIncludes = userData.transformer.originFunctionIncludeAnnotations syntheticFunctionIncludes.forEach { include -> val classId = include.classInfo.toClassId() @@ -213,9 +221,26 @@ private fun generateTransformBodyForFunction( if (secondType.isClassType(coroutineScopeTypeNameUnsafe)) { function.dispatchReceiverParameter?.also { dispatchReceiverParameter -> context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef -> +// irGet(dispatchReceiverParameter) +// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>() if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) { // put 'this' to second arg putValueArgument(1, irGet(dispatchReceiverParameter)) + } else { + // TODO scope safe cast + val scopeType = coroutineScopeRef.defaultType +// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) + + val irSafeAs = IrTypeOperatorCallImpl( + startOffset, + endOffset, + scopeType, + IrTypeOperator.SAFE_CAST, + scopeType, + irGet(dispatchReceiverParameter) + ) + + putValueArgument(1, irSafeAs) } } } From 74eb23be426db16721e709538fcf214a9db7d64c Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Wed, 5 Jul 2023 17:07:50 +0800 Subject: [PATCH 2/4] =?UTF-8?q?WIP:=20=E5=B0=9D=E8=AF=95=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=AF=B9=20CoroutineScope=20=E7=9A=84=E5=AE=89=E5=85=A8?= =?UTF-8?q?=E7=B1=BB=E5=9E=8B=E8=BD=AC=E5=8C=96=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ir/SuspendTransformTransformer.kt | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt b/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt index 8e97c82..2c8f3fb 100644 --- a/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt +++ b/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt @@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.types.isNullable import org.jetbrains.kotlin.ir.types.isSubtypeOfClass import org.jetbrains.kotlin.ir.types.typeWith import org.jetbrains.kotlin.ir.util.isAnnotationWithEqualFqName @@ -229,18 +230,22 @@ private fun generateTransformBodyForFunction( } else { // TODO scope safe cast val scopeType = coroutineScopeRef.defaultType -// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) - val irSafeAs = IrTypeOperatorCallImpl( - startOffset, - endOffset, - scopeType, - IrTypeOperator.SAFE_CAST, - scopeType, - irGet(dispatchReceiverParameter) - ) + if (getValueArgument(1)?.type?.isNullable() == true) { + val irSafeAs = IrTypeOperatorCallImpl( + startOffset, + endOffset, + scopeType, + IrTypeOperator.SAFE_CAST, + scopeType, + irGet(dispatchReceiverParameter) + ) + + putValueArgument(1, irSafeAs) + } + +// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) - putValueArgument(1, irSafeAs) } } } From 94d28177f0c84201ed74f0bba19cac87469bdf13 Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Tue, 8 Aug 2023 18:11:30 +0800 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=E9=92=88=E5=AF=B9=20CoroutineScope?= =?UTF-8?q?=20=E7=B1=BB=E5=9E=8B=E7=9A=84=E5=8F=82=E6=95=B0=E7=9A=84?= =?UTF-8?q?=E5=A1=AB=E5=85=85=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/IProject.kt | 2 +- .../ir/SuspendTransformTransformer.kt | 139 ++++++++++++------ .../suspendtrans/runtime/RunInSuspendJvm.kt | 4 +- settings.gradle.kts | 2 +- .../build.gradle.kts | 17 ++- .../suspendtrans/sample/ForteScarlet.kt | 16 +- 7 files changed, 127 insertions(+), 55 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 9d385fe..3f035b5 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -9,7 +9,7 @@ repositories { } val kotlinVersion = "1.8.21" -val dokkaPluginVersion = "1.8.10" +val dokkaPluginVersion = "1.8.20" val gradleCommon = "0.0.11" dependencies { diff --git a/buildSrc/src/main/kotlin/IProject.kt b/buildSrc/src/main/kotlin/IProject.kt index 8adbfb1..2492bb3 100644 --- a/buildSrc/src/main/kotlin/IProject.kt +++ b/buildSrc/src/main/kotlin/IProject.kt @@ -8,7 +8,7 @@ object IProject : ProjectDetail() { const val DESCRIPTION = "Generate platform-compatible functions for Kotlin suspend functions" const val HOMEPAGE = "https://github.com/ForteScarlet/kotlin-suspend-transform-compiler-plugin" - override val version: Version = version(0, 3, 2) + override val version: Version = version(0, 4, 0) override val homepage: String get() = HOMEPAGE diff --git a/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt b/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt index 2c8f3fb..bbd3f2c 100644 --- a/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt +++ b/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt @@ -13,18 +13,13 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.builders.* -import org.jetbrains.kotlin.ir.declarations.IrDeclaration -import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer -import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.declarations.IrProperty +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrTypeOperator import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol -import org.jetbrains.kotlin.ir.types.defaultType -import org.jetbrains.kotlin.ir.types.isNullable -import org.jetbrains.kotlin.ir.types.isSubtypeOfClass -import org.jetbrains.kotlin.ir.types.typeWith +import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.isAnnotationWithEqualFqName import org.jetbrains.kotlin.ir.util.primaryConstructor import org.jetbrains.kotlin.name.ClassId @@ -214,45 +209,107 @@ private fun generateTransformBodyForFunction( //println(transformTargetFunctionCall.owner.valueParameters) val owner = transformTargetFunctionCall.owner + // CoroutineScope if (owner.valueParameters.size > 1) { - val secondType = owner.valueParameters[1].type - val coroutineScopeTypeName = "kotlinx.coroutines.CoroutineScope".fqn - val coroutineScopeTypeClassId = ClassId.topLevel("kotlinx.coroutines.CoroutineScope".fqn) - val coroutineScopeTypeNameUnsafe = coroutineScopeTypeName.toUnsafe() - if (secondType.isClassType(coroutineScopeTypeNameUnsafe)) { - function.dispatchReceiverParameter?.also { dispatchReceiverParameter -> - context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef -> -// irGet(dispatchReceiverParameter) -// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>() - if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) { - // put 'this' to second arg - putValueArgument(1, irGet(dispatchReceiverParameter)) - } else { - // TODO scope safe cast - val scopeType = coroutineScopeRef.defaultType - - if (getValueArgument(1)?.type?.isNullable() == true) { - val irSafeAs = IrTypeOperatorCallImpl( - startOffset, - endOffset, - scopeType, - IrTypeOperator.SAFE_CAST, - scopeType, - irGet(dispatchReceiverParameter) - ) - - putValueArgument(1, irSafeAs) - } - -// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) - - } - } + owner.valueParameters.forEachIndexed { index, valueParameter -> + if (index == 0) { + return@forEachIndexed } + + val type = valueParameter.type + tryResolveCoroutineScopeValueParameter(type, context, function, owner, this@irBlockBody, index) } +// val secondType = owner.valueParameters[1].type +// val coroutineScopeTypeName = "kotlinx.coroutines.CoroutineScope".fqn +// val coroutineScopeTypeClassId = ClassId.topLevel("kotlinx.coroutines.CoroutineScope".fqn) +// val coroutineScopeTypeNameUnsafe = coroutineScopeTypeName.toUnsafe() +// if (secondType.isClassType(coroutineScopeTypeNameUnsafe)) { +// function.dispatchReceiverParameter?.also { dispatchReceiverParameter -> +// context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef -> +//// irGet(dispatchReceiverParameter) +//// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>() +// if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) { +// // put 'this' to second arg +// putValueArgument(1, irGet(dispatchReceiverParameter)) +// } else { +// // scope safe cast +// val scopeType = coroutineScopeRef.defaultType +// +// val scopeParameter = owner.valueParameters.getOrNull(1) +// +// if (scopeParameter?.type?.isNullable() == true) { +// val irSafeAs = IrTypeOperatorCallImpl( +// startOffset, +// endOffset, +// scopeType, +// IrTypeOperator.SAFE_CAST, +// scopeType, +// irGet(dispatchReceiverParameter) +// ) +// +// putValueArgument(1, irSafeAs) +// } +//// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) +// } +// } +// } +// } + } }) } } + +private val coroutineScopeTypeName = "kotlinx.coroutines.CoroutineScope".fqn +private val coroutineScopeTypeClassId = ClassId.topLevel("kotlinx.coroutines.CoroutineScope".fqn) +private val coroutineScopeTypeNameUnsafe = coroutineScopeTypeName.toUnsafe() + +/** + * 解析类型为 CoroutineScope 的参数。 + * 如果当前参数类型为 CoroutineScope: + * - 如果当前 dispatcher 即为 CoroutineScope 类型,将其填充 + * - 如果当前 dispatcher 不是 CoroutineScope 类型,但是此参数可以为 null,则使用 safe-cast 将 dispatcher 转化为 CoroutineScope ( `dispatcher as? CoroutineScope` ) + * - 其他情况忽略此参数(适用于此参数有默认值的情况) + */ +private fun IrCall.tryResolveCoroutineScopeValueParameter( + type: IrType, + context: IrPluginContext, + function: IrFunction, + owner: IrSimpleFunction, + builderWithScope: IrBuilderWithScope, + index: Int +) { + if (type.isClassType(coroutineScopeTypeNameUnsafe)) { + function.dispatchReceiverParameter?.also { dispatchReceiverParameter -> + context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef -> +// irGet(dispatchReceiverParameter) +// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>() + if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) { + // put 'this' to second arg + putValueArgument(index, builderWithScope.irGet(dispatchReceiverParameter)) + } else { + // scope safe cast + val scopeType = coroutineScopeRef.defaultType + + val scopeParameter = owner.valueParameters.getOrNull(1) + + if (scopeParameter?.type?.isNullable() == true) { + val irSafeAs = IrTypeOperatorCallImpl( + startOffset, + endOffset, + scopeType, + IrTypeOperator.SAFE_CAST, + scopeType, + builderWithScope.irGet(dispatchReceiverParameter) + ) + + putValueArgument(index, irSafeAs) + } +// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) + } + } + } + } +} diff --git a/runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt b/runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt index 53b8b5c..741ccc3 100644 --- a/runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt +++ b/runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt @@ -74,9 +74,9 @@ private val transformer: FutureTransformer = @Suppress("FunctionName") public fun `$runInAsync$`( block: suspend () -> T, - scope: CoroutineScope = `$CoroutineScope4J$` + scope: CoroutineScope? = null //`$CoroutineScope4J$` ): CompletableFuture { - return transformer.trans(scope, block) + return transformer.trans(scope ?: `$CoroutineScope4J$`, block) } diff --git a/settings.gradle.kts b/settings.gradle.kts index f518c2b..55fd4b0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,5 +8,5 @@ include(":runtime:suspend-transform-runtime") include(":plugins:suspend-transform-plugin-gradle") -//include(":suspend-transform-plugin-sample") +include(":suspend-transform-plugin-sample") // include(":plugins:ide:suspend-transform-plugin-idea") diff --git a/suspend-transform-plugin-sample/build.gradle.kts b/suspend-transform-plugin-sample/build.gradle.kts index f7a00f6..34e2533 100644 --- a/suspend-transform-plugin-sample/build.gradle.kts +++ b/suspend-transform-plugin-sample/build.gradle.kts @@ -8,6 +8,7 @@ plugins { // id(project(":suspend-transform-plugin-gradle")) } + buildscript { this@buildscript.repositories { mavenLocal() @@ -15,7 +16,7 @@ plugins { } dependencies { //this.implementation() - classpath("love.forte.plugin.suspend-transform:suspend-transform-plugin-gradle:0.3.2") + classpath("love.forte.plugin.suspend-transform:suspend-transform-plugin-gradle:0.4.0") } } @@ -24,9 +25,10 @@ plugins { // sourceCompatibility = "11" // targetCompatibility = "11" //} -//withType { -// kotlinOptions.jvmTarget = "11" -//} + +tasks.withType { + kotlinOptions.freeCompilerArgs += "-Xjvm-default=all" +} repositories { mavenLocal() @@ -36,9 +38,10 @@ apply(plugin = "love.forte.plugin.suspend-transform") dependencies { api(kotlin("stdlib")) -// api("love.forte.plugin.suspend-transform:suspend-transform-runtime:0.3.2") -// api("love.forte.plugin.suspend-transform:suspend-transform-annotation:0.3.2") - api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.0") +// 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") + api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") } extensions.getByType().apply { diff --git a/suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt b/suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt index 9c743d7..6f13de3 100644 --- a/suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt +++ b/suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt @@ -7,18 +7,30 @@ import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext +abstract class IForteScarlet { + @JvmAsync + abstract suspend fun stringToInt(value: String): Int +} + + /** * * @author ForteScarlet */ -class ForteScarlet : CoroutineScope { +class ForteScarlet : CoroutineScope, IForteScarlet() { override val coroutineContext: CoroutineContext get() = EmptyCoroutineContext @JvmAsync - suspend fun stringToInt(value: String): Int { + override suspend fun stringToInt(value: String): Int { delay(5) return value.toInt() } + // @JvmAsync +// suspend fun stringToInt(value: String): Int { +// delay(5) +// return value.toInt() +// } + } From 46bd845d212658ff361c3c4d1f9562a2a0078a77 Mon Sep 17 00:00:00 2001 From: ForteScarlet Date: Wed, 9 Aug 2023 09:49:57 +0800 Subject: [PATCH 4/4] =?UTF-8?q?feat:=20=E9=92=88=E5=AF=B9=20CoroutineScope?= =?UTF-8?q?=20=E7=B1=BB=E5=9E=8B=E7=9A=84=E5=8F=82=E6=95=B0=E7=9A=84?= =?UTF-8?q?=E5=A1=AB=E5=85=85=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .run/PublishAllToLocal.run.xml | 29 +++++ .../ir/SuspendTransformTransformer.kt | 104 ++++++------------ .../suspendtrans/runtime/RunInSuspendJvm.kt | 2 +- settings.gradle.kts | 2 +- .../suspendtrans/sample/ForteScarlet.kt | 3 + 5 files changed, 67 insertions(+), 73 deletions(-) create mode 100644 .run/PublishAllToLocal.run.xml diff --git a/.run/PublishAllToLocal.run.xml b/.run/PublishAllToLocal.run.xml new file mode 100644 index 0000000..8d3e8ff --- /dev/null +++ b/.run/PublishAllToLocal.run.xml @@ -0,0 +1,29 @@ + + + + + + + + true + true + false + false + + + \ No newline at end of file diff --git a/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt b/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt index bbd3f2c..ba44e2c 100644 --- a/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt +++ b/compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt @@ -210,52 +210,14 @@ private fun generateTransformBodyForFunction( val owner = transformTargetFunctionCall.owner // CoroutineScope - if (owner.valueParameters.size > 1) { - owner.valueParameters.forEachIndexed { index, valueParameter -> - if (index == 0) { - return@forEachIndexed - } + val ownerValueParameters = owner.valueParameters + if (ownerValueParameters.size > 1) { + for (index in 1..ownerValueParameters.lastIndex) { + val valueParameter = ownerValueParameters[index] val type = valueParameter.type tryResolveCoroutineScopeValueParameter(type, context, function, owner, this@irBlockBody, index) } - -// val secondType = owner.valueParameters[1].type -// val coroutineScopeTypeName = "kotlinx.coroutines.CoroutineScope".fqn -// val coroutineScopeTypeClassId = ClassId.topLevel("kotlinx.coroutines.CoroutineScope".fqn) -// val coroutineScopeTypeNameUnsafe = coroutineScopeTypeName.toUnsafe() -// if (secondType.isClassType(coroutineScopeTypeNameUnsafe)) { -// function.dispatchReceiverParameter?.also { dispatchReceiverParameter -> -// context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef -> -//// irGet(dispatchReceiverParameter) -//// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>() -// if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) { -// // put 'this' to second arg -// putValueArgument(1, irGet(dispatchReceiverParameter)) -// } else { -// // scope safe cast -// val scopeType = coroutineScopeRef.defaultType -// -// val scopeParameter = owner.valueParameters.getOrNull(1) -// -// if (scopeParameter?.type?.isNullable() == true) { -// val irSafeAs = IrTypeOperatorCallImpl( -// startOffset, -// endOffset, -// scopeType, -// IrTypeOperator.SAFE_CAST, -// scopeType, -// irGet(dispatchReceiverParameter) -// ) -// -// putValueArgument(1, irSafeAs) -// } -//// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) -// } -// } -// } -// } - } }) @@ -269,8 +231,9 @@ private val coroutineScopeTypeNameUnsafe = coroutineScopeTypeName.toUnsafe() /** * 解析类型为 CoroutineScope 的参数。 * 如果当前参数类型为 CoroutineScope: - * - 如果当前 dispatcher 即为 CoroutineScope 类型,将其填充 - * - 如果当前 dispatcher 不是 CoroutineScope 类型,但是此参数可以为 null,则使用 safe-cast 将 dispatcher 转化为 CoroutineScope ( `dispatcher as? CoroutineScope` ) + * - 如果当前 receiver 即为 CoroutineScope 类型,将其填充 + * - 如果当前 receiver 不是 CoroutineScope 类型,但是此参数可以为 null, + * 则使用 safe-cast 将 receiver 转化为 CoroutineScope ( `dispatcher as? CoroutineScope` ) * - 其他情况忽略此参数(适用于此参数有默认值的情况) */ private fun IrCall.tryResolveCoroutineScopeValueParameter( @@ -281,34 +244,33 @@ private fun IrCall.tryResolveCoroutineScopeValueParameter( builderWithScope: IrBuilderWithScope, index: Int ) { - if (type.isClassType(coroutineScopeTypeNameUnsafe)) { - function.dispatchReceiverParameter?.also { dispatchReceiverParameter -> - context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef -> -// irGet(dispatchReceiverParameter) -// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>() - if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) { - // put 'this' to second arg - putValueArgument(index, builderWithScope.irGet(dispatchReceiverParameter)) - } else { - // scope safe cast - val scopeType = coroutineScopeRef.defaultType - - val scopeParameter = owner.valueParameters.getOrNull(1) - - if (scopeParameter?.type?.isNullable() == true) { - val irSafeAs = IrTypeOperatorCallImpl( - startOffset, - endOffset, - scopeType, - IrTypeOperator.SAFE_CAST, - scopeType, - builderWithScope.irGet(dispatchReceiverParameter) - ) - - putValueArgument(index, irSafeAs) - } -// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) + if (!type.isClassType(coroutineScopeTypeNameUnsafe)) { + return + } + + function.dispatchReceiverParameter?.also { dispatchReceiverParameter -> + context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef -> + if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) { + // put 'this' to the arg + putValueArgument(index, builderWithScope.irGet(dispatchReceiverParameter)) + } else { + val scopeType = coroutineScopeRef.defaultType + + val scopeParameter = owner.valueParameters.getOrNull(1) + + if (scopeParameter?.type?.isNullable() == true) { + val irSafeAs = IrTypeOperatorCallImpl( + startOffset, + endOffset, + scopeType, + IrTypeOperator.SAFE_CAST, + scopeType, + builderWithScope.irGet(dispatchReceiverParameter) + ) + + putValueArgument(index, irSafeAs) } +// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType) } } } diff --git a/runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt b/runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt index 741ccc3..d344b6a 100644 --- a/runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt +++ b/runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt @@ -74,7 +74,7 @@ private val transformer: FutureTransformer = @Suppress("FunctionName") public fun `$runInAsync$`( block: suspend () -> T, - scope: CoroutineScope? = null //`$CoroutineScope4J$` + scope: CoroutineScope? = null ): CompletableFuture { return transformer.trans(scope ?: `$CoroutineScope4J$`, block) } diff --git a/settings.gradle.kts b/settings.gradle.kts index 55fd4b0..f518c2b 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -8,5 +8,5 @@ include(":runtime:suspend-transform-runtime") include(":plugins:suspend-transform-plugin-gradle") -include(":suspend-transform-plugin-sample") +//include(":suspend-transform-plugin-sample") // include(":plugins:ide:suspend-transform-plugin-idea") diff --git a/suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt b/suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt index 6f13de3..3e789a0 100644 --- a/suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt +++ b/suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt @@ -3,12 +3,14 @@ package love.forte.plugin.suspendtrans.sample import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.delay import love.forte.plugin.suspendtrans.annotation.JvmAsync +import love.forte.plugin.suspendtrans.annotation.JvmBlocking import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext abstract class IForteScarlet { @JvmAsync + @JvmBlocking abstract suspend fun stringToInt(value: String): Int } @@ -22,6 +24,7 @@ class ForteScarlet : CoroutineScope, IForteScarlet() { get() = EmptyCoroutineContext @JvmAsync + @JvmBlocking override suspend fun stringToInt(value: String): Int { delay(5) return value.toInt()