FutureMind/koru

override modifier missing for interface properties

Gepro83 opened this issue · 8 comments

I have an interface:

    interface Feature<Wish : Any, State : Any, News : Any> {
        fun accept(wish: Wish)

        val state: StateFlow<State>
        val news: SharedFlow<News>
    }

and a class implementing it:

@ToNativeClass(launchOnScope = MainScopeProvider::class)
class DemoFeature : Feature<DemoFeature.Wish, DemoFeature.State, Nothing> {
    private val _state: MutableStateFlow<State> =  MutableStateFlow(State(false))

    override val state: StateFlow<State> = _state
    override val news: SharedFlow<Nothing> = MutableSharedFlow()
}

it seems the override modifiers are not present in the generated classes, i get:
...apps/features/DemoFeatureNative.kt: (17, 14): 'state' hides member of supertype 'Feature' and needs 'override' modifier

What happens if you add ToNativeInterface to the interface Feature?

Generated class cannot override the Feature interface because the signatures will be different (generated will return FlowWrapper, not StateFlow). I wonder if the generated class should extend the original interface if it doesn't have @ToNativeInterface. I think it should just forget the original interface altogether in that case, must have missed that though.

hm i tried annotating the interface, however it is generic which seems to not be supported yet:

@ToNativeInterface
interface Feature<Wish : Any, State : Any, News : Any> {
    fun accept(wish: Wish)

    val state: StateFlow<State>
    val news: SharedFlow<News>
}

is translated to:

public interface FeatureNativeProtocol {
  public val news: FlowWrapper<News>

  public val state: FlowWrapper<State>

  public fun accept(wish: Wish): Unit
}

getting:
...vi/FeatureNativeProtocol.kt: (9, 33): Unresolved reference: State

Yeah, not yet and it's probably not that easy but I'll look into that.
But if I'm not mistaken, for your use case just getting the original interface out of the way should work and not be that hard. Then you'll have the generated DemoFeatureWrapper class which will just wrap the concrete DemoFeature class without overriding anything.

hm yeah i guess it would be possible, the interface is kind of the main interface we are building our application on so we kind of need that, thank you though! :)

Okay, now I remembered it's probably not even possible to support generics in this scenario. The generic information is lost when converting from obj-c to swift (https://developer.apple.com/forums/thread/7394). But it should not be necessary in your case at all. The architecture goes like this:

  • kotlin interface Feature<Wish : Any, State : Any, News : Any>
  • kotlin class DemoFeature : Feature<DemoFeature.Wish, DemoFeature.State, Nothing> is annotated with @ToNativeClass
  • kotlin class DemoFeatureWrapper generated by Koru
  • Swift code just accesses DemoFeatureWrapper, the original generic is an implementation detail, Swift code has no interest in it.

For that to work I just need to make the fix - class DemoFeatureWrapper should not extend interface Feature, that's all. I will try to fix this week.

yeah that would work and would be awsome !

I released 0.8.0 (should be on maven central soon) - let me know if that fixes your issue.

Related test:

fun `should not extend superinterface if it is not annotated (and thus should strip override annotation)`() {

Closing for lack of activity (and I'm pretty sure it should be fixed already)