Skip to content

File tree

8 files changed

+211
-61
lines changed

8 files changed

+211
-61
lines changed

buildSrc/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ dependencies {
2424
api("gradle.plugin.com.bnorm.power:kotlin-power-assert-gradle:0.12.0")
2525
api("io.github.gradle-nexus:publish-plugin:1.1.0")
2626

27-
api("com.github.jengelman.gradle.plugins:shadow:6.1.0")
27+
api("com.github.jengelman.gradle.plugins:shadow:6.1.0")
2828

2929
implementation("love.forte.gradle.common:gradle-common-core:$gradleCommon")
3030
implementation("love.forte.gradle.common:gradle-common-kotlin-multiplatform:$gradleCommon")

buildSrc/src/main/kotlin/IProject.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import love.forte.gradle.common.core.project.ProjectDetail
22
import love.forte.gradle.common.core.project.Version
3+
import love.forte.gradle.common.core.project.minus
34
import love.forte.gradle.common.core.project.version
45

56
object IProject : ProjectDetail() {
@@ -8,7 +9,7 @@ object IProject : ProjectDetail() {
89
const val DESCRIPTION = "Generate platform-compatible functions for Kotlin suspend functions"
910
const val HOMEPAGE = "https://github.com/ForteScarlet/kotlin-suspend-transform-compiler-plugin"
1011

11-
override val version: Version = version(0, 5, 1)
12+
override val version: Version = version(0, 5, 1) - version("local-test-2")
1213

1314
override val homepage: String get() = HOMEPAGE
1415

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import love.forte.plugin.suspendtrans.SuspendTransformUserDataKey
66
import love.forte.plugin.suspendtrans.fqn
77
import love.forte.plugin.suspendtrans.utils.*
88
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
9-
import org.jetbrains.kotlin.backend.common.extensions.FirIncompatiblePluginAPI
109
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
1110
import org.jetbrains.kotlin.descriptors.CallableDescriptor
1211
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
@@ -108,7 +107,6 @@ class SuspendTransformTransformer(
108107
return generatedOriginFunction
109108
}
110109

111-
@OptIn(FirIncompatiblePluginAPI::class)
112110
private fun postProcessGenerateOriginFunction(function: IrFunction, userData: SuspendTransformUserData) {
113111
function.annotations = buildList {
114112
val currentAnnotations = function.annotations
@@ -192,7 +190,7 @@ private fun generateTransformBodyForFunction(
192190

193191
return context.createIrBuilder(function.symbol).irBlockBody {
194192
val suspendLambda = context.createSuspendLambdaWithCoroutineScope(
195-
parent = function,
193+
parent = originFunction.parent,
196194
// suspend () -> ?
197195
lambdaType = context.symbols.suspendFunctionN(0).typeWith(originFunction.returnType),
198196
originFunction = originFunction

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

Lines changed: 130 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ fun IrSimpleFunction.asProperty(): IrProperty {
4040
parent = parentClassOrFile
4141
getter = baseFunction
4242
}
43-
43+
4444
return property
4545
}
4646

@@ -59,17 +59,125 @@ fun IrPluginContext.createSuspendLambdaWithCoroutineScope(
5959
return IrFactoryImpl.buildClass {
6060
name = SpecialNames.NO_NAME_PROVIDED
6161
kind = ClassKind.CLASS
62-
// isInner = true
62+
/*
63+
Those three lines are required, especially `visibility` and `isInner`
64+
All the local classes should have it
65+
66+
see https://youtrack.jetbrains.com/issue/KT-53993/IR-kotlin.NotImplementedError-An-operation-is-not-implemented-IrClassImpl-is-not-supported-yet-here#focus=Comments-27-8622204.0-0
67+
*/
68+
69+
isFun = true
70+
//isInner = true
71+
visibility = DescriptorVisibilities.LOCAL
72+
}.apply clazz@{
73+
this.parent = parent
74+
superTypes = listOf(lambdaType)
75+
76+
val fields = originFunction.paramsAndReceiversAsParamsList().map {
77+
addField(it.name.identifierOrMappedSpecialName.synthesizedName, it.type)
78+
}
79+
80+
createImplicitParameterDeclarationWithWrappedDescriptor()
81+
82+
addConstructor {
83+
isPrimary = true
84+
}.apply constructor@{
85+
val newParams = fields.associateWith { irField ->
86+
this@constructor.addValueParameter {
87+
name = irField.name
88+
type = irField.type
89+
}
90+
}
91+
92+
this@constructor.body = createIrBuilder(symbol).irBlockBody {
93+
+irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single())
94+
95+
for ((irField, irValueParam) in newParams) {
96+
+irSetField(irGet(this@clazz.thisReceiver!!), irField, irGet(irValueParam))
97+
}
98+
99+
100+
}
101+
}
102+
103+
val irClass = this
104+
105+
addFunction("invoke", lambdaType.arguments.last().typeOrNull!!, isSuspend = true).apply functionInvoke@{
106+
this.overriddenSymbols =
107+
// listOf(irClass.superTypes[0].getClass()!!.functionsSequence.single { it.name.identifier == "invoke" && it.isOverridable }.symbol)
108+
listOf(lambdaType.getClass()!!.functionsSequence.single { it.name.identifier == "invoke" && it.isOverridable }.symbol)
109+
110+
// this.createDispatchReceiverParameter()
111+
this.body = createIrBuilder(symbol).run {
112+
// don't use expr body, coroutine codegen can't generate for it.
113+
irBlockBody {
114+
+irCall(originFunction).apply call@{
115+
// set arguments
116+
117+
val arguments = fields.mapTo(LinkedList()) { it } // preserve order
118+
119+
fun IrField.irGetField0(): IrGetFieldImpl {
120+
return irGetField(
121+
receiver = irGet(this@functionInvoke.dispatchReceiverParameter!!),
122+
field = this
123+
)
124+
}
125+
126+
if (originFunction.dispatchReceiverParameter != null) {
127+
this@call.dispatchReceiver = arguments.pop().irGetField0()
128+
}
129+
if (originFunction.extensionReceiverParameter != null) {
130+
this@call.extensionReceiver = arguments.pop().irGetField0()
131+
}
132+
133+
// this@call.putValueArgument(0, irGet(scopeParam))
134+
for ((index, irField) in arguments.withIndex()) {
135+
this@call.putValueArgument(index, irField.irGetField0())
136+
}
137+
}
138+
}
139+
}
140+
}
141+
}
142+
}
143+
144+
/**
145+
* Generates a suspend lambda.
146+
*
147+
* - extends `suspend () -> Unit`.
148+
* - takes dispatch and extension receivers as param, followed by normal value params, to the constructor of this object
149+
*/
150+
fun IrPluginContext.createSuspendLambdaFunctionWithCoroutineScope(
151+
parent: IrDeclarationParent,
152+
lambdaType: IrSimpleType,
153+
originFunction: IrFunction,
154+
): IrClass {
155+
156+
157+
return IrFactoryImpl.buildClass {
158+
name = SpecialNames.NO_NAME_PROVIDED
159+
kind = ClassKind.CLASS
160+
161+
/*
162+
Those three lines are required, especially `visibility` and `isInner`
163+
All the local classes should have it
164+
165+
see https://youtrack.jetbrains.com/issue/KT-53993/IR-kotlin.NotImplementedError-An-operation-is-not-implemented-IrClassImpl-is-not-supported-yet-here#focus=Comments-27-8622204.0-0
166+
*/
167+
168+
isFun = true
169+
//isInner = true
170+
visibility = DescriptorVisibilities.LOCAL
63171
}.apply clazz@{
64172
this.parent = parent
65173
superTypes = listOf(lambdaType)
66-
174+
67175
val fields = originFunction.paramsAndReceiversAsParamsList().map {
68176
addField(it.name.identifierOrMappedSpecialName.synthesizedName, it.type)
69177
}
70-
178+
71179
createImplicitParameterDeclarationWithWrappedDescriptor()
72-
180+
73181
addConstructor {
74182
isPrimary = true
75183
}.apply constructor@{
@@ -79,42 +187,48 @@ fun IrPluginContext.createSuspendLambdaWithCoroutineScope(
79187
type = irField.type
80188
}
81189
}
82-
190+
83191
this@constructor.body = createIrBuilder(symbol).irBlockBody {
84192
+irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single())
85-
193+
86194
for ((irField, irValueParam) in newParams) {
87195
+irSetField(irGet(this@clazz.thisReceiver!!), irField, irGet(irValueParam))
88196
}
197+
198+
89199
}
90200
}
91-
201+
92202
val irClass = this
93-
203+
94204
addFunction("invoke", lambdaType.arguments.last().typeOrNull!!, isSuspend = true).apply functionInvoke@{
95205
this.overriddenSymbols =
96-
listOf(irClass.superTypes[0].getClass()!!.functionsSequence.single { it.name.identifier == "invoke" && it.isOverridable }.symbol)
97-
206+
// listOf(irClass.superTypes[0].getClass()!!.functionsSequence.single { it.name.identifier == "invoke" && it.isOverridable }.symbol)
207+
listOf(lambdaType.getClass()!!.functionsSequence.single { it.name.identifier == "invoke" && it.isOverridable }.symbol)
208+
98209
// this.createDispatchReceiverParameter()
99210
this.body = createIrBuilder(symbol).run {
100211
// don't use expr body, coroutine codegen can't generate for it.
101212
irBlockBody {
102213
+irCall(originFunction).apply call@{
103214
// set arguments
104-
215+
105216
val arguments = fields.mapTo(LinkedList()) { it } // preserve order
106-
217+
107218
fun IrField.irGetField0(): IrGetFieldImpl {
108-
return irGetField(receiver = irGet(this@functionInvoke.dispatchReceiverParameter!!), field = this)
219+
return irGetField(
220+
receiver = irGet(this@functionInvoke.dispatchReceiverParameter!!),
221+
field = this
222+
)
109223
}
110-
224+
111225
if (originFunction.dispatchReceiverParameter != null) {
112226
this@call.dispatchReceiver = arguments.pop().irGetField0()
113227
}
114228
if (originFunction.extensionReceiverParameter != null) {
115229
this@call.extensionReceiver = arguments.pop().irGetField0()
116230
}
117-
231+
118232
// this@call.putValueArgument(0, irGet(scopeParam))
119233
for ((index, irField) in arguments.withIndex()) {
120234
this@call.putValueArgument(index, irField.irGetField0())

runtime/suspend-transform-annotation/build.gradle.kts

Lines changed: 39 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ plugins {
55

66
kotlin {
77
explicitApi()
8+
applyDefaultHierarchyTemplate()
89

910
jvm {
1011
compilations.all {
@@ -20,27 +21,45 @@ kotlin {
2021
js(IR) {
2122
nodejs()
2223
}
23-
val mainPresets = mutableSetOf<org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet>()
24-
val testPresets = mutableSetOf<org.jetbrains.kotlin.gradle.plugin.KotlinSourceSet>()
25-
26-
targets {
27-
presets
28-
.filterIsInstance<org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinNativeTargetPreset<*>>()
29-
.forEach { presets ->
30-
val target = fromPreset(presets, presets.name)
31-
mainPresets.add(target.compilations["main"].kotlinSourceSets.first())
32-
testPresets.add(target.compilations["test"].kotlinSourceSets.first())
33-
}
34-
}
3524

36-
sourceSets {
37-
val commonMain by getting
38-
val commonTest by getting
25+
// tier1
26+
linuxX64()
27+
macosX64()
28+
macosArm64()
29+
iosSimulatorArm64()
30+
iosX64()
3931

40-
val nativeMain by creating { dependsOn(commonMain) }
41-
val nativeTest by creating { dependsOn(commonTest) }
32+
// tier2
33+
linuxArm64()
34+
watchosSimulatorArm64()
35+
watchosX64()
36+
watchosArm32()
37+
watchosArm64()
38+
tvosSimulatorArm64()
39+
tvosX64()
40+
tvosArm64()
41+
iosArm64()
4242

43-
configure(mainPresets) { dependsOn(nativeMain) }
44-
configure(testPresets) { dependsOn(nativeTest) }
45-
}
43+
// tier3
44+
androidNativeArm32()
45+
androidNativeArm64()
46+
androidNativeX86()
47+
androidNativeX64()
48+
mingwX64()
49+
watchosDeviceArm64()
50+
51+
// withKotlinTargets { target ->
52+
// targets.findByName(target.name)?.compilations?.all {
53+
// // 'expect'/'actual' classes (including interfaces, objects, annotations, enums, and 'actual' typealiases) are in Beta. You can use -Xexpect-actual-classes flag to suppress this warning. Also see: https://youtrack.jetbrains.com/issue/KT-61573
54+
// kotlinOptions.freeCompilerArgs += "-Xexpect-actual-classes"
55+
// }
56+
// }
4657
}
58+
59+
60+
//fun Project.withKotlinTargets(fn: (KotlinTarget) -> Unit) {
61+
// extensions.findByType(KotlinTargetsContainer::class.java)?.let { kotlinExtension ->
62+
// // find all compilations given sourceSet belongs to
63+
// kotlinExtension.targets.all { target -> fn(target) }
64+
// }
65+
//}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package love.forte.plugin.suspendtrans.runtime
22

33
import kotlinx.coroutines.CoroutineScope
4-
import kotlinx.coroutines.CoroutineStart
54
import kotlinx.coroutines.promise
65
import kotlin.coroutines.CoroutineContext
76
import kotlin.coroutines.EmptyCoroutineContext
@@ -13,9 +12,13 @@ private val CoroutineScope4Js: CoroutineScope = CoroutineScope(CoroutineContext4
1312

1413

1514
@Suppress("FunctionName")
16-
@Deprecated("Just for generate.", level = DeprecationLevel.HIDDEN)
17-
public fun <T> `$runInAsync$`(
18-
block: suspend () -> T,
15+
//@Deprecated("Just for generate.", level = DeprecationLevel.HIDDEN)
16+
public fun <T, F : suspend () -> T> `$runInAsync$`(
17+
block: F,
18+
scope: CoroutineScope? = null
1919
): Promise<T> {
20-
return CoroutineScope4Js.promise(start = CoroutineStart.UNDISPATCHED) { block() }
20+
println("block: $block")
21+
println("block.asDynamic().invoke: " + block.asDynamic().invoke)
22+
println("block::class: " + block::class)
23+
return (scope ?: CoroutineScope4Js).promise { block.invoke() }
2124
}

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

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,18 @@ import love.forte.plugin.suspendtrans.gradle.SuspendTransformGradleExtension
22

33
plugins {
44
kotlin("js")
5-
// id("love.forte.plugin.suspend-transform")
6-
// id("suspend-transform.jvm-maven-publish")
7-
// id(project(":suspend-transform-plugin-gradle"))
85
}
96

107

11-
buildscript {
12-
this@buildscript.repositories {
13-
mavenLocal()
14-
mavenCentral()
15-
}
16-
dependencies {
17-
//this.implementation()
18-
classpath("love.forte.plugin.suspend-transform:suspend-transform-plugin-gradle:0.5.1")
19-
}
20-
}
8+
buildscript {
9+
this@buildscript.repositories {
10+
mavenLocal()
11+
mavenCentral()
12+
}
13+
dependencies {
14+
classpath("love.forte.plugin.suspend-transform:suspend-transform-plugin-gradle:0.5.1-local-test-2")
15+
}
16+
}
2117

2218

2319
kotlin {
@@ -42,6 +38,5 @@ dependencies {
4238
}
4339

4440
extensions.getByType<SuspendTransformGradleExtension>().apply {
45-
println(this)
4641
useJsDefault()
4742
}

0 commit comments

Comments
 (0)