Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changelog/v2.2.20-0.13.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Kotlin version: `v2.2.20`
1 change: 1 addition & 0 deletions .changelog/v2.2.20-Beta1-0.13.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Kotlin version: `v2.2.20-Beta1`
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/IProject.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ object IProject : ProjectDetail() {
const val HOMEPAGE = "https://github.com/ForteScarlet/kotlin-suspend-transform-compiler-plugin"

// Remember the libs.versions.toml!
val ktVersion = "2.2.10"
val ktVersion = "2.2.20"
val pluginVersion = "0.13.1"

override val version: String = "$ktVersion-$pluginVersion"
Expand Down
3 changes: 1 addition & 2 deletions compiler/suspend-transform-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,7 @@ kotlin {
)
freeCompilerArgs.addAll(
"-Xjvm-default=all",
// "-opt-in=kotlin.RequiresOptIn",
// "-opt-in=org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI",
"-Xcontext-parameters"
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class SuspendTransformFirTransformer(
}

private val cache: FirCache<FirCacheKey, Map<Name, Map<FirNamedFunctionSymbol, SyntheticFunData>>?, Nothing?> =
session.firCachesFactory.createCache { cacheKey, c ->
session.firCachesFactory.createCache { cacheKey, _ ->
val (symbol, scope) = cacheKey
initScopeSymbol()
val transformerFunctionMap = initTransformerFunctionSymbolMap(symbol, scope)
Expand Down Expand Up @@ -212,7 +212,7 @@ class SuspendTransformFirTransformer(
): List<FirValueParameter> {
return map { vp ->
buildValueParameterCopy(vp) {
symbol = FirValueParameterSymbol(vp.symbol.name)
symbol = FirValueParameterSymbol()
Copy link
Preview

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing the name parameter from FirValueParameterSymbol() constructor may cause issues with parameter identification. The original code FirValueParameterSymbol(vp.symbol.name) preserved parameter naming which could be important for debugging and reflection.

Suggested change
symbol = FirValueParameterSymbol()
symbol = FirValueParameterSymbol(vp.symbol.name)

Copilot uses AI. Check for mistakes.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

containingDeclarationSymbol = newContainingDeclarationSymbol

val copiedConeType = vp.returnTypeRef.coneTypeOrNull
Expand Down Expand Up @@ -348,11 +348,11 @@ class SuspendTransformFirTransformer(
newFunTarget: FirFunctionTarget,
transformer: Transformer
): FirBlock = buildBlock {
this.source = originFunc.body?.source

this.source = originFunSymbol.bodySource ?: originFunSymbol.source
// lambda: suspend () -> T
val lambdaTarget = FirFunctionTarget(null, isLambda = true)
val lambda = buildAnonymousFunction {
this.source = originFunSymbol.bodySource ?: originFunSymbol.source
this.resolvePhase = FirResolvePhase.BODY_RESOLVE
// this.resolvePhase = FirResolvePhase.RAW_FIR
this.isLambda = true
Expand Down Expand Up @@ -701,7 +701,7 @@ class SuspendTransformFirTransformer(
val (functionAnnotations, propertyAnnotations, includeToOriginal) =
copyAnnotations(original, funData)

val pSymbol = FirPropertySymbol(callableId)
val pSymbol = FirRegularPropertySymbol(callableId)
Copy link
Preview

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed from FirPropertySymbol to FirRegularPropertySymbol. Ensure this change is compatible with the property generation requirements and doesn't break synthetic property creation.

Suggested change
val pSymbol = FirRegularPropertySymbol(callableId)
// Use FirPropertySymbol to allow for synthetic property creation if needed.
val pSymbol: FirPropertySymbol = FirRegularPropertySymbol(callableId)

Copilot uses AI. Check for mistakes.


// val pKey = SuspendTransformPluginKey(
// data = SuspendTransformUserDataFir(
Expand Down Expand Up @@ -754,7 +754,6 @@ class SuspendTransformFirTransformer(
)

isVar = false
isLocal = false
// Copy return type
returnTypeRef = resolvedReturnType
deprecationsProvider = UnresolvedDeprecationProvider //original.deprecationsProvider
Expand Down Expand Up @@ -837,51 +836,50 @@ class SuspendTransformFirTransformer(
val markAnnotation = syntheticFunData.transformer.markAnnotation

if (func.isOverride && !isOverride) {
// func.processOverriddenFunctionsSafe()
func.processOverriddenFunctionsSafe(
checkContext
) processOverridden@{ overriddenFunction ->
if (!isOverride) {
// check parameters and receivers
val resolvedReceiverTypeRef = overriddenFunction.resolvedReceiverTypeRef
val originReceiverTypeRef = func.resolvedReceiverTypeRef

// origin receiver should be the same as symbol receiver
if (originReceiverTypeRef != resolvedReceiverTypeRef) {
return@processOverridden
}

// all value parameters should be a subtype of symbol's value parameters
val symbolParameterSymbols = overriddenFunction.valueParameterSymbols
val originParameterSymbols = func.valueParameterSymbols
with(checkContext) {
func.processOverriddenFunctionsSafe processOverridden@{ overriddenFunction ->
Comment on lines +839 to +840
Copy link
Preview

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The massive simplification of the override checking logic removes important validation steps. The original code verified receiver types, parameter counts, and parameter types before determining override status. This simplified version may incorrectly mark functions as overrides.

Copilot uses AI. Check for mistakes.

if (!isOverride) {
// check parameters and receivers
val resolvedReceiverTypeRef = overriddenFunction.resolvedReceiverTypeRef
val originReceiverTypeRef = func.resolvedReceiverTypeRef

// origin receiver should be the same as symbol receiver
if (originReceiverTypeRef != resolvedReceiverTypeRef) {
return@processOverridden
}

if (symbolParameterSymbols.size != originParameterSymbols.size) {
return@processOverridden
}
// all value parameters should be a subtype of symbol's value parameters
val symbolParameterSymbols = overriddenFunction.valueParameterSymbols
val originParameterSymbols = func.valueParameterSymbols

for ((index, symbolParameter) in symbolParameterSymbols.withIndex()) {
val originParameter = originParameterSymbols[index]
if (
originParameter.resolvedReturnType != symbolParameter.resolvedReturnType
) {
if (symbolParameterSymbols.size != originParameterSymbols.size) {
return@processOverridden
}
}

val overriddenAnnotation = firAnnotation(
overriddenFunction, markAnnotation, overriddenFunction.getContainingClassSymbol()
) ?: return@processOverridden
for ((index, symbolParameter) in symbolParameterSymbols.withIndex()) {
val originParameter = originParameterSymbols[index]
if (
originParameter.resolvedReturnType != symbolParameter.resolvedReturnType
) {
return@processOverridden
}
}

val overriddenAnnotation = firAnnotation(
overriddenFunction, markAnnotation, overriddenFunction.getContainingClassSymbol()
) ?: return@processOverridden

val overriddenAnnoData = overriddenAnnotation.toTransformAnnotationData(
markAnnotation, overriddenFunction.name.asString()
)
val overriddenAnnoData = overriddenAnnotation.toTransformAnnotationData(
markAnnotation, overriddenFunction.name.asString()
)

// Same functionName, same asProperty, the generated synthetic function will be same too.
if (
overriddenAnnoData.functionName == annoData.functionName
&& overriddenAnnoData.asProperty == annoData.asProperty
) {
isOverride = true
// Same functionName, same asProperty, the generated synthetic function will be same too.
if (
overriddenAnnoData.functionName == annoData.functionName
&& overriddenAnnoData.asProperty == annoData.asProperty
) {
isOverride = true
}
}
}
}
Expand Down Expand Up @@ -1220,7 +1218,7 @@ class SuspendTransformFirTransformer(
// it.declarationSymbols.filterIsInstance<FirPropertySymbol>()
}
.filter { !it.isFinal }
.filter { it.callableId.callableName == functionName }
.filter { it.callableId?.callableName == functionName }
Copy link
Preview

Copilot AI Sep 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added null-safe operator ?. to callableId access. While this prevents null pointer exceptions, it may hide underlying issues where callableId should not be null. Consider investigating why callableId might be null and handle it more explicitly.

Suggested change
.filter { it.callableId?.callableName == functionName }
.filter {
val callableId = it.callableId
requireNotNull(callableId) { "Property symbol ${it} has null callableId, which should not happen." }
callableId.callableName == functionName
}

Copilot uses AI. Check for mistakes.

// overridable receiver parameter.
.filter {
thisReceiverTypeRef sameAs it.resolvedReceiverTypeRef
Expand Down Expand Up @@ -1349,16 +1347,20 @@ class SuspendTransformFirTransformer(
}

is ConeCapturedType -> {
// val lowerType = projection.lowerType?.let { lowerType ->
// findCopied(lowerType)
// }?.toConeType()

val lowerType = projection.lowerType?.copyWithTypeParameters(parameters)
val constructorLowerType = projection.constructor.lowerType?.copyWithTypeParameters(parameters)

if (lowerType == null) {
projection.copy(lowerType = lowerType)
} else {
if (constructorLowerType == null) {
null
} else {
projection.copy(
constructor = ConeCapturedTypeConstructor(
projection = projection.constructor.projection,
lowerType = constructorLowerType,
captureStatus = projection.constructor.captureStatus,
supertypes = projection.constructor.supertypes,
typeParameterMarker = projection.constructor.typeParameterMarker,
)
)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ class SuspendTransformTransformer(
private fun IrFunction.reportLocation(): CompilerMessageSourceLocation? {
return when (val sourceLocation =
// getSourceLocation(runCatching { fileEntry }.getOrNull())) {
getSourceLocation(declaration = symbol, file = file)) {
getSourceLocation(declaration = symbol, fileEntry = runCatching { fileEntry }.getOrNull())) {

is SourceLocation.WithFileAndLineNumberInformation ->
CompilerMessageLocation.create(
Expand Down
14 changes: 14 additions & 0 deletions docs/docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@ From my memory and guess, Kotlin versions have a higher probability of incompati
and a smaller probability of incompatibility when patch is added (e.g. `1.9.21` -> `1.9.22`).
:::

### Version Follow-up

We typically actively follow updates for regular Kotlin release versions (such as `2.1.0`, `2.2.20`, etc.).
For non-regular versions (such as `2.1.0-RC1`, `2.2.20-Beta2`, etc.), we **do not guarantee** that we will update for
every version.

However, if:

- You need a specific version that is incompatible with previous versions and we haven't updated for it
- We haven't noticed/updated after a regular release update

Feel free to let us know
through [issues](https://github.com/ForteScarlet/kotlin-suspend-transform-compiler-plugin/issues)!

## Gradle Setup

<Tabs>
Expand Down
16 changes: 16 additions & 0 deletions docs/docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,21 @@ function getSiteTagline() {
}
}

function getAnnouncementBarContent() {
switch(process.env.DOCUSAURUS_CURRENT_LOCALE) {
case "zh-CN": return '🚧 抱歉!本文档仍在建设中 - 如果你发现任何问题,请告诉我们!我们很乐意听取你的意见! 🌟';
default: return '🚧 Oops! This doc is still under construction - If you spot any quirks, give us a shout! We\'d love to hear from you! 🌟';
}
}

function getAnnouncementBar() {
return {
id: 'IN_WIP',
content: getAnnouncementBarContent(),
isCloseable: true
};
}

const config: Config = {
title: 'Kotlin Suspend Transform Compiler Plugin',
tagline: getSiteTagline(), // 'Make suspend less shy',
Expand Down Expand Up @@ -88,6 +103,7 @@ const config: Config = {
],

themeConfig: {
announcementBar: getAnnouncementBar(),
// Replace with your project's social card
// image: 'img/docusaurus-social-card.jpg',
navbar: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,19 @@ import versionInfo from '@site/src/version.json';
而当补丁版本号增加时(例如 `1.9.21` -> `1.9.22`),不兼容的概率较小。
:::

### 版本跟进

通常我们会主动跟进正常的 Kotlin release 版本的更新(例如 `2.1.0`, `2.2.20` 等)。
而对于一些非常规的版本(例如 `2.1.0-RC1`, `2.2.20-Beta2` 等),我们**不保证**每个版本都会跟随着更新。

不过如果:

- 你需要某个版本、这个版本与之前的版本不兼容且我们没有更新
- 某个正常的 release 更新后我们一直没发现/没更新

欢迎随时通过 [issues](https://github.com/ForteScarlet/kotlin-suspend-transform-compiler-plugin/issues)
让我们知道~


## Gradle 设置

Expand Down
2 changes: 1 addition & 1 deletion docs/src/version.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version": "2.2.10-0.13.1"}
{"version": "2.2.20-0.13.1"}
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ kotlinx-coroutines = "1.8.0"
kotlinx-serialization = "1.7.1"
google-auto-service = "1.0.1"
# Remember the `IProject.ktVersion`!
kotlin = "2.2.10"
kotlin = "2.2.20"

# https://www.jetbrains.com/help/kotlin-multiplatform-dev/multiplatform-publish-libraries.html#configure-the-project
# https://github.com/vanniktech/gradle-maven-publish-plugin
Expand Down
Loading
Loading