Kotlin / dukat

Converter of <any kind of declarations> to Kotlin external declarations
552 stars 44 forks source link

Declarations for RxJs fail to build #406

Open ScottPierce opened 3 years ago

ScottPierce commented 3 years ago

Using Kotlin 1.4.0

implementation(npm("rxjs", "6.6.3", generateExternals = true))

https://youtrack.jetbrains.com/issue/KT-41822

Here are the errors:

> Task :presentation:compileKotlinJs FAILED
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/AnimationFrameScheduler.module_rxjs.kt: (18, 15): Class 'AnimationFrameScheduler' is not abstract and does not implement abstract base class member public abstract fun now(): Number defined in AsyncScheduler
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/AsapScheduler.module_rxjs.kt: (18, 15): Class 'AsapScheduler' is not abstract and does not implement abstract base class member public abstract fun now(): Number defined in AsyncScheduler
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/AsyncScheduler.module_rxjs.kt: (18, 15): Class 'AsyncScheduler' is not abstract and does not implement abstract base class member public abstract fun now(): Number defined in Scheduler
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/ConnectableObservable.module_rxjs.kt: (19, 26): Type of 'source' doesn't match the type of the overridden var-property 'public open var source: Observable<Any> defined in Observable'
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/InnerSubscriber.module_rxjs.kt: (18, 15): Class 'InnerSubscriber' is not abstract and does not implement abstract base class member public abstract var next: (value: R) -> Unit defined in Subscriber
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/InnerSubscriber.module_rxjs.kt: (23, 14): '_next' hides member of supertype 'Subscriber' and needs 'override' modifier
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/OuterSubscriber.module_rxjs.kt: (18, 15): Class 'OuterSubscriber' is not abstract and does not implement abstract base class member public abstract var next: (value: T) -> Unit defined in Subscriber
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/QueueScheduler.module_rxjs.kt: (18, 15): Class 'QueueScheduler' is not abstract and does not implement abstract base class member public abstract fun now(): Number defined in AsyncScheduler
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/Scheduler.module_rxjs.kt: (18, 15): Class 'Scheduler' is not abstract and does not implement abstract member public abstract fun now(): Number defined in SchedulerLike
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/Subscriber.module_rxjs.kt: (18, 15): Class 'Subscriber' is not abstract and does not implement abstract member public abstract var next: (value: T) -> Unit defined in Observer
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/Subscriber.module_rxjs.kt: (18, 15): Class 'Subscriber' must override public open var closed: Boolean defined in Subscription because it inherits many implementations of it
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/Subscriber.module_rxjs.kt: (18, 15): 'public open var closed: Boolean defined in Subscriber' clashes with 'public open var closed: Boolean? defined in Observer': property types do not match
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/VirtualTimeScheduler.module_rxjs.kt: (18, 15): Class 'VirtualTimeScheduler' is not abstract and does not implement abstract base class member public abstract fun now(): Number defined in AsyncScheduler
e: /Users/scott.pierce/workspace/dev.scottpierce/mobile-tester/mobile-tester-repository/presentation/build/externals/mobile-tester-presentation/src/VirtualTimeScheduler.module_rxjs.kt: (30, 29): Type of 'scheduler' doesn't match the type of the overridden var-property 'public open var scheduler: AsyncScheduler defined in AsyncAction'
ScottPierce commented 3 years ago

I ended up exporting the declarations, adding their folder to the source set manually, and resolving the errors that way, but there were key problems in the resulting exported code that stopped it from working still:

  1. I'm in a nodejs environment and there were no @JsModule declarations, so the even when I resolve the build problems, the types / code can't be found at runtime.
  2. Dukat translates the constructor lambda parameters incorrectly. Here is more information on that:

Here is the definition of Observable:

export class Observable<T> implements Subscribable<T> {
  constructor(subscribe?: (this: Observable<T>, subscriber: Subscriber<T>) => TeardownLogic) {
    // ...
  }

  //...
}

Here is the definition dukat creates:

open external class Observable<T>(subscribe: (self: Observable<T>, subscriber: Subscriber<T>) -> dynamic = definedExternally) : Subscribable<T> {
  // ...
}

And here is how Typescript has me use it:

new Observable<String>((subscriber) => {
  //...
})

Typescript actually complains when I add a second parameter to the lambda. Perhaps there is a feature of typescript that allows this to be set for the parameter when it's named this? Either way, when I use the Kotlin version at runtime, the subscriber parameter is incorrectly undefined

ScottPierce commented 3 years ago

The first issue I mentioned seems to be referenced here I think - https://github.com/Kotlin/dukat/issues/263

diesieben07 commented 3 years ago

this parameters in function types describe what this will be in that function. However that won't be the case if an arrow function is used. The most natural way to express this in Kotlin would be to translate it to an extension function type, however I am not sure if the JS translation permits that, that extension function would have to be translated to a JS function that uses the JS this (instead of Kotlin's synthetic "receiver" parameter.