[jnigen] Convert Kotlin's `suspend fun` to Dart's async methods (https://github.com/dart-lang/jnigen/issues/171)
Added a boolean option to jnigen.yaml called `suspend_fun_to_async`. When `true`, Kotlin suspendable functions, specified by `suspend fun`, will be converted into Dart async methods.
A Kotlin suspendable function gets de-sugared into a continutation-passing style (CPS) method which takes a `kotlin.coroutines.Continuation` as its final argument.
At the preprocessing stage – if the `suspend_fun_to_async` option is set – the `asyncReturnType` of each method that has `kotlin.coroutines.Continuation` as its final argument will be set so that later in the binding generation step, the return type of the method gets converted to `Future<{asyncReturnType}>`.
The generated bindings instead passes a special `PortContinuation` instance which is defined by `package:jni`. This class implements `Continuation` and gets a native send port address in its constructor. Later, when the `suspend fun` wants to resume, the `resumeWith` method of the `PortContinuation` instance gets called, which in turn calls the `_resumeWith` native method defined in `dartjni.c`. This method send the address of the object to through the send port specified.
All the boilerplate regarding the creation of `NativePort`, `PortContinuation`, awaiting responses, checking for errors and such are automatically generated by `package:jnigen`.
For native ports to work, `package:jni` provides a handy `Jni.initDLApi()` to be called first.
Example:
This:
```kotlin
public suspend fun thinkBeforeAnswering(): String
```
Gets converted to:
```dart
Future<jni.JString> thinkBeforeAnswering() async
```114 files changed