Skip to content

Commit 34b29f0

Browse files
committed
Improved transformer initialization, improved exceptions, improved parameter padding
1 parent b607797 commit 34b29f0

File tree

3 files changed

+100
-31
lines changed

3 files changed

+100
-31
lines changed

compiler/suspend-transform-plugin/src/main/kotlin/love/forte/plugin/suspendtrans/fir/SuspendTransformFirTransformer.kt

Lines changed: 82 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
3232
import org.jetbrains.kotlin.fir.resolve.ScopeSession
3333
import org.jetbrains.kotlin.fir.resolve.SessionHolderImpl
3434
import org.jetbrains.kotlin.fir.resolve.getSuperTypes
35+
import org.jetbrains.kotlin.fir.resolve.providers.dependenciesSymbolProvider
3536
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
3637
import org.jetbrains.kotlin.fir.resolve.toRegularClassSymbol
3738
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
@@ -90,22 +91,29 @@ class SuspendTransformFirTransformer(
9091
)
9192

9293
private fun initScopeSymbol() {
93-
coroutineScopeSymbol = session.symbolProvider.getClassLikeSymbolByClassId(
94-
ClassId(
95-
FqName.fromSegments(listOf("kotlinx", "coroutines")),
96-
Name.identifier("CoroutineScope")
97-
)
98-
) ?: error("Cannot resolve `kotlinx.coroutines.CoroutineScope` symbol.")
94+
95+
val classId = ClassId(
96+
FqName.fromSegments(listOf("kotlinx", "coroutines")),
97+
Name.identifier("CoroutineScope")
98+
)
99+
100+
coroutineScopeSymbol = session.symbolProvider.getClassLikeSymbolByClassId(classId)
101+
?: session.dependenciesSymbolProvider.getClassLikeSymbolByClassId(classId)
102+
?: error("Cannot resolve `kotlinx.coroutines.CoroutineScope` symbol.")
99103
}
100104

101105
private fun initTransformerFunctionSymbolMap() {
102106
// 尝试找到所有配置的 bridge function, 例如 `runBlocking` 等
107+
val symbolProvider = session.symbolProvider
108+
val dependenciesSymbolProvider = session.dependenciesSymbolProvider
109+
103110
suspendTransformConfiguration.transformers
104-
.forEach { (_, transformerList) ->
111+
.forEach { (platform, transformerList) ->
105112
for (transformer in transformerList) {
106113
val transformFunctionInfo = transformer.transformFunctionInfo
107114
val packageName = transformFunctionInfo.packageName
108115
val functionName = transformFunctionInfo.functionName
116+
109117
@Suppress("DEPRECATION")
110118
val className = transformFunctionInfo.className
111119
if (className != null) {
@@ -117,11 +125,18 @@ class SuspendTransformFirTransformer(
117125

118126
// TODO 校验funcs?
119127

128+
val functionNameIdentifier = Name.identifier(functionName)
129+
120130
val transformerFunctionSymbols =
121-
session.symbolProvider.getTopLevelFunctionSymbols(
131+
symbolProvider.getTopLevelFunctionSymbols(
122132
packageName.fqn,
123-
Name.identifier(functionName)
124-
)
133+
functionNameIdentifier
134+
).ifEmpty {
135+
dependenciesSymbolProvider.getTopLevelFunctionSymbols(
136+
packageName.fqn,
137+
functionNameIdentifier
138+
)
139+
}
125140

126141
if (transformerFunctionSymbols.isNotEmpty()) {
127142
if (transformerFunctionSymbols.size == 1) {
@@ -130,7 +145,8 @@ class SuspendTransformFirTransformer(
130145
error("Found multiple transformer function symbols for transformer: $transformer")
131146
}
132147
} else {
133-
error("Cannot find transformer function symbol for transformer: $transformer")
148+
// 有时候在不同平台中寻找,可能会找不到,例如在jvm中找不到js的函数
149+
// error("Cannot find transformer function symbol $packageName.$functionName (${session.moduleData.platform}) for transformer: $transformer")
134150
}
135151
}
136152
}
@@ -331,7 +347,6 @@ class SuspendTransformFirTransformer(
331347
}
332348
}
333349

334-
// TODO?
335350
this.contextReceiverArguments.addAll(thisContextReceivers.map { receiver ->
336351
buildThisReceiverExpression {
337352
coneTypeOrNull = receiver.typeRef.coneTypeOrNull
@@ -390,13 +405,13 @@ class SuspendTransformFirTransformer(
390405
this.resolvedSymbol = bridgeFunSymbol
391406
}
392407

393-
// this.dispatchReceiver = buildThisReceiverExpression {
394-
// coneTypeOrNull = originFunSymbol.dispatchReceiverType
395-
// source = originFunSymbol.source
396-
// calleeReference = buildImplicitThisReference {
397-
// boundSymbol = owner
398-
// }
399-
// }
408+
// this.dispatchReceiver = buildThisReceiverExpression {
409+
// coneTypeOrNull = originFunSymbol.dispatchReceiverType
410+
// source = originFunSymbol.source
411+
// calleeReference = buildImplicitThisReference {
412+
// boundSymbol = owner
413+
// }
414+
// }
400415

401416
this.argumentList = buildResolvedArgumentList(
402417
null,
@@ -416,21 +431,36 @@ class SuspendTransformFirTransformer(
416431
bridgeFunSymbol.valueParameterSymbols
417432

418433
if (valueParameterSymbols.size > 1) {
434+
// 支持:
435+
// CoroutineScope? -> this as? CoroutineScope
436+
// CoroutineScope -> this or throw error
437+
// CoroutineScope (optional) -> this or ignore
438+
// TODO Any -> this
439+
// TODO 后面的所有参数处理
440+
441+
// val listIterator = valueParameterSymbols.listIterator(1)
442+
// listIterator.forEach { otherParameter ->
443+
//
444+
// }
445+
419446
val secondParameter = valueParameterSymbols[1]
420447

421448
val secondParameterType = secondParameter.resolvedReturnType
422449
val secondParameterTypeNotNullable =
423450
secondParameterType.makeConeTypeDefinitelyNotNullOrNotNull(session.typeContext)
424451

425-
val isCoroutineScope = secondParameterTypeNotNullable.isSubtypeOf(
426-
coroutineScopeSymbol.toLookupTag().constructClassType(),
427-
session,
428-
)
452+
fun ConeKotlinType.isCoroutineScope(): Boolean {
453+
return isSubtypeOf(
454+
coroutineScopeSymbol.toLookupTag().constructClassType(),
455+
session
456+
)
457+
}
458+
459+
val isCoroutineScope = secondParameterTypeNotNullable.isCoroutineScope()
429460

430461
if (isCoroutineScope) {
431462
if (secondParameterType.isMarkedNullable) {
432463
// this as? CoroutineScope
433-
434464
val secondParameterTypeNotNullable =
435465
secondParameterType.makeConeTypeDefinitelyNotNullOrNotNull(
436466
session.typeContext
@@ -458,15 +488,39 @@ class SuspendTransformFirTransformer(
458488
operation = FirOperation.SAFE_AS
459489
conversionTypeRef =
460490
secondParameterTypeNotNullable.toFirResolvedTypeRef()
461-
462491
},
463492
secondParameter.fir
464493
)
465494

466495
} else {
467-
// this as CoroutineScope
468-
// or throw error?
496+
// if this is CoroutineScope, put, or throw error?
497+
498+
var ownerIsCoroutineScopeOrParameterIsOptional = secondParameter.hasDefaultValue
499+
500+
for (superType in owner.getSuperTypes(session, recursive = false)) {
501+
if (superType.isCoroutineScope()) {
502+
put(
503+
buildThisReceiverExpression {
504+
coneTypeOrNull = originFunSymbol.dispatchReceiverType
505+
source = originFunSymbol.source
506+
calleeReference = buildImplicitThisReference {
507+
boundSymbol = owner
508+
}
509+
},
510+
secondParameter.fir
511+
)
512+
ownerIsCoroutineScopeOrParameterIsOptional = true
513+
break
514+
}
515+
}
469516

517+
// or throw error?
518+
if (!ownerIsCoroutineScopeOrParameterIsOptional) {
519+
error(
520+
"Owner is not a CoroutineScope, " +
521+
"and the transformer function requires a `CoroutineScope` parameter."
522+
)
523+
}
470524
}
471525

472526
}
@@ -535,10 +589,6 @@ class SuspendTransformFirTransformer(
535589
),
536590
)
537591

538-
// val returnType = resolveReturnType(originFunc, funData, returnTypeRef)
539-
// returnTypeRef = returnType
540-
// returnTypeRef = funData.bridgeFunData.returnType
541-
542592
// Copy the typeParameters.
543593
// Otherwise, in functions like the following, an error will occur
544594
// suspend fun <A> data(value: A): T = ...
@@ -869,6 +919,7 @@ class SuspendTransformFirTransformer(
869919
val anno = firAnnotation(func, markAnnotation, classSymbol)
870920
?: continue
871921

922+
872923
val transformerFunctionSymbol = transformerFunctionSymbolMap[transformer]
873924
?: error("Cannot find transformer function symbol for transformer: $transformer")
874925

compiler/suspend-transform-plugin/src/test-gen/love/forte/plugin/suspendtrans/runners/CodeGenTestRunnerGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ public void testBasic() {
3232
runTest("src/testData/codegen/basic.kt");
3333
}
3434

35+
@Test
36+
@TestMetadata("async.kt")
37+
public void testAsync() {
38+
runTest("src/testData/codegen/async.kt");
39+
}
40+
3541
@Test
3642
@TestMetadata("override.kt")
3743
public void testOverride() {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// FIR_DUMP
2+
// DUMP_IR
3+
// SOURCE
4+
// FILE: Main.kt [MainKt#main]
5+
6+
import love.forte.plugin.suspendtrans.annotation.JvmAsync
7+
import love.forte.plugin.suspendtrans.annotation.JvmBlocking
8+
9+
class BasicFoo {
10+
@JvmAsync
11+
suspend fun foo(): String = "foo"
12+
}

0 commit comments

Comments
 (0)