Skip to content

Commit 8960a13

Browse files
committed
基本成功
1 parent 61c031c commit 8960a13

File tree

9 files changed

+688
-338
lines changed

9 files changed

+688
-338
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,11 @@ data class SuspendTransformUserDataFir(
147147
val transformer: Transformer
148148
)
149149

150+
data class SuspendTransformBridgeFunDataFir(
151+
val asProperty: Boolean,
152+
val transformer: Transformer
153+
)
154+
150155
fun FirNamedFunctionSymbol.asOriginSymbol(
151156
targetMarker: ClassId?,
152157
typeParameters: List<FirTypeParameter>,

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

Lines changed: 459 additions & 281 deletions
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,17 @@
11
package love.forte.plugin.suspendtrans.fir
22

3+
import love.forte.plugin.suspendtrans.SuspendTransformBridgeFunDataFir
34
import love.forte.plugin.suspendtrans.SuspendTransformUserDataFir
45
import org.jetbrains.kotlin.GeneratedDeclarationKey
56

6-
data class SuspendTransformPluginKey(val data: SuspendTransformUserDataFir) : GeneratedDeclarationKey() {
7+
sealed class SuspendTransformGeneratedDeclarationKey() : GeneratedDeclarationKey()
8+
9+
data class SuspendTransformPluginKey(val data: SuspendTransformUserDataFir) :
10+
SuspendTransformGeneratedDeclarationKey() {
711
override fun toString(): String {
812
return "SuspendTransformPlugin(data=$data)"
913
}
1014
}
15+
16+
data class SuspendTransformBridgeFunctionKey(val data: SuspendTransformBridgeFunDataFir) :
17+
SuspendTransformGeneratedDeclarationKey()

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

Lines changed: 113 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package love.forte.plugin.suspendtrans.ir
22

33
import love.forte.plugin.suspendtrans.*
4+
import love.forte.plugin.suspendtrans.fir.SuspendTransformBridgeFunctionKey
5+
import love.forte.plugin.suspendtrans.fir.SuspendTransformGeneratedDeclarationKey
46
import love.forte.plugin.suspendtrans.fir.SuspendTransformPluginKey
57
import love.forte.plugin.suspendtrans.utils.*
68
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
@@ -15,10 +17,7 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
1517
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
1618
import org.jetbrains.kotlin.ir.builders.*
1719
import org.jetbrains.kotlin.ir.declarations.*
18-
import org.jetbrains.kotlin.ir.expressions.IrBody
19-
import org.jetbrains.kotlin.ir.expressions.IrCall
20-
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
21-
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
20+
import org.jetbrains.kotlin.ir.expressions.*
2221
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl
2322
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
2423
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
@@ -72,43 +71,77 @@ class SuspendTransformTransformer(
7271
val pluginKey = if (property != null) {
7372
// from property
7473
(property.origin as? IrDeclarationOrigin.GeneratedByPlugin)
75-
?.pluginKey as? SuspendTransformPluginKey
74+
?.pluginKey as? SuspendTransformGeneratedDeclarationKey
7675
} else {
7776
(declaration.origin as? IrDeclarationOrigin.GeneratedByPlugin)
78-
?.pluginKey as? SuspendTransformPluginKey
77+
?.pluginKey as? SuspendTransformGeneratedDeclarationKey
7978
}
8079

8180
// K1 ?
8281
val userData = descriptor.getUserData(SuspendTransformUserDataKey)
8382

8483
val generatedOriginFunction: IrFunction? = when {
8584
pluginKey != null -> {
86-
val callableFunction =
87-
pluginContext.referenceFunctions(pluginKey.data.transformer.transformFunctionInfo.toCallableId())
88-
.firstOrNull()
89-
?: throw IllegalStateException("Transform function ${pluginKey.data.transformer.transformFunctionInfo} not found")
9085

91-
resolveFunctionBody(
92-
pluginKey,
93-
declaration,
94-
{ f ->
95-
pluginKey.data.originSymbol.checkSame(pluginKey.data.markerId, f)
96-
},
97-
callableFunction
98-
).also { generatedOriginFunction ->
99-
if (property != null) {
100-
// NO! BACKING! FIELD!
101-
property.backingField = null
102-
}
103-
104-
if (generatedOriginFunction != null) {
105-
postProcessGenerateOriginFunction(
106-
generatedOriginFunction,
107-
pluginKey.data.transformer.originFunctionIncludeAnnotations
86+
when (pluginKey) {
87+
is SuspendTransformBridgeFunctionKey -> {
88+
val callableFunction =
89+
pluginContext.referenceFunctions(pluginKey.data.transformer.transformFunctionInfo.toCallableId())
90+
.firstOrNull()
91+
?: throw IllegalStateException("Transform function ${pluginKey.data.transformer.transformFunctionInfo} not found")
92+
93+
resolveBridgeFunctionBody(
94+
pluginKey,
95+
declaration,
96+
callableFunction
10897
)
98+
99+
null
100+
// .also { generatedOriginFunction ->
101+
// if (property != null) {
102+
// // NO! BACKING! FIELD!
103+
// property.backingField = null
104+
// }
105+
//
106+
// if (generatedOriginFunction != null) {
107+
// postProcessGenerateOriginFunction(
108+
// generatedOriginFunction,
109+
// pluginKey.data.transformer.originFunctionIncludeAnnotations
110+
// )
111+
// }
112+
// }
109113
}
110114

115+
is SuspendTransformPluginKey -> {
116+
val callableFunction =
117+
pluginContext.referenceFunctions(pluginKey.data.transformer.transformFunctionInfo.toCallableId())
118+
.firstOrNull()
119+
?: throw IllegalStateException("Transform function ${pluginKey.data.transformer.transformFunctionInfo} not found")
120+
121+
resolveFunctionBody(
122+
pluginKey,
123+
declaration,
124+
{ f ->
125+
pluginKey.data.originSymbol.checkSame(pluginKey.data.markerId, f)
126+
},
127+
callableFunction
128+
).also { generatedOriginFunction ->
129+
if (property != null) {
130+
// NO! BACKING! FIELD!
131+
property.backingField = null
132+
}
133+
134+
if (generatedOriginFunction != null) {
135+
postProcessGenerateOriginFunction(
136+
generatedOriginFunction,
137+
pluginKey.data.transformer.originFunctionIncludeAnnotations
138+
)
139+
}
140+
}
141+
}
111142
}
143+
144+
112145
}
113146

114147
userData != null -> {
@@ -159,6 +192,9 @@ class SuspendTransformTransformer(
159192
}
160193
}
161194

195+
/**
196+
* @return origin function
197+
*/
162198
@OptIn(ObsoleteDescriptorBasedAPI::class)
163199
private inline fun resolveFunctionBody(
164200
sourceKey: Any?,
@@ -274,10 +310,25 @@ class SuspendTransformTransformer(
274310
return originFunction
275311
}
276312

277-
278-
279313
return null
280314
}
315+
316+
/**
317+
* 直接为bridge fun生成body
318+
*/
319+
private fun resolveBridgeFunctionBody(
320+
sourceKey: Any?,
321+
function: IrFunction,
322+
transformTargetFunctionCall: IrSimpleFunctionSymbol,
323+
) {
324+
// body: return $transform(block, scope?)
325+
function.body = generateTransformBodyForFunctionLambda(
326+
pluginContext,
327+
function,
328+
null,
329+
transformTargetFunctionCall
330+
)
331+
}
281332
}
282333

283334
private fun IrFunction.reportLocation(): CompilerMessageSourceLocation? {
@@ -353,45 +404,54 @@ private fun generateTransformBodyForFunction(
353404
private fun generateTransformBodyForFunctionLambda(
354405
context: IrPluginContext,
355406
function: IrFunction,
356-
originFunction: IrFunction,
407+
originFunction: IrFunction?,
357408
transformTargetFunctionCall: IrSimpleFunctionSymbol,
358409
): IrBody {
359-
val originValueParameters = originFunction.valueParameters
360-
function.valueParameters.forEachIndexed { index, parameter ->
361-
val originFunctionValueParameter = originValueParameters[index]
362-
parameter.defaultValue = originFunctionValueParameter.defaultValue
410+
// 不为null,说明是直接生成。否则是bridge
411+
originFunction?.valueParameters?.also { originValueParameters ->
412+
function.valueParameters.forEachIndexed { index, parameter ->
413+
val originFunctionValueParameter = originValueParameters[index]
414+
parameter.defaultValue = originFunctionValueParameter.defaultValue
415+
}
363416
}
364417

365418
return context.createIrBuilder(function.symbol).irBlockBody {
366-
val suspendLambdaFunc = context.createSuspendLambdaFunctionWithCoroutineScope(
367-
originFunction = originFunction,
368-
function = function
369-
)
370419

371-
val lambdaType = context.symbols.suspendFunctionN(0).typeWith(suspendLambdaFunc.returnType)
420+
val lambdaExpression: IrExpression = if (originFunction != null) {
421+
val suspendLambdaFunc = context.createSuspendLambdaFunctionWithCoroutineScope(
422+
originFunction = originFunction,
423+
function = function
424+
)
372425

373-
+irReturn(irCall(transformTargetFunctionCall).apply {
374-
putValueArgument(
375-
0,
376-
IrFunctionExpressionImpl(
377-
UNDEFINED_OFFSET,
378-
UNDEFINED_OFFSET,
379-
lambdaType,
380-
suspendLambdaFunc,
381-
IrStatementOrigin.LAMBDA
382-
)
426+
val lambdaType = context.symbols.suspendFunctionN(0).typeWith(suspendLambdaFunc.returnType)
427+
428+
IrFunctionExpressionImpl(
429+
UNDEFINED_OFFSET,
430+
UNDEFINED_OFFSET,
431+
lambdaType,
432+
suspendLambdaFunc,
433+
IrStatementOrigin.LAMBDA
383434
)
384-
// argument: 1, if is CoroutineScope, and this is CoroutineScope.
385-
val owner = transformTargetFunctionCall.owner
435+
} else {
436+
// is bridge fun, use the first param `block`
437+
val blockParameter = function.valueParameters.first()
438+
irGet(blockParameter)
439+
}
440+
441+
+irReturn(irCall(transformTargetFunctionCall).apply {
442+
putValueArgument(0, lambdaExpression)
443+
444+
val transformFunctionOwner = transformTargetFunctionCall.owner
386445

387446
// CoroutineScope
388-
val ownerValueParameters = owner.valueParameters
447+
val ownerValueParameters = transformFunctionOwner.valueParameters
389448

449+
// argument: 1, if is CoroutineScope, and this is CoroutineScope.
390450
if (ownerValueParameters.size > 1) {
391451
for (index in 1..ownerValueParameters.lastIndex) {
392452
val valueParameter = ownerValueParameters[index]
393453
val type = valueParameter.type
394-
tryResolveCoroutineScopeValueParameter(type, context, function, owner, this@irBlockBody, index)
454+
tryResolveCoroutineScopeValueParameter(type, context, function, transformFunctionOwner, this@irBlockBody, index)
395455
}
396456
}
397457

compiler/suspend-transform-plugin/src/test/love/forte/plugin/suspendtrans/runners/AbstractCodeGenTestRunner.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ abstract class AbstractCodeGenTestRunner : AbstractTestRunner() {
2626
}
2727

2828
configureJvmArtifactsHandlersStep {
29-
useHandlers(::BytecodeListingHandler,::AsmLikeInstructionListingHandler, )
29+
useHandlers(::BytecodeListingHandler, ::AsmLikeInstructionListingHandler)
3030
}
3131

3232
defaultDirectives {

compiler/suspend-transform-plugin/src/testData/codegen/varargParam.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import kotlinx.coroutines.runBlocking
77
import love.forte.plugin.suspendtrans.annotation.JvmAsync
88
import love.forte.plugin.suspendtrans.annotation.JvmBlocking
99

10-
public interface DeleteOption
1110

1211
abstract class MyClass {
1312
@JvmBlocking
1413
@JvmAsync
15-
suspend open fun deleteAll(vararg options: DeleteOption): Int {
14+
suspend open fun deleteAll(option: Int): Int {
1615
return 1
1716
}
17+
1818
}
19+

local-helper/build.gradle.kts

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2+
3+
plugins {
4+
`java-library`
5+
kotlin("multiplatform")
6+
// id("love.forte.plugin.suspend-transform")
7+
// id("suspend-transform.jvm-maven-publish")
8+
// id(project(":suspend-transform-plugin-gradle"))
9+
}
10+
11+
repositories {
12+
mavenCentral()
13+
}
14+
15+
kotlin {
16+
jvmToolchain(8)
17+
18+
jvm {
19+
compilerOptions {
20+
freeCompilerArgs.add("-Xjvm-default=all")
21+
jvmTarget = JvmTarget.JVM_1_8
22+
}
23+
24+
testRuns["test"].executionTask.configure {
25+
useJUnitPlatform()
26+
}
27+
}
28+
29+
js {
30+
nodejs()
31+
compilerOptions {
32+
useEsModules()
33+
// https://kotlinlang.org/docs/js-ir-compiler.html#output-mode
34+
freeCompilerArgs.add("-Xir-per-file")
35+
}
36+
generateTypeScriptDefinitions()
37+
binaries.library()
38+
}
39+
40+
macosX64()
41+
linuxX64()
42+
mingwX64()
43+
44+
sourceSets {
45+
commonMain {
46+
dependencies {
47+
// api(kotlin("reflect"))
48+
api(libs.kotlinx.coroutines.core)
49+
}
50+
}
51+
52+
jvmTest {
53+
dependencies {
54+
api(kotlin("test-junit5"))
55+
}
56+
}
57+
}
58+
}
59+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import kotlinx.coroutines.CoroutineScope
2+
import kotlin.js.ExperimentalJsExport
3+
import kotlin.js.JsExport
4+
5+
/**
6+
*
7+
* @author ForteScarlet
8+
*/
9+
@JsExport
10+
interface MyInterface {
11+
12+
@JsExport.Ignore
13+
suspend fun run(times: Int): Int
14+
15+
@Suppress("NOTHING_TO_INLINE")
16+
private inline fun __suspendTransform__run_0_runBlocking(noinline block: suspend () -> Int): Int {
17+
return runBlocking(block, this as? CoroutineScope)
18+
}
19+
20+
fun runBlocking(times: Int): Int = __suspendTransform__run_0_runBlocking({ run(times) })
21+
}
22+
23+
@JsExport
24+
@OptIn(ExperimentalJsExport::class)
25+
interface MyInterface2 : MyInterface {
26+
@JsExport.Ignore
27+
suspend fun <T> run2(times: T): T
28+
29+
@Suppress("NOTHING_TO_INLINE")
30+
private inline fun <T> __suspendTransform__run2_0_runBlocking(noinline block: suspend () -> T): T {
31+
return runBlocking(block, this as? CoroutineScope)
32+
}
33+
34+
fun <T> run2Blocking(value: T): T = __suspendTransform__run2_0_runBlocking({ run2(value) })
35+
36+
}
37+
38+
fun <T> runBlocking(block: suspend () -> T, scope: CoroutineScope?): T = TODO()

0 commit comments

Comments
 (0)