Skip to content

Commit 71a8ce4

Browse files
committed
Refactoring K2 code generation logic
1 parent 8960a13 commit 71a8ce4

File tree

80 files changed

+6348
-1177
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+6348
-1177
lines changed

buildSrc/src/main/kotlin/IProject.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ object IProject : ProjectDetail() {
1111

1212
// Remember the libs.versions.toml!
1313
val ktVersion = "2.1.0"
14-
val pluginVersion = "0.10.2"
14+
val pluginVersion = "0.11.0"
1515

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

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

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import kotlinx.serialization.Serializable
55
@Serializable
66
data class FunctionInfo(
77
var packageName: String,
8-
var className: String?,
8+
@Deprecated("Top-Level function supported only")
9+
var className: String? = null,
910
var functionName: String,
1011
)
1112

@@ -162,8 +163,11 @@ open class SuspendTransformConfiguration {
162163
/**
163164
* 在 K2 中,用于使 IR 的合成函数可以定位到 FIR 中原始函数的辅助注解。
164165
*
166+
* 昙花一现,在 `*-0.11.0` 之后不再需要此类过渡用注解。
167+
*
165168
* @since *-0.10.0
166169
*/
170+
@Deprecated("Unused after *-0.11.0")
167171
open var targetMarker: ClassInfo? = targetMarkerClassInfo
168172

169173
open fun clear() {

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

Lines changed: 587 additions & 718 deletions
Large diffs are not rendered by default.

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ data class SuspendTransformPluginKey(val data: SuspendTransformUserDataFir) :
1515

1616
data class SuspendTransformBridgeFunctionKey(val data: SuspendTransformBridgeFunDataFir) :
1717
SuspendTransformGeneratedDeclarationKey()
18+
19+
/**
20+
* The v3 logic for generating suspend bridge functions: generate body in FIR stage.
21+
*/
22+
object SuspendTransformK2V3Key : SuspendTransformGeneratedDeclarationKey()

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

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package love.forte.plugin.suspendtrans.ir
33
import love.forte.plugin.suspendtrans.*
44
import love.forte.plugin.suspendtrans.fir.SuspendTransformBridgeFunctionKey
55
import love.forte.plugin.suspendtrans.fir.SuspendTransformGeneratedDeclarationKey
6+
import love.forte.plugin.suspendtrans.fir.SuspendTransformK2V3Key
67
import love.forte.plugin.suspendtrans.fir.SuspendTransformPluginKey
78
import love.forte.plugin.suspendtrans.utils.*
89
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
@@ -81,9 +82,15 @@ class SuspendTransformTransformer(
8182
val userData = descriptor.getUserData(SuspendTransformUserDataKey)
8283

8384
val generatedOriginFunction: IrFunction? = when {
84-
pluginKey != null -> {
85+
// K2 v3, 如果已经有body了,则不再需要生成,直接跳过。
86+
declaration.body != null -> return null
8587

88+
pluginKey != null -> {
8689
when (pluginKey) {
90+
// K2 v3, 通常是已经完成body生成的,跳过(应该到不了这一步,因为 body != null 已经在上面被检测过了
91+
is SuspendTransformK2V3Key -> null
92+
93+
// K2 v2
8794
is SuspendTransformBridgeFunctionKey -> {
8895
val callableFunction =
8996
pluginContext.referenceFunctions(pluginKey.data.transformer.transformFunctionInfo.toCallableId())
@@ -321,13 +328,15 @@ class SuspendTransformTransformer(
321328
function: IrFunction,
322329
transformTargetFunctionCall: IrSimpleFunctionSymbol,
323330
) {
324-
// body: return $transform(block, scope?)
325-
function.body = generateTransformBodyForFunctionLambda(
326-
pluginContext,
327-
function,
328-
null,
329-
transformTargetFunctionCall
330-
)
331+
if (function.body == null) {
332+
// body: return $transform(block, scope?)
333+
function.body = generateTransformBodyForFunctionLambda(
334+
pluginContext,
335+
function,
336+
null,
337+
transformTargetFunctionCall
338+
)
339+
}
331340
}
332341
}
333342

Lines changed: 3 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,8 @@
11
package love.forte.plugin.suspendtrans.utils
22

3-
import org.jetbrains.kotlin.fir.FirSession
43
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
5-
import org.jetbrains.kotlin.fir.expressions.FirEmptyArgumentList
6-
import org.jetbrains.kotlin.fir.expressions.builder.buildAnnotationCall
7-
import org.jetbrains.kotlin.fir.moduleData
8-
import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference
9-
import org.jetbrains.kotlin.fir.resolve.defaultType
10-
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
11-
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
12-
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
13-
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
14-
import org.jetbrains.kotlin.name.ClassId
15-
import org.jetbrains.kotlin.platform.isJs
16-
import org.jetbrains.kotlin.platform.jvm.isJvm
17-
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
4+
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
185

19-
private val jsExportIgnore = ClassId.fromString("kotlin/js/JsExport.Ignore")
20-
private val jvmSynthetic = ClassId.fromString("kotlin/jvm/JvmSynthetic")
21-
22-
fun FirDeclaration.excludeFromJsExport(session: FirSession) {
23-
if (!session.moduleData.platform.isJs()) {
24-
return
25-
}
26-
val jsExportIgnore = session.symbolProvider.getClassLikeSymbolByClassId(jsExportIgnore)
27-
val jsExportIgnoreAnnotation = jsExportIgnore as? FirRegularClassSymbol ?: return
28-
val jsExportIgnoreConstructor =
29-
jsExportIgnoreAnnotation.declarationSymbols.firstIsInstanceOrNull<FirConstructorSymbol>() ?: return
30-
31-
val jsExportIgnoreAnnotationCall = buildAnnotationCall {
32-
argumentList = FirEmptyArgumentList
33-
annotationTypeRef = buildResolvedTypeRef {
34-
coneType = jsExportIgnoreAnnotation.defaultType()
35-
}
36-
calleeReference = buildResolvedNamedReference {
37-
name = jsExportIgnoreAnnotation.name
38-
resolvedSymbol = jsExportIgnoreConstructor
39-
}
40-
41-
containingDeclarationSymbol = this@excludeFromJsExport.symbol
42-
}
43-
44-
replaceAnnotations(annotations + jsExportIgnoreAnnotationCall)
45-
}
46-
47-
fun FirDeclaration.jvmSynthetic(session: FirSession) {
48-
if (!session.moduleData.platform.isJvm()) {
49-
return
50-
}
51-
52-
val jvmSynthetic = session.symbolProvider.getClassLikeSymbolByClassId(jvmSynthetic)
53-
val jvmExportIgnoreAnnotation = jvmSynthetic as? FirRegularClassSymbol ?: return
54-
val jvmExportIgnoreConstructor =
55-
jvmExportIgnoreAnnotation.declarationSymbols.firstIsInstanceOrNull<FirConstructorSymbol>() ?: return
56-
57-
val jvmSyntheticAnnotationCall = buildAnnotationCall {
58-
argumentList = FirEmptyArgumentList
59-
annotationTypeRef = buildResolvedTypeRef {
60-
coneType = jvmExportIgnoreAnnotation.defaultType()
61-
}
62-
calleeReference = buildResolvedNamedReference {
63-
name = jvmExportIgnoreAnnotation.name
64-
resolvedSymbol = jvmExportIgnoreConstructor
65-
}
66-
67-
containingDeclarationSymbol = this@jvmSynthetic.symbol
68-
}
69-
70-
replaceAnnotations(annotations + jvmSyntheticAnnotationCall)
6+
fun FirDeclaration.includeAnnotations(includes: List<FirAnnotation>) {
7+
replaceAnnotations(annotations + includes)
718
}

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
@@ -44,6 +44,12 @@ public void testTypeAttr() {
4444
runTest("src/testData/codegen/typeAttr.kt");
4545
}
4646

47+
@Test
48+
@TestMetadata("typeAttrNested.kt")
49+
public void testTypeAttrNested() {
50+
runTest("src/testData/codegen/typeAttrNested.kt");
51+
}
52+
4753
@Test
4854
@TestMetadata("opt.kt")
4955
public void testOpt() {

compiler/suspend-transform-plugin/src/test/love/forte/plugin/suspendtrans/services/SuspendTransformerEnvironmentConfigurator.kt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,17 +50,33 @@ class SuspendTransformerEnvironmentConfigurator(testServices: TestServices) : En
5050
it
5151
)
5252
}
53+
54+
// register coroutines
55+
getRuntimeJarFile("kotlinx.coroutines.CoroutineScope")?.let {
56+
configuration.addJvmClasspathRoot(
57+
it
58+
)
59+
}
5360
}
5461

5562
private fun getRuntimeJarFile(className: String): File? {
5663
try {
57-
val clazz = Class.forName(className)
58-
return PathUtil.getResourcePathForClass(clazz)
59-
} catch (e: ClassNotFoundException) {
64+
return getRuntimeJarFile(Class.forName(className))
65+
} catch (_: ClassNotFoundException) {
6066
System.err.println("Runtime jar '$className' not found!")
6167
// assert(false) { "Runtime jar '$className' not found!" }
6268
}
6369
return null
6470
}
6571

72+
private fun getRuntimeJarFile(clazz: Class<*>): File {
73+
// try {
74+
return PathUtil.getResourcePathForClass(clazz)
75+
// } catch (e: ClassNotFoundException) {
76+
// System.err.println("Runtime jar '$clazz' not found!")
77+
//// assert(false) { "Runtime jar '$className' not found!" }
78+
// }
79+
// return null
80+
}
81+
6682
}

compiler/suspend-transform-plugin/src/testData/codegen/alias.fir.ir.txt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ FILE fqName:<root> fileName:/Main.kt
1818
overridden:
1919
public open fun toString (): kotlin.String declared in kotlin.Any
2020
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
21-
FUN GENERATED[love.forte.plugin.suspendtrans.fir.SuspendTransformPluginKey] name:errorReproductionAsync visibility:public modality:FINAL <> ($this:<root>.MyClass, amount:kotlin.Long) returnType:java.util.concurrent.CompletableFuture
21+
FUN GENERATED[love.forte.plugin.suspendtrans.fir.SuspendTransformK2V3Key] name:errorReproductionAsync visibility:public modality:FINAL <> ($this:<root>.MyClass, amount:kotlin.Long) returnType:java.util.concurrent.CompletableFuture
2222
annotations:
2323
Api4J
2424
$this: VALUE_PARAMETER name:<this> type:<root>.MyClass
@@ -27,34 +27,35 @@ FILE fqName:<root> fileName:/Main.kt
2727
RETURN type=kotlin.Nothing from='public final fun errorReproductionAsync (amount: kotlin.Long): java.util.concurrent.CompletableFuture declared in <root>.MyClass'
2828
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
2929
<T>: <none>
30-
block: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<java.util.concurrent.CompletableFuture> origin=LAMBDA
31-
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<no name provided> visibility:local modality:FINAL <> () returnType:java.util.concurrent.CompletableFuture [suspend]
30+
block: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=LAMBDA
31+
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend]
3232
BLOCK_BODY
33-
RETURN type=kotlin.Nothing from='local final fun <no name provided> (): java.util.concurrent.CompletableFuture declared in <root>.MyClass.errorReproductionAsync'
33+
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.MyClass.errorReproductionAsync'
3434
CALL 'public final fun errorReproduction (amount: kotlin.Long): kotlin.Unit declared in <root>.MyClass' type=kotlin.Unit origin=null
3535
$this: GET_VAR '<this>: <root>.MyClass declared in <root>.MyClass.errorReproductionAsync' type=<root>.MyClass origin=null
3636
amount: GET_VAR 'amount: kotlin.Long declared in <root>.MyClass.errorReproductionAsync' type=kotlin.Long origin=null
37-
FUN GENERATED[love.forte.plugin.suspendtrans.fir.SuspendTransformPluginKey] name:errorReproductionBlocking visibility:public modality:FINAL <> ($this:<root>.MyClass, amount:kotlin.Long) returnType:kotlin.Unit
37+
scope: TYPE_OP type=kotlinx.coroutines.CoroutineScope? origin=SAFE_CAST typeOperand=kotlinx.coroutines.CoroutineScope
38+
GET_VAR '<this>: <root>.MyClass declared in <root>.MyClass.errorReproductionAsync' type=<root>.MyClass origin=null
39+
FUN GENERATED[love.forte.plugin.suspendtrans.fir.SuspendTransformK2V3Key] name:errorReproductionBlocking visibility:public modality:FINAL <> ($this:<root>.MyClass, amount:kotlin.Long) returnType:kotlin.Unit
3840
annotations:
3941
Api4J
4042
$this: VALUE_PARAMETER name:<this> type:<root>.MyClass
4143
VALUE_PARAMETER name:amount index:0 type:kotlin.Long
4244
BLOCK_BODY
4345
RETURN type=kotlin.Nothing from='public final fun errorReproductionBlocking (amount: kotlin.Long): kotlin.Unit declared in <root>.MyClass'
44-
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
46+
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=kotlin.Unit origin=null
4547
<T>: <none>
4648
block: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=LAMBDA
47-
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<no name provided> visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend]
49+
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit [suspend]
4850
BLOCK_BODY
49-
RETURN type=kotlin.Nothing from='local final fun <no name provided> (): kotlin.Unit declared in <root>.MyClass.errorReproductionBlocking'
51+
RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.Unit declared in <root>.MyClass.errorReproductionBlocking'
5052
CALL 'public final fun errorReproduction (amount: kotlin.Long): kotlin.Unit declared in <root>.MyClass' type=kotlin.Unit origin=null
5153
$this: GET_VAR '<this>: <root>.MyClass declared in <root>.MyClass.errorReproductionBlocking' type=<root>.MyClass origin=null
5254
amount: GET_VAR 'amount: kotlin.Long declared in <root>.MyClass.errorReproductionBlocking' type=kotlin.Long origin=null
5355
FUN name:errorReproduction visibility:public modality:FINAL <> ($this:<root>.MyClass, amount:kotlin.Long) returnType:kotlin.Unit [suspend]
5456
annotations:
5557
JvmBlocking(baseName = <null>, suffix = <null>, asProperty = <null>)
5658
JvmAsync(baseName = <null>, suffix = <null>, asProperty = <null>)
57-
TargetMarker(value = "ZXJyb3JSZXByb2R1Y3Rpb25NeUNsYXNzbnVsbHtNb25leVZhbHVlPX0ga290bGluL0xvbmc=")
5859
JvmSynthetic
5960
$this: VALUE_PARAMETER name:<this> type:<root>.MyClass
6061
VALUE_PARAMETER name:amount index:0 type:kotlin.Long

compiler/suspend-transform-plugin/src/testData/codegen/alias.fir.txt

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,22 @@ FILE: Main.kt
55
super<R|kotlin/Any|>()
66
}
77

8-
@R|love/forte/plugin/suspendtrans/annotation/JvmBlocking|() @R|love/forte/plugin/suspendtrans/annotation/JvmAsync|() @R|love/forte/plugin/suspendtrans/annotation/TargetMarker|(value = String(ZXJyb3JSZXByb2R1Y3Rpb25NeUNsYXNzbnVsbHtNb25leVZhbHVlPX0ga290bGluL0xvbmc=)) public final suspend fun errorReproduction(amount: R|{MoneyValue=} kotlin/Long|): R|kotlin/Unit| {
8+
@R|love/forte/plugin/suspendtrans/annotation/JvmBlocking|() @R|love/forte/plugin/suspendtrans/annotation/JvmAsync|() @R|kotlin/jvm/JvmSynthetic|() public final suspend fun errorReproduction(amount: R|{MoneyValue=} kotlin/Long|): R|kotlin/Unit| {
99
R|kotlin/io/println|(R|<local>/amount|)
1010
}
1111

12-
@R|love/forte/plugin/suspendtrans/annotation/Api4J|() public final fun errorReproductionAsync(amount: R|{MoneyValue=} kotlin/Long|): R|java/util/concurrent/CompletableFuture<out kotlin/Unit>|
12+
@R|love/forte/plugin/suspendtrans/annotation/Api4J|() public final fun errorReproductionAsync(amount: R|{MoneyValue=} kotlin/Long|): R|java/util/concurrent/CompletableFuture<out kotlin/Unit>| {
13+
^errorReproductionAsync R|love/forte/plugin/suspendtrans/runtime/$runInAsync$|(suspend fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
14+
^ this@R|/MyClass|.R|/MyClass.errorReproduction|(R|<local>/amount|)
15+
}
16+
, (this@R|/MyClass| as? R|kotlinx/coroutines/CoroutineScope|))
17+
}
1318

14-
@R|love/forte/plugin/suspendtrans/annotation/Api4J|() public final fun errorReproductionBlocking(amount: R|{MoneyValue=} kotlin/Long|): R|kotlin/Unit|
19+
@R|love/forte/plugin/suspendtrans/annotation/Api4J|() public final fun errorReproductionBlocking(amount: R|{MoneyValue=} kotlin/Long|): R|kotlin/Unit| {
20+
^errorReproductionBlocking R|love/forte/plugin/suspendtrans/runtime/$runInBlocking$|(suspend fun <anonymous>(): R|kotlin/Unit| <inline=Unknown> {
21+
^ this@R|/MyClass|.R|/MyClass.errorReproduction|(R|<local>/amount|)
22+
}
23+
)
24+
}
1525

1626
}

0 commit comments

Comments
 (0)