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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public class KmpNativeCoroutinesChecker(
if (descriptor !is CallableMemberDescriptor) return
if (descriptor !is SimpleFunctionDescriptor && descriptor !is PropertyDescriptor) return
val annotations = descriptor.getNativeCoroutinesAnnotations()
val isRefined = descriptor.isRefined
val isRefined = descriptor.isRefined || descriptor.containingDeclaration.isRefined
val isPublic = descriptor.isEffectivelyPublicApi
val isOverride = descriptor.overriddenDescriptors.isNotEmpty()
val isActual = descriptor.isActual
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
import org.jetbrains.kotlin.fir.resolve.getContainingClass
import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenMembersWithBaseScopeSafe
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import java.nio.file.Path
Expand Down Expand Up @@ -100,7 +101,9 @@ internal class FirKmpNativeCoroutinesDeclarationChecker(
}

val annotations = declaration.getNativeCoroutinesAnnotations(context.session)
val isRefined = declaration.isRefined(context.session)
val isRefined =
declaration.isRefined(context.session) || (declaration.getContainingClass()?.isRefined(context.session)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

On the second thought, the whole containment chain needs to be checked for cases where the top-level class is hidden & nested classes have suspend functions/flows.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed.

?: false)
val isPublic = declaration.effectiveVisibility.publicApi
val isOverride = declaration.isOverride
val isActual = declaration.isActual
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.rickclephas.kmp.nativecoroutines.compiler.fir.utils
import com.rickclephas.kmp.nativecoroutines.compiler.utils.ClassIds
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
import org.jetbrains.kotlin.fir.declarations.FirClassLikeDeclaration
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassId
import org.jetbrains.kotlin.fir.declarations.toAnnotationClassLikeSymbol
import org.jetbrains.kotlin.fir.expressions.FirAnnotation
Expand All @@ -12,6 +13,11 @@ internal fun FirCallableDeclaration.isRefined(session: FirSession): Boolean =
!annotation.isNativeCoroutinesAnnotation(session) && annotation.isRefinementAnnotation(session)
}

internal fun FirClassLikeDeclaration.isRefined(session: FirSession): Boolean =
Copy link
Contributor Author

@nikolaykasyanov nikolaykasyanov Dec 30, 2025

Choose a reason for hiding this comment

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

isRefined is probably not the best name here as types can't be annotated with @RefinesInSwift, so the only option is @HidesFromObjC.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Addressed.

annotations.any { annotation ->
annotation.isRefinementAnnotation(session)
}

private fun FirAnnotation.isRefinementAnnotation(session: FirSession): Boolean =
toAnnotationClassLikeSymbol(session)?.resolvedAnnotationsWithClassIds.orEmpty().any { metaAnnotation ->
val classId = metaAnnotation.toAnnotationClassId(session)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,14 @@ interface TestInterface {
val flowInterfaceProperty: Flow<Int>
}

@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
interface TestHiddenFromObjCInterface {
suspend fun suspendInterfaceFunction(): Int

val flowInterfaceProperty: Flow<Int>
}

class TestClassA: TestInterface {

override suspend fun suspendInterfaceFunction(): Int = 0
Expand Down Expand Up @@ -120,3 +128,11 @@ actual class TestClassC {

actual val flowProperty: Flow<Int> get() = throw Throwable()
}

@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
class TestHiddenFromObjCClass {
suspend fun suspendFunction(): Int = 0

val flowProperty: Flow<Int> get() = throw Throwable()
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ interface TestInterface {
val flowInterfaceProperty: <!EXPOSED_FLOW_TYPE_ERROR!>Flow<Int><!>
}

@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
interface TestHiddenFromObjCInterface {
suspend fun suspendInterfaceFunction(): Int

val flowInterfaceProperty: Flow<Int>
}

class TestClassA: TestInterface {

override suspend fun suspendInterfaceFunction(): Int = 0
Expand Down Expand Up @@ -96,3 +104,11 @@ actual class TestClassC {

actual val flowProperty: Flow<Int> get() = throw Throwable()
}

@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
class TestHiddenFromObjCClass {
suspend fun suspendFunction(): Int = 0

val flowProperty: Flow<Int> get() = throw Throwable()
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ interface TestInterface {
val flowInterfaceProperty: Flow<Int>
}

@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
interface TestHiddenFromObjCInterface {
suspend fun suspendInterfaceFunction(): Int

val flowInterfaceProperty: Flow<Int>
}

class TestClassA: TestInterface {

override suspend fun suspendInterfaceFunction(): Int = 0
Expand Down Expand Up @@ -96,3 +104,11 @@ actual class TestClassC {

actual val flowProperty: Flow<Int> get() = throw Throwable()
}

@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
class TestHiddenFromObjCClass {
suspend fun suspendFunction(): Int = 0

val flowProperty: Flow<Int> get() = throw Throwable()
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ interface TestInterface {
val flowInterfaceProperty: <!EXPOSED_FLOW_TYPE!>Flow<Int><!>
}

@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
interface TestHiddenFromObjCInterface {
suspend fun suspendInterfaceFunction(): Int

val flowInterfaceProperty: Flow<Int>
}

class TestClassA: TestInterface {

override suspend fun suspendInterfaceFunction(): Int = 0
Expand Down Expand Up @@ -96,3 +104,11 @@ actual class TestClassC {

actual val flowProperty: Flow<Int> get() = throw Throwable()
}

@OptIn(ExperimentalObjCRefinement::class)
@HiddenFromObjC
class TestHiddenFromObjCClass {
suspend fun suspendFunction(): Int = 0

val flowProperty: Flow<Int> get() = throw Throwable()
}