Skip to content

Commit 94d2817

Browse files
committed
feat: 针对 CoroutineScope 类型的参数的填充优化
1 parent 74eb23b commit 94d2817

File tree

7 files changed

+127
-55
lines changed

7 files changed

+127
-55
lines changed

buildSrc/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ repositories {
99
}
1010

1111
val kotlinVersion = "1.8.21"
12-
val dokkaPluginVersion = "1.8.10"
12+
val dokkaPluginVersion = "1.8.20"
1313
val gradleCommon = "0.0.11"
1414

1515
dependencies {

buildSrc/src/main/kotlin/IProject.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ object IProject : ProjectDetail() {
88
const val DESCRIPTION = "Generate platform-compatible functions for Kotlin suspend functions"
99
const val HOMEPAGE = "https://github.com/ForteScarlet/kotlin-suspend-transform-compiler-plugin"
1010

11-
override val version: Version = version(0, 3, 2)
11+
override val version: Version = version(0, 4, 0)
1212

1313
override val homepage: String get() = HOMEPAGE
1414

compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/ir/SuspendTransformTransformer.kt

Lines changed: 98 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,13 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
1313
import org.jetbrains.kotlin.ir.IrStatement
1414
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
1515
import org.jetbrains.kotlin.ir.builders.*
16-
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
17-
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
18-
import org.jetbrains.kotlin.ir.declarations.IrFunction
19-
import org.jetbrains.kotlin.ir.declarations.IrProperty
16+
import org.jetbrains.kotlin.ir.declarations.*
2017
import org.jetbrains.kotlin.ir.expressions.IrBody
18+
import org.jetbrains.kotlin.ir.expressions.IrCall
2119
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
2220
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
2321
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
24-
import org.jetbrains.kotlin.ir.types.defaultType
25-
import org.jetbrains.kotlin.ir.types.isNullable
26-
import org.jetbrains.kotlin.ir.types.isSubtypeOfClass
27-
import org.jetbrains.kotlin.ir.types.typeWith
22+
import org.jetbrains.kotlin.ir.types.*
2823
import org.jetbrains.kotlin.ir.util.isAnnotationWithEqualFqName
2924
import org.jetbrains.kotlin.ir.util.primaryConstructor
3025
import org.jetbrains.kotlin.name.ClassId
@@ -214,45 +209,107 @@ private fun generateTransformBodyForFunction(
214209
//println(transformTargetFunctionCall.owner.valueParameters)
215210
val owner = transformTargetFunctionCall.owner
216211

212+
// CoroutineScope
217213
if (owner.valueParameters.size > 1) {
218-
val secondType = owner.valueParameters[1].type
219-
val coroutineScopeTypeName = "kotlinx.coroutines.CoroutineScope".fqn
220-
val coroutineScopeTypeClassId = ClassId.topLevel("kotlinx.coroutines.CoroutineScope".fqn)
221-
val coroutineScopeTypeNameUnsafe = coroutineScopeTypeName.toUnsafe()
222-
if (secondType.isClassType(coroutineScopeTypeNameUnsafe)) {
223-
function.dispatchReceiverParameter?.also { dispatchReceiverParameter ->
224-
context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef ->
225-
// irGet(dispatchReceiverParameter)
226-
// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>()
227-
if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) {
228-
// put 'this' to second arg
229-
putValueArgument(1, irGet(dispatchReceiverParameter))
230-
} else {
231-
// TODO scope safe cast
232-
val scopeType = coroutineScopeRef.defaultType
233-
234-
if (getValueArgument(1)?.type?.isNullable() == true) {
235-
val irSafeAs = IrTypeOperatorCallImpl(
236-
startOffset,
237-
endOffset,
238-
scopeType,
239-
IrTypeOperator.SAFE_CAST,
240-
scopeType,
241-
irGet(dispatchReceiverParameter)
242-
)
243-
244-
putValueArgument(1, irSafeAs)
245-
}
246-
247-
// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType)
248-
249-
}
250-
}
214+
owner.valueParameters.forEachIndexed { index, valueParameter ->
215+
if (index == 0) {
216+
return@forEachIndexed
251217
}
218+
219+
val type = valueParameter.type
220+
tryResolveCoroutineScopeValueParameter(type, context, function, owner, this@irBlockBody, index)
252221
}
253222

223+
// val secondType = owner.valueParameters[1].type
224+
// val coroutineScopeTypeName = "kotlinx.coroutines.CoroutineScope".fqn
225+
// val coroutineScopeTypeClassId = ClassId.topLevel("kotlinx.coroutines.CoroutineScope".fqn)
226+
// val coroutineScopeTypeNameUnsafe = coroutineScopeTypeName.toUnsafe()
227+
// if (secondType.isClassType(coroutineScopeTypeNameUnsafe)) {
228+
// function.dispatchReceiverParameter?.also { dispatchReceiverParameter ->
229+
// context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef ->
230+
//// irGet(dispatchReceiverParameter)
231+
//// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>()
232+
// if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) {
233+
// // put 'this' to second arg
234+
// putValueArgument(1, irGet(dispatchReceiverParameter))
235+
// } else {
236+
// // scope safe cast
237+
// val scopeType = coroutineScopeRef.defaultType
238+
//
239+
// val scopeParameter = owner.valueParameters.getOrNull(1)
240+
//
241+
// if (scopeParameter?.type?.isNullable() == true) {
242+
// val irSafeAs = IrTypeOperatorCallImpl(
243+
// startOffset,
244+
// endOffset,
245+
// scopeType,
246+
// IrTypeOperator.SAFE_CAST,
247+
// scopeType,
248+
// irGet(dispatchReceiverParameter)
249+
// )
250+
//
251+
// putValueArgument(1, irSafeAs)
252+
// }
253+
//// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType)
254+
// }
255+
// }
256+
// }
257+
// }
258+
254259
}
255260

256261
})
257262
}
258263
}
264+
265+
private val coroutineScopeTypeName = "kotlinx.coroutines.CoroutineScope".fqn
266+
private val coroutineScopeTypeClassId = ClassId.topLevel("kotlinx.coroutines.CoroutineScope".fqn)
267+
private val coroutineScopeTypeNameUnsafe = coroutineScopeTypeName.toUnsafe()
268+
269+
/**
270+
* 解析类型为 CoroutineScope 的参数。
271+
* 如果当前参数类型为 CoroutineScope:
272+
* - 如果当前 dispatcher 即为 CoroutineScope 类型,将其填充
273+
* - 如果当前 dispatcher 不是 CoroutineScope 类型,但是此参数可以为 null,则使用 safe-cast 将 dispatcher 转化为 CoroutineScope ( `dispatcher as? CoroutineScope` )
274+
* - 其他情况忽略此参数(适用于此参数有默认值的情况)
275+
*/
276+
private fun IrCall.tryResolveCoroutineScopeValueParameter(
277+
type: IrType,
278+
context: IrPluginContext,
279+
function: IrFunction,
280+
owner: IrSimpleFunction,
281+
builderWithScope: IrBuilderWithScope,
282+
index: Int
283+
) {
284+
if (type.isClassType(coroutineScopeTypeNameUnsafe)) {
285+
function.dispatchReceiverParameter?.also { dispatchReceiverParameter ->
286+
context.referenceClass(coroutineScopeTypeClassId)?.also { coroutineScopeRef ->
287+
// irGet(dispatchReceiverParameter)
288+
// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef).safeAs<>()
289+
if (dispatchReceiverParameter.type.isSubtypeOfClass(coroutineScopeRef)) {
290+
// put 'this' to second arg
291+
putValueArgument(index, builderWithScope.irGet(dispatchReceiverParameter))
292+
} else {
293+
// scope safe cast
294+
val scopeType = coroutineScopeRef.defaultType
295+
296+
val scopeParameter = owner.valueParameters.getOrNull(1)
297+
298+
if (scopeParameter?.type?.isNullable() == true) {
299+
val irSafeAs = IrTypeOperatorCallImpl(
300+
startOffset,
301+
endOffset,
302+
scopeType,
303+
IrTypeOperator.SAFE_CAST,
304+
scopeType,
305+
builderWithScope.irGet(dispatchReceiverParameter)
306+
)
307+
308+
putValueArgument(index, irSafeAs)
309+
}
310+
// irAs(irGet(dispatchReceiverParameter), coroutineScopeRef.defaultType)
311+
}
312+
}
313+
}
314+
}
315+
}

runtime/suspend-transform-runtime/src/jvmMain/kotlin/love/forte/plugin/suspendtrans/runtime/RunInSuspendJvm.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ private val transformer: FutureTransformer =
7474
@Suppress("FunctionName")
7575
public fun <T> `$runInAsync$`(
7676
block: suspend () -> T,
77-
scope: CoroutineScope = `$CoroutineScope4J$`
77+
scope: CoroutineScope? = null //`$CoroutineScope4J$`
7878
): CompletableFuture<T> {
79-
return transformer.trans(scope, block)
79+
return transformer.trans(scope ?: `$CoroutineScope4J$`, block)
8080
}
8181

8282

settings.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ include(":runtime:suspend-transform-runtime")
88

99
include(":plugins:suspend-transform-plugin-gradle")
1010

11-
//include(":suspend-transform-plugin-sample")
11+
include(":suspend-transform-plugin-sample")
1212
// include(":plugins:ide:suspend-transform-plugin-idea")

suspend-transform-plugin-sample/build.gradle.kts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ plugins {
88
// id(project(":suspend-transform-plugin-gradle"))
99
}
1010

11+
1112
buildscript {
1213
this@buildscript.repositories {
1314
mavenLocal()
1415
mavenCentral()
1516
}
1617
dependencies {
1718
//this.implementation()
18-
classpath("love.forte.plugin.suspend-transform:suspend-transform-plugin-gradle:0.3.2")
19+
classpath("love.forte.plugin.suspend-transform:suspend-transform-plugin-gradle:0.4.0")
1920
}
2021
}
2122

@@ -24,9 +25,10 @@ plugins {
2425
// sourceCompatibility = "11"
2526
// targetCompatibility = "11"
2627
//}
27-
//withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
28-
// kotlinOptions.jvmTarget = "11"
29-
//}
28+
29+
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
30+
kotlinOptions.freeCompilerArgs += "-Xjvm-default=all"
31+
}
3032

3133
repositories {
3234
mavenLocal()
@@ -36,9 +38,10 @@ apply(plugin = "love.forte.plugin.suspend-transform")
3638

3739
dependencies {
3840
api(kotlin("stdlib"))
39-
// api("love.forte.plugin.suspend-transform:suspend-transform-runtime:0.3.2")
40-
// api("love.forte.plugin.suspend-transform:suspend-transform-annotation:0.3.2")
41-
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.0")
41+
// val pluginVersion = "0.4.0"
42+
// api("love.forte.plugin.suspend-transform:suspend-transform-runtime:$pluginVersion")
43+
// api("love.forte.plugin.suspend-transform:suspend-transform-annotation:$pluginVersion")
44+
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
4245
}
4346

4447
extensions.getByType<SuspendTransformGradleExtension>().apply {

suspend-transform-plugin-sample/src/main/kotlin/love/forte/plugin/suspendtrans/sample/ForteScarlet.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,30 @@ import kotlin.coroutines.CoroutineContext
77
import kotlin.coroutines.EmptyCoroutineContext
88

99

10+
abstract class IForteScarlet {
11+
@JvmAsync
12+
abstract suspend fun stringToInt(value: String): Int
13+
}
14+
15+
1016
/**
1117
*
1218
* @author ForteScarlet
1319
*/
14-
class ForteScarlet : CoroutineScope {
20+
class ForteScarlet : CoroutineScope, IForteScarlet() {
1521
override val coroutineContext: CoroutineContext
1622
get() = EmptyCoroutineContext
1723

1824
@JvmAsync
19-
suspend fun stringToInt(value: String): Int {
25+
override suspend fun stringToInt(value: String): Int {
2026
delay(5)
2127
return value.toInt()
2228
}
2329

30+
// @JvmAsync
31+
// suspend fun stringToInt(value: String): Int {
32+
// delay(5)
33+
// return value.toInt()
34+
// }
35+
2436
}

0 commit comments

Comments
 (0)