Skip to content

Commit d886df1

Browse files
authored
Merge pull request #122 from ForteScarlet/improve-structure
Improve and optimize code and structure
2 parents 5098f68 + 3ad8cae commit d886df1

29 files changed

Lines changed: 2847 additions & 1884 deletions

buildSrc/src/main/kotlin/IProject.kt

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

3737
// Remember the libs.versions.toml!
3838
val ktVersion = "2.3.20"
39-
val pluginVersion = "0.13.2"
39+
val pluginVersion = "0.14.0"
4040

4141
override val version: String = "$ktVersion-$pluginVersion"
4242

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,14 @@ import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
3535
import org.jetbrains.kotlin.config.CompilerConfiguration
3636
import org.jetbrains.kotlin.config.CompilerConfigurationKey
3737

38+
/**
39+
* CLI entry point that decodes serialized suspend-transform configuration and
40+
* stores it in the compiler configuration.
41+
*/
3842
@OptIn(ExperimentalCompilerApi::class)
3943
class SuspendTransformCommandLineProcessor : CommandLineProcessor {
4044
companion object {
45+
/** Compiler configuration key used to carry merged plugin configuration. */
4146
val CONFIGURATION_KEY: CompilerConfigurationKey<SuspendTransformConfiguration> =
4247
CompilerConfigurationKey.create(SuspendTransformCliOptions.CONFIGURATION)
4348
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
3535
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter
3636
import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension
3737

38+
/**
39+
* Registers every compiler extension entry point used by the suspend-transform plugin.
40+
*/
3841
@OptIn(ExperimentalCompilerApi::class)
3942
class SuspendTransformComponentRegistrar : CompilerPluginRegistrar() {
4043

@@ -51,13 +54,19 @@ class SuspendTransformComponentRegistrar : CompilerPluginRegistrar() {
5154

5255

5356
companion object {
57+
/**
58+
* Resolves plugin configuration from compiler arguments and registers all extensions.
59+
*/
5460
fun register(storage: ExtensionStorage, configuration: CompilerConfiguration) {
5561
val suspendTransformConfiguration =/* defaultConfiguration ?: */
5662
configuration.resolveToSuspendTransformConfiguration()
5763

5864
register(storage, suspendTransformConfiguration)
5965
}
6066

67+
/**
68+
* Registers FIR, IR, and legacy synthetic resolve extensions for the given configuration.
69+
*/
6170
fun register(storage: ExtensionStorage, configuration: SuspendTransformConfiguration) {
6271
val suspendTransformSyntheticResolveExtension =
6372
SuspendTransformSyntheticResolveExtension(configuration)
@@ -85,6 +94,9 @@ class SuspendTransformComponentRegistrar : CompilerPluginRegistrar() {
8594
// // }
8695
// }
8796

97+
/**
98+
* Reads the merged suspend-transform configuration from compiler configuration storage.
99+
*/
88100
@OptIn(InternalSuspendTransformConfigurationApi::class)
89101
private fun CompilerConfiguration.resolveToSuspendTransformConfiguration(): SuspendTransformConfiguration {
90102
return get(
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
/*
2+
* Copyright (c) 2022-2025 Forte Scarlet
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in all
12+
* copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
package love.forte.plugin.suspendtrans.fir
24+
25+
import org.jetbrains.kotlin.fir.FirSession
26+
import org.jetbrains.kotlin.fir.plugin.createConeType
27+
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
28+
import org.jetbrains.kotlin.fir.types.*
29+
30+
/**
31+
* Attempts to copy a FIR type while remapping any function-scoped type parameters.
32+
*/
33+
internal fun ConeKotlinType.copyConeType(
34+
originalTypeParameterCache: MutableList<CopiedTypeParameterPair>,
35+
session: FirSession
36+
): ConeKotlinType? {
37+
return copyWithTypeParameters(originalTypeParameterCache, session)
38+
}
39+
40+
/**
41+
* Copies a FIR type while preserving the original value when no remapping is needed.
42+
*/
43+
internal fun ConeKotlinType.copyConeTypeOrSelf(
44+
originalTypeParameterCache: MutableList<CopiedTypeParameterPair>,
45+
session: FirSession
46+
): ConeKotlinType {
47+
return copyConeType(originalTypeParameterCache, session) ?: this
48+
}
49+
50+
/**
51+
* Copies a FIR type while remapping any references to copied function-scoped type
52+
* parameters. The implementation intentionally preserves the original unsupported
53+
* branches and comments because it mirrors the existing behavior.
54+
*/
55+
internal fun ConeKotlinType.copyWithTypeParameters(
56+
parameters: List<CopiedTypeParameterPair>,
57+
session: FirSession,
58+
): ConeKotlinType? {
59+
fun findCopied(target: ConeKotlinType) = parameters.find { (original, _) ->
60+
original.symbol.toConeType() == target
61+
}?.copied
62+
63+
val copiedThis = findCopied(this)
64+
if (copiedThis != null) {
65+
return copiedThis.symbol.toConeType()
66+
}
67+
68+
when (this) {
69+
is ConeDynamicType -> {
70+
}
71+
72+
is ConeFlexibleType -> {
73+
}
74+
75+
is ConeClassLikeType -> {
76+
if (typeArguments.isNotEmpty()) {
77+
fun mapProjection(projection: ConeTypeProjection): ConeTypeProjection? {
78+
val findCopiedDirectly = projection.type?.let { type -> findCopied(type) }
79+
if (findCopiedDirectly != null) {
80+
return findCopiedDirectly.symbol.toConeType()
81+
}
82+
83+
return when (projection) {
84+
// is ConeFlexibleType -> { }
85+
86+
is ConeClassLikeType -> {
87+
projection.copyWithTypeParameters(parameters, session)
88+
}
89+
90+
is ConeCapturedType -> {
91+
val constructorLowerType = projection.constructor.lowerType?.copyWithTypeParameters(parameters, session)
92+
93+
if (constructorLowerType == null) {
94+
null
95+
} else {
96+
projection.copy(
97+
constructor = ConeCapturedTypeConstructor(
98+
projection = projection.constructor.projection,
99+
lowerType = constructorLowerType,
100+
captureStatus = projection.constructor.captureStatus,
101+
supertypes = projection.constructor.supertypes,
102+
typeParameterMarker = projection.constructor.typeParameterMarker,
103+
)
104+
)
105+
}
106+
}
107+
108+
is ConeDefinitelyNotNullType -> {
109+
findCopied(projection.original)
110+
?.symbol?.toConeType()
111+
?.let { projection.copy(it) }
112+
}
113+
// is ConeIntegerConstantOperatorType -> TODO()
114+
// is ConeIntegerLiteralConstantType -> TODO()
115+
is ConeIntersectionType -> {
116+
val upperBoundForApproximation = projection.upperBoundForApproximation
117+
?.copyWithTypeParameters(parameters, session)
118+
// val upperBoundForApproximation =
119+
// projection.upperBoundForApproximation
120+
// ?.let { findCopied(it) }
121+
// ?.toConeType()
122+
123+
var anyIntersectedTypes = false
124+
125+
val intersectedTypes = projection.intersectedTypes.map { ktype ->
126+
findCopied(ktype)?.symbol?.toConeType()
127+
// ktype.copyWithTypeParameters(parameters, session)
128+
?.also { anyIntersectedTypes = true }
129+
?: ktype
130+
}
131+
132+
if (upperBoundForApproximation != null || anyIntersectedTypes) {
133+
ConeIntersectionType(
134+
intersectedTypes,
135+
upperBoundForApproximation
136+
)
137+
} else {
138+
null
139+
}
140+
}
141+
// is ConeLookupTagBasedType -> TODO()
142+
// is ConeStubTypeForTypeVariableInSubtyping -> TODO()
143+
// is ConeTypeVariableType -> TODO()
144+
is ConeKotlinTypeConflictingProjection -> {
145+
// findCopied(projection.type)
146+
// ?.toConeType()
147+
// ?.let { projection.copy(it) }
148+
149+
projection.type.copyWithTypeParameters(parameters, session)
150+
?.let { projection.copy(it) }
151+
}
152+
153+
is ConeKotlinTypeProjectionIn -> {
154+
// findCopied(projection.type)
155+
// ?.toConeType()
156+
// ?.let { projection.copy(it) }
157+
158+
projection.type.copyWithTypeParameters(parameters, session)
159+
?.let { projection.copy(it) }
160+
}
161+
162+
is ConeKotlinTypeProjectionOut -> {
163+
// findCopied(projection.type)
164+
// ?.toConeType()
165+
// ?.let { projection.copy(it) }
166+
167+
projection.type.copyWithTypeParameters(parameters, session)
168+
?.let { projection.copy(it) }
169+
}
170+
171+
is ConeTypeParameterType -> {
172+
// findCopied(projection)?.toConeType()
173+
projection.copyWithTypeParameters(parameters, session)
174+
}
175+
176+
ConeStarProjection -> ConeStarProjection
177+
178+
// Other unknowns, e.g., ClassLike
179+
else -> null
180+
}
181+
}
182+
183+
val typeArguments: Array<ConeTypeProjection> = typeArguments.map { projection ->
184+
mapProjection(projection) ?: projection
185+
}.toTypedArray()
186+
187+
return classId.createConeType(
188+
session = session,
189+
typeArguments = typeArguments,
190+
nullable = isMarkedNullable
191+
)
192+
}
193+
194+
return classId.createConeType(session = session, nullable = isMarkedNullable)
195+
}
196+
197+
is ConeTypeParameterType -> {
198+
return findCopied(this)?.symbol?.toConeType() ?: this
199+
// return parameters.find { (original, _) ->
200+
// original.symbol.toConeType() == this
201+
// }?.copied?.symbol?.toConeType() ?: this
202+
}
203+
204+
else -> {
205+
// ?
206+
}
207+
}
208+
209+
return null
210+
}

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension
2727
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
2828

2929
/**
30+
* Registers FIR declaration generation for suspend-transform synthetic members.
3031
*
3132
* @author ForteScarlet
3233
*/

0 commit comments

Comments
 (0)