diff --git a/.github/workflows/release-kotlin-preview.yaml b/.github/workflows/release-kotlin-preview.yaml
index f103e943..7234aa30 100644
--- a/.github/workflows/release-kotlin-preview.yaml
+++ b/.github/workflows/release-kotlin-preview.yaml
@@ -4,6 +4,8 @@ on:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+-kotlin-[0-9]+.[0-9]+.[0-9]+-Beta'
- 'v[0-9]+.[0-9]+.[0-9]+-ALPHA-[0-9]+-kotlin-[0-9]+.[0-9]+.[0-9]+-Beta'
+ - 'v[0-9]+.[0-9]+.[0-9]+-kotlin-[0-9]+.[0-9]+.[0-9]+-Beta[0-9]+'
+ - 'v[0-9]+.[0-9]+.[0-9]+-ALPHA-[0-9]+-kotlin-[0-9]+.[0-9]+.[0-9]+-Beta[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-kotlin-[0-9]+.[0-9]+.[0-9]+-RC'
- 'v[0-9]+.[0-9]+.[0-9]+-ALPHA-[0-9]+-kotlin-[0-9]+.[0-9]+.[0-9]+-RC'
- 'v[0-9]+.[0-9]+.[0-9]+-kotlin-[0-9]+.[0-9]+.[0-9]+-RC[0-9]+'
@@ -33,3 +35,10 @@ jobs:
SIGNING_SECRET_KEY: ${{ secrets.SIGNING_SECRET_KEY }}
OSSRH_USERNAME: ${{ secrets.OSSRH_USERNAME }}
OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }}
+ - name: Publish IDEA plugin
+ run: ./gradlew publishPlugin
+ env:
+ IDEA_CERTIFICATE_CHAIN: ${{ secrets.IDEA_CERTIFICATE_CHAIN }}
+ IDEA_PRIVATE_KEY: ${{ secrets.IDEA_PRIVATE_KEY }}
+ IDEA_PRIVATE_KEY_PASSWORD: ${{ secrets.IDEA_PRIVATE_KEY_PASSWORD }}
+ IDEA_PUBLISH_TOKEN: ${{ secrets.IDEA_PUBLISH_TOKEN }}
diff --git a/.github/workflows/release-kotlin.yaml b/.github/workflows/release-kotlin.yaml
index fd62bee6..89f830f3 100644
--- a/.github/workflows/release-kotlin.yaml
+++ b/.github/workflows/release-kotlin.yaml
@@ -39,10 +39,10 @@ jobs:
SIGNING_SECRET_KEY: ${{ secrets.SIGNING_SECRET_KEY }}
GRADLE_PUBLISH_KEY: ${{ secrets.GRADLE_PUBLISH_KEY }}
GRADLE_PUBLISH_SECRET: ${{ secrets.GRADLE_PUBLISH_SECRET }}
-# - name: Publish IDEA plugin
-# run: ./gradlew publishPlugin
-# env:
-# IDEA_CERTIFICATE_CHAIN: ${{ secrets.IDEA_CERTIFICATE_CHAIN }}
-# IDEA_PRIVATE_KEY: ${{ secrets.IDEA_PRIVATE_KEY }}
-# IDEA_PRIVATE_KEY_PASSWORD: ${{ secrets.IDEA_PRIVATE_KEY_PASSWORD }}
-# IDEA_PUBLISH_TOKEN: ${{ secrets.IDEA_PUBLISH_TOKEN }}
+ - name: Publish IDEA plugin
+ run: ./gradlew publishPlugin
+ env:
+ IDEA_CERTIFICATE_CHAIN: ${{ secrets.IDEA_CERTIFICATE_CHAIN }}
+ IDEA_PRIVATE_KEY: ${{ secrets.IDEA_PRIVATE_KEY }}
+ IDEA_PRIVATE_KEY_PASSWORD: ${{ secrets.IDEA_PRIVATE_KEY_PASSWORD }}
+ IDEA_PUBLISH_TOKEN: ${{ secrets.IDEA_PUBLISH_TOKEN }}
diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml
index fdf8d994..e805548a 100644
--- a/.idea/kotlinc.xml
+++ b/.idea/kotlinc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/KMPNativeCoroutinesAsync.podspec b/KMPNativeCoroutinesAsync.podspec
index 94d0645f..60b137c1 100644
--- a/KMPNativeCoroutinesAsync.podspec
+++ b/KMPNativeCoroutinesAsync.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'KMPNativeCoroutinesAsync'
- s.version = '1.0.0-ALPHA-17'
+ s.version = '1.0.0-ALPHA-21'
s.summary = 'Swift library for Kotlin Coroutines with Swift Async/Await'
s.homepage = 'https://github.com/rickclephas/KMP-NativeCoroutines'
diff --git a/KMPNativeCoroutinesCombine.podspec b/KMPNativeCoroutinesCombine.podspec
index 92a46ecd..f07052de 100644
--- a/KMPNativeCoroutinesCombine.podspec
+++ b/KMPNativeCoroutinesCombine.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'KMPNativeCoroutinesCombine'
- s.version = '1.0.0-ALPHA-17'
+ s.version = '1.0.0-ALPHA-21'
s.summary = 'Swift library for Kotlin Coroutines with Combine'
s.homepage = 'https://github.com/rickclephas/KMP-NativeCoroutines'
diff --git a/KMPNativeCoroutinesCore.podspec b/KMPNativeCoroutinesCore.podspec
index 4001a93d..aa71bceb 100644
--- a/KMPNativeCoroutinesCore.podspec
+++ b/KMPNativeCoroutinesCore.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'KMPNativeCoroutinesCore'
- s.version = '1.0.0-ALPHA-17'
+ s.version = '1.0.0-ALPHA-21'
s.summary = 'Swift library for Kotlin Coroutines'
s.homepage = 'https://github.com/rickclephas/KMP-NativeCoroutines'
diff --git a/KMPNativeCoroutinesRxSwift.podspec b/KMPNativeCoroutinesRxSwift.podspec
index 2092d787..694e73ef 100644
--- a/KMPNativeCoroutinesRxSwift.podspec
+++ b/KMPNativeCoroutinesRxSwift.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'KMPNativeCoroutinesRxSwift'
- s.version = '1.0.0-ALPHA-17'
+ s.version = '1.0.0-ALPHA-21'
s.summary = 'Swift library for Kotlin Coroutines with RxSwift'
s.homepage = 'https://github.com/rickclephas/KMP-NativeCoroutines'
diff --git a/MIGRATING_TO_V1.md b/MIGRATING_TO_V1.md
index 5a0dc4f2..66c93b69 100644
--- a/MIGRATING_TO_V1.md
+++ b/MIGRATING_TO_V1.md
@@ -2,7 +2,8 @@
The 1.0 release will bring some improvements that require some changes in your code 😅.
-> **Note**: make sure to use the same library versions for your Kotlin and Swift code!
+> [!NOTE]
+> Make sure to use the same library versions for your Kotlin and Swift code!
## KSP
@@ -26,7 +27,8 @@ To tell the plugin what declarations should be refined for ObjC/Swift you'll nee
suspend fun getRandomLetters(): String = ""
```
-> **Note**: error messages and IDE support are currently limited.
+> [!NOTE]
+> Error messages and IDE support are currently limited.
> Please track [#81](https://github.com/rickclephas/KMP-NativeCoroutines/issues/81) and
> [#82](https://github.com/rickclephas/KMP-NativeCoroutines/issues/82) for improved error messages.
@@ -62,7 +64,8 @@ The value and replay cache property names also drop the `Native` suffix:
+ let replayCache = clock.timeReplayCache
```
-> **Note**: you can now customize the value and replay cache suffixes,
+> [!NOTE]
+> You can now customize the value and replay cache suffixes,
> or if desired completely remove those properties from the generated code.
> Checkout the [README](README.md#name-suffix) for more info.
diff --git a/README.md b/README.md
index 17c1c8ba..88fba41b 100644
--- a/README.md
+++ b/README.md
@@ -2,6 +2,7 @@
A library to use Kotlin Coroutines from Swift code in KMP apps.
+> [!IMPORTANT]
> Looking to upgrade from the 0.x releases? Checkout the [migration steps](MIGRATING_TO_V1.md).
## Why this library?
@@ -12,7 +13,8 @@ The most important limitation is cancellation support.
Kotlin suspend functions are exposed to Swift as functions with a completion handler.
This allows you to easily use them from your Swift code, but it doesn't support cancellation.
-> **Note**: while Swift 5.5 brings async functions to Swift, it doesn't solve this issue.
+> [!NOTE]
+> While Swift 5.5 brings async functions to Swift, it doesn't solve this issue.
> For interoperability with ObjC all functions with a completion handler can be called like an async function.
> This means starting with Swift 5.5 your Kotlin suspend functions will look like Swift async functions.
> But that's just syntactic sugar, so there's still no cancellation support.
@@ -24,19 +26,21 @@ This library solves both of these limitations 😄.
## Compatibility
-The latest version of the library uses Kotlin version `1.9.0`.
+The latest version of the library uses Kotlin version `1.9.20`.
Compatibility versions for older and/or preview Kotlin versions are also available:
-| Version | Version suffix | Kotlin | KSP | Coroutines |
-|----------------|--------------------|:---------:|:----------:|:----------:|
-| **_latest_** | **_no suffix_** | **1.9.0** | **1.0.12** | **1.7.3** |
-| 1.0.0-ALPHA-13 | _no suffix_ | 1.9.0 | 1.0.11 | 1.7.2 |
-| 1.0.0-ALPHA-12 | _no suffix_ | 1.8.22 | 1.0.11 | 1.7.2 |
-| 1.0.0-ALPHA-10 | _no suffix_ | 1.8.21 | 1.0.11 | 1.7.1 |
-| 1.0.0-ALPHA-8 | _no suffix_ | 1.8.21 | 1.0.11 | 1.6.4 |
-| 1.0.0-ALPHA-7 | _no suffix_ | 1.8.20 | 1.0.10 | 1.6.4 |
-| 1.0.0-ALPHA-5 | _no suffix_ | 1.8.10 | 1.0.9 | 1.6.4 |
-| 1.0.0-ALPHA-4 | _no suffix_ | 1.8.0 | 1.0.8 | 1.6.4 |
+| Version | Version suffix | Kotlin | KSP | Coroutines |
+|----------------|---------------------|:-----------:|:----------:|:----------:|
+| _latest_ | -kotlin-2.0.0-Beta1 | 2.0.0-Beta1 | 1.0.14 | 1.7.3 |
+| **_latest_** | **_no suffix_** | **1.9.20** | **1.0.14** | **1.7.3** |
+| 1.0.0-ALPHA-19 | _no suffix_ | 1.9.20 | 1.0.13 | 1.7.3 |
+| 1.0.0-ALPHA-18 | _no suffix_ | 1.9.10 | 1.0.13 | 1.7.3 |
+| 1.0.0-ALPHA-17 | _no suffix_ | 1.9.0 | 1.0.12 | 1.7.3 |
+| 1.0.0-ALPHA-13 | _no suffix_ | 1.9.0 | 1.0.11 | 1.7.2 |
+| 1.0.0-ALPHA-12 | _no suffix_ | 1.8.22 | 1.0.11 | 1.7.2 |
+| 1.0.0-ALPHA-10 | _no suffix_ | 1.8.21 | 1.0.11 | 1.7.1 |
+| 1.0.0-ALPHA-8 | _no suffix_ | 1.8.21 | 1.0.11 | 1.6.4 |
+| 1.0.0-ALPHA-7 | _no suffix_ | 1.8.20 | 1.0.10 | 1.6.4 |
You can choose from a couple of Swift implementations.
Depending on the implementation you can support as low as iOS 9, macOS 10.9, tvOS 9 and watchOS 3:
@@ -60,8 +64,8 @@ Make sure to always use the same versions for all the libraries!
For Kotlin just add the plugin to your `build.gradle.kts`:
```kotlin
plugins {
- id("com.google.devtools.ksp") version "1.9.0-1.0.12"
- id("com.rickclephas.kmp.nativecoroutines") version "1.0.0-ALPHA-17"
+ id("com.google.devtools.ksp") version "1.9.20-1.0.14"
+ id("com.rickclephas.kmp.nativecoroutines") version "1.0.0-ALPHA-21"
}
```
and make sure to opt in to the experimental `@ObjCName` annotation:
@@ -77,28 +81,44 @@ The Swift implementations are available via the Swift Package Manager.
Just add it to your `Package.swift` file:
```swift
dependencies: [
- .package(url: "https://github.com/rickclephas/KMP-NativeCoroutines.git", from: "1.0.0-ALPHA-17")
+ .package(url: "https://github.com/rickclephas/KMP-NativeCoroutines.git", exact: "1.0.0-ALPHA-21")
+],
+targets: [
+ .target(
+ name: "MyTargetName",
+ dependencies: [
+ // Swift Concurrency implementation
+ .product(name: "KMPNativeCoroutinesAsync", package: "KMP-NativeCoroutines"),
+ // Combine implementation
+ .product(name: "KMPNativeCoroutinesCombine", package: "KMP-NativeCoroutines"),
+ // RxSwift implementation
+ .product(name: "KMPNativeCoroutinesRxSwift", package: "KMP-NativeCoroutines")
+ ]
+ )
]
```
Or add it in Xcode by going to `File` > `Add Packages...` and providing the URL:
`https://github.com/rickclephas/KMP-NativeCoroutines.git`.
-> **Note**: the version for the Swift package should not contain the Kotlin version suffix
+> [!NOTE]
+> The version for the Swift package should not contain the Kotlin version suffix
> (e.g. `-new-mm` or `-kotlin-1.6.0`).
-> **Note**: if you only need a single implementation you can also use the SPM specific versions with suffixes
+> [!NOTE]
+> If you only need a single implementation you can also use the SPM specific versions with suffixes
> `-spm-async`, `-spm-combine` and `-spm-rxswift`.
### Swift (CocoaPods)
If you use CocoaPods add one or more of the following libraries to your `Podfile`:
```ruby
-pod 'KMPNativeCoroutinesAsync', '1.0.0-ALPHA-17' # Swift Concurrency implementation
-pod 'KMPNativeCoroutinesCombine', '1.0.0-ALPHA-17' # Combine implementation
-pod 'KMPNativeCoroutinesRxSwift', '1.0.0-ALPHA-17' # RxSwift implementation
+pod 'KMPNativeCoroutinesAsync', '1.0.0-ALPHA-21' # Swift Concurrency implementation
+pod 'KMPNativeCoroutinesCombine', '1.0.0-ALPHA-21' # Combine implementation
+pod 'KMPNativeCoroutinesRxSwift', '1.0.0-ALPHA-21' # RxSwift implementation
```
-> **Note**: the version for CocoaPods should not contain the Kotlin version suffix (e.g. `-new-mm` or `-kotlin-1.6.0`).
+> [!NOTE]
+> The version for CocoaPods should not contain the Kotlin version suffix (e.g. `-new-mm` or `-kotlin-1.6.0`).
### IntelliJ / Android Studio
@@ -317,7 +337,8 @@ handle.cancel()
The Combine implementation provides a couple functions to get an `AnyPublisher` for your Coroutines code.
-> **Note**: these functions create deferred `AnyPublisher`s.
+> [!NOTE]
+> These functions create deferred `AnyPublisher`s.
> Meaning every subscription will trigger the collection of the `Flow` or execution of the suspend function.
#### Publisher
@@ -369,7 +390,8 @@ cancellable.cancel()
The RxSwift implementation provides a couple functions to get an `Observable` or `Single` for your Coroutines code.
-> **Note**: these functions create deferred `Observable`s and `Single`s.
+> [!NOTE]
+> These functions create deferred `Observable`s and `Single`s.
> Meaning every subscription will trigger the collection of the `Flow` or execution of the suspend function.
#### Observable
@@ -464,14 +486,16 @@ class Clock {
}
```
-> **Note**: your custom coroutine scope must be either `internal` or `public`.
+> [!NOTE]
+> Your custom coroutine scope must be either `internal` or `public`.
If you don't provide a `CoroutineScope` the default scope will be used which is defined as:
```kotlin
internal val defaultCoroutineScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
```
-> **Note**: KMP-NativeCoroutines has built-in support for [KMM-ViewModel](https://github.com/rickclephas/KMM-ViewModel).
+> [!NOTE]
+> KMP-NativeCoroutines has built-in support for [KMM-ViewModel](https://github.com/rickclephas/KMM-ViewModel).
> Coroutines inside your `KMMViewModel` will (by default) use the `CoroutineScope` from the `ViewModelScope`.
### Ignoring declarations
@@ -494,7 +518,8 @@ If for some reason you would like to further refine your Kotlin declarations in
These will tell the plugin to add the [`ShouldRefineInSwift`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.native/-should-refine-in-swift/)
annotation to the generated properties/function.
-> **Note**: this currently requires a module-wide opt-in to `kotlin.experimental.ExperimentalObjCRefinement`.
+> [!NOTE]
+> This currently requires a module-wide opt-in to `kotlin.experimental.ExperimentalObjCRefinement`.
You could for example refine your `Flow` property to an `AnyPublisher` property:
```kotlin
diff --git a/build.gradle.kts b/build.gradle.kts
index 5e357436..fa300ea4 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -12,7 +12,7 @@ buildscript {
allprojects {
group = "com.rickclephas.kmp"
- version = "1.0.0-ALPHA-17"
+ version = "1.0.0-ALPHA-21"
repositories {
mavenCentral()
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 346fbe07..7d56b1cc 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,7 +1,7 @@
[versions]
-kotlin = "1.9.0"
+kotlin = "1.9.20"
kotlinx-coroutines = "1.7.3"
-ksp = "1.9.0-1.0.12"
+ksp = "1.9.20-1.0.14"
kotlinpoet = "1.14.2"
junit = "5.9.1"
@@ -20,7 +20,7 @@ kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotl
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" }
kotlin-compiler-internalTestFramework = { module = "org.jetbrains.kotlin:kotlin-compiler-internal-test-framework", version.ref = "kotlin" }
kotlinx-coroutines-test = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-test", version.ref = "kotlinx-coroutines" }
-kotlinCompileTesting-ksp = { module = "com.github.tschuchortdev:kotlin-compile-testing-ksp", version = "1.5.0" }
+kotlinCompileTesting-ksp = { module = "dev.zacsweers.kctfork:ksp", version = "0.3.2" }
junit = { module = "junit:junit", version = "4.13.2" }
junit-bom = { module = "org.junit:junit-bom", version.ref = "junit" }
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter" }
diff --git a/kmp-nativecoroutines-compiler/build.gradle.kts b/kmp-nativecoroutines-compiler/build.gradle.kts
index 63363de8..da62412f 100644
--- a/kmp-nativecoroutines-compiler/build.gradle.kts
+++ b/kmp-nativecoroutines-compiler/build.gradle.kts
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
+
plugins {
alias(libs.plugins.kotlin.jvm)
`kmp-nativecoroutines-publish`
@@ -38,12 +40,17 @@ tasks.compileKotlin.configure {
}
tasks.test {
+ systemProperty("kotlin.internal.native.test.nativeHome", NativeCompilerDownloader(project).compilerDirectory.absolutePath)
inputs.dir("src/testData")
useJUnitPlatform()
}
+val deleteGeneratedTests by tasks.registering(Delete::class) {
+ delete("src/test/generated")
+}
+
val generateTests by tasks.registering(JavaExec::class) {
- doFirst { delete("src/test/generated") }
+ dependsOn(deleteGeneratedTests)
classpath = sourceSets.test.get().runtimeClasspath
mainClass.set("com.rickclephas.kmp.nativecoroutines.compiler.GenerateTestsKt")
}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/KmpNativeCoroutinesCompilerPluginRegistrar.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/KmpNativeCoroutinesCompilerPluginRegistrar.kt
index 147669da..16489596 100644
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/KmpNativeCoroutinesCompilerPluginRegistrar.kt
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/KmpNativeCoroutinesCompilerPluginRegistrar.kt
@@ -1,17 +1,20 @@
package com.rickclephas.kmp.nativecoroutines.compiler
-import com.rickclephas.kmp.nativecoroutines.compiler.extensions.KmpNativeCoroutinesStorageComponentContainerContributor
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.extensions.KmpNativeCoroutinesStorageComponentContainerContributor
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.extensions.KmpNativeCoroutinesFirExtensionRegistrar
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor
+import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter
@OptIn(ExperimentalCompilerApi::class)
public class KmpNativeCoroutinesCompilerPluginRegistrar: CompilerPluginRegistrar() {
- override val supportsK2: Boolean = false // TODO: Add K2 support
+ override val supportsK2: Boolean = true
override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
+ FirExtensionRegistrarAdapter.registerExtension(KmpNativeCoroutinesFirExtensionRegistrar(configuration))
StorageComponentContainerContributor.registerExtension(
KmpNativeCoroutinesStorageComponentContainerContributor(configuration)
)
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/DefaultErrorMessages.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/DefaultErrorMessages.kt
new file mode 100644
index 00000000..96cfb0d5
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/DefaultErrorMessages.kt
@@ -0,0 +1,66 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics
+
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.CONFLICT_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINE_SCOPE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.UNSUPPORTED_CLASS_EXTENSION_PROPERTY
+import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
+import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap
+
+@Suppress("DuplicatedCode")
+internal object DefaultErrorMessages : DefaultErrorMessages.Extension {
+ override fun getMap(): DiagnosticFactoryToRendererMap = DiagnosticFactoryToRendererMap("KmpNativeCoroutines").apply {
+ put(CONFLICT_COROUTINES, "NativeCoroutines, NativeCoroutinesRefined, NativeCoroutinesRefinedState and NativeCoroutinesState can't be combined")
+ put(EXPOSED_FLOW_TYPE, "Flow type is exposed to ObjC")
+ put(EXPOSED_FLOW_TYPE_ERROR, "Flow type is exposed to ObjC")
+ put(EXPOSED_STATE_FLOW_PROPERTY, "StateFlow property is exposed to ObjC")
+ put(EXPOSED_STATE_FLOW_PROPERTY_ERROR, "StateFlow property is exposed to ObjC")
+ put(EXPOSED_SUSPEND_FUNCTION, "suspend function is exposed to ObjC")
+ put(EXPOSED_SUSPEND_FUNCTION_ERROR, "suspend function is exposed to ObjC")
+ put(IGNORED_COROUTINES, "NativeCoroutinesIgnore overrides NativeCoroutines")
+ put(IGNORED_COROUTINES_REFINED, "NativeCoroutinesIgnore overrides NativeCoroutinesRefined")
+ put(IGNORED_COROUTINES_REFINED_STATE, "NativeCoroutinesIgnore overrides NativeCoroutinesRefinedState")
+ put(IGNORED_COROUTINES_STATE, "NativeCoroutinesIgnore overrides NativeCoroutinesState")
+ put(INVALID_COROUTINES, "NativeCoroutines is only supported on suspend-functions and Flow declarations")
+ put(INVALID_COROUTINES_IGNORE, "NativeCoroutinesIgnore is only supported on suspend-functions and Flow declarations")
+ put(INVALID_COROUTINES_REFINED, "NativeCoroutinesRefined is only supported on suspend-functions and Flow declarations")
+ put(INVALID_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState is only supported on StateFlow properties")
+ put(INVALID_COROUTINES_STATE, "NativeCoroutinesState is only supported on StateFlow properties")
+ put(INVALID_COROUTINE_SCOPE, "NativeCoroutineScope is only supported on CoroutineScope properties")
+ put(REDUNDANT_OVERRIDE_COROUTINES, "NativeCoroutines should be applied to overridden declaration instead")
+ put(REDUNDANT_OVERRIDE_COROUTINES_IGNORE, "NativeCoroutinesIgnore isn't supported on overridden declarations")
+ put(REDUNDANT_OVERRIDE_COROUTINES_REFINED, "NativeCoroutinesRefined should be applied to overridden declaration instead")
+ put(REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState should be applied to overridden declaration instead")
+ put(REDUNDANT_OVERRIDE_COROUTINES_STATE, "NativeCoroutinesState should be applied to overridden declaration instead")
+ put(REDUNDANT_PRIVATE_COROUTINES, "NativeCoroutines is only supported on public declarations")
+ put(REDUNDANT_PRIVATE_COROUTINES_IGNORE, "NativeCoroutinesIgnore is only supported on public declarations")
+ put(REDUNDANT_PRIVATE_COROUTINES_REFINED, "NativeCoroutinesRefined is only supported on public declarations")
+ put(REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState is only supported on public declarations")
+ put(REDUNDANT_PRIVATE_COROUTINES_STATE, "NativeCoroutinesState is only supported on public declarations")
+ put(UNSUPPORTED_CLASS_EXTENSION_PROPERTY, "Class extension properties aren't supported")
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/KmpNativeCoroutinesChecker.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/KmpNativeCoroutinesChecker.kt
new file mode 100644
index 00000000..c342dd75
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/KmpNativeCoroutinesChecker.kt
@@ -0,0 +1,175 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics
+
+import com.rickclephas.kmp.nativecoroutines.compiler.config.ExposedSeverity
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.CONFLICT_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINE_SCOPE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.UNSUPPORTED_CLASS_EXTENSION_PROPERTY
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.utils.NativeCoroutinesAnnotations
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.utils.coroutinesReturnType
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.CoroutinesReturnType
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.FunctionDescriptor
+import org.jetbrains.kotlin.descriptors.PropertyDescriptor
+import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
+import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
+import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
+import org.jetbrains.kotlin.psi.KtDeclaration
+import org.jetbrains.kotlin.psi.KtElement
+import org.jetbrains.kotlin.resolve.BindingTrace
+import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromAnnotation
+import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
+import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
+import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
+import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
+
+public class KmpNativeCoroutinesChecker(
+ exposedSeverity: ExposedSeverity
+): DeclarationChecker {
+
+ private val exposedSuspendFunction = when (exposedSeverity) {
+ ExposedSeverity.NONE -> null
+ ExposedSeverity.WARNING -> EXPOSED_SUSPEND_FUNCTION
+ ExposedSeverity.ERROR -> EXPOSED_SUSPEND_FUNCTION_ERROR
+ }
+
+ private val exposedFlowType = when (exposedSeverity) {
+ ExposedSeverity.NONE -> null
+ ExposedSeverity.WARNING -> EXPOSED_FLOW_TYPE
+ ExposedSeverity.ERROR -> EXPOSED_FLOW_TYPE_ERROR
+ }
+
+ private val exposedStateFlowProperty = when (exposedSeverity) {
+ ExposedSeverity.NONE -> null
+ ExposedSeverity.WARNING -> EXPOSED_STATE_FLOW_PROPERTY
+ ExposedSeverity.ERROR -> EXPOSED_STATE_FLOW_PROPERTY_ERROR
+ }
+
+ override fun check(
+ declaration: KtDeclaration,
+ descriptor: DeclarationDescriptor,
+ context: DeclarationCheckerContext
+ ) {
+ if (descriptor !is CallableDescriptor) return
+ if (descriptor !is SimpleFunctionDescriptor && descriptor !is PropertyDescriptor) return
+ val annotations = NativeCoroutinesAnnotations(descriptor)
+ val isPublic = descriptor.isEffectivelyPublicApi
+ val isOverride = descriptor.overriddenDescriptors.isNotEmpty()
+ val isSuspend = descriptor is FunctionDescriptor && descriptor.isSuspend
+ val returnType = descriptor.coroutinesReturnType
+
+ //region CONFLICT_COROUTINES
+ val coroutinesAnnotations = listOf(
+ annotations.nativeCoroutines,
+ annotations.nativeCoroutinesRefined,
+ annotations.nativeCoroutinesRefinedState,
+ annotations.nativeCoroutinesState,
+ )
+ val annotationCount = coroutinesAnnotations.count { it != null }
+ if (annotationCount > 1) {
+ coroutinesAnnotations.forEach {
+ context.trace.report(CONFLICT_COROUTINES, it, declaration)
+ }
+ }
+ //endregion
+
+ //region EXPOSED_*
+ if (isPublic && !isOverride && annotationCount == 0 && annotations.nativeCoroutinesIgnore == null) {
+ if (isSuspend) {
+ exposedSuspendFunction?.on(declaration)?.let(context.trace::report)
+ }
+ if (returnType is CoroutinesReturnType.Flow) {
+ val diagnosticFactory = when {
+ descriptor !is PropertyDescriptor -> exposedFlowType
+ returnType != CoroutinesReturnType.Flow.State -> exposedFlowType
+ else -> exposedStateFlowProperty
+ }
+ diagnosticFactory?.on(declaration)?.let(context.trace::report)
+ }
+ }
+ //endregion
+
+ //region IGNORED_*
+ if (annotations.nativeCoroutinesIgnore != null) {
+ context.trace.report(IGNORED_COROUTINES, annotations.nativeCoroutines, declaration)
+ context.trace.report(IGNORED_COROUTINES_REFINED, annotations.nativeCoroutinesRefined, declaration)
+ context.trace.report(IGNORED_COROUTINES_REFINED_STATE, annotations.nativeCoroutinesRefinedState, declaration)
+ context.trace.report(IGNORED_COROUTINES_STATE, annotations.nativeCoroutinesState, declaration)
+ }
+ //endregion
+
+ //region INVALID_*
+ if (descriptor !is PropertyDescriptor || returnType != CoroutinesReturnType.CoroutineScope) {
+ context.trace.report(INVALID_COROUTINE_SCOPE, annotations.nativeCoroutineScope, declaration)
+ }
+ if (!isSuspend && returnType !is CoroutinesReturnType.Flow) {
+ context.trace.report(INVALID_COROUTINES, annotations.nativeCoroutines, declaration)
+ context.trace.report(INVALID_COROUTINES_IGNORE, annotations.nativeCoroutinesIgnore, declaration)
+ context.trace.report(INVALID_COROUTINES_REFINED, annotations.nativeCoroutinesRefined, declaration)
+ }
+ if (descriptor !is PropertyDescriptor || returnType !is CoroutinesReturnType.Flow.State) {
+ context.trace.report(INVALID_COROUTINES_REFINED_STATE, annotations.nativeCoroutinesRefinedState, declaration)
+ context.trace.report(INVALID_COROUTINES_STATE, annotations.nativeCoroutinesState, declaration)
+ }
+ //endregion
+
+ //region REDUNDANT_*
+ if (isOverride) {
+ context.trace.report(REDUNDANT_OVERRIDE_COROUTINES, annotations.nativeCoroutines, declaration)
+ context.trace.report(REDUNDANT_OVERRIDE_COROUTINES_IGNORE, annotations.nativeCoroutinesIgnore, declaration)
+ context.trace.report(REDUNDANT_OVERRIDE_COROUTINES_REFINED, annotations.nativeCoroutinesRefined, declaration)
+ context.trace.report(REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE, annotations.nativeCoroutinesRefinedState, declaration)
+ context.trace.report(REDUNDANT_OVERRIDE_COROUTINES_STATE, annotations.nativeCoroutinesState, declaration)
+ }
+ if (!isPublic) {
+ context.trace.report(REDUNDANT_PRIVATE_COROUTINES, annotations.nativeCoroutines, declaration)
+ context.trace.report(REDUNDANT_PRIVATE_COROUTINES_IGNORE, annotations.nativeCoroutinesIgnore, declaration)
+ context.trace.report(REDUNDANT_PRIVATE_COROUTINES_REFINED, annotations.nativeCoroutinesRefined, declaration)
+ context.trace.report(REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE, annotations.nativeCoroutinesRefinedState, declaration)
+ context.trace.report(REDUNDANT_PRIVATE_COROUTINES_STATE, annotations.nativeCoroutinesState, declaration)
+ }
+ //endregion
+
+ //region UNSUPPORTED_*
+ if (descriptor is PropertyDescriptor && descriptor.dispatchReceiverParameter != null && descriptor.isExtension) {
+ coroutinesAnnotations.forEach {
+ context.trace.report(UNSUPPORTED_CLASS_EXTENSION_PROPERTY, it, declaration)
+ }
+ }
+ //endregion
+ }
+
+ private fun BindingTrace.report(
+ diagnosticFactory: DiagnosticFactory0,
+ annotationDescriptor: AnnotationDescriptor?,
+ declaration: KtDeclaration
+ ) {
+ if (annotationDescriptor == null) return
+ report(diagnosticFactory.on(getSourceFromAnnotation(annotationDescriptor) ?: declaration))
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/KmpNativeCoroutinesErrors.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/KmpNativeCoroutinesErrors.kt
similarity index 71%
rename from kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/KmpNativeCoroutinesErrors.kt
rename to kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/KmpNativeCoroutinesErrors.kt
index 4e90648b..683b8997 100644
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/KmpNativeCoroutinesErrors.kt
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/diagnostics/KmpNativeCoroutinesErrors.kt
@@ -1,26 +1,27 @@
-package com.rickclephas.kmp.nativecoroutines.compiler.diagnostics
+package com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics
-import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
import org.jetbrains.kotlin.diagnostics.Errors
+import org.jetbrains.kotlin.diagnostics.PositioningStrategies
import org.jetbrains.kotlin.diagnostics.Severity
+import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
public object KmpNativeCoroutinesErrors {
@JvmField
public val CONFLICT_COROUTINES: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
@JvmField
- public val EXPOSED_FLOW_TYPE: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.WARNING)
+ public val EXPOSED_FLOW_TYPE: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.WARNING, PositioningStrategies.DECLARATION_RETURN_TYPE)
@JvmField
- public val EXPOSED_FLOW_TYPE_ERROR: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
+ public val EXPOSED_FLOW_TYPE_ERROR: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR, PositioningStrategies.DECLARATION_RETURN_TYPE)
@JvmField
- public val EXPOSED_STATE_FLOW_PROPERTY: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.WARNING)
+ public val EXPOSED_STATE_FLOW_PROPERTY: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.WARNING, PositioningStrategies.DECLARATION_RETURN_TYPE)
@JvmField
- public val EXPOSED_STATE_FLOW_PROPERTY_ERROR: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
+ public val EXPOSED_STATE_FLOW_PROPERTY_ERROR: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR, PositioningStrategies.DECLARATION_RETURN_TYPE)
@JvmField
- public val EXPOSED_SUSPEND_FUNCTION: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.WARNING)
+ public val EXPOSED_SUSPEND_FUNCTION: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.WARNING, PositioningStrategies.SUSPEND_MODIFIER)
@JvmField
- public val EXPOSED_SUSPEND_FUNCTION_ERROR: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
+ public val EXPOSED_SUSPEND_FUNCTION_ERROR: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR, PositioningStrategies.SUSPEND_MODIFIER)
@JvmField
public val IGNORED_COROUTINES: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
@JvmField
@@ -60,7 +61,9 @@ public object KmpNativeCoroutinesErrors {
@JvmField
public val REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
@JvmField
- public val REDUNDANT_PRIVATE_COROUTINES_STATE: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
+ public val REDUNDANT_PRIVATE_COROUTINES_STATE: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
+ @JvmField
+ public val UNSUPPORTED_CLASS_EXTENSION_PROPERTY: DiagnosticFactory0 = DiagnosticFactory0.create(Severity.ERROR)
init {
Errors.Initializer.initializeFactoryNamesAndDefaultErrorMessages(KmpNativeCoroutinesErrors::class.java, DefaultErrorMessages)
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt
similarity index 84%
rename from kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt
rename to kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt
index 86b96bbf..56d87bfc 100644
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt
@@ -1,8 +1,8 @@
-package com.rickclephas.kmp.nativecoroutines.compiler.extensions
+package com.rickclephas.kmp.nativecoroutines.compiler.classic.extensions
import com.rickclephas.kmp.nativecoroutines.compiler.config.EXPOSED_SEVERITY
import com.rickclephas.kmp.nativecoroutines.compiler.config.get
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesChecker
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesChecker
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useInstance
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/utils/CoroutinesReturnType.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/utils/CoroutinesReturnType.kt
new file mode 100644
index 00000000..05909f42
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/utils/CoroutinesReturnType.kt
@@ -0,0 +1,32 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.classic.utils
+
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.CoroutinesClassIds
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.CoroutinesReturnType
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.ModuleDescriptor
+import org.jetbrains.kotlin.descriptors.findClassifierAcrossModuleDependencies
+import org.jetbrains.kotlin.name.ClassId
+import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
+import org.jetbrains.kotlin.resolve.descriptorUtil.module
+import org.jetbrains.kotlin.types.TypeConstructor
+import org.jetbrains.kotlin.types.typeUtil.supertypes
+
+internal val CallableDescriptor.coroutinesReturnType: CoroutinesReturnType? get() {
+ val returnType = returnTypeOrNothing
+ val stateFlowConstructor = module.findTypeConstructor(CoroutinesClassIds.stateFlow)
+ if (returnType.constructor == stateFlowConstructor) return CoroutinesReturnType.Flow.State
+ val flowConstructor = module.findTypeConstructor(CoroutinesClassIds.flow)
+ if (returnType.constructor == flowConstructor) return CoroutinesReturnType.Flow.Generic
+ val coroutineScopeConstructor = module.findTypeConstructor(CoroutinesClassIds.coroutineScope)
+ if (returnType.constructor == coroutineScopeConstructor) return CoroutinesReturnType.CoroutineScope
+ returnType.supertypes().forEach {
+ if (it.constructor == stateFlowConstructor) return CoroutinesReturnType.Flow.State
+ if (it.constructor == flowConstructor) return CoroutinesReturnType.Flow.Generic
+ if (it.constructor == coroutineScopeConstructor) return CoroutinesReturnType.CoroutineScope
+ }
+ return null
+}
+
+private fun ModuleDescriptor.findTypeConstructor(classId: ClassId): TypeConstructor =
+ findClassifierAcrossModuleDependencies(classId)?.typeConstructor
+ ?: throw NoSuchElementException("Couldn't find ${classId.relativeClassName} constructor")
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/NativeCoroutinesAnnotations.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/utils/NativeCoroutinesAnnotations.kt
similarity index 96%
rename from kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/NativeCoroutinesAnnotations.kt
rename to kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/utils/NativeCoroutinesAnnotations.kt
index 308cae4e..a006aa16 100644
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/NativeCoroutinesAnnotations.kt
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/classic/utils/NativeCoroutinesAnnotations.kt
@@ -1,4 +1,4 @@
-package com.rickclephas.kmp.nativecoroutines.compiler.utils
+package com.rickclephas.kmp.nativecoroutines.compiler.classic.utils
import com.rickclephas.kmp.nativecoroutines.compiler.utils.NativeCoroutinesFqNames as FqNames
import org.jetbrains.kotlin.descriptors.CallableDescriptor
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/DefaultErrorMessages.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/DefaultErrorMessages.kt
deleted file mode 100644
index 7c102431..00000000
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/DefaultErrorMessages.kt
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.rickclephas.kmp.nativecoroutines.compiler.diagnostics
-
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.CONFLICT_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINE_SCOPE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_STATE
-import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
-import org.jetbrains.kotlin.diagnostics.rendering.DiagnosticFactoryToRendererMap
-
-internal object DefaultErrorMessages : DefaultErrorMessages.Extension {
- override fun getMap(): DiagnosticFactoryToRendererMap = DiagnosticFactoryToRendererMap("KmpNativeCoroutines").apply {
- put(CONFLICT_COROUTINES, "NativeCoroutines, NativeCoroutinesRefined, NativeCoroutinesRefinedState and NativeCoroutinesState can't be combined")
- put(EXPOSED_FLOW_TYPE, "Flow type is exposed to ObjC")
- put(EXPOSED_FLOW_TYPE_ERROR, "Flow type is exposed to ObjC")
- put(EXPOSED_STATE_FLOW_PROPERTY, "StateFlow property is exposed to ObjC")
- put(EXPOSED_STATE_FLOW_PROPERTY_ERROR, "StateFlow property is exposed to ObjC")
- put(EXPOSED_SUSPEND_FUNCTION, "suspend function is exposed to ObjC")
- put(EXPOSED_SUSPEND_FUNCTION_ERROR, "suspend function is exposed to ObjC")
- put(IGNORED_COROUTINES, "NativeCoroutinesIgnore overrides NativeCoroutines")
- put(IGNORED_COROUTINES_REFINED, "NativeCoroutinesIgnore overrides NativeCoroutinesRefined")
- put(IGNORED_COROUTINES_REFINED_STATE, "NativeCoroutinesIgnore overrides NativeCoroutinesRefinedState")
- put(IGNORED_COROUTINES_STATE, "NativeCoroutinesIgnore overrides NativeCoroutinesState")
- put(INVALID_COROUTINES, "NativeCoroutines is only supported on suspend-functions and Flow declarations")
- put(INVALID_COROUTINES_IGNORE, "NativeCoroutinesIgnore is only supported on suspend-functions and Flow declarations")
- put(INVALID_COROUTINES_REFINED, "NativeCoroutinesRefined is only supported on suspend-functions and Flow declarations")
- put(INVALID_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState is only supported on StateFlow properties")
- put(INVALID_COROUTINES_STATE, "NativeCoroutinesState is only supported on StateFlow properties")
- put(INVALID_COROUTINE_SCOPE, "NativeCoroutineScope is only supported on CoroutineScope properties")
- put(REDUNDANT_OVERRIDE_COROUTINES, "NativeCoroutines should be applied to overridden declaration instead")
- put(REDUNDANT_OVERRIDE_COROUTINES_IGNORE, "NativeCoroutinesIgnore isn't supported on overridden declarations")
- put(REDUNDANT_OVERRIDE_COROUTINES_REFINED, "NativeCoroutinesRefined should be applied to overridden declaration instead")
- put(REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState should be applied to overridden declaration instead")
- put(REDUNDANT_OVERRIDE_COROUTINES_STATE, "NativeCoroutinesState should be applied to overridden declaration instead")
- put(REDUNDANT_PRIVATE_COROUTINES, "NativeCoroutines is only supported on public declarations")
- put(REDUNDANT_PRIVATE_COROUTINES_IGNORE, "NativeCoroutinesIgnore is only supported on public declarations")
- put(REDUNDANT_PRIVATE_COROUTINES_REFINED, "NativeCoroutinesRefined is only supported on public declarations")
- put(REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState is only supported on public declarations")
- put(REDUNDANT_PRIVATE_COROUTINES_STATE, "NativeCoroutinesState is only supported on public declarations")
- }
-}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/KmpNativeCoroutinesChecker.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/KmpNativeCoroutinesChecker.kt
deleted file mode 100644
index 77e7b4c7..00000000
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/diagnostics/KmpNativeCoroutinesChecker.kt
+++ /dev/null
@@ -1,163 +0,0 @@
-package com.rickclephas.kmp.nativecoroutines.compiler.diagnostics
-
-import com.intellij.psi.PsiElement
-import com.rickclephas.kmp.nativecoroutines.compiler.config.ExposedSeverity
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.CONFLICT_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINE_SCOPE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.utils.NativeCoroutinesAnnotations
-import com.rickclephas.kmp.nativecoroutines.compiler.utils.CoroutinesReturnType
-import com.rickclephas.kmp.nativecoroutines.compiler.utils.coroutinesReturnType
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
-import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.descriptors.PropertyDescriptor
-import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
-import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
-import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0
-import org.jetbrains.kotlin.lexer.KtTokens
-import org.jetbrains.kotlin.psi.KtCallableDeclaration
-import org.jetbrains.kotlin.psi.KtDeclaration
-import org.jetbrains.kotlin.psi.KtElement
-import org.jetbrains.kotlin.resolve.BindingTrace
-import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromAnnotation
-import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
-import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
-import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyPublicApi
-
-public class KmpNativeCoroutinesChecker(
- private val exposedSeverity: ExposedSeverity
-): DeclarationChecker {
-
- override fun check(
- declaration: KtDeclaration,
- descriptor: DeclarationDescriptor,
- context: DeclarationCheckerContext
- ) {
- if (descriptor !is CallableDescriptor) return
- if (descriptor !is SimpleFunctionDescriptor && descriptor !is PropertyDescriptor) return
- val annotations = NativeCoroutinesAnnotations(descriptor)
- val isPublic = descriptor.isEffectivelyPublicApi
- val isOverride = descriptor.overriddenDescriptors.isNotEmpty()
- val isSuspend = descriptor is FunctionDescriptor && descriptor.isSuspend
- val returnType = descriptor.coroutinesReturnType
-
- var annotationCount = 0
- if (annotations.nativeCoroutines != null) annotationCount++
- if (annotations.nativeCoroutinesRefined != null) annotationCount++
- if (annotations.nativeCoroutinesRefinedState != null) annotationCount++
- if (annotations.nativeCoroutinesState != null) annotationCount++
- if (annotationCount > 1) {
- context.trace.report(CONFLICT_COROUTINES, annotations.nativeCoroutines, declaration)
- context.trace.report(CONFLICT_COROUTINES, annotations.nativeCoroutinesRefined, declaration)
- context.trace.report(CONFLICT_COROUTINES, annotations.nativeCoroutinesRefinedState, declaration)
- context.trace.report(CONFLICT_COROUTINES, annotations.nativeCoroutinesState, declaration)
- }
-
- val exposedSuspendFunction: DiagnosticFactory0?
- val exposedFlowType: DiagnosticFactory0?
- val exposedStateFlowProperty: DiagnosticFactory0?
- when (exposedSeverity) {
- ExposedSeverity.NONE -> {
- exposedSuspendFunction = null
- exposedFlowType = null
- exposedStateFlowProperty = null
- }
- ExposedSeverity.WARNING -> {
- exposedSuspendFunction = EXPOSED_SUSPEND_FUNCTION
- exposedFlowType = EXPOSED_FLOW_TYPE
- exposedStateFlowProperty = EXPOSED_STATE_FLOW_PROPERTY
- }
- ExposedSeverity.ERROR -> {
- exposedSuspendFunction = EXPOSED_SUSPEND_FUNCTION_ERROR
- exposedFlowType = EXPOSED_FLOW_TYPE_ERROR
- exposedStateFlowProperty = EXPOSED_STATE_FLOW_PROPERTY_ERROR
- }
- }
- if (isPublic && !isOverride && annotationCount == 0 && annotations.nativeCoroutinesIgnore == null) {
- if (isSuspend) {
- val element = declaration.modifierList?.getModifier(KtTokens.SUSPEND_KEYWORD) ?: declaration
- exposedSuspendFunction?.on(element)?.let(context.trace::report)
- }
- if (returnType is CoroutinesReturnType.Flow) {
- val diagnosticFactory = when {
- descriptor !is PropertyDescriptor -> exposedFlowType
- returnType != CoroutinesReturnType.Flow.State -> exposedFlowType
- else -> exposedStateFlowProperty
- }
- val element = (declaration as? KtCallableDeclaration)?.let {
- it.typeReference ?: it.nameIdentifier
- } ?: declaration
- diagnosticFactory?.on(element)?.let(context.trace::report)
- }
- }
-
- if (annotations.nativeCoroutinesIgnore != null) {
- context.trace.report(IGNORED_COROUTINES, annotations.nativeCoroutines, declaration)
- context.trace.report(IGNORED_COROUTINES_REFINED, annotations.nativeCoroutinesRefined, declaration)
- context.trace.report(IGNORED_COROUTINES_REFINED_STATE, annotations.nativeCoroutinesRefinedState, declaration)
- context.trace.report(IGNORED_COROUTINES_STATE, annotations.nativeCoroutinesState, declaration)
- }
-
- if (descriptor !is PropertyDescriptor || returnType != CoroutinesReturnType.CoroutineScope) {
- context.trace.report(INVALID_COROUTINE_SCOPE, annotations.nativeCoroutineScope, declaration)
- }
- if (!isSuspend && returnType !is CoroutinesReturnType.Flow) {
- context.trace.report(INVALID_COROUTINES, annotations.nativeCoroutines, declaration)
- context.trace.report(INVALID_COROUTINES_IGNORE, annotations.nativeCoroutinesIgnore, declaration)
- context.trace.report(INVALID_COROUTINES_REFINED, annotations.nativeCoroutinesRefined, declaration)
- }
- if (descriptor !is PropertyDescriptor || returnType !is CoroutinesReturnType.Flow.State) {
- context.trace.report(INVALID_COROUTINES_REFINED_STATE, annotations.nativeCoroutinesRefinedState, declaration)
- context.trace.report(INVALID_COROUTINES_STATE, annotations.nativeCoroutinesState, declaration)
- }
-
- if (isOverride) {
- context.trace.report(REDUNDANT_OVERRIDE_COROUTINES, annotations.nativeCoroutines, declaration)
- context.trace.report(REDUNDANT_OVERRIDE_COROUTINES_IGNORE, annotations.nativeCoroutinesIgnore, declaration)
- context.trace.report(REDUNDANT_OVERRIDE_COROUTINES_REFINED, annotations.nativeCoroutinesRefined, declaration)
- context.trace.report(REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE, annotations.nativeCoroutinesRefinedState, declaration)
- context.trace.report(REDUNDANT_OVERRIDE_COROUTINES_STATE, annotations.nativeCoroutinesState, declaration)
- }
- if (!isPublic) {
- context.trace.report(REDUNDANT_PRIVATE_COROUTINES, annotations.nativeCoroutines, declaration)
- context.trace.report(REDUNDANT_PRIVATE_COROUTINES_IGNORE, annotations.nativeCoroutinesIgnore, declaration)
- context.trace.report(REDUNDANT_PRIVATE_COROUTINES_REFINED, annotations.nativeCoroutinesRefined, declaration)
- context.trace.report(REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE, annotations.nativeCoroutinesRefinedState, declaration)
- context.trace.report(REDUNDANT_PRIVATE_COROUTINES_STATE, annotations.nativeCoroutinesState, declaration)
- }
- }
-
- private fun BindingTrace.report(
- diagnosticFactory: DiagnosticFactory0,
- annotationDescriptor: AnnotationDescriptor?,
- declaration: KtDeclaration
- ) {
- if (annotationDescriptor == null) return
- report(diagnosticFactory.on(getSourceFromAnnotation(annotationDescriptor) ?: declaration))
- }
-}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirDefaultErrorMessages.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirDefaultErrorMessages.kt
new file mode 100644
index 00000000..8dc8139f
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirDefaultErrorMessages.kt
@@ -0,0 +1,66 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics
+
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.CONFLICT_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.IGNORED_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.IGNORED_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINE_SCOPE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.UNSUPPORTED_CLASS_EXTENSION_PROPERTY
+import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
+import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
+
+@Suppress("DuplicatedCode")
+internal object FirDefaultErrorMessages: BaseDiagnosticRendererFactory() {
+ override val MAP: KtDiagnosticFactoryToRendererMap = KtDiagnosticFactoryToRendererMap("KmpNativeCoroutines").apply {
+ put(CONFLICT_COROUTINES, "NativeCoroutines, NativeCoroutinesRefined, NativeCoroutinesRefinedState and NativeCoroutinesState can't be combined")
+ put(EXPOSED_FLOW_TYPE, "Flow type is exposed to ObjC")
+ put(EXPOSED_FLOW_TYPE_ERROR, "Flow type is exposed to ObjC")
+ put(EXPOSED_STATE_FLOW_PROPERTY, "StateFlow property is exposed to ObjC")
+ put(EXPOSED_STATE_FLOW_PROPERTY_ERROR, "StateFlow property is exposed to ObjC")
+ put(EXPOSED_SUSPEND_FUNCTION, "suspend function is exposed to ObjC")
+ put(EXPOSED_SUSPEND_FUNCTION_ERROR, "suspend function is exposed to ObjC")
+ put(IGNORED_COROUTINES, "NativeCoroutinesIgnore overrides NativeCoroutines")
+ put(IGNORED_COROUTINES_REFINED, "NativeCoroutinesIgnore overrides NativeCoroutinesRefined")
+ put(IGNORED_COROUTINES_REFINED_STATE, "NativeCoroutinesIgnore overrides NativeCoroutinesRefinedState")
+ put(IGNORED_COROUTINES_STATE, "NativeCoroutinesIgnore overrides NativeCoroutinesState")
+ put(INVALID_COROUTINES, "NativeCoroutines is only supported on suspend-functions and Flow declarations")
+ put(INVALID_COROUTINES_IGNORE, "NativeCoroutinesIgnore is only supported on suspend-functions and Flow declarations")
+ put(INVALID_COROUTINES_REFINED, "NativeCoroutinesRefined is only supported on suspend-functions and Flow declarations")
+ put(INVALID_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState is only supported on StateFlow properties")
+ put(INVALID_COROUTINES_STATE, "NativeCoroutinesState is only supported on StateFlow properties")
+ put(INVALID_COROUTINE_SCOPE, "NativeCoroutineScope is only supported on CoroutineScope properties")
+ put(REDUNDANT_OVERRIDE_COROUTINES, "NativeCoroutines should be applied to overridden declaration instead")
+ put(REDUNDANT_OVERRIDE_COROUTINES_IGNORE, "NativeCoroutinesIgnore isn't supported on overridden declarations")
+ put(REDUNDANT_OVERRIDE_COROUTINES_REFINED, "NativeCoroutinesRefined should be applied to overridden declaration instead")
+ put(REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState should be applied to overridden declaration instead")
+ put(REDUNDANT_OVERRIDE_COROUTINES_STATE, "NativeCoroutinesState should be applied to overridden declaration instead")
+ put(REDUNDANT_PRIVATE_COROUTINES, "NativeCoroutines is only supported on public declarations")
+ put(REDUNDANT_PRIVATE_COROUTINES_IGNORE, "NativeCoroutinesIgnore is only supported on public declarations")
+ put(REDUNDANT_PRIVATE_COROUTINES_REFINED, "NativeCoroutinesRefined is only supported on public declarations")
+ put(REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE, "NativeCoroutinesRefinedState is only supported on public declarations")
+ put(REDUNDANT_PRIVATE_COROUTINES_STATE, "NativeCoroutinesState is only supported on public declarations")
+ put(UNSUPPORTED_CLASS_EXTENSION_PROPERTY, "Class extension properties aren't supported")
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirKmpNativeCoroutinesDeclarationChecker.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirKmpNativeCoroutinesDeclarationChecker.kt
new file mode 100644
index 00000000..90cda341
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirKmpNativeCoroutinesDeclarationChecker.kt
@@ -0,0 +1,166 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics
+
+import com.rickclephas.kmp.nativecoroutines.compiler.config.ExposedSeverity
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.CONFLICT_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.IGNORED_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.IGNORED_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.INVALID_COROUTINE_SCOPE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesErrors.UNSUPPORTED_CLASS_EXTENSION_PROPERTY
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.utils.NativeCoroutinesAnnotations
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.utils.getCoroutinesReturnType
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.CoroutinesReturnType
+import org.jetbrains.kotlin.AbstractKtSourceElement
+import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
+import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
+import org.jetbrains.kotlin.diagnostics.reportOn
+import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
+import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirCallableDeclarationChecker
+import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
+import org.jetbrains.kotlin.fir.declarations.FirProperty
+import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
+import org.jetbrains.kotlin.fir.declarations.utils.effectiveVisibility
+import org.jetbrains.kotlin.fir.declarations.utils.isExtension
+import org.jetbrains.kotlin.fir.declarations.utils.isOverride
+import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
+import org.jetbrains.kotlin.fir.expressions.FirAnnotation
+
+internal class FirKmpNativeCoroutinesDeclarationChecker(
+ exposedSeverity: ExposedSeverity
+): FirCallableDeclarationChecker() {
+
+ private val exposedSuspendFunction = when (exposedSeverity) {
+ ExposedSeverity.NONE -> null
+ ExposedSeverity.WARNING -> EXPOSED_SUSPEND_FUNCTION
+ ExposedSeverity.ERROR -> EXPOSED_SUSPEND_FUNCTION_ERROR
+ }
+
+ private val exposedFlowType = when (exposedSeverity) {
+ ExposedSeverity.NONE -> null
+ ExposedSeverity.WARNING -> EXPOSED_FLOW_TYPE
+ ExposedSeverity.ERROR -> EXPOSED_FLOW_TYPE_ERROR
+ }
+
+ private val exposedStateFlowProperty = when (exposedSeverity) {
+ ExposedSeverity.NONE -> null
+ ExposedSeverity.WARNING -> EXPOSED_STATE_FLOW_PROPERTY
+ ExposedSeverity.ERROR -> EXPOSED_STATE_FLOW_PROPERTY_ERROR
+ }
+
+ override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
+ if (declaration !is FirSimpleFunction && declaration !is FirProperty) return
+
+ fun KtDiagnosticFactory0.reportOn(annotation: FirAnnotation?) {
+ if (annotation == null) return
+ reporter.reportOn(annotation.source, this, context)
+ }
+
+ fun KtDiagnosticFactory0?.reportOn(source: AbstractKtSourceElement?) {
+ if (this == null) return
+ reporter.reportOn(source, this, context)
+ }
+
+ val annotations = NativeCoroutinesAnnotations(declaration, context.session)
+ val isPublic = declaration.effectiveVisibility.publicApi
+ val isOverride = declaration.isOverride
+ val isSuspend = declaration.isSuspend
+ val returnType = declaration.getCoroutinesReturnType(context.session)
+
+ //region CONFLICT_COROUTINES
+ val coroutinesAnnotations = listOf(
+ annotations.nativeCoroutines,
+ annotations.nativeCoroutinesRefined,
+ annotations.nativeCoroutinesRefinedState,
+ annotations.nativeCoroutinesState,
+ )
+ val annotationCount = coroutinesAnnotations.count { it != null }
+ if (annotationCount > 1) {
+ coroutinesAnnotations.forEach { CONFLICT_COROUTINES.reportOn(it) }
+ }
+ //endregion
+
+ //region EXPOSED_*
+ if (isPublic && !isOverride && annotationCount == 0 && annotations.nativeCoroutinesIgnore == null) {
+ if (isSuspend) {
+ exposedSuspendFunction.reportOn(declaration.source)
+ }
+ if (returnType is CoroutinesReturnType.Flow) {
+ val diagnosticFactory = when {
+ declaration is FirProperty && returnType == CoroutinesReturnType.Flow.State -> exposedStateFlowProperty
+ else -> exposedFlowType
+ }
+ diagnosticFactory.reportOn(declaration.source)
+ }
+ }
+ //endregion
+
+ //region IGNORED_*
+ if (annotations.nativeCoroutinesIgnore != null) {
+ IGNORED_COROUTINES.reportOn(annotations.nativeCoroutines)
+ IGNORED_COROUTINES_REFINED.reportOn(annotations.nativeCoroutinesRefined)
+ IGNORED_COROUTINES_REFINED_STATE.reportOn(annotations.nativeCoroutinesRefinedState)
+ IGNORED_COROUTINES_STATE.reportOn(annotations.nativeCoroutinesState)
+ }
+ //endregion
+
+ //region INVALID_*
+ if (declaration !is FirProperty || returnType != CoroutinesReturnType.CoroutineScope) {
+ INVALID_COROUTINE_SCOPE.reportOn(annotations.nativeCoroutineScope)
+ }
+ if (!isSuspend && returnType !is CoroutinesReturnType.Flow) {
+ INVALID_COROUTINES.reportOn(annotations.nativeCoroutines)
+ INVALID_COROUTINES_IGNORE.reportOn(annotations.nativeCoroutinesIgnore)
+ INVALID_COROUTINES_REFINED.reportOn(annotations.nativeCoroutinesRefined)
+ }
+ if (declaration !is FirProperty || returnType !is CoroutinesReturnType.Flow.State) {
+ INVALID_COROUTINES_REFINED_STATE.reportOn(annotations.nativeCoroutinesRefinedState)
+ INVALID_COROUTINES_STATE.reportOn(annotations.nativeCoroutinesState)
+ }
+ //endregion
+
+ //region REDUNDANT_*
+ if (isOverride) {
+ REDUNDANT_OVERRIDE_COROUTINES.reportOn(annotations.nativeCoroutines)
+ REDUNDANT_OVERRIDE_COROUTINES_IGNORE.reportOn(annotations.nativeCoroutinesIgnore)
+ REDUNDANT_OVERRIDE_COROUTINES_REFINED.reportOn(annotations.nativeCoroutinesRefined)
+ REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE.reportOn(annotations.nativeCoroutinesRefinedState)
+ REDUNDANT_OVERRIDE_COROUTINES_STATE.reportOn(annotations.nativeCoroutinesState)
+ }
+ if (!isPublic) {
+ REDUNDANT_PRIVATE_COROUTINES.reportOn(annotations.nativeCoroutines)
+ REDUNDANT_PRIVATE_COROUTINES_IGNORE.reportOn(annotations.nativeCoroutinesIgnore)
+ REDUNDANT_PRIVATE_COROUTINES_REFINED.reportOn(annotations.nativeCoroutinesRefined)
+ REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE.reportOn(annotations.nativeCoroutinesRefinedState)
+ REDUNDANT_PRIVATE_COROUTINES_STATE.reportOn(annotations.nativeCoroutinesState)
+ }
+ //endregion
+
+ //region UNSUPPORTED_*
+ if (declaration is FirProperty && declaration.dispatchReceiverType != null && declaration.isExtension) {
+ coroutinesAnnotations.forEach { UNSUPPORTED_CLASS_EXTENSION_PROPERTY.reportOn(it) }
+ }
+ //endregion
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirKmpNativeCoroutinesErrors.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirKmpNativeCoroutinesErrors.kt
new file mode 100644
index 00000000..0766b3e7
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/diagnostics/FirKmpNativeCoroutinesErrors.kt
@@ -0,0 +1,43 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics
+
+import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactory0
+import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
+import org.jetbrains.kotlin.diagnostics.error0
+import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
+import org.jetbrains.kotlin.diagnostics.warning0
+import org.jetbrains.kotlin.psi.KtElement
+
+public object FirKmpNativeCoroutinesErrors {
+ public val CONFLICT_COROUTINES: KtDiagnosticFactory0 by error0()
+ public val EXPOSED_FLOW_TYPE: KtDiagnosticFactory0 by warning0(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
+ public val EXPOSED_FLOW_TYPE_ERROR: KtDiagnosticFactory0 by error0(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
+ public val EXPOSED_STATE_FLOW_PROPERTY: KtDiagnosticFactory0 by warning0(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
+ public val EXPOSED_STATE_FLOW_PROPERTY_ERROR: KtDiagnosticFactory0 by error0(SourceElementPositioningStrategies.DECLARATION_RETURN_TYPE)
+ public val EXPOSED_SUSPEND_FUNCTION: KtDiagnosticFactory0 by warning0(SourceElementPositioningStrategies.SUSPEND_MODIFIER)
+ public val EXPOSED_SUSPEND_FUNCTION_ERROR: KtDiagnosticFactory0 by error0(SourceElementPositioningStrategies.SUSPEND_MODIFIER)
+ public val IGNORED_COROUTINES: KtDiagnosticFactory0 by error0()
+ public val IGNORED_COROUTINES_REFINED: KtDiagnosticFactory0 by error0()
+ public val IGNORED_COROUTINES_REFINED_STATE: KtDiagnosticFactory0 by error0()
+ public val IGNORED_COROUTINES_STATE: KtDiagnosticFactory0 by error0()
+ public val INVALID_COROUTINES: KtDiagnosticFactory0 by error0()
+ public val INVALID_COROUTINES_IGNORE: KtDiagnosticFactory0 by error0()
+ public val INVALID_COROUTINES_REFINED: KtDiagnosticFactory0 by error0()
+ public val INVALID_COROUTINES_REFINED_STATE: KtDiagnosticFactory0 by error0()
+ public val INVALID_COROUTINES_STATE: KtDiagnosticFactory0 by error0()
+ public val INVALID_COROUTINE_SCOPE: KtDiagnosticFactory0 by error0()
+ public val REDUNDANT_OVERRIDE_COROUTINES: KtDiagnosticFactory0 by warning0()
+ public val REDUNDANT_OVERRIDE_COROUTINES_IGNORE: KtDiagnosticFactory0 by error0()
+ public val REDUNDANT_OVERRIDE_COROUTINES_REFINED: KtDiagnosticFactory0 by warning0()
+ public val REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE: KtDiagnosticFactory0 by warning0()
+ public val REDUNDANT_OVERRIDE_COROUTINES_STATE: KtDiagnosticFactory0 by warning0()
+ public val REDUNDANT_PRIVATE_COROUTINES: KtDiagnosticFactory0 by error0()
+ public val REDUNDANT_PRIVATE_COROUTINES_IGNORE: KtDiagnosticFactory0 by error0()
+ public val REDUNDANT_PRIVATE_COROUTINES_REFINED: KtDiagnosticFactory0 by error0()
+ public val REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE: KtDiagnosticFactory0 by error0()
+ public val REDUNDANT_PRIVATE_COROUTINES_STATE: KtDiagnosticFactory0 by error0()
+ public val UNSUPPORTED_CLASS_EXTENSION_PROPERTY: KtDiagnosticFactory0 by error0()
+
+ init {
+ RootDiagnosticRendererFactory.registerFactory(FirDefaultErrorMessages)
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/extensions/KmpNativeCoroutinesFirAdditionalCheckersExtension.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/extensions/KmpNativeCoroutinesFirAdditionalCheckersExtension.kt
new file mode 100644
index 00000000..e2258a52
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/extensions/KmpNativeCoroutinesFirAdditionalCheckersExtension.kt
@@ -0,0 +1,17 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.fir.extensions
+
+import com.rickclephas.kmp.nativecoroutines.compiler.config.ExposedSeverity
+import com.rickclephas.kmp.nativecoroutines.compiler.fir.diagnostics.FirKmpNativeCoroutinesDeclarationChecker
+import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
+import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
+
+internal class KmpNativeCoroutinesFirAdditionalCheckersExtension(
+ session: FirSession,
+ exposedSeverity: ExposedSeverity
+): FirAdditionalCheckersExtension(session) {
+
+ override val declarationCheckers: DeclarationCheckers = object : DeclarationCheckers() {
+ override val callableDeclarationCheckers = setOf(FirKmpNativeCoroutinesDeclarationChecker(exposedSeverity))
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/extensions/KmpNativeCoroutinesFirExtensionRegistrar.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/extensions/KmpNativeCoroutinesFirExtensionRegistrar.kt
new file mode 100644
index 00000000..21022a96
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/extensions/KmpNativeCoroutinesFirExtensionRegistrar.kt
@@ -0,0 +1,14 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.fir.extensions
+
+import com.rickclephas.kmp.nativecoroutines.compiler.config.EXPOSED_SEVERITY
+import com.rickclephas.kmp.nativecoroutines.compiler.config.get
+import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
+
+internal class KmpNativeCoroutinesFirExtensionRegistrar(
+ private val configuration: CompilerConfiguration
+): FirExtensionRegistrar() {
+ override fun ExtensionRegistrarContext.configurePlugin() {
+ +::KmpNativeCoroutinesFirAdditionalCheckersExtension.bind(configuration[EXPOSED_SEVERITY])
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/utils/CoroutinesReturnType.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/utils/CoroutinesReturnType.kt
new file mode 100644
index 00000000..1a2ef6fe
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/utils/CoroutinesReturnType.kt
@@ -0,0 +1,23 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.fir.utils
+
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.CoroutinesClassIds
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.CoroutinesReturnType
+import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.analysis.checkers.toClassLikeSymbol
+import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
+import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
+import org.jetbrains.kotlin.fir.resolve.isSubclassOf
+import org.jetbrains.kotlin.fir.types.toLookupTag
+
+internal fun FirCallableDeclaration.getCoroutinesReturnType(session: FirSession): CoroutinesReturnType? {
+ val symbol = returnTypeRef.toClassLikeSymbol(session)?.fullyExpandedClass(session) ?: return null
+ return coroutinesReturnTypes.firstNotNullOfOrNull { (lookupTag, returnType) ->
+ returnType.takeIf { symbol.isSubclassOf(lookupTag, session, isStrict = false, lookupInterfaces = true) }
+ }
+}
+
+private val coroutinesReturnTypes = mapOf(
+ CoroutinesClassIds.stateFlow.toLookupTag() to CoroutinesReturnType.Flow.State,
+ CoroutinesClassIds.flow.toLookupTag() to CoroutinesReturnType.Flow.Generic,
+ CoroutinesClassIds.coroutineScope.toLookupTag() to CoroutinesReturnType.CoroutineScope,
+)
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/utils/NativeCoroutinesAnnotations.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/utils/NativeCoroutinesAnnotations.kt
new file mode 100644
index 00000000..f35628a3
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/fir/utils/NativeCoroutinesAnnotations.kt
@@ -0,0 +1,18 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.fir.utils
+
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.NativeCoroutinesClassIds as ClassIds
+import org.jetbrains.kotlin.fir.FirSession
+import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
+import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
+
+internal class NativeCoroutinesAnnotations(
+ declaration: FirCallableDeclaration,
+ session: FirSession
+) {
+ val nativeCoroutines = declaration.getAnnotationByClassId(ClassIds.nativeCoroutines, session)
+ val nativeCoroutineScope = declaration.getAnnotationByClassId(ClassIds.nativeCoroutineScope, session)
+ val nativeCoroutinesIgnore = declaration.getAnnotationByClassId(ClassIds.nativeCoroutinesIgnore, session)
+ val nativeCoroutinesRefined = declaration.getAnnotationByClassId(ClassIds.nativeCoroutinesRefined, session)
+ val nativeCoroutinesRefinedState = declaration.getAnnotationByClassId(ClassIds.nativeCoroutinesRefinedState, session)
+ val nativeCoroutinesState = declaration.getAnnotationByClassId(ClassIds.nativeCoroutinesState, session)
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutineScope.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutineScope.kt
deleted file mode 100644
index 38ef2986..00000000
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutineScope.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.rickclephas.kmp.nativecoroutines.compiler.utils
-
-import org.jetbrains.kotlin.descriptors.ModuleDescriptor
-import org.jetbrains.kotlin.descriptors.findClassifierAcrossModuleDependencies
-import org.jetbrains.kotlin.name.ClassId
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.types.TypeConstructor
-
-private val coroutineScopeFqName = FqName("kotlinx.coroutines.CoroutineScope")
-private val coroutineScopeClassId = ClassId.topLevel(coroutineScopeFqName)
-
-internal fun ModuleDescriptor.findCoroutineScopeConstructor(): TypeConstructor =
- findClassifierAcrossModuleDependencies(coroutineScopeClassId)?.typeConstructor
- ?: throw NoSuchElementException("Couldn't find CoroutineScope constructor")
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesClassIds.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesClassIds.kt
new file mode 100644
index 00000000..fe3c1b5f
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesClassIds.kt
@@ -0,0 +1,10 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.utils
+
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.CoroutinesFqNames as FqNames
+import org.jetbrains.kotlin.name.ClassId
+
+internal object CoroutinesClassIds {
+ val coroutineScope: ClassId = ClassId.topLevel(FqNames.coroutineScope)
+ val flow: ClassId = ClassId.topLevel(FqNames.flow)
+ val stateFlow: ClassId = ClassId.topLevel(FqNames.stateFlow)
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesFqNames.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesFqNames.kt
new file mode 100644
index 00000000..374f47a5
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesFqNames.kt
@@ -0,0 +1,9 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.utils
+
+import org.jetbrains.kotlin.name.FqName
+
+internal object CoroutinesFqNames {
+ val coroutineScope: FqName = FqName("kotlinx.coroutines.CoroutineScope")
+ val flow: FqName = FqName("kotlinx.coroutines.flow.Flow")
+ val stateFlow: FqName = FqName("kotlinx.coroutines.flow.StateFlow")
+}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesReturnType.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesReturnType.kt
index 05385b4c..08cf4806 100644
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesReturnType.kt
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/CoroutinesReturnType.kt
@@ -1,10 +1,5 @@
package com.rickclephas.kmp.nativecoroutines.compiler.utils
-import org.jetbrains.kotlin.descriptors.CallableDescriptor
-import org.jetbrains.kotlin.resolve.calls.inference.returnTypeOrNothing
-import org.jetbrains.kotlin.resolve.descriptorUtil.module
-import org.jetbrains.kotlin.types.typeUtil.supertypes
-
internal sealed class CoroutinesReturnType private constructor() {
data object CoroutineScope: CoroutinesReturnType()
sealed class Flow private constructor(): CoroutinesReturnType() {
@@ -12,19 +7,3 @@ internal sealed class CoroutinesReturnType private constructor() {
data object State: Flow()
}
}
-
-internal val CallableDescriptor.coroutinesReturnType: CoroutinesReturnType? get() {
- val returnType = returnTypeOrNothing
- val stateFlowConstructor = module.findStateFlowConstructor()
- if (returnType.constructor == stateFlowConstructor) return CoroutinesReturnType.Flow.State
- val flowConstructor = module.findFlowConstructor()
- if (returnType.constructor == flowConstructor) return CoroutinesReturnType.Flow.Generic
- val coroutineScopeConstructor = module.findCoroutineScopeConstructor()
- if (returnType.constructor == coroutineScopeConstructor) return CoroutinesReturnType.CoroutineScope
- returnType.supertypes().forEach {
- if (it.constructor == stateFlowConstructor) return CoroutinesReturnType.Flow.State
- if (it.constructor == flowConstructor) return CoroutinesReturnType.Flow.Generic
- if (it.constructor == coroutineScopeConstructor) return CoroutinesReturnType.CoroutineScope
- }
- return null
-}
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/Flow.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/Flow.kt
deleted file mode 100644
index 3f5050b5..00000000
--- a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/Flow.kt
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.rickclephas.kmp.nativecoroutines.compiler.utils
-
-import org.jetbrains.kotlin.descriptors.ModuleDescriptor
-import org.jetbrains.kotlin.descriptors.findClassifierAcrossModuleDependencies
-import org.jetbrains.kotlin.name.ClassId
-import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.types.TypeConstructor
-
-private val flowFqName = FqName("kotlinx.coroutines.flow.Flow")
-private val flowClassId = ClassId.topLevel(flowFqName)
-
-internal fun ModuleDescriptor.findFlowConstructor(): TypeConstructor =
- findClassifierAcrossModuleDependencies(flowClassId)?.typeConstructor
- ?: throw NoSuchElementException("Couldn't find Flow constructor")
-
-
-private val stateFlowFqName = FqName("kotlinx.coroutines.flow.StateFlow")
-private val stateFlowClassId = ClassId.topLevel(stateFlowFqName)
-
-internal fun ModuleDescriptor.findStateFlowConstructor(): TypeConstructor =
- findClassifierAcrossModuleDependencies(stateFlowClassId)?.typeConstructor
- ?: throw NoSuchElementException("Couldn't find StateFlow constructor")
diff --git a/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/NativeCoroutinesClassIds.kt b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/NativeCoroutinesClassIds.kt
new file mode 100644
index 00000000..df80b15e
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/utils/NativeCoroutinesClassIds.kt
@@ -0,0 +1,13 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.utils
+
+import com.rickclephas.kmp.nativecoroutines.compiler.utils.NativeCoroutinesFqNames as FqNames
+import org.jetbrains.kotlin.name.ClassId
+
+public object NativeCoroutinesClassIds {
+ public val nativeCoroutines: ClassId = ClassId.topLevel(FqNames.nativeCoroutines)
+ public val nativeCoroutineScope: ClassId = ClassId.topLevel(FqNames.nativeCoroutineScope)
+ public val nativeCoroutinesIgnore: ClassId = ClassId.topLevel(FqNames.nativeCoroutinesIgnore)
+ public val nativeCoroutinesRefined: ClassId = ClassId.topLevel(FqNames.nativeCoroutinesRefined)
+ public val nativeCoroutinesRefinedState: ClassId = ClassId.topLevel(FqNames.nativeCoroutinesRefinedState)
+ public val nativeCoroutinesState: ClassId = ClassId.topLevel(FqNames.nativeCoroutinesState)
+}
diff --git a/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/ClassicDiagnosticsTestGenerated.java b/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/ClassicDiagnosticsTestGenerated.java
new file mode 100644
index 00000000..b0fcb95c
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/ClassicDiagnosticsTestGenerated.java
@@ -0,0 +1,77 @@
+
+
+package com.rickclephas.kmp.nativecoroutines.compiler.runners;
+
+import com.intellij.testFramework.TestDataPath;
+import org.jetbrains.kotlin.test.util.KtTestUtil;
+import org.jetbrains.kotlin.test.TestMetadata;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.util.regex.Pattern;
+
+/** This class is generated by {@link com.rickclephas.kmp.nativecoroutines.compiler.GenerateTestsKt}. DO NOT MODIFY MANUALLY */
+@SuppressWarnings("all")
+@TestMetadata("src/testData/diagnostics")
+@TestDataPath("$PROJECT_ROOT")
+public class ClassicDiagnosticsTestGenerated extends AbstractClassicDiagnosticsTest {
+ @Test
+ public void testAllFilesPresentInDiagnostics() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("src/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true);
+ }
+
+ @Test
+ @TestMetadata("conflict.kt")
+ public void testConflict() throws Exception {
+ runTest("src/testData/diagnostics/conflict.kt");
+ }
+
+ @Test
+ @TestMetadata("exposedAnnotated.kt")
+ public void testExposedAnnotated() throws Exception {
+ runTest("src/testData/diagnostics/exposedAnnotated.kt");
+ }
+
+ @Test
+ @TestMetadata("exposedError.kt")
+ public void testExposedError() throws Exception {
+ runTest("src/testData/diagnostics/exposedError.kt");
+ }
+
+ @Test
+ @TestMetadata("exposedNone.kt")
+ public void testExposedNone() throws Exception {
+ runTest("src/testData/diagnostics/exposedNone.kt");
+ }
+
+ @Test
+ @TestMetadata("exposedWarning.kt")
+ public void testExposedWarning() throws Exception {
+ runTest("src/testData/diagnostics/exposedWarning.kt");
+ }
+
+ @Test
+ @TestMetadata("ignored.kt")
+ public void testIgnored() throws Exception {
+ runTest("src/testData/diagnostics/ignored.kt");
+ }
+
+ @Test
+ @TestMetadata("invalid.kt")
+ public void testInvalid() throws Exception {
+ runTest("src/testData/diagnostics/invalid.kt");
+ }
+
+ @Test
+ @TestMetadata("redundant.kt")
+ public void testRedundant() throws Exception {
+ runTest("src/testData/diagnostics/redundant.kt");
+ }
+
+ @Test
+ @TestMetadata("unsupported.kt")
+ public void testUnsupported() throws Exception {
+ runTest("src/testData/diagnostics/unsupported.kt");
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/FirLightTreeDiagnosticsTestGenerated.java b/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/FirLightTreeDiagnosticsTestGenerated.java
new file mode 100644
index 00000000..bf59d892
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/FirLightTreeDiagnosticsTestGenerated.java
@@ -0,0 +1,77 @@
+
+
+package com.rickclephas.kmp.nativecoroutines.compiler.runners;
+
+import com.intellij.testFramework.TestDataPath;
+import org.jetbrains.kotlin.test.util.KtTestUtil;
+import org.jetbrains.kotlin.test.TestMetadata;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.util.regex.Pattern;
+
+/** This class is generated by {@link com.rickclephas.kmp.nativecoroutines.compiler.GenerateTestsKt}. DO NOT MODIFY MANUALLY */
+@SuppressWarnings("all")
+@TestMetadata("src/testData/diagnostics")
+@TestDataPath("$PROJECT_ROOT")
+public class FirLightTreeDiagnosticsTestGenerated extends AbstractFirLightTreeDiagnosticsTest {
+ @Test
+ public void testAllFilesPresentInDiagnostics() throws Exception {
+ KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("src/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true);
+ }
+
+ @Test
+ @TestMetadata("conflict.kt")
+ public void testConflict() throws Exception {
+ runTest("src/testData/diagnostics/conflict.kt");
+ }
+
+ @Test
+ @TestMetadata("exposedAnnotated.kt")
+ public void testExposedAnnotated() throws Exception {
+ runTest("src/testData/diagnostics/exposedAnnotated.kt");
+ }
+
+ @Test
+ @TestMetadata("exposedError.kt")
+ public void testExposedError() throws Exception {
+ runTest("src/testData/diagnostics/exposedError.kt");
+ }
+
+ @Test
+ @TestMetadata("exposedNone.kt")
+ public void testExposedNone() throws Exception {
+ runTest("src/testData/diagnostics/exposedNone.kt");
+ }
+
+ @Test
+ @TestMetadata("exposedWarning.kt")
+ public void testExposedWarning() throws Exception {
+ runTest("src/testData/diagnostics/exposedWarning.kt");
+ }
+
+ @Test
+ @TestMetadata("ignored.kt")
+ public void testIgnored() throws Exception {
+ runTest("src/testData/diagnostics/ignored.kt");
+ }
+
+ @Test
+ @TestMetadata("invalid.kt")
+ public void testInvalid() throws Exception {
+ runTest("src/testData/diagnostics/invalid.kt");
+ }
+
+ @Test
+ @TestMetadata("redundant.kt")
+ public void testRedundant() throws Exception {
+ runTest("src/testData/diagnostics/redundant.kt");
+ }
+
+ @Test
+ @TestMetadata("unsupported.kt")
+ public void testUnsupported() throws Exception {
+ runTest("src/testData/diagnostics/unsupported.kt");
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/DiagnosticsTestGenerated.java b/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/FirPsiDiagnosticsTestGenerated.java
similarity index 89%
rename from kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/DiagnosticsTestGenerated.java
rename to kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/FirPsiDiagnosticsTestGenerated.java
index dd9298ee..8e789f92 100644
--- a/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/DiagnosticsTestGenerated.java
+++ b/kmp-nativecoroutines-compiler/src/test/generated/com/rickclephas/kmp/nativecoroutines/compiler/runners/FirPsiDiagnosticsTestGenerated.java
@@ -15,7 +15,7 @@
@SuppressWarnings("all")
@TestMetadata("src/testData/diagnostics")
@TestDataPath("$PROJECT_ROOT")
-public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
+public class FirPsiDiagnosticsTestGenerated extends AbstractFirPsiDiagnosticsTest {
@Test
public void testAllFilesPresentInDiagnostics() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("src/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true);
@@ -68,4 +68,10 @@ public void testInvalid() throws Exception {
public void testRedundant() throws Exception {
runTest("src/testData/diagnostics/redundant.kt");
}
+
+ @Test
+ @TestMetadata("unsupported.kt")
+ public void testUnsupported() throws Exception {
+ runTest("src/testData/diagnostics/unsupported.kt");
+ }
}
diff --git a/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/GenerateTests.kt b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/GenerateTests.kt
index 8c712acc..27b05b03 100644
--- a/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/GenerateTests.kt
+++ b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/GenerateTests.kt
@@ -1,12 +1,20 @@
package com.rickclephas.kmp.nativecoroutines.compiler
-import com.rickclephas.kmp.nativecoroutines.compiler.runners.AbstractDiagnosticsTest
+import com.rickclephas.kmp.nativecoroutines.compiler.runners.AbstractClassicDiagnosticsTest
+import com.rickclephas.kmp.nativecoroutines.compiler.runners.AbstractFirLightTreeDiagnosticsTest
+import com.rickclephas.kmp.nativecoroutines.compiler.runners.AbstractFirPsiDiagnosticsTest
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
fun main() {
generateTestGroupSuiteWithJUnit5 {
testGroup(testDataRoot = "src/testData", testsRoot = "src/test/generated") {
- testClass {
+ testClass {
+ model("diagnostics")
+ }
+ testClass {
+ model("diagnostics")
+ }
+ testClass {
model("diagnostics")
}
}
diff --git a/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractBaseDiagnosticsTest.kt b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractBaseDiagnosticsTest.kt
new file mode 100644
index 00000000..4d906c20
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractBaseDiagnosticsTest.kt
@@ -0,0 +1,32 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.runners
+
+import org.jetbrains.kotlin.platform.konan.NativePlatforms
+import org.jetbrains.kotlin.test.Constructor
+import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
+import org.jetbrains.kotlin.test.directives.ConfigurationDirectives
+import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor
+import org.jetbrains.kotlin.test.model.*
+import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
+import org.jetbrains.kotlin.test.services.configuration.NativeEnvironmentConfigurator
+
+abstract class AbstractBaseDiagnosticsTest>: AbstractKmpNativeCoroutinesTest() {
+ abstract val targetFrontend: FrontendKind
+ abstract val frontend: Constructor>
+ abstract fun TestConfigurationBuilder.handlersSetup()
+
+ final override fun TestConfigurationBuilder.configuration() {
+ globalDefaults {
+ frontend = targetFrontend
+ targetPlatform = NativePlatforms.unspecifiedNativePlatform
+ dependencyKind = DependencyKind.Source
+ }
+ defaultDirectives {
+ +ConfigurationDirectives.WITH_STDLIB
+ }
+ enableMetaInfoHandler()
+ useConfigurators(::CommonEnvironmentConfigurator, ::NativeEnvironmentConfigurator)
+ useMetaInfoProcessors(::OldNewInferenceMetaInfoProcessor)
+ facadeStep(frontend)
+ handlersSetup()
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractClassicDiagnosticsTest.kt b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractClassicDiagnosticsTest.kt
new file mode 100644
index 00000000..8337a803
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractClassicDiagnosticsTest.kt
@@ -0,0 +1,19 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.runners
+
+import org.jetbrains.kotlin.test.Constructor
+import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
+import org.jetbrains.kotlin.test.builders.classicFrontendHandlersStep
+import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
+import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendOutputArtifact
+import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticsHandler
+import org.jetbrains.kotlin.test.model.*
+
+abstract class AbstractClassicDiagnosticsTest: AbstractBaseDiagnosticsTest() {
+ final override val targetFrontend: FrontendKind
+ get() = FrontendKinds.ClassicFrontend
+ final override val frontend: Constructor>
+ get() = ::ClassicFrontendFacade
+ final override fun TestConfigurationBuilder.handlersSetup() = classicFrontendHandlersStep {
+ useHandlers(::ClassicDiagnosticsHandler)
+ }
+}
diff --git a/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractDiagnosticsTest.kt b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractDiagnosticsTest.kt
deleted file mode 100644
index 00e62184..00000000
--- a/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractDiagnosticsTest.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.rickclephas.kmp.nativecoroutines.compiler.runners
-
-import org.jetbrains.kotlin.platform.konan.NativePlatforms
-import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
-import org.jetbrains.kotlin.test.builders.classicFrontendHandlersStep
-import org.jetbrains.kotlin.test.frontend.classic.ClassicFrontendFacade
-import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticsHandler
-import org.jetbrains.kotlin.test.frontend.classic.handlers.OldNewInferenceMetaInfoProcessor
-import org.jetbrains.kotlin.test.model.DependencyKind
-import org.jetbrains.kotlin.test.model.FrontendKinds
-import org.jetbrains.kotlin.test.services.configuration.CommonEnvironmentConfigurator
-
-abstract class AbstractDiagnosticsTest: AbstractKmpNativeCoroutinesTest() {
-
- override fun TestConfigurationBuilder.configuration() {
- globalDefaults {
- frontend = FrontendKinds.ClassicFrontend
- targetPlatform = NativePlatforms.unspecifiedNativePlatform
- dependencyKind = DependencyKind.Source
- }
- enableMetaInfoHandler()
- useConfigurators(::CommonEnvironmentConfigurator)
- useMetaInfoProcessors(::OldNewInferenceMetaInfoProcessor)
- facadeStep(::ClassicFrontendFacade)
- classicFrontendHandlersStep {
- useHandlers(::ClassicDiagnosticsHandler)
- }
- }
-}
diff --git a/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractFirDiagnosticsTest.kt b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractFirDiagnosticsTest.kt
new file mode 100644
index 00000000..6013ff1e
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/compiler/runners/AbstractFirDiagnosticsTest.kt
@@ -0,0 +1,40 @@
+package com.rickclephas.kmp.nativecoroutines.compiler.runners
+
+import org.jetbrains.kotlin.test.Constructor
+import org.jetbrains.kotlin.test.FirParser
+import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
+import org.jetbrains.kotlin.test.builders.firHandlersStep
+import org.jetbrains.kotlin.test.directives.configureFirParser
+import org.jetbrains.kotlin.test.frontend.fir.FirFrontendFacade
+import org.jetbrains.kotlin.test.frontend.fir.FirOutputArtifact
+import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticsHandler
+import org.jetbrains.kotlin.test.frontend.fir.handlers.FirResolvedTypesVerifier
+import org.jetbrains.kotlin.test.model.*
+import org.jetbrains.kotlin.test.runners.configurationForClassicAndFirTestsAlongside
+import org.jetbrains.kotlin.test.runners.enableLazyResolvePhaseChecking
+
+abstract class AbstractFirBaseDiagnosticsTest(
+ private val parser: FirParser
+): AbstractBaseDiagnosticsTest() {
+ final override val targetFrontend: FrontendKind
+ get() = FrontendKinds.FIR
+ final override val frontend: Constructor>
+ get() = ::FirFrontendFacade
+ final override fun TestConfigurationBuilder.handlersSetup() = firHandlersStep {
+ useHandlers(::FirDiagnosticsHandler, ::FirResolvedTypesVerifier)
+ }
+
+ override fun configure(builder: TestConfigurationBuilder) {
+ super.configure(builder)
+ with(builder) {
+ configureFirParser(parser)
+ enableLazyResolvePhaseChecking()
+ forTestsMatching("testData/diagnostics/*") {
+ configurationForClassicAndFirTestsAlongside()
+ }
+ }
+ }
+}
+
+abstract class AbstractFirPsiDiagnosticsTest: AbstractFirBaseDiagnosticsTest(FirParser.Psi)
+abstract class AbstractFirLightTreeDiagnosticsTest: AbstractFirBaseDiagnosticsTest(FirParser.LightTree)
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/conflict.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/conflict.kt
index 7944639d..d68d8511 100644
--- a/kmp-nativecoroutines-compiler/src/testData/diagnostics/conflict.kt
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/conflict.kt
@@ -1,3 +1,5 @@
+// FIR_IDENTICAL
+
import com.rickclephas.kmp.nativecoroutines.NativeCoroutines
import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesRefined
import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesRefinedState
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedAnnotated.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedAnnotated.kt
index 4a5eba6f..d589efb7 100644
--- a/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedAnnotated.kt
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedAnnotated.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// EXPOSED_SEVERITY: WARNING
// FILE: customFlow.kt
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedError.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedError.kt
index 24b6916d..048e3eca 100644
--- a/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedError.kt
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedError.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// EXPOSED_SEVERITY: ERROR
// FILE: customFlows.kt
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedNone.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedNone.kt
index 276f0fbb..6951a7f1 100644
--- a/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedNone.kt
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedNone.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// EXPOSED_SEVERITY: NONE
// FILE: customFlows.kt
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedWarning.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedWarning.kt
index f287a88a..297eace6 100644
--- a/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedWarning.kt
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/exposedWarning.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// EXPOSED_SEVERITY: WARNING
// FILE: customFlows.kt
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/ignored.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/ignored.kt
index 6c4983d6..f60d2dca 100644
--- a/kmp-nativecoroutines-compiler/src/testData/diagnostics/ignored.kt
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/ignored.kt
@@ -1,3 +1,5 @@
+// FIR_IDENTICAL
+
import com.rickclephas.kmp.nativecoroutines.NativeCoroutines
import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesIgnore
import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesRefined
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/invalid.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/invalid.kt
index 95cea7e0..fc6edc81 100644
--- a/kmp-nativecoroutines-compiler/src/testData/diagnostics/invalid.kt
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/invalid.kt
@@ -1,3 +1,4 @@
+// FIR_IDENTICAL
// FILE: customStateFlow.kt
import kotlinx.coroutines.flow.StateFlow
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/redundant.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/redundant.kt
index 5c8aad6a..c865cb2d 100644
--- a/kmp-nativecoroutines-compiler/src/testData/diagnostics/redundant.kt
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/redundant.kt
@@ -1,3 +1,5 @@
+// FIR_IDENTICAL
+
import com.rickclephas.kmp.nativecoroutines.NativeCoroutines
import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesIgnore
import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesRefined
diff --git a/kmp-nativecoroutines-compiler/src/testData/diagnostics/unsupported.kt b/kmp-nativecoroutines-compiler/src/testData/diagnostics/unsupported.kt
new file mode 100644
index 00000000..f041b9df
--- /dev/null
+++ b/kmp-nativecoroutines-compiler/src/testData/diagnostics/unsupported.kt
@@ -0,0 +1,26 @@
+// FIR_IDENTICAL
+
+import com.rickclephas.kmp.nativecoroutines.NativeCoroutines
+import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesIgnore
+import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesRefined
+import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesRefinedState
+import com.rickclephas.kmp.nativecoroutines.NativeCoroutinesState
+import kotlinx.coroutines.flow.StateFlow
+
+class TestClass {
+
+ @NativeCoroutines
+ val Int.extensionPropertyA: StateFlow get() = throw Throwable()
+
+ @NativeCoroutinesIgnore
+ val Int.extensionPropertyE: StateFlow get() = throw Throwable()
+
+ @NativeCoroutinesRefined
+ val Int.extensionPropertyB: StateFlow get() = throw Throwable()
+
+ @NativeCoroutinesRefinedState
+ val Int.extensionPropertyC: StateFlow get() = throw Throwable()
+
+ @NativeCoroutinesState
+ val Int.extensionPropertyD: StateFlow get() = throw Throwable()
+}
diff --git a/kmp-nativecoroutines-core/build.gradle.kts b/kmp-nativecoroutines-core/build.gradle.kts
index 5d5654e6..923a32e5 100644
--- a/kmp-nativecoroutines-core/build.gradle.kts
+++ b/kmp-nativecoroutines-core/build.gradle.kts
@@ -1,3 +1,5 @@
+import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
+
plugins {
alias(libs.plugins.kotlin.multiplatform)
`kmp-nativecoroutines-publish`
@@ -7,19 +9,28 @@ kotlin {
explicitApi()
jvmToolchain(11)
- val macosX64 = macosX64()
- val macosArm64 = macosArm64()
- val iosArm64 = iosArm64()
- val iosX64 = iosX64()
- val iosSimulatorArm64 = iosSimulatorArm64()
- val watchosArm32 = watchosArm32()
- val watchosArm64 = watchosArm64()
- val watchosX64 = watchosX64()
- val watchosSimulatorArm64 = watchosSimulatorArm64()
- val watchosDeviceArm64 = watchosDeviceArm64()
- val tvosArm64 = tvosArm64()
- val tvosX64 = tvosX64()
- val tvosSimulatorArm64 = tvosSimulatorArm64()
+ @OptIn(ExperimentalKotlinGradlePluginApi::class)
+ applyDefaultHierarchyTemplate {
+ common {
+ group("nativeCoroutines") {
+ group("apple")
+ }
+ }
+ }
+
+ macosX64()
+ macosArm64()
+ iosArm64()
+ iosX64()
+ iosSimulatorArm64()
+ watchosArm32()
+ watchosArm64()
+ watchosX64()
+ watchosSimulatorArm64()
+ watchosDeviceArm64()
+ tvosArm64()
+ tvosX64()
+ tvosSimulatorArm64()
jvm()
js {
browser()
@@ -28,42 +39,26 @@ kotlin {
linuxArm64()
linuxX64()
mingwX64()
+
+ targets.all {
+ compilations.all {
+ compilerOptions.configure {
+ freeCompilerArgs.add("-Xexpect-actual-classes")
+ }
+ }
+ }
+
sourceSets {
- val commonMain by getting {
+ commonMain {
dependencies {
api(libs.kotlinx.coroutines.core)
}
}
- val commonTest by getting {
+ commonTest {
dependencies {
implementation(libs.kotlin.test)
implementation(libs.kotlinx.coroutines.test)
}
}
- val nativeCoroutinesMain by creating {
- dependsOn(commonMain)
- }
- val nativeCoroutinesTest by creating {
- dependsOn(commonTest)
- }
- val appleMain by creating {
- dependsOn(nativeCoroutinesMain)
- }
- val appleTest by creating {
- dependsOn(nativeCoroutinesTest)
- }
- listOf(
- macosX64, macosArm64,
- iosArm64, iosX64, iosSimulatorArm64,
- watchosArm32, watchosArm64, watchosX64, watchosSimulatorArm64, watchosDeviceArm64,
- tvosArm64, tvosX64, tvosSimulatorArm64
- ).forEach {
- getByName("${it.targetName}Main") {
- dependsOn(appleMain)
- }
- getByName("${it.targetName}Test") {
- dependsOn(appleTest)
- }
- }
}
}
diff --git a/kmp-nativecoroutines-idea-plugin/build.gradle.kts b/kmp-nativecoroutines-idea-plugin/build.gradle.kts
index b56c18e1..699f106a 100644
--- a/kmp-nativecoroutines-idea-plugin/build.gradle.kts
+++ b/kmp-nativecoroutines-idea-plugin/build.gradle.kts
@@ -39,6 +39,9 @@ tasks {
publishPlugin {
token = System.getenv("IDEA_PUBLISH_TOKEN")
+ if ((version as String).contains("-kotlin-")) {
+ channels = listOf("eap")
+ }
}
runIde {
diff --git a/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/compiler/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt b/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/compiler/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt
index 5bf917ea..c98f2db3 100644
--- a/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/compiler/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt
+++ b/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/compiler/extensions/KmpNativeCoroutinesStorageComponentContainerContributor.kt
@@ -2,7 +2,7 @@ package com.rickclephas.kmp.nativecoroutines.idea.compiler.extensions
import com.rickclephas.kmp.nativecoroutines.compiler.config.ConfigOption
import com.rickclephas.kmp.nativecoroutines.compiler.config.EXPOSED_SEVERITY
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesChecker
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesChecker
import org.jetbrains.kotlin.analyzer.moduleInfo
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useInstance
diff --git a/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/quickfixes/AddAnnotationFixFactory.kt b/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/quickfixes/AddAnnotationFixFactory.kt
index b16baecc..679a47e6 100644
--- a/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/quickfixes/AddAnnotationFixFactory.kt
+++ b/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/quickfixes/AddAnnotationFixFactory.kt
@@ -3,7 +3,6 @@ package com.rickclephas.kmp.nativecoroutines.idea.quickfixes
import com.intellij.codeInsight.intention.HighPriorityAction
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.LowPriorityAction
-import com.intellij.psi.PsiElement
import com.intellij.psi.util.findParentOfType
import com.rickclephas.kmp.nativecoroutines.compiler.utils.NativeCoroutinesFqNames
import org.jetbrains.kotlin.diagnostics.Diagnostic
@@ -13,17 +12,18 @@ import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionsFactory
import org.jetbrains.kotlin.idea.quickfix.QuickFixes
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtCallableDeclaration
+import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtModifierListOwner
internal class AddAnnotationFixFactory(
- private val diagnosticFactories: List>,
+ private val diagnosticFactories: List>,
private val preferredFqName: FqName,
private val alternativeFqName: FqName?
): KotlinIntentionActionsFactory() {
internal companion object {
fun QuickFixes.registerAddAnnotationFix(
- diagnosticFactories: List>,
+ diagnosticFactories: List>,
preferredFqName: FqName,
alternativeFqName: FqName? = null
) {
diff --git a/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/quickfixes/KmpNativeCoroutinesQuickFixContributor.kt b/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/quickfixes/KmpNativeCoroutinesQuickFixContributor.kt
index 9678b5b3..a94ad397 100644
--- a/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/quickfixes/KmpNativeCoroutinesQuickFixContributor.kt
+++ b/kmp-nativecoroutines-idea-plugin/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/idea/quickfixes/KmpNativeCoroutinesQuickFixContributor.kt
@@ -1,32 +1,32 @@
package com.rickclephas.kmp.nativecoroutines.idea.quickfixes
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.CONFLICT_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION_ERROR
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINE_SCOPE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_IGNORE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE
-import com.rickclephas.kmp.nativecoroutines.compiler.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.CONFLICT_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_FLOW_TYPE_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_STATE_FLOW_PROPERTY_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.EXPOSED_SUSPEND_FUNCTION_ERROR
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.IGNORED_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.INVALID_COROUTINE_SCOPE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_OVERRIDE_COROUTINES_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_IGNORE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_REFINED_STATE
+import com.rickclephas.kmp.nativecoroutines.compiler.classic.diagnostics.KmpNativeCoroutinesErrors.REDUNDANT_PRIVATE_COROUTINES_STATE
import com.rickclephas.kmp.nativecoroutines.idea.quickfixes.AddAnnotationFixFactory.Companion.registerAddAnnotationFix
import com.rickclephas.kmp.nativecoroutines.idea.quickfixes.RemoveAnnotationFixFactory.Companion.registerRemoveAnnotationFix
import com.rickclephas.kmp.nativecoroutines.compiler.utils.NativeCoroutinesFqNames as FqNames
diff --git a/kmp-nativecoroutines-ksp/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/ksp/NativeCoroutinesPropertySpecs.kt b/kmp-nativecoroutines-ksp/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/ksp/NativeCoroutinesPropertySpecs.kt
index 86d19783..44961483 100644
--- a/kmp-nativecoroutines-ksp/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/ksp/NativeCoroutinesPropertySpecs.kt
+++ b/kmp-nativecoroutines-ksp/src/main/kotlin/com/rickclephas/kmp/nativecoroutines/ksp/NativeCoroutinesPropertySpecs.kt
@@ -14,27 +14,27 @@ internal fun KSPropertyDeclaration.toNativeCoroutinesPropertySpecs(
): List? {
val typeParameterResolver = getTypeParameterResolver()
val type = type.getReturnType(typeParameterResolver) ?: return null
- if (type !is ReturnType.Flow) error("Only Flow properties are supported")
+ if (type !is ReturnType.Flow) return emptyList() // Only Flow properties are supported
return buildList {
val flowSuffix = if (asState) options.stateFlowSuffix else options.suffix
if (flowSuffix != null)
- add(toNativeCoroutinesPropertySpec(scopeProperty, flowSuffix, !asState, typeParameterResolver, type, shouldRefine))
+ toPropertySpec(scopeProperty, flowSuffix, !asState, typeParameterResolver, type, shouldRefine)?.let(::add)
val valueSuffix = if (asState) options.stateSuffix else options.flowValueSuffix
if (type is ReturnType.Flow.State && valueSuffix != null)
- add(toNativeCoroutinesValuePropertySpec(valueSuffix, asState, typeParameterResolver, type, shouldRefine))
+ toValuePropertySpec(valueSuffix, asState, typeParameterResolver, type, shouldRefine)?.let(::add)
if (type is ReturnType.Flow.Shared && options.flowReplayCacheSuffix != null)
- add(toNativeCoroutinesReplayCachePropertySpec(options.flowReplayCacheSuffix, typeParameterResolver, type, shouldRefine))
+ toReplayCachePropertySpec(options.flowReplayCacheSuffix, typeParameterResolver, type, shouldRefine)?.let(::add)
}
}
-private fun KSPropertyDeclaration.toNativeCoroutinesPropertySpec(
+private fun KSPropertyDeclaration.toPropertySpec(
scopeProperty: CoroutineScopeProvider.ScopeProperty,
nameSuffix: String,
setObjCName: Boolean,
typeParameterResolver: TypeParameterResolver,
type: ReturnType.Flow,
shouldRefine: Boolean
-): PropertySpec {
+): PropertySpec? {
var typeName: TypeName = nativeFlowClassName.parameterizedBy(type.valueType).copy(nullable = type.nullable)
typeName = typeName.copy(annotations = type.typeReference.annotations.toAnnotationSpecs())
val simpleName = simpleName.asString()
@@ -44,18 +44,18 @@ private fun KSPropertyDeclaration.toNativeCoroutinesPropertySpec(
codeArgs.add(asNativeFlowMemberName)
scopeProperty.codeArg.let(codeArgs::addAll)
addCode("return $code${if(type.nullable) "?." else "."}%M(${scopeProperty.code})", *codeArgs.toTypedArray())
- }).apply {
+ })?.apply {
scopeProperty.containingFile?.let(::addOriginatingKSFile)
- }.build()
+ }?.build()
}
-private fun KSPropertyDeclaration.toNativeCoroutinesValuePropertySpec(
+private fun KSPropertyDeclaration.toValuePropertySpec(
nameSuffix: String,
setObjCName: Boolean,
typeParameterResolver: TypeParameterResolver,
type: ReturnType.Flow.State,
shouldRefine: Boolean
-): PropertySpec {
+): PropertySpec? {
var typeName = type.valueType.copy(annotations = type.typeReference.annotations.toAnnotationSpecs())
if (type.nullable) typeName = typeName.copy(nullable = true)
val simpleName = simpleName.asString()
@@ -68,22 +68,22 @@ private fun KSPropertyDeclaration.toNativeCoroutinesValuePropertySpec(
else -> { code, codeArgs ->
addCode("$code${if(type.nullable) "?." else "."}value = value", *codeArgs.toTypedArray())
}
- }).build()
+ })?.build()
}
-private fun KSPropertyDeclaration.toNativeCoroutinesReplayCachePropertySpec(
+private fun KSPropertyDeclaration.toReplayCachePropertySpec(
nameSuffix: String,
typeParameterResolver: TypeParameterResolver,
type: ReturnType.Flow.Shared,
shouldRefine: Boolean
-): PropertySpec {
+): PropertySpec? {
var typeName: TypeName = LIST.parameterizedBy(type.valueType).copy(nullable = type.nullable)
typeName = typeName.copy(annotations = type.typeReference.annotations.toAnnotationSpecs())
val simpleName = simpleName.asString()
val name = "$simpleName$nameSuffix"
return createPropertySpec(typeParameterResolver, name, null, typeName, shouldRefine, { code, codeArgs ->
addCode("return $code${if(type.nullable) "?." else "."}replayCache", *codeArgs.toTypedArray())
- }).build()
+ })?.build()
}
private fun KSPropertyDeclaration.createPropertySpec(
@@ -94,7 +94,7 @@ private fun KSPropertyDeclaration.createPropertySpec(
shouldRefine: Boolean,
addGetterCode: FunSpec.Builder.(code: String, codeArgs: MutableList) -> Unit,
addSetterCode: (FunSpec.Builder.(code: String, codeArgs: MutableList) -> Unit)? = null
-): PropertySpec.Builder {
+): PropertySpec.Builder? {
val classDeclaration = parentDeclaration as? KSClassDeclaration
val builder = PropertySpec.builder(name, typeName)
@@ -119,7 +119,7 @@ private fun KSPropertyDeclaration.createPropertySpec(
val extensionReceiver = extensionReceiver
if (classDeclaration != null) {
builder.receiver(classDeclaration.toTypeName(typeParameterResolver))
- if (extensionReceiver != null) error("Class extension properties aren't supported")
+ if (extensionReceiver != null) return null // Class extension properties aren't supported
} else if (extensionReceiver != null) {
builder.receiver(extensionReceiver.toTypeName(typeParameterResolver))
}
diff --git a/kmp-nativecoroutines-ksp/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/ksp/CompilationTests.kt b/kmp-nativecoroutines-ksp/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/ksp/CompilationTests.kt
index 5b7e8a98..aec86c48 100644
--- a/kmp-nativecoroutines-ksp/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/ksp/CompilationTests.kt
+++ b/kmp-nativecoroutines-ksp/src/test/kotlin/com/rickclephas/kmp/nativecoroutines/ksp/CompilationTests.kt
@@ -2,6 +2,7 @@ package com.rickclephas.kmp.nativecoroutines.ksp
import com.tschuchort.compiletesting.*
import org.intellij.lang.annotations.Language
+import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi
import org.junit.Rule
import org.junit.rules.TemporaryFolder
import java.lang.Integer.max
@@ -11,6 +12,7 @@ open class CompilationTests {
@Rule @JvmField val temporaryFolder: TemporaryFolder = TemporaryFolder()
+ @OptIn(ExperimentalCompilerApi::class)
protected fun runKspTest(
@Language("kotlin") inputContent: String,
@Language("kotlin") outputContent: String,
@@ -34,6 +36,7 @@ open class CompilationTests {
}
}
+@OptIn(ExperimentalCompilerApi::class)
private fun KotlinCompilation.assertKspSourceFile(path: String, @Language("kotlin") contents: String) {
val file = kspSourcesDir.resolve("kotlin/$path")
assert(file.exists()) { "KSP source file <$path> doesn't exist." }
@@ -45,8 +48,9 @@ private fun KotlinCompilation.assertKspSourceFile(path: String, @Language("kotli
}
}
+@OptIn(ExperimentalCompilerApi::class)
private fun KotlinCompilation.assertCompile(
exitCode: KotlinCompilation.ExitCode = KotlinCompilation.ExitCode.OK
-): KotlinCompilation.Result = compile().also {
+): CompilationResult = compile().also {
assertEquals(exitCode, it.exitCode)
}
diff --git a/sample/shared/build.gradle.kts b/sample/shared/build.gradle.kts
index 8e59d9a3..00c44b06 100644
--- a/sample/shared/build.gradle.kts
+++ b/sample/shared/build.gradle.kts
@@ -27,22 +27,16 @@ kotlin {
all {
languageSettings.optIn("kotlin.experimental.ExperimentalObjCName")
}
- val commonMain by getting {
+ commonMain {
dependencies {
implementation(libs.kotlinx.serialization.json)
}
}
- val commonTest by getting {
+ commonTest {
dependencies {
implementation(libs.kotlin.test)
}
}
- val appleMain by creating {
- dependsOn(commonMain)
- }
- val appleTest by creating {
- dependsOn(commonTest)
- }
listOf(
macosX64, macosArm64,
iosArm64, iosX64, iosSimulatorArm64,
@@ -52,12 +46,6 @@ kotlin {
it.binaries.framework {
baseName = "NativeCoroutinesSampleShared"
}
- getByName("${it.targetName}Main") {
- dependsOn(appleMain)
- }
- getByName("${it.targetName}Test") {
- dependsOn(appleTest)
- }
}
}
}