diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index ea6cd9df5b5..7e9c46e85a9 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,3 +1,7 @@ +## 17.3.0 + +* [kotlin] Adds implementation for `@ProxyApi`. + ## 17.2.0 * [dart] Adds implementation for `@ProxyApi`. diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index bc4ec8c4477..26319e59d2d 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -4,6 +4,7 @@ import 'package:collection/collection.dart' show ListEquality; import 'package:meta/meta.dart'; +import 'kotlin_generator.dart'; import 'pigeon_lib.dart'; typedef _ListEquals = bool Function(List, List); @@ -139,6 +140,7 @@ class AstProxyApi extends Api { required this.fields, this.superClass, this.interfaces = const {}, + this.kotlinOptions, }); /// List of constructors inside the API. @@ -153,6 +155,10 @@ class AstProxyApi extends Api { /// Name of the classes this class considers to be implemented. Set interfaces; + /// Options that control how Kotlin code will be generated for a specific + /// ProxyApi. + final KotlinProxyApiOptions? kotlinOptions; + /// Methods implemented in the host platform language. Iterable get hostMethods => methods.where( (Method method) => method.location == ApiLocation.host, diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index 66dd99750f3..840be332b59 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -13,7 +13,7 @@ import 'ast.dart'; /// The current version of pigeon. /// /// This must match the version in pubspec.yaml. -const String pigeonVersion = '17.2.0'; +const String pigeonVersion = '17.3.0'; /// Read all the content from [stdin] to a String. String readStdin() { @@ -301,6 +301,12 @@ const String seeAlsoWarning = 'See also: https://pub.dev/packages/pigeon'; /// parameters. const String classNamePrefix = 'Pigeon'; +/// Prefix for apis generated for ProxyApi. +/// +/// Since ProxyApis are intended to wrap a class and will often share the name +/// of said class, host APIs should prefix the API with this protected name. +const String hostApiPrefix = '${classNamePrefix}Api'; + /// Name for the generated InstanceManager for ProxyApis. /// /// This lowers the chances of variable name collisions with user defined diff --git a/packages/pigeon/lib/kotlin/templates.dart b/packages/pigeon/lib/kotlin/templates.dart new file mode 100644 index 00000000000..276ed9e284c --- /dev/null +++ b/packages/pigeon/lib/kotlin/templates.dart @@ -0,0 +1,347 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import '../generator_tools.dart'; + +/// The Kotlin `InstanceManager`. +const String instanceManagerTemplate = ''' +/** + * Maintains instances used to communicate with the corresponding objects in Dart. + * + *

Objects stored in this container are represented by an object in Dart that is also stored in + * an InstanceManager with the same identifier. + * + *

When an instance is added with an identifier, either can be used to retrieve the other. + * + *

Added instances are added as a weak reference and a strong reference. When the strong + * reference is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener` is made with the instance's identifier. However, if the strong reference + * is removed and then the identifier is retrieved with the intention to pass the identifier to Dart + * (e.g. calling [getIdentifierForStrongReference]), the strong reference to the + * instance is recreated. The strong reference will then need to be removed manually again. + */ +@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "unused") +class $instanceManagerClassName(private val finalizationListener: $_finalizationListenerClassName) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ + interface $_finalizationListenerClassName { + fun onFinalize(identifier: Long) + } + + private val identifiers = java.util.WeakHashMap() + private val weakInstances = HashMap>() + private val strongInstances = HashMap() + private val referenceQueue = java.lang.ref.ReferenceQueue() + private val weakReferencesToIdentifiers = HashMap, Long>() + private val handler = android.os.Handler(android.os.Looper.getMainLooper()) + private var nextIdentifier: Long = minHostCreatedIdentifier + private var hasFinalizationListenerStopped = false + + init { + handler.postDelayed( + { releaseAllFinalizedInstances() }, + clearFinalizedWeakReferencesInterval + ) + } + + companion object { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private const val minHostCreatedIdentifier: Long = 65536 + private const val clearFinalizedWeakReferencesInterval: Long = 3000 + private const val tag = "$instanceManagerClassName" + + /** + * Instantiate a new manager. + * + * + * When the manager is no longer needed, [stopFinalizationListener] must be called. + * + * @param finalizationListener the listener for garbage collected weak references. + * @return a new `$instanceManagerClassName`. + */ + fun create(finalizationListener: $_finalizationListenerClassName): $instanceManagerClassName { + return $instanceManagerClassName(finalizationListener) + } + + /** + * Instantiate a new manager with an `$instanceManagerClassName`. + * + * @param api handles removing garbage collected weak references. + * @return a new `$instanceManagerClassName`. + */ + fun create(api: ${instanceManagerClassName}Api): $instanceManagerClassName { + val instanceManager = create( + object : $_finalizationListenerClassName { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e(tag, "Failed to remove Dart strong reference with identifier: \$identifier") + } + } + } + }) + $_instanceManagerApiName.setUpMessageHandlers(api.binaryMessenger, instanceManager) + return instanceManager + } + } + + /** + * Removes `identifier` and its associated strongly referenced instance, if present, from the + * manager. + * + * @param identifier the identifier paired to an instance. + * @param the expected return type. + * @return the removed instance if the manager contains the given identifier, otherwise `null` if + * the manager doesn't contain the value. + */ + fun remove(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + return strongInstances.remove(identifier) as T? + } + + /** + * Retrieves the identifier paired with an instance. + * + * + * If the manager contains a strong reference to `instance`, it will return the identifier + * associated with `instance`. If the manager contains only a weak reference to `instance`, a new + * strong reference to `instance` will be added and will need to be removed again with [remove]. + * + * + * If this method returns a nonnull identifier, this method also expects the Dart + * `$instanceManagerClassName` to have, or recreate, a weak reference to the Dart instance the + * identifier is associated with. + * + * @param instance an instance that may be stored in the manager. + * @return the identifier associated with `instance` if the manager contains the value, otherwise + * `null` if the manager doesn't contain the value. + */ + fun getIdentifierForStrongReference(instance: Any?): Long? { + logWarningIfFinalizationListenerHasStopped() + val identifier = identifiers[instance] + if (identifier != null) { + strongInstances[identifier] = instance!! + } + return identifier + } + + /** + * Adds a new instance that was instantiated from Dart. + * + * + * The same instance can be added multiple times, but each identifier must be unique. This + * allows two objects that are equivalent (e.g. the `equals` method returns true and their + * hashcodes are equal) to both be added. + * + * @param instance the instance to be stored. + * @param identifier the identifier to be paired with instance. This value must be >= 0 and + * unique. + */ + fun addDartCreatedInstance(instance: Any, identifier: Long) { + logWarningIfFinalizationListenerHasStopped() + addInstance(instance, identifier) + } + + /** + * Adds a new instance that was instantiated from the host platform. + * + * @param instance the instance to be stored. This must be unique to all other added instances. + * @return the unique identifier (>= 0) stored with instance. + */ + fun addHostCreatedInstance(instance: Any): Long { + logWarningIfFinalizationListenerHasStopped() + require(!containsInstance(instance)) { "Instance of \${instance.javaClass} has already been added." } + val identifier = nextIdentifier++ + addInstance(instance, identifier) + return identifier + } + + /** + * Retrieves the instance associated with identifier. + * + * @param identifier the identifier associated with an instance. + * @param the expected return type. + * @return the instance associated with `identifier` if the manager contains the value, otherwise + * `null` if the manager doesn't contain the value. + */ + fun getInstance(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + val instance = weakInstances[identifier] as java.lang.ref.WeakReference? + return instance?.get() + } + + /** + * Returns whether this manager contains the given `instance`. + * + * @param instance the instance whose presence in this manager is to be tested. + * @return whether this manager contains the given `instance`. + */ + fun containsInstance(instance: Any?): Boolean { + logWarningIfFinalizationListenerHasStopped() + return identifiers.containsKey(instance) + } + + /** + * Stop the periodic run of the [$_finalizationListenerClassName] for instances that have been garbage + * collected. + * + * + * The InstanceManager can continue to be used, but the [$_finalizationListenerClassName] will no + * longer be called and methods will log a warning. + */ + fun stopFinalizationListener() { + handler.removeCallbacks { this.releaseAllFinalizedInstances() } + hasFinalizationListenerStopped = true + } + + /** + * Removes all of the instances from this manager. + * + * + * The manager will be empty after this call returns. + */ + fun clear() { + identifiers.clear() + weakInstances.clear() + strongInstances.clear() + weakReferencesToIdentifiers.clear() + } + + /** + * Whether the [$_finalizationListenerClassName] is still being called for instances that are garbage + * collected. + * + * + * See [stopFinalizationListener]. + */ + fun hasFinalizationListenerStopped(): Boolean { + return hasFinalizationListenerStopped + } + + private fun releaseAllFinalizedInstances() { + if (hasFinalizationListenerStopped()) { + return + } + var reference: java.lang.ref.WeakReference? + while ((referenceQueue.poll() as java.lang.ref.WeakReference?).also { reference = it } != null) { + val identifier = weakReferencesToIdentifiers.remove(reference) + if (identifier != null) { + weakInstances.remove(identifier) + strongInstances.remove(identifier) + finalizationListener.onFinalize(identifier) + } + } + handler.postDelayed( + { releaseAllFinalizedInstances() }, + clearFinalizedWeakReferencesInterval + ) + } + + private fun addInstance(instance: Any, identifier: Long) { + require(identifier >= 0) { "Identifier must be >= 0: \$identifier" } + require(!weakInstances.containsKey(identifier)) { + "Identifier has already been added: \$identifier" + } + val weakReference = java.lang.ref.WeakReference(instance, referenceQueue) + identifiers[instance] = identifier + weakInstances[identifier] = weakReference + weakReferencesToIdentifiers[weakReference] = identifier + strongInstances[identifier] = instance + } + + private fun logWarningIfFinalizationListenerHasStopped() { + if (hasFinalizationListenerStopped()) { + Log.w( + tag, + "The manager was used after calls to the $_finalizationListenerClassName have been stopped." + ) + } + } +} +'''; + +/// Creates the `InstanceManagerApi` with the passed string values. +String instanceManagerApiTemplate({ + required String dartPackageName, + required String errorClassName, +}) { + final String removeStrongReferenceName = makeChannelNameWithStrings( + apiName: _instanceManagerApiName, + methodName: 'removeStrongReference', + dartPackageName: dartPackageName, + ); + final String clearName = makeChannelNameWithStrings( + apiName: _instanceManagerApiName, + methodName: 'clear', + dartPackageName: dartPackageName, + ); + return ''' +/** +* Generated API for managing the Dart and native `$instanceManagerClassName`s. +*/ +class $_instanceManagerApiName(internal val binaryMessenger: BinaryMessenger) { + companion object { + /** The codec used by $_instanceManagerApiName. */ + private val codec: MessageCodec by lazy { + StandardMessageCodec() + } + + /** + * Sets up an instance of `$_instanceManagerApiName` to handle messages from the + * `binaryMessenger`. + */ + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: $instanceManagerClassName) { + run { + val channel = BasicMessageChannel(binaryMessenger, "$removeStrongReferenceName", codec) + channel.setMessageHandler { message, reply -> + val identifier = message as Number + val wrapped: List = try { + instanceManager.remove(identifier.toLong()) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } + run { + val channel = BasicMessageChannel(binaryMessenger, "$clearName", codec) + channel.setMessageHandler { _, reply -> + val wrapped: List = try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } + } + } + + fun removeStrongReference(identifier: Long, callback: (Result) -> Unit) { + val channelName = "$removeStrongReferenceName" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(identifier) { + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure($errorClassName(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } +} +'''; +} + +const String _instanceManagerApiName = '${instanceManagerClassName}Api'; + +const String _finalizationListenerClassName = + '${classNamePrefix}FinalizationListener'; diff --git a/packages/pigeon/lib/kotlin_generator.dart b/packages/pigeon/lib/kotlin_generator.dart index 39697fa3242..61391e2ecd2 100644 --- a/packages/pigeon/lib/kotlin_generator.dart +++ b/packages/pigeon/lib/kotlin_generator.dart @@ -2,10 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'dart:math'; + +import 'package:graphs/graphs.dart'; + import 'ast.dart'; import 'functional.dart'; import 'generator.dart'; import 'generator_tools.dart'; +import 'kotlin/templates.dart'; import 'pigeon_lib.dart' show TaskQueueType; /// Documentation open symbol. @@ -80,6 +85,26 @@ class KotlinOptions { } } +/// Options that control how Kotlin code will be generated for a specific +/// ProxyApi. +class KotlinProxyApiOptions { + /// Construct a [KotlinProxyApiOptions]. + const KotlinProxyApiOptions({ + required this.fullClassName, + this.minAndroidApi, + }); + + /// The name of the full runtime Kotlin class name (including the package). + final String fullClassName; + + /// The minimum Android api version. + /// + /// This adds the [RequiresApi](https://developer.android.com/reference/androidx/annotation/RequiresApi) + /// annotations on top of any constructor, field, or method that references + /// this element. + final int? minAndroidApi; +} + /// Class that manages all Kotlin code generation. class KotlinGenerator extends StructuredGenerator { /// Instantiates a Kotlin Generator. @@ -463,6 +488,251 @@ class KotlinGenerator extends StructuredGenerator { }); } + @override + void writeInstanceManager( + KotlinOptions generatorOptions, + Root root, + Indent indent, { + required String dartPackageName, + }) { + indent.format(instanceManagerTemplate); + } + + @override + void writeInstanceManagerApi( + KotlinOptions generatorOptions, + Root root, + Indent indent, { + required String dartPackageName, + }) { + indent.format(instanceManagerApiTemplate( + dartPackageName: dartPackageName, + errorClassName: _getErrorClassName(generatorOptions), + )); + } + + @override + void writeProxyApiBaseCodec( + KotlinOptions generatorOptions, + Root root, + Indent indent, + ) { + const String codecName = '${classNamePrefix}ProxyApiBaseCodec'; + + final Iterable allProxyApis = + root.apis.whereType(); + + // Sort APIs where edges are an API's super class and interfaces. + // + // This sorts the apis to have child classes be listed before their parent + // classes. This prevents the scenario where a method might return the super + // class of the actual class, so the incorrect Dart class gets created + // because the 'value is ' was checked first in the codec. For + // example: + // + // class Shape {} + // class Circle extends Shape {} + // + // class SomeClass { + // Shape giveMeAShape() => Circle(); + // } + final List sortedApis = topologicalSort( + allProxyApis, + (AstProxyApi api) { + final List edges = [ + if (api.superClass?.associatedProxyApi != null) + api.superClass!.associatedProxyApi!, + ...api.interfaces.map( + (TypeDeclaration interface) => interface.associatedProxyApi!, + ), + ]; + return edges; + }, + ); + + indent.writeScoped( + 'abstract class $codecName(val binaryMessenger: BinaryMessenger, val instanceManager: $instanceManagerClassName) : StandardMessageCodec() {', + '}', + () { + for (final AstProxyApi api in sortedApis) { + _writeMethodDeclaration( + indent, + name: 'get$hostApiPrefix${api.name}', + isAbstract: true, + documentationComments: [ + 'An implementation of [$hostApiPrefix${api.name}] used to add a new Dart instance of', + '`${api.name}` to the Dart `InstanceManager`.' + ], + returnType: TypeDeclaration( + baseName: '$hostApiPrefix${api.name}', + isNullable: false, + ), + parameters: [], + ); + indent.newln(); + } + + indent.writeScoped('fun setUpMessageHandlers() {', '}', () { + for (final AstProxyApi api in sortedApis) { + final bool hasHostMessageCalls = api.constructors.isNotEmpty || + api.attachedFields.isNotEmpty || + api.hostMethods.isNotEmpty; + if (hasHostMessageCalls) { + indent.writeln( + '$hostApiPrefix${api.name}.setUpMessageHandlers(binaryMessenger, get$hostApiPrefix${api.name}())', + ); + } + } + }); + + indent.format( + 'override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {\n' + ' return when (type) {\n' + ' 128.toByte() -> {\n' + ' return instanceManager.getInstance(\n' + ' readValue(buffer).let { if (it is Int) it.toLong() else it as Long })\n' + ' }\n' + ' else -> super.readValueOfType(type, buffer)\n' + ' }\n' + '}', + ); + indent.newln(); + + indent.writeScoped( + 'override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {', + '}', + () { + enumerate( + sortedApis, + (int index, AstProxyApi api) { + final String className = + api.kotlinOptions?.fullClassName ?? api.name; + + final int? minApi = api.kotlinOptions?.minAndroidApi; + final String versionCheck = minApi != null + ? 'android.os.Build.VERSION.SDK_INT >= $minApi && ' + : ''; + + indent.format( + '${index > 0 ? ' else ' : ''}if (${versionCheck}value is $className) {\n' + ' get$hostApiPrefix${api.name}().${classMemberNamePrefix}newInstance(value) { }\n' + '}', + ); + }, + ); + indent.newln(); + + indent.format( + 'when {\n' + ' instanceManager.containsInstance(value) -> {\n' + ' stream.write(128)\n' + ' writeValue(stream, instanceManager.getIdentifierForStrongReference(value))\n' + ' }\n' + ' else -> super.writeValue(stream, value)\n' + '}', + ); + }, + ); + }, + ); + } + + @override + void writeProxyApi( + KotlinOptions generatorOptions, + Root root, + Indent indent, + AstProxyApi api, { + required String dartPackageName, + }) { + const String codecName = '${classNamePrefix}ProxyApiBaseCodec'; + final String fullKotlinClassName = + api.kotlinOptions?.fullClassName ?? api.name; + final String kotlinApiName = '$hostApiPrefix${api.name}'; + + addDocumentationComments( + indent, + api.documentationComments, + _docCommentSpec, + ); + indent.writeln('@Suppress("UNCHECKED_CAST")'); + indent.writeScoped( + 'abstract class $kotlinApiName(val codec: $codecName) {', + '}', + () { + final TypeDeclaration apiAsTypeDeclaration = TypeDeclaration( + baseName: api.name, + isNullable: false, + associatedProxyApi: api, + ); + + _writeProxyApiConstructorAbstractMethods( + indent, + api, + apiAsTypeDeclaration: apiAsTypeDeclaration, + ); + + _writeProxyApiAttachedFieldAbstractMethods( + indent, + api, + apiAsTypeDeclaration: apiAsTypeDeclaration, + ); + + if (api.hasCallbackConstructor()) { + _writeProxyApiUnattachedFieldAbstractMethods( + indent, + api, + apiAsTypeDeclaration: apiAsTypeDeclaration, + ); + } + + _writeProxyApiHostMethodAbstractMethods( + indent, + api, + apiAsTypeDeclaration: apiAsTypeDeclaration, + ); + + if (api.constructors.isNotEmpty || + api.attachedFields.isNotEmpty || + api.hostMethods.isNotEmpty) { + indent.writeScoped('companion object {', '}', () { + _writeProxyApiMessageHandlerMethod( + indent, + api, + apiAsTypeDeclaration: apiAsTypeDeclaration, + kotlinApiName: kotlinApiName, + dartPackageName: dartPackageName, + fullKotlinClassName: fullKotlinClassName, + ); + }); + indent.newln(); + } + + const String newInstanceMethodName = + '${classMemberNamePrefix}newInstance'; + + _writeProxyApiNewInstanceMethod( + indent, + api, + generatorOptions: generatorOptions, + apiAsTypeDeclaration: apiAsTypeDeclaration, + newInstanceMethodName: newInstanceMethodName, + dartPackageName: dartPackageName, + ); + + _writeProxyApiFlutterMethods( + indent, + api, + generatorOptions: generatorOptions, + apiAsTypeDeclaration: apiAsTypeDeclaration, + dartPackageName: dartPackageName, + ); + + _writeProxyApiInheritedApiMethods(indent, api); + }, + ); + } + /// Writes the codec class that will be used by [api]. /// Example: /// private static class FooCodec extends StandardMessageCodec {...} @@ -588,12 +858,13 @@ class KotlinGenerator extends StructuredGenerator { final bool hasFlutterApi = root.apis .whereType() .any((Api api) => api.methods.isNotEmpty); + final bool hasProxyApi = root.apis.any((Api api) => api is AstProxyApi); - if (hasHostApi) { + if (hasHostApi || hasProxyApi) { _writeWrapResult(indent); _writeWrapError(generatorOptions, indent); } - if (hasFlutterApi) { + if (hasFlutterApi || hasProxyApi) { _writeCreateConnectionError(generatorOptions, indent); } if (generatorOptions.includeErrorClass) { @@ -860,6 +1131,526 @@ class KotlinGenerator extends StructuredGenerator { }); }); } + + // Writes the abstract method that instantiates a new instance of the Kotlin + // class. + void _writeProxyApiConstructorAbstractMethods( + Indent indent, + AstProxyApi api, { + required TypeDeclaration apiAsTypeDeclaration, + }) { + for (final Constructor constructor in api.constructors) { + _writeMethodDeclaration( + indent, + name: constructor.name.isNotEmpty + ? constructor.name + : '${classMemberNamePrefix}defaultConstructor', + returnType: apiAsTypeDeclaration, + documentationComments: constructor.documentationComments, + minApiRequirement: _typeWithHighestApiRequirement([ + apiAsTypeDeclaration, + ...constructor.parameters.map( + (Parameter parameter) => parameter.type, + ), + ])?.associatedProxyApi?.kotlinOptions?.minAndroidApi, + isAbstract: true, + parameters: [ + ...api.unattachedFields.map((ApiField field) { + return Parameter(name: field.name, type: field.type); + }), + ...constructor.parameters + ], + ); + indent.newln(); + } + } + + // Writes the abstract method that handles instantiating an attached field. + void _writeProxyApiAttachedFieldAbstractMethods( + Indent indent, + AstProxyApi api, { + required TypeDeclaration apiAsTypeDeclaration, + }) { + for (final ApiField field in api.attachedFields) { + _writeMethodDeclaration( + indent, + name: field.name, + documentationComments: field.documentationComments, + returnType: field.type, + isAbstract: true, + minApiRequirement: _typeWithHighestApiRequirement([ + apiAsTypeDeclaration, + field.type, + ])?.associatedProxyApi?.kotlinOptions?.minAndroidApi, + parameters: [ + if (!field.isStatic) + Parameter( + name: '${classMemberNamePrefix}instance', + type: apiAsTypeDeclaration, + ), + ], + ); + indent.newln(); + } + } + + // Writes the abstract method that handles accessing an unattached field. + void _writeProxyApiUnattachedFieldAbstractMethods( + Indent indent, + AstProxyApi api, { + required TypeDeclaration apiAsTypeDeclaration, + }) { + for (final ApiField field in api.unattachedFields) { + _writeMethodDeclaration( + indent, + name: field.name, + documentationComments: field.documentationComments, + returnType: field.type, + isAbstract: true, + minApiRequirement: _typeWithHighestApiRequirement([ + apiAsTypeDeclaration, + field.type, + ])?.associatedProxyApi?.kotlinOptions?.minAndroidApi, + parameters: [ + Parameter( + name: '${classMemberNamePrefix}instance', + type: apiAsTypeDeclaration, + ), + ], + ); + indent.newln(); + } + } + + // Writes the abstract method that handles making a call from for a host + // method. + void _writeProxyApiHostMethodAbstractMethods( + Indent indent, + AstProxyApi api, { + required TypeDeclaration apiAsTypeDeclaration, + }) { + for (final Method method in api.hostMethods) { + _writeMethodDeclaration( + indent, + name: method.name, + returnType: method.returnType, + documentationComments: method.documentationComments, + isAsynchronous: method.isAsynchronous, + isAbstract: true, + minApiRequirement: _typeWithHighestApiRequirement( + [ + if (!method.isStatic) apiAsTypeDeclaration, + method.returnType, + ...method.parameters.map((Parameter p) => p.type), + ], + )?.associatedProxyApi?.kotlinOptions?.minAndroidApi, + parameters: [ + if (!method.isStatic) + Parameter( + name: '${classMemberNamePrefix}instance', + type: apiAsTypeDeclaration, + ), + ...method.parameters, + ], + ); + indent.newln(); + } + } + + // Writes the `..setUpMessageHandler` method to ensure incoming messages are + // handled by the correct abstract host methods. + void _writeProxyApiMessageHandlerMethod( + Indent indent, + AstProxyApi api, { + required TypeDeclaration apiAsTypeDeclaration, + required String kotlinApiName, + required String dartPackageName, + required String fullKotlinClassName, + }) { + indent.writeln('@Suppress("LocalVariableName")'); + indent.writeScoped( + 'fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: $kotlinApiName?) {', + '}', + () { + indent.writeln( + 'val codec = api?.codec ?: StandardMessageCodec()', + ); + void writeWithApiCheckIfNecessary( + List types, { + required String channelName, + required void Function() onWrite, + }) { + final TypeDeclaration? typeWithRequirement = + _typeWithHighestApiRequirement(types); + if (typeWithRequirement != null) { + final int apiRequirement = typeWithRequirement + .associatedProxyApi!.kotlinOptions!.minAndroidApi!; + indent.writeScoped( + 'if (android.os.Build.VERSION.SDK_INT >= $apiRequirement) {', + '}', + onWrite, + addTrailingNewline: false, + ); + indent.writeScoped(' else {', '}', () { + final String className = typeWithRequirement + .associatedProxyApi?.kotlinOptions?.fullClassName ?? + typeWithRequirement.baseName; + indent.format( + 'val channel = BasicMessageChannel(\n' + ' binaryMessenger,\n' + ' "$channelName",\n' + ' codec\n' + ')\n' + 'if (api != null) {\n' + ' channel.setMessageHandler { _, reply ->\n' + ' reply.reply(wrapError(\n' + ' UnsupportedOperationException(\n' + ' "Call references class `$className`, which requires api version $apiRequirement.")))\n' + ' }\n' + '} else {\n' + ' channel.setMessageHandler(null)\n' + '}', + ); + }); + } else { + onWrite(); + } + } + + for (final Constructor constructor in api.constructors) { + final String name = constructor.name.isNotEmpty + ? constructor.name + : '${classMemberNamePrefix}defaultConstructor'; + final String channelName = makeChannelNameWithStrings( + apiName: api.name, + methodName: name, + dartPackageName: dartPackageName, + ); + writeWithApiCheckIfNecessary( + [ + apiAsTypeDeclaration, + ...api.unattachedFields.map((ApiField f) => f.type), + ...constructor.parameters.map((Parameter p) => p.type), + ], + channelName: channelName, + onWrite: () { + _writeHostMethodMessageHandler( + indent, + api: api, + name: name, + channelName: channelName, + taskQueueType: TaskQueueType.serial, + returnType: const TypeDeclaration.voidDeclaration(), + onCreateCall: ( + List methodParameters, { + required String apiVarName, + }) { + return '$apiVarName.codec.instanceManager.addDartCreatedInstance(' + '$apiVarName.$name(${methodParameters.skip(1).join(',')}), ${methodParameters.first})'; + }, + parameters: [ + Parameter( + name: '${classMemberNamePrefix}identifier', + type: const TypeDeclaration( + baseName: 'int', + isNullable: false, + ), + ), + ...api.unattachedFields.map((ApiField field) { + return Parameter( + name: field.name, + type: field.type, + ); + }), + ...constructor.parameters, + ], + ); + }, + ); + } + + for (final ApiField field in api.attachedFields) { + final String channelName = makeChannelNameWithStrings( + apiName: api.name, + methodName: field.name, + dartPackageName: dartPackageName, + ); + writeWithApiCheckIfNecessary( + [apiAsTypeDeclaration, field.type], + channelName: channelName, + onWrite: () { + _writeHostMethodMessageHandler( + indent, + api: api, + name: field.name, + channelName: channelName, + taskQueueType: TaskQueueType.serial, + returnType: const TypeDeclaration.voidDeclaration(), + onCreateCall: ( + List methodParameters, { + required String apiVarName, + }) { + final String param = + methodParameters.length > 1 ? methodParameters.first : ''; + return '$apiVarName.codec.instanceManager.addDartCreatedInstance(' + '$apiVarName.${field.name}($param), ${methodParameters.last})'; + }, + parameters: [ + if (!field.isStatic) + Parameter( + name: '${classMemberNamePrefix}instance', + type: apiAsTypeDeclaration, + ), + Parameter( + name: '${classMemberNamePrefix}identifier', + type: const TypeDeclaration( + baseName: 'int', + isNullable: false, + ), + ), + ], + ); + }, + ); + } + + for (final Method method in api.hostMethods) { + final String channelName = + makeChannelName(api, method, dartPackageName); + writeWithApiCheckIfNecessary( + [ + if (!method.isStatic) apiAsTypeDeclaration, + method.returnType, + ...method.parameters.map((Parameter p) => p.type), + ], + channelName: channelName, + onWrite: () { + _writeHostMethodMessageHandler( + indent, + api: api, + name: method.name, + channelName: makeChannelName(api, method, dartPackageName), + taskQueueType: method.taskQueueType, + returnType: method.returnType, + isAsynchronous: method.isAsynchronous, + parameters: [ + if (!method.isStatic) + Parameter( + name: '${classMemberNamePrefix}instance', + type: TypeDeclaration( + baseName: fullKotlinClassName, + isNullable: false, + associatedProxyApi: api, + ), + ), + ...method.parameters, + ], + ); + }, + ); + } + }, + ); + } + + // Writes the method that calls to Dart to instantiate a new Dart instance. + void _writeProxyApiNewInstanceMethod( + Indent indent, + AstProxyApi api, { + required KotlinOptions generatorOptions, + required TypeDeclaration apiAsTypeDeclaration, + required String newInstanceMethodName, + required String dartPackageName, + }) { + indent.writeln('@Suppress("LocalVariableName", "FunctionName")'); + _writeFlutterMethod( + indent, + generatorOptions: generatorOptions, + name: newInstanceMethodName, + returnType: const TypeDeclaration.voidDeclaration(), + documentationComments: [ + 'Creates a Dart instance of ${api.name} and attaches it to [${classMemberNamePrefix}instanceArg].', + ], + channelName: makeChannelNameWithStrings( + apiName: api.name, + methodName: newInstanceMethodName, + dartPackageName: dartPackageName, + ), + minApiRequirement: _typeWithHighestApiRequirement([ + apiAsTypeDeclaration, + ...api.unattachedFields.map((ApiField field) => field.type), + ])?.associatedProxyApi?.kotlinOptions?.minAndroidApi, + dartPackageName: dartPackageName, + parameters: [ + Parameter( + name: '${classMemberNamePrefix}instance', + type: TypeDeclaration( + baseName: api.name, + isNullable: false, + associatedProxyApi: api, + ), + ), + ], + onWriteBody: ( + Indent indent, { + required List parameters, + required TypeDeclaration returnType, + required String channelName, + required String errorClassName, + }) { + indent.writeScoped( + 'if (codec.instanceManager.containsInstance(${classMemberNamePrefix}instanceArg)) {', + '}', + () { + indent.writeln('Result.success(Unit)'); + indent.writeln('return'); + }, + ); + if (api.hasCallbackConstructor()) { + indent.writeln( + 'val ${classMemberNamePrefix}identifierArg = codec.instanceManager.addHostCreatedInstance(${classMemberNamePrefix}instanceArg)', + ); + enumerate(api.unattachedFields, (int index, ApiField field) { + final String argName = _getSafeArgumentName(index, field); + indent.writeln( + 'val $argName = ${field.name}(${classMemberNamePrefix}instanceArg)', + ); + }); + + indent.writeln('val binaryMessenger = codec.binaryMessenger'); + _writeFlutterMethodMessageCall( + indent, + returnType: returnType, + channelName: channelName, + errorClassName: errorClassName, + parameters: [ + Parameter( + name: '${classMemberNamePrefix}identifier', + type: const TypeDeclaration( + baseName: 'int', + isNullable: false, + ), + ), + ...api.unattachedFields.map( + (ApiField field) { + return Parameter(name: field.name, type: field.type); + }, + ), + ], + ); + } else { + indent.writeln( + 'throw IllegalStateException("Attempting to create a new Dart instance of ${api.name}, but the class has a nonnull callback method.")', + ); + } + }, + ); + indent.newln(); + } + + // Writes the Flutter methods that call back to Dart. + void _writeProxyApiFlutterMethods( + Indent indent, + AstProxyApi api, { + required KotlinOptions generatorOptions, + required TypeDeclaration apiAsTypeDeclaration, + required String dartPackageName, + }) { + for (final Method method in api.flutterMethods) { + _writeFlutterMethod( + indent, + generatorOptions: generatorOptions, + name: method.name, + returnType: method.returnType, + channelName: makeChannelName(api, method, dartPackageName), + dartPackageName: dartPackageName, + documentationComments: method.documentationComments, + minApiRequirement: _typeWithHighestApiRequirement([ + apiAsTypeDeclaration, + method.returnType, + ...method.parameters.map((Parameter p) => p.type), + ])?.associatedProxyApi?.kotlinOptions?.minAndroidApi, + parameters: [ + Parameter( + name: '${classMemberNamePrefix}instance', + type: TypeDeclaration( + baseName: api.name, + isNullable: false, + associatedProxyApi: api, + ), + ), + ...method.parameters, + ], + onWriteBody: ( + Indent indent, { + required List parameters, + required TypeDeclaration returnType, + required String channelName, + required String errorClassName, + }) { + indent.writeln('val binaryMessenger = codec.binaryMessenger'); + _writeFlutterMethodMessageCall( + indent, + returnType: returnType, + channelName: channelName, + errorClassName: errorClassName, + parameters: parameters, + ); + }, + ); + indent.newln(); + } + } + + // Writes the getters for accessing the implementation of other ProxyApis. + // + // These are used for inherited Flutter methods. + void _writeProxyApiInheritedApiMethods(Indent indent, AstProxyApi api) { + final Set inheritedApiNames = { + if (api.superClass != null) api.superClass!.baseName, + ...api.interfaces.map((TypeDeclaration type) => type.baseName), + }; + for (final String name in inheritedApiNames) { + indent.writeln('@Suppress("FunctionName")'); + final String apiName = '$hostApiPrefix$name'; + _writeMethodDeclaration( + indent, + name: '${classMemberNamePrefix}get$apiName', + documentationComments: [ + 'An implementation of [$apiName] used to access callback methods', + ], + returnType: TypeDeclaration(baseName: apiName, isNullable: false), + parameters: [], + ); + + indent.writeScoped('{', '}', () { + indent.writeln('return codec.get$apiName()'); + }); + indent.newln(); + } + } +} + +TypeDeclaration? _typeWithHighestApiRequirement( + Iterable types, +) { + int highestMin = 1; + TypeDeclaration? highestNamedType; + + for (final TypeDeclaration type in types) { + final int? typeMin = type.associatedProxyApi?.kotlinOptions?.minAndroidApi; + final int? typeArgumentMin = _typeWithHighestApiRequirement( + type.typeArguments, + )?.associatedProxyApi?.kotlinOptions?.minAndroidApi; + final int newMin = max(typeMin ?? 1, typeArgumentMin ?? 1); + + if (newMin > highestMin) { + highestMin = newMin; + highestNamedType = type; + } + } + + return highestMin == 1 ? null : highestNamedType; } HostDatatype _getHostDatatype(Root root, NamedType field) { @@ -953,8 +1744,19 @@ String? _kotlinTypeForBuiltinDartType(TypeDeclaration type) { } } +String? _kotlinTypeForProxyApiType(TypeDeclaration type) { + if (type.isProxyApi) { + return type.associatedProxyApi!.kotlinOptions?.fullClassName ?? + type.associatedProxyApi!.name; + } + + return null; +} + String _kotlinTypeForDartType(TypeDeclaration type) { - return _kotlinTypeForBuiltinDartType(type) ?? type.baseName; + return _kotlinTypeForBuiltinDartType(type) ?? + _kotlinTypeForProxyApiType(type) ?? + type.baseName; } String _nullSafeKotlinTypeForDartType(TypeDeclaration type) { diff --git a/packages/pigeon/lib/pigeon.dart b/packages/pigeon/lib/pigeon.dart index 7f2fb7505fa..aa84da034c7 100644 --- a/packages/pigeon/lib/pigeon.dart +++ b/packages/pigeon/lib/pigeon.dart @@ -7,7 +7,7 @@ export 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; export 'cpp_generator.dart' show CppOptions; export 'dart_generator.dart' show DartOptions; export 'java_generator.dart' show JavaOptions; -export 'kotlin_generator.dart' show KotlinOptions; +export 'kotlin_generator.dart' show KotlinOptions, KotlinProxyApiOptions; export 'objc_generator.dart' show ObjcOptions; export 'pigeon_lib.dart'; export 'swift_generator.dart' show SwiftOptions; diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 8f418d04259..47d076870e2 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -138,7 +138,7 @@ class FlutterApi { /// methods. class ProxyApi { /// Parametric constructor for [ProxyApi]. - const ProxyApi({this.superClass}); + const ProxyApi({this.superClass, this.kotlinOptions}); /// The proxy api that is a super class to this one. /// @@ -148,6 +148,10 @@ class ProxyApi { /// Note that using this instead of `extends` can cause unexpected conflicts /// with inherited method names. final Type? superClass; + + /// Options that control how Kotlin code will be generated for a specific + /// ProxyApi. + final KotlinProxyApiOptions? kotlinOptions; } /// Metadata to annotation methods to control the selector used for objc output. @@ -1535,6 +1539,16 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { } } + KotlinProxyApiOptions? kotlinOptions; + final Map? kotlinOptionsMap = + annotationMap['kotlinOptions'] as Map?; + if (kotlinOptionsMap != null) { + kotlinOptions = KotlinProxyApiOptions( + fullClassName: kotlinOptionsMap['fullClassName']! as String, + minAndroidApi: kotlinOptionsMap['minAndroidApi'] as int?, + ); + } + _currentApi = AstProxyApi( name: node.name.lexeme, methods: [], @@ -1542,6 +1556,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { fields: [], superClass: superClass, interfaces: interfaces, + kotlinOptions: kotlinOptions, documentationComments: _documentationCommentsParser(node.documentationComment?.tokens), ); diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/generated.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/generated.dart index 31aff33a3f3..b7861ee4d57 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/generated.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/generated.dart @@ -3,3 +3,5 @@ // found in the LICENSE file. export 'src/generated/core_tests.gen.dart'; +export 'src/generated/proxy_api_tests.gen.dart' + show ProxyApiSuperClass, ProxyApiTestClass, ProxyApiTestEnum; diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/integration_tests.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/integration_tests.dart index 4ebee6b740a..3241de598c9 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/integration_tests.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/integration_tests.dart @@ -1470,6 +1470,596 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) { expect(echoEnum, sentEnum); }); }); + + group('Proxy API Tests', () { + if (targetGenerator != TargetGenerator.kotlin) { + return; + } + + testWidgets('noop', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + await expectLater(api.noop(), completes); + }); + + testWidgets('throwError', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + await expectLater( + () => api.throwError(), + throwsA(isA()), + ); + }); + + testWidgets('throwErrorFromVoid', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + await expectLater( + () => api.throwErrorFromVoid(), + throwsA(isA()), + ); + }); + + testWidgets('throwFlutterError', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + await expectLater( + () => api.throwFlutterError(), + throwsA( + (dynamic e) { + return e is PlatformException && + e.code == 'code' && + e.message == 'message' && + e.details == 'details'; + }, + ), + ); + }); + + testWidgets('echoInt', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const int value = 0; + expect(await api.echoInt(value), value); + }); + + testWidgets('echoDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const double value = 0.0; + expect(await api.echoDouble(value), value); + }); + + testWidgets('echoBool', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const bool value = true; + expect(await api.echoBool(value), value); + }); + + testWidgets('echoString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const String value = 'string'; + expect(await api.echoString(value), value); + }); + + testWidgets('echoUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + final Uint8List value = Uint8List(0); + expect(await api.echoUint8List(value), value); + }); + + testWidgets('echoObject', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const Object value = 'apples'; + expect(await api.echoObject(value), value); + }); + + testWidgets('echoList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const List value = [1, 2]; + expect(await api.echoList(value), value); + }); + + testWidgets('echoProxyApiList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + final List value = [ + _createGenericProxyApiTestClass(), + _createGenericProxyApiTestClass(), + ]; + expect(await api.echoProxyApiList(value), value); + }); + + testWidgets('echoMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const Map value = {'apple': 'pie'}; + expect(await api.echoMap(value), value); + }); + + testWidgets('echoProxyApiMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + final Map value = + { + '42': _createGenericProxyApiTestClass(), + }; + expect(await api.echoProxyApiMap(value), value); + }); + + testWidgets('echoEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const ProxyApiTestEnum value = ProxyApiTestEnum.three; + expect(await api.echoEnum(value), value); + }); + + testWidgets('echoProxyApi', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + final ProxyApiSuperClass value = ProxyApiSuperClass(); + expect(await api.echoProxyApi(value), value); + }); + + testWidgets('echoNullableInt', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableInt(null), null); + }); + + testWidgets('echoNullableDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableDouble(null), null); + }); + + testWidgets('echoNullableBool', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableBool(null), null); + }); + + testWidgets('echoNullableString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableString(null), null); + }); + + testWidgets('echoNullableUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableUint8List(null), null); + }); + + testWidgets('echoNullableObject', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableObject(null), null); + }); + + testWidgets('echoNullableList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableList(null), null); + }); + + testWidgets('echoNullableMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableMap(null), null); + }); + + testWidgets('echoNullableEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableEnum(null), null); + }); + + testWidgets('echoNullableProxyApi', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableProxyApi(null), null); + }); + + testWidgets('noopAsync', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + await expectLater(api.noopAsync(), completes); + }); + + testWidgets('echoAsyncInt', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const int value = 0; + expect(await api.echoAsyncInt(value), value); + }); + + testWidgets('echoAsyncDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const double value = 0.0; + expect(await api.echoAsyncDouble(value), value); + }); + + testWidgets('echoAsyncBool', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const bool value = false; + expect(await api.echoAsyncBool(value), value); + }); + + testWidgets('echoAsyncString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const String value = 'ping'; + expect(await api.echoAsyncString(value), value); + }); + + testWidgets('echoAsyncUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + final Uint8List value = Uint8List(0); + expect(await api.echoAsyncUint8List(value), value); + }); + + testWidgets('echoAsyncObject', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const Object value = 0; + expect(await api.echoAsyncObject(value), value); + }); + + testWidgets('echoAsyncList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const List value = ['apple', 'pie']; + expect(await api.echoAsyncList(value), value); + }); + + testWidgets('echoAsyncMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + final Map value = { + 'something': ProxyApiSuperClass(), + }; + expect(await api.echoAsyncMap(value), value); + }); + + testWidgets('echoAsyncEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + const ProxyApiTestEnum value = ProxyApiTestEnum.two; + expect(await api.echoAsyncEnum(value), value); + }); + + testWidgets('throwAsyncError', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + await expectLater( + () => api.throwAsyncError(), + throwsA(isA()), + ); + }); + + testWidgets('throwAsyncErrorFromVoid', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + await expectLater( + () => api.throwAsyncErrorFromVoid(), + throwsA(isA()), + ); + }); + + testWidgets('throwAsyncFlutterError', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + + await expectLater( + () => api.throwAsyncFlutterError(), + throwsA( + (dynamic e) { + return e is PlatformException && + e.code == 'code' && + e.message == 'message' && + e.details == 'details'; + }, + ), + ); + }); + + testWidgets('echoAsyncNullableInt', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableInt(null), null); + }); + + testWidgets('echoAsyncNullableDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableDouble(null), null); + }); + + testWidgets('echoAsyncNullableBool', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableBool(null), null); + }); + + testWidgets('echoAsyncNullableString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableString(null), null); + }); + + testWidgets('echoAsyncNullableUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableUint8List(null), null); + }); + + testWidgets('echoAsyncNullableObject', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableObject(null), null); + }); + + testWidgets('echoAsyncNullableList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableList(null), null); + }); + + testWidgets('echoAsyncNullableMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableMap(null), null); + }); + + testWidgets('echoAsyncNullableEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableEnum(null), null); + }); + + testWidgets('staticNoop', (_) async { + await expectLater(ProxyApiTestClass.staticNoop(), completes); + }); + + testWidgets('echoStaticString', (_) async { + const String value = 'static string'; + expect(await ProxyApiTestClass.echoStaticString(value), value); + }); + + testWidgets('staticAsyncNoop', (_) async { + await expectLater(ProxyApiTestClass.staticAsyncNoop(), completes); + }); + + testWidgets('callFlutterNoop', (_) async { + bool called = false; + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterNoop: (ProxyApiTestClass instance) async { + called = true; + }, + ); + + await api.callFlutterNoop(); + expect(called, isTrue); + }); + + testWidgets('callFlutterThrowError', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterThrowError: (_) { + throw FlutterError('this is an error'); + }, + ); + + await expectLater( + api.callFlutterThrowError(), + throwsA( + isA().having( + (PlatformException exception) => exception.message, + 'message', + equals('this is an error'), + ), + ), + ); + }); + + testWidgets('callFlutterThrowErrorFromVoid', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterThrowErrorFromVoid: (_) { + throw FlutterError('this is an error'); + }, + ); + + await expectLater( + api.callFlutterThrowErrorFromVoid(), + throwsA( + isA().having( + (PlatformException exception) => exception.message, + 'message', + equals('this is an error'), + ), + ), + ); + }); + + testWidgets('callFlutterEchoBool', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoBool: (_, bool aBool) => aBool, + ); + + const bool value = true; + expect(await api.callFlutterEchoBool(value), value); + }); + + testWidgets('callFlutterEchoInt', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoInt: (_, int anInt) => anInt, + ); + + const int value = 0; + expect(await api.callFlutterEchoInt(value), value); + }); + + testWidgets('callFlutterEchoDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoDouble: (_, double aDouble) => aDouble, + ); + + const double value = 0.0; + expect(await api.callFlutterEchoDouble(value), value); + }); + + testWidgets('callFlutterEchoString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoString: (_, String aString) => aString, + ); + + const String value = 'a string'; + expect(await api.callFlutterEchoString(value), value); + }); + + testWidgets('callFlutterEchoUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoUint8List: (_, Uint8List aUint8List) => aUint8List, + ); + + final Uint8List value = Uint8List(0); + expect(await api.callFlutterEchoUint8List(value), value); + }); + + testWidgets('callFlutterEchoList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoList: (_, List aList) => aList, + ); + + final List value = [0, 0.0, true, ProxyApiSuperClass()]; + expect(await api.callFlutterEchoList(value), value); + }); + + testWidgets('callFlutterEchoProxyApiList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoProxyApiList: (_, List aList) => aList, + ); + + final List value = [ + _createGenericProxyApiTestClass(), + ]; + expect(await api.callFlutterEchoProxyApiList(value), value); + }); + + testWidgets('callFlutterEchoMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoMap: (_, Map aMap) => aMap, + ); + + final Map value = { + 'a String': 4, + }; + expect(await api.callFlutterEchoMap(value), value); + }); + + testWidgets('callFlutterEchoProxyApiMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoProxyApiMap: (_, Map aMap) => + aMap, + ); + + final Map value = + { + 'a String': _createGenericProxyApiTestClass(), + }; + expect(await api.callFlutterEchoProxyApiMap(value), value); + }); + + testWidgets('callFlutterEchoEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoEnum: (_, ProxyApiTestEnum anEnum) => anEnum, + ); + + const ProxyApiTestEnum value = ProxyApiTestEnum.three; + expect(await api.callFlutterEchoEnum(value), value); + }); + + testWidgets('callFlutterEchoProxyApi', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoProxyApi: (_, ProxyApiSuperClass aProxyApi) => aProxyApi, + ); + + final ProxyApiSuperClass value = ProxyApiSuperClass(); + expect(await api.callFlutterEchoProxyApi(value), value); + }); + + testWidgets('callFlutterEchoNullableBool', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableBool: (_, bool? aBool) => aBool, + ); + expect(await api.callFlutterEchoNullableBool(null), null); + }); + + testWidgets('callFlutterEchoNullableInt', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableInt: (_, int? anInt) => anInt, + ); + expect(await api.callFlutterEchoNullableInt(null), null); + }); + + testWidgets('callFlutterEchoNullableDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableDouble: (_, double? aDouble) => aDouble, + ); + expect(await api.callFlutterEchoNullableDouble(null), null); + }); + + testWidgets('callFlutterEchoNullableString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableString: (_, String? aString) => aString, + ); + expect(await api.callFlutterEchoNullableString(null), null); + }); + + testWidgets('callFlutterEchoNullableUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableUint8List: (_, Uint8List? aUint8List) => aUint8List, + ); + expect(await api.callFlutterEchoNullableUint8List(null), null); + }); + + testWidgets('callFlutterEchoNullableList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableList: (_, List? aList) => aList, + ); + expect(await api.callFlutterEchoNullableList(null), null); + }); + + testWidgets('callFlutterEchoNullableMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableMap: (_, Map? aMap) => aMap, + ); + expect(await api.callFlutterEchoNullableMap(null), null); + }); + + testWidgets('callFlutterEchoNullableEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableEnum: (_, ProxyApiTestEnum? anEnum) => anEnum, + ); + expect(await api.callFlutterEchoNullableEnum(null), null); + }); + + testWidgets('callFlutterEchoNullableProxyApi', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableProxyApi: (_, ProxyApiSuperClass? aProxyApi) => + aProxyApi, + ); + expect(await api.callFlutterEchoNullableProxyApi(null), null); + }); + + testWidgets('callFlutterNoopAsync', (_) async { + bool called = false; + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterNoopAsync: (ProxyApiTestClass instance) async { + called = true; + }, + ); + + await api.callFlutterNoopAsync(); + expect(called, isTrue); + }); + + testWidgets('callFlutterEchoAsyncString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoAsyncString: (_, String aString) async => aString, + ); + + const String value = 'a string'; + expect(await api.callFlutterEchoAsyncString(value), value); + }); + }); } class _FlutterApiTestImplementation implements FlutterIntegrationCoreApi { @@ -1561,3 +2151,142 @@ class _FlutterApiTestImplementation implements FlutterIntegrationCoreApi { return aString; } } + +ProxyApiTestClass _createGenericProxyApiTestClass({ + void Function(ProxyApiTestClass instance)? flutterNoop, + Object? Function(ProxyApiTestClass instance)? flutterThrowError, + void Function( + ProxyApiTestClass instance, + )? flutterThrowErrorFromVoid, + bool Function( + ProxyApiTestClass instance, + bool aBool, + )? flutterEchoBool, + int Function( + ProxyApiTestClass instance, + int anInt, + )? flutterEchoInt, + double Function( + ProxyApiTestClass instance, + double aDouble, + )? flutterEchoDouble, + String Function( + ProxyApiTestClass instance, + String aString, + )? flutterEchoString, + Uint8List Function( + ProxyApiTestClass instance, + Uint8List aList, + )? flutterEchoUint8List, + List Function( + ProxyApiTestClass instance, + List aList, + )? flutterEchoList, + List Function( + ProxyApiTestClass instance, + List aList, + )? flutterEchoProxyApiList, + Map Function( + ProxyApiTestClass instance, + Map aMap, + )? flutterEchoMap, + Map Function( + ProxyApiTestClass instance, + Map aMap, + )? flutterEchoProxyApiMap, + ProxyApiTestEnum Function( + ProxyApiTestClass instance, + ProxyApiTestEnum anEnum, + )? flutterEchoEnum, + ProxyApiSuperClass Function( + ProxyApiTestClass instance, + ProxyApiSuperClass aProxyApi, + )? flutterEchoProxyApi, + bool? Function( + ProxyApiTestClass instance, + bool? aBool, + )? flutterEchoNullableBool, + int? Function( + ProxyApiTestClass instance, + int? anInt, + )? flutterEchoNullableInt, + double? Function( + ProxyApiTestClass instance, + double? aDouble, + )? flutterEchoNullableDouble, + String? Function( + ProxyApiTestClass instance, + String? aString, + )? flutterEchoNullableString, + Uint8List? Function( + ProxyApiTestClass instance, + Uint8List? aList, + )? flutterEchoNullableUint8List, + List? Function( + ProxyApiTestClass instance, + List? aList, + )? flutterEchoNullableList, + Map? Function( + ProxyApiTestClass instance, + Map? aMap, + )? flutterEchoNullableMap, + ProxyApiTestEnum? Function( + ProxyApiTestClass instance, + ProxyApiTestEnum? anEnum, + )? flutterEchoNullableEnum, + ProxyApiSuperClass? Function( + ProxyApiTestClass instance, + ProxyApiSuperClass? aProxyApi, + )? flutterEchoNullableProxyApi, + Future Function(ProxyApiTestClass instance)? flutterNoopAsync, + Future Function( + ProxyApiTestClass instance, + String aString, + )? flutterEchoAsyncString, +}) { + return ProxyApiTestClass( + aBool: true, + anInt: 0, + aDouble: 0.0, + aString: '', + aUint8List: Uint8List(0), + aList: const [], + aMap: const {}, + anEnum: ProxyApiTestEnum.one, + aProxyApi: ProxyApiSuperClass(), + boolParam: true, + intParam: 0, + doubleParam: 0.0, + stringParam: '', + aUint8ListParam: Uint8List(0), + listParam: const [], + mapParam: const {}, + enumParam: ProxyApiTestEnum.one, + proxyApiParam: ProxyApiSuperClass(), + flutterNoop: flutterNoop, + flutterThrowError: flutterThrowError, + flutterThrowErrorFromVoid: flutterThrowErrorFromVoid, + flutterEchoBool: flutterEchoBool, + flutterEchoInt: flutterEchoInt, + flutterEchoDouble: flutterEchoDouble, + flutterEchoString: flutterEchoString, + flutterEchoUint8List: flutterEchoUint8List, + flutterEchoList: flutterEchoList, + flutterEchoProxyApiList: flutterEchoProxyApiList, + flutterEchoMap: flutterEchoMap, + flutterEchoProxyApiMap: flutterEchoProxyApiMap, + flutterEchoEnum: flutterEchoEnum, + flutterEchoProxyApi: flutterEchoProxyApi, + flutterEchoNullableBool: flutterEchoNullableBool, + flutterEchoNullableInt: flutterEchoNullableInt, + flutterEchoNullableDouble: flutterEchoNullableDouble, + flutterEchoNullableString: flutterEchoNullableString, + flutterEchoNullableUint8List: flutterEchoNullableUint8List, + flutterEchoNullableList: flutterEchoNullableList, + flutterEchoNullableMap: flutterEchoNullableMap, + flutterEchoNullableEnum: flutterEchoNullableEnum, + flutterEchoNullableProxyApi: flutterEchoNullableProxyApi, + flutterNoopAsync: flutterNoopAsync, + flutterEchoAsyncString: flutterEchoAsyncString, + ); +} diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/.gitignore b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/.gitignore index a870aa16cae..4ec9cb9997a 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/.gitignore +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/.gitignore @@ -3,4 +3,6 @@ # such as a flag to suppress version stamp generation. *.kt !TestPlugin.kt -!CoreTests.gen.kt \ No newline at end of file +!CoreTests.gen.kt +!ProxyApiTestApiImpls.kt +!ProxyApiTests.gen.kt diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/ProxyApiTestApiImpls.kt b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/ProxyApiTestApiImpls.kt new file mode 100644 index 00000000000..0843e4aac79 --- /dev/null +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/ProxyApiTestApiImpls.kt @@ -0,0 +1,684 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package com.example.test_plugin + +import io.flutter.plugin.common.BinaryMessenger + +class ProxyApiTestClass : ProxyApiSuperClass(), ProxyApiInterface + +open class ProxyApiSuperClass + +interface ProxyApiInterface + +class ProxyApiCodec(binaryMessenger: BinaryMessenger, instanceManager: PigeonInstanceManager) : + PigeonProxyApiBaseCodec(binaryMessenger, instanceManager) { + override fun getPigeonApiProxyApiTestClass(): PigeonApiProxyApiTestClass { + return ProxyApiTestClassApi(this) + } + + override fun getPigeonApiProxyApiSuperClass(): PigeonApiProxyApiSuperClass { + return ProxyApiSuperClassApi(this) + } + + override fun getPigeonApiProxyApiInterface(): PigeonApiProxyApiInterface { + return ProxyApiInterfaceApi(this) + } +} + +class ProxyApiTestClassApi(codec: PigeonProxyApiBaseCodec) : PigeonApiProxyApiTestClass(codec) { + + override fun pigeon_defaultConstructor( + aBool: Boolean, + anInt: Long, + aDouble: Double, + aString: String, + aUint8List: ByteArray, + aList: List, + aMap: Map, + anEnum: ProxyApiTestEnum, + aProxyApi: ProxyApiSuperClass, + aNullableBool: Boolean?, + aNullableInt: Long?, + aNullableDouble: Double?, + aNullableString: String?, + aNullableUint8List: ByteArray?, + aNullableList: List?, + aNullableMap: Map?, + aNullableEnum: ProxyApiTestEnum?, + aNullableProxyApi: ProxyApiSuperClass?, + boolParam: Boolean, + intParam: Long, + doubleParam: Double, + stringParam: String, + aUint8ListParam: ByteArray, + listParam: List, + mapParam: Map, + enumParam: ProxyApiTestEnum, + proxyApiParam: ProxyApiSuperClass, + nullableBoolParam: Boolean?, + nullableIntParam: Long?, + nullableDoubleParam: Double?, + nullableStringParam: String?, + nullableUint8ListParam: ByteArray?, + nullableListParam: List?, + nullableMapParam: Map?, + nullableEnumParam: ProxyApiTestEnum?, + nullableProxyApiParam: ProxyApiSuperClass? + ): ProxyApiTestClass { + return ProxyApiTestClass() + } + + override fun attachedField(pigeon_instance: ProxyApiTestClass): ProxyApiSuperClass { + return ProxyApiSuperClass() + } + + override fun staticAttachedField(): ProxyApiSuperClass { + return ProxyApiSuperClass() + } + + override fun aBool(pigeon_instance: ProxyApiTestClass): Boolean { + return true + } + + override fun anInt(pigeon_instance: ProxyApiTestClass): Long { + return 0 + } + + override fun aDouble(pigeon_instance: ProxyApiTestClass): Double { + return 0.0 + } + + override fun aString(pigeon_instance: ProxyApiTestClass): String { + return "" + } + + override fun aUint8List(pigeon_instance: ProxyApiTestClass): ByteArray { + return byteArrayOf() + } + + override fun aList(pigeon_instance: ProxyApiTestClass): List { + return listOf() + } + + override fun aMap(pigeon_instance: ProxyApiTestClass): Map { + return mapOf() + } + + override fun anEnum(pigeon_instance: ProxyApiTestClass): ProxyApiTestEnum { + return ProxyApiTestEnum.ONE + } + + override fun aProxyApi(pigeon_instance: ProxyApiTestClass): ProxyApiSuperClass { + return ProxyApiSuperClass() + } + + override fun aNullableBool(pigeon_instance: ProxyApiTestClass): Boolean? { + return null + } + + override fun aNullableInt(pigeon_instance: ProxyApiTestClass): Long? { + return null + } + + override fun aNullableDouble(pigeon_instance: ProxyApiTestClass): Double? { + return null + } + + override fun aNullableString(pigeon_instance: ProxyApiTestClass): String? { + return null + } + + override fun aNullableUint8List(pigeon_instance: ProxyApiTestClass): ByteArray? { + return null + } + + override fun aNullableList(pigeon_instance: ProxyApiTestClass): List? { + return null + } + + override fun aNullableMap(pigeon_instance: ProxyApiTestClass): Map? { + return null + } + + override fun aNullableEnum(pigeon_instance: ProxyApiTestClass): ProxyApiTestEnum? { + return null + } + + override fun aNullableProxyApi(pigeon_instance: ProxyApiTestClass): ProxyApiSuperClass? { + return null + } + + override fun noop(pigeon_instance: ProxyApiTestClass) {} + + override fun throwError(pigeon_instance: ProxyApiTestClass): Any? { + throw Exception("message") + } + + override fun throwErrorFromVoid(pigeon_instance: ProxyApiTestClass) { + throw Exception("message") + } + + override fun throwFlutterError(pigeon_instance: ProxyApiTestClass): Any? { + throw ProxyApiTestsError("code", "message", "details") + } + + override fun echoInt(pigeon_instance: ProxyApiTestClass, anInt: Long): Long { + return anInt + } + + override fun echoDouble(pigeon_instance: ProxyApiTestClass, aDouble: Double): Double { + return aDouble + } + + override fun echoBool(pigeon_instance: ProxyApiTestClass, aBool: Boolean): Boolean { + return aBool + } + + override fun echoString(pigeon_instance: ProxyApiTestClass, aString: String): String { + return aString + } + + override fun echoUint8List(pigeon_instance: ProxyApiTestClass, aUint8List: ByteArray): ByteArray { + return aUint8List + } + + override fun echoObject(pigeon_instance: ProxyApiTestClass, anObject: Any): Any { + return anObject + } + + override fun echoList(pigeon_instance: ProxyApiTestClass, aList: List): List { + return aList + } + + override fun echoProxyApiList( + pigeon_instance: ProxyApiTestClass, + aList: List + ): List { + return aList + } + + override fun echoMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map + ): Map { + return aMap + } + + override fun echoProxyApiMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map + ): Map { + return aMap + } + + override fun echoEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum + ): ProxyApiTestEnum { + return anEnum + } + + override fun echoProxyApi( + pigeon_instance: ProxyApiTestClass, + aProxyApi: ProxyApiSuperClass + ): ProxyApiSuperClass { + return aProxyApi + } + + override fun echoNullableInt(pigeon_instance: ProxyApiTestClass, aNullableInt: Long?): Long? { + return aNullableInt + } + + override fun echoNullableDouble( + pigeon_instance: ProxyApiTestClass, + aNullableDouble: Double? + ): Double? { + return aNullableDouble + } + + override fun echoNullableBool( + pigeon_instance: ProxyApiTestClass, + aNullableBool: Boolean? + ): Boolean? { + return aNullableBool + } + + override fun echoNullableString( + pigeon_instance: ProxyApiTestClass, + aNullableString: String? + ): String? { + return aNullableString + } + + override fun echoNullableUint8List( + pigeon_instance: ProxyApiTestClass, + aNullableUint8List: ByteArray? + ): ByteArray? { + return aNullableUint8List + } + + override fun echoNullableObject(pigeon_instance: ProxyApiTestClass, aNullableObject: Any?): Any? { + return aNullableObject + } + + override fun echoNullableList( + pigeon_instance: ProxyApiTestClass, + aNullableList: List? + ): List? { + return aNullableList + } + + override fun echoNullableMap( + pigeon_instance: ProxyApiTestClass, + aNullableMap: Map? + ): Map? { + return aNullableMap + } + + override fun echoNullableEnum( + pigeon_instance: ProxyApiTestClass, + aNullableEnum: ProxyApiTestEnum? + ): ProxyApiTestEnum? { + return aNullableEnum + } + + override fun echoNullableProxyApi( + pigeon_instance: ProxyApiTestClass, + aNullableProxyApi: ProxyApiSuperClass? + ): ProxyApiSuperClass? { + return aNullableProxyApi + } + + override fun noopAsync(pigeon_instance: ProxyApiTestClass, callback: (Result) -> Unit) { + callback(Result.success(Unit)) + } + + override fun echoAsyncInt( + pigeon_instance: ProxyApiTestClass, + anInt: Long, + callback: (Result) -> Unit + ) { + callback(Result.success(anInt)) + } + + override fun echoAsyncDouble( + pigeon_instance: ProxyApiTestClass, + aDouble: Double, + callback: (Result) -> Unit + ) { + callback(Result.success(aDouble)) + } + + override fun echoAsyncBool( + pigeon_instance: ProxyApiTestClass, + aBool: Boolean, + callback: (Result) -> Unit + ) { + callback(Result.success(aBool)) + } + + override fun echoAsyncString( + pigeon_instance: ProxyApiTestClass, + aString: String, + callback: (Result) -> Unit + ) { + callback(Result.success(aString)) + } + + override fun echoAsyncUint8List( + pigeon_instance: ProxyApiTestClass, + aUint8List: ByteArray, + callback: (Result) -> Unit + ) { + callback(Result.success(aUint8List)) + } + + override fun echoAsyncObject( + pigeon_instance: ProxyApiTestClass, + anObject: Any, + callback: (Result) -> Unit + ) { + callback(Result.success(anObject)) + } + + override fun echoAsyncList( + pigeon_instance: ProxyApiTestClass, + aList: List, + callback: (Result>) -> Unit + ) { + callback(Result.success(aList)) + } + + override fun echoAsyncMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map, + callback: (Result>) -> Unit + ) { + callback(Result.success(aMap)) + } + + override fun echoAsyncEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum, + callback: (Result) -> Unit + ) { + callback(Result.success(anEnum)) + } + + override fun throwAsyncError( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) { + callback(Result.failure(Exception("message"))) + } + + override fun throwAsyncErrorFromVoid( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) { + callback(Result.failure(Exception("message"))) + } + + override fun throwAsyncFlutterError( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) { + callback(Result.failure(ProxyApiTestsError("code", "message", "details"))) + } + + override fun echoAsyncNullableInt( + pigeon_instance: ProxyApiTestClass, + anInt: Long?, + callback: (Result) -> Unit + ) { + callback(Result.success(anInt)) + } + + override fun echoAsyncNullableDouble( + pigeon_instance: ProxyApiTestClass, + aDouble: Double?, + callback: (Result) -> Unit + ) { + callback(Result.success(aDouble)) + } + + override fun echoAsyncNullableBool( + pigeon_instance: ProxyApiTestClass, + aBool: Boolean?, + callback: (Result) -> Unit + ) { + callback(Result.success(aBool)) + } + + override fun echoAsyncNullableString( + pigeon_instance: ProxyApiTestClass, + aString: String?, + callback: (Result) -> Unit + ) { + callback(Result.success(aString)) + } + + override fun echoAsyncNullableUint8List( + pigeon_instance: ProxyApiTestClass, + aUint8List: ByteArray?, + callback: (Result) -> Unit + ) { + callback(Result.success(aUint8List)) + } + + override fun echoAsyncNullableObject( + pigeon_instance: ProxyApiTestClass, + anObject: Any?, + callback: (Result) -> Unit + ) { + callback(Result.success(anObject)) + } + + override fun echoAsyncNullableList( + pigeon_instance: ProxyApiTestClass, + aList: List?, + callback: (Result?>) -> Unit + ) { + callback(Result.success(aList)) + } + + override fun echoAsyncNullableMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map?, + callback: (Result?>) -> Unit + ) { + callback(Result.success(aMap)) + } + + override fun echoAsyncNullableEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum?, + callback: (Result) -> Unit + ) { + callback(Result.success(anEnum)) + } + + override fun staticNoop() {} + + override fun echoStaticString(aString: String): String { + return aString + } + + override fun staticAsyncNoop(callback: (Result) -> Unit) { + callback(Result.success(Unit)) + } + + override fun callFlutterNoop( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) { + flutterNoop(pigeon_instance, callback) + } + + override fun callFlutterThrowError( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) { + flutterThrowError(pigeon_instance) { result -> + val exception = result.exceptionOrNull() + callback(Result.failure(exception!!)) + } + } + + override fun callFlutterThrowErrorFromVoid( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) { + flutterThrowErrorFromVoid(pigeon_instance) { result -> + val exception = result.exceptionOrNull() + callback(Result.failure(exception!!)) + } + } + + override fun callFlutterEchoBool( + pigeon_instance: ProxyApiTestClass, + aBool: Boolean, + callback: (Result) -> Unit + ) { + flutterEchoBool(pigeon_instance, aBool, callback) + } + + override fun callFlutterEchoInt( + pigeon_instance: ProxyApiTestClass, + anInt: Long, + callback: (Result) -> Unit + ) { + flutterEchoInt(pigeon_instance, anInt, callback) + } + + override fun callFlutterEchoDouble( + pigeon_instance: ProxyApiTestClass, + aDouble: Double, + callback: (Result) -> Unit + ) { + flutterEchoDouble(pigeon_instance, aDouble, callback) + } + + override fun callFlutterEchoString( + pigeon_instance: ProxyApiTestClass, + aString: String, + callback: (Result) -> Unit + ) { + flutterEchoString(pigeon_instance, aString, callback) + } + + override fun callFlutterEchoUint8List( + pigeon_instance: ProxyApiTestClass, + aUint8List: ByteArray, + callback: (Result) -> Unit + ) { + flutterEchoUint8List(pigeon_instance, aUint8List, callback) + } + + override fun callFlutterEchoList( + pigeon_instance: ProxyApiTestClass, + aList: List, + callback: (Result>) -> Unit + ) { + flutterEchoList(pigeon_instance, aList, callback) + } + + override fun callFlutterEchoProxyApiList( + pigeon_instance: ProxyApiTestClass, + aList: List, + callback: (Result>) -> Unit + ) { + flutterEchoProxyApiList(pigeon_instance, aList, callback) + } + + override fun callFlutterEchoMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map, + callback: (Result>) -> Unit + ) { + flutterEchoMap(pigeon_instance, aMap, callback) + } + + override fun callFlutterEchoProxyApiMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map, + callback: (Result>) -> Unit + ) { + flutterEchoProxyApiMap(pigeon_instance, aMap, callback) + } + + override fun callFlutterEchoEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum, + callback: (Result) -> Unit + ) { + flutterEchoEnum(pigeon_instance, anEnum, callback) + } + + override fun callFlutterEchoProxyApi( + pigeon_instance: ProxyApiTestClass, + aProxyApi: ProxyApiSuperClass, + callback: (Result) -> Unit + ) { + flutterEchoProxyApi(pigeon_instance, aProxyApi, callback) + } + + override fun callFlutterEchoNullableBool( + pigeon_instance: ProxyApiTestClass, + aBool: Boolean?, + callback: (Result) -> Unit + ) { + flutterEchoNullableBool(pigeon_instance, aBool, callback) + } + + override fun callFlutterEchoNullableInt( + pigeon_instance: ProxyApiTestClass, + anInt: Long?, + callback: (Result) -> Unit + ) { + flutterEchoNullableInt(pigeon_instance, anInt, callback) + } + + override fun callFlutterEchoNullableDouble( + pigeon_instance: ProxyApiTestClass, + aDouble: Double?, + callback: (Result) -> Unit + ) { + flutterEchoNullableDouble(pigeon_instance, aDouble, callback) + } + + override fun callFlutterEchoNullableString( + pigeon_instance: ProxyApiTestClass, + aString: String?, + callback: (Result) -> Unit + ) { + flutterEchoNullableString(pigeon_instance, aString, callback) + } + + override fun callFlutterEchoNullableUint8List( + pigeon_instance: ProxyApiTestClass, + aUint8List: ByteArray?, + callback: (Result) -> Unit + ) { + flutterEchoNullableUint8List(pigeon_instance, aUint8List, callback) + } + + override fun callFlutterEchoNullableList( + pigeon_instance: ProxyApiTestClass, + aList: List?, + callback: (Result?>) -> Unit + ) { + flutterEchoNullableList(pigeon_instance, aList, callback) + } + + override fun callFlutterEchoNullableMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map?, + callback: (Result?>) -> Unit + ) { + flutterEchoNullableMap(pigeon_instance, aMap, callback) + } + + override fun callFlutterEchoNullableEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum?, + callback: (Result) -> Unit + ) { + flutterEchoNullableEnum(pigeon_instance, anEnum, callback) + } + + override fun callFlutterEchoNullableProxyApi( + pigeon_instance: ProxyApiTestClass, + aProxyApi: ProxyApiSuperClass?, + callback: (Result) -> Unit + ) { + flutterEchoNullableProxyApi(pigeon_instance, aProxyApi, callback) + } + + override fun callFlutterNoopAsync( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) { + flutterNoopAsync(pigeon_instance, callback) + } + + override fun callFlutterEchoAsyncString( + pigeon_instance: ProxyApiTestClass, + aString: String, + callback: (Result) -> Unit + ) { + flutterEchoAsyncString(pigeon_instance, aString, callback) + } +} + +class ProxyApiSuperClassApi(codec: PigeonProxyApiBaseCodec) : PigeonApiProxyApiSuperClass(codec) { + override fun pigeon_defaultConstructor(): ProxyApiSuperClass { + return ProxyApiSuperClass() + } + + override fun aSuperMethod(pigeon_instance: ProxyApiSuperClass) {} +} + +class ProxyApiInterfaceApi(codec: PigeonProxyApiBaseCodec) : PigeonApiProxyApiInterface(codec) diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/ProxyApiTests.gen.kt b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/ProxyApiTests.gen.kt new file mode 100644 index 00000000000..24e199664b6 --- /dev/null +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/ProxyApiTests.gen.kt @@ -0,0 +1,3867 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Autogenerated from Pigeon, do not edit directly. +// See also: https://pub.dev/packages/pigeon + +package com.example.test_plugin + +import android.util.Log +import io.flutter.plugin.common.BasicMessageChannel +import io.flutter.plugin.common.BinaryMessenger +import io.flutter.plugin.common.MessageCodec +import io.flutter.plugin.common.StandardMessageCodec +import java.io.ByteArrayOutputStream +import java.nio.ByteBuffer + +private fun wrapResult(result: Any?): List { + return listOf(result) +} + +private fun wrapError(exception: Throwable): List { + if (exception is ProxyApiTestsError) { + return listOf(exception.code, exception.message, exception.details) + } else { + return listOf( + exception.javaClass.simpleName, + exception.toString(), + "Cause: " + exception.cause + ", Stacktrace: " + Log.getStackTraceString(exception)) + } +} + +private fun createConnectionError(channelName: String): ProxyApiTestsError { + return ProxyApiTestsError( + "channel-error", "Unable to establish connection on channel: '$channelName'.", "") +} + +/** + * Error class for passing custom error details to Flutter via a thrown PlatformException. + * + * @property code The error code. + * @property message The error message. + * @property details The error details. Must be a datatype supported by the api codec. + */ +class ProxyApiTestsError( + val code: String, + override val message: String? = null, + val details: Any? = null +) : Throwable() +/** + * Maintains instances used to communicate with the corresponding objects in Dart. + * + *

Objects stored in this container are represented by an object in Dart that is also stored in + * an InstanceManager with the same identifier. + * + *

When an instance is added with an identifier, either can be used to retrieve the other. + * + *

Added instances are added as a weak reference and a strong reference. When the strong + * reference is removed with [remove] and the weak reference is deallocated, the + * `finalizationListener` is made with the instance's identifier. However, if the strong reference + * is removed and then the identifier is retrieved with the intention to pass the identifier to Dart + * (e.g. calling [getIdentifierForStrongReference]), the strong reference to the instance is + * recreated. The strong reference will then need to be removed manually again. + */ +@Suppress("UNCHECKED_CAST", "MemberVisibilityCanBePrivate", "unused") +class PigeonInstanceManager(private val finalizationListener: PigeonFinalizationListener) { + /** Interface for listening when a weak reference of an instance is removed from the manager. */ + interface PigeonFinalizationListener { + fun onFinalize(identifier: Long) + } + + private val identifiers = java.util.WeakHashMap() + private val weakInstances = HashMap>() + private val strongInstances = HashMap() + private val referenceQueue = java.lang.ref.ReferenceQueue() + private val weakReferencesToIdentifiers = HashMap, Long>() + private val handler = android.os.Handler(android.os.Looper.getMainLooper()) + private var nextIdentifier: Long = minHostCreatedIdentifier + private var hasFinalizationListenerStopped = false + + init { + handler.postDelayed({ releaseAllFinalizedInstances() }, clearFinalizedWeakReferencesInterval) + } + + companion object { + // Identifiers are locked to a specific range to avoid collisions with objects + // created simultaneously from Dart. + // Host uses identifiers >= 2^16 and Dart is expected to use values n where, + // 0 <= n < 2^16. + private const val minHostCreatedIdentifier: Long = 65536 + private const val clearFinalizedWeakReferencesInterval: Long = 3000 + private const val tag = "PigeonInstanceManager" + + /** + * Instantiate a new manager. + * + * When the manager is no longer needed, [stopFinalizationListener] must be called. + * + * @param finalizationListener the listener for garbage collected weak references. + * @return a new `PigeonInstanceManager`. + */ + fun create(finalizationListener: PigeonFinalizationListener): PigeonInstanceManager { + return PigeonInstanceManager(finalizationListener) + } + + /** + * Instantiate a new manager with an `PigeonInstanceManager`. + * + * @param api handles removing garbage collected weak references. + * @return a new `PigeonInstanceManager`. + */ + fun create(api: PigeonInstanceManagerApi): PigeonInstanceManager { + val instanceManager = + create( + object : PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + tag, + "Failed to remove Dart strong reference with identifier: $identifier") + } + } + } + }) + PigeonInstanceManagerApi.setUpMessageHandlers(api.binaryMessenger, instanceManager) + return instanceManager + } + } + + /** + * Removes `identifier` and its associated strongly referenced instance, if present, from the + * manager. + * + * @param identifier the identifier paired to an instance. + * @param the expected return type. + * @return the removed instance if the manager contains the given identifier, otherwise `null` if + * the manager doesn't contain the value. + */ + fun remove(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + return strongInstances.remove(identifier) as T? + } + + /** + * Retrieves the identifier paired with an instance. + * + * If the manager contains a strong reference to `instance`, it will return the identifier + * associated with `instance`. If the manager contains only a weak reference to `instance`, a new + * strong reference to `instance` will be added and will need to be removed again with [remove]. + * + * If this method returns a nonnull identifier, this method also expects the Dart + * `PigeonInstanceManager` to have, or recreate, a weak reference to the Dart instance the + * identifier is associated with. + * + * @param instance an instance that may be stored in the manager. + * @return the identifier associated with `instance` if the manager contains the value, otherwise + * `null` if the manager doesn't contain the value. + */ + fun getIdentifierForStrongReference(instance: Any?): Long? { + logWarningIfFinalizationListenerHasStopped() + val identifier = identifiers[instance] + if (identifier != null) { + strongInstances[identifier] = instance!! + } + return identifier + } + + /** + * Adds a new instance that was instantiated from Dart. + * + * The same instance can be added multiple times, but each identifier must be unique. This allows + * two objects that are equivalent (e.g. the `equals` method returns true and their hashcodes are + * equal) to both be added. + * + * @param instance the instance to be stored. + * @param identifier the identifier to be paired with instance. This value must be >= 0 and + * unique. + */ + fun addDartCreatedInstance(instance: Any, identifier: Long) { + logWarningIfFinalizationListenerHasStopped() + addInstance(instance, identifier) + } + + /** + * Adds a new instance that was instantiated from the host platform. + * + * @param instance the instance to be stored. This must be unique to all other added instances. + * @return the unique identifier (>= 0) stored with instance. + */ + fun addHostCreatedInstance(instance: Any): Long { + logWarningIfFinalizationListenerHasStopped() + require(!containsInstance(instance)) { + "Instance of ${instance.javaClass} has already been added." + } + val identifier = nextIdentifier++ + addInstance(instance, identifier) + return identifier + } + + /** + * Retrieves the instance associated with identifier. + * + * @param identifier the identifier associated with an instance. + * @param the expected return type. + * @return the instance associated with `identifier` if the manager contains the value, otherwise + * `null` if the manager doesn't contain the value. + */ + fun getInstance(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + val instance = weakInstances[identifier] as java.lang.ref.WeakReference? + return instance?.get() + } + + /** + * Returns whether this manager contains the given `instance`. + * + * @param instance the instance whose presence in this manager is to be tested. + * @return whether this manager contains the given `instance`. + */ + fun containsInstance(instance: Any?): Boolean { + logWarningIfFinalizationListenerHasStopped() + return identifiers.containsKey(instance) + } + + /** + * Stop the periodic run of the [PigeonFinalizationListener] for instances that have been garbage + * collected. + * + * The InstanceManager can continue to be used, but the [PigeonFinalizationListener] will no + * longer be called and methods will log a warning. + */ + fun stopFinalizationListener() { + handler.removeCallbacks { this.releaseAllFinalizedInstances() } + hasFinalizationListenerStopped = true + } + + /** + * Removes all of the instances from this manager. + * + * The manager will be empty after this call returns. + */ + fun clear() { + identifiers.clear() + weakInstances.clear() + strongInstances.clear() + weakReferencesToIdentifiers.clear() + } + + /** + * Whether the [PigeonFinalizationListener] is still being called for instances that are garbage + * collected. + * + * See [stopFinalizationListener]. + */ + fun hasFinalizationListenerStopped(): Boolean { + return hasFinalizationListenerStopped + } + + private fun releaseAllFinalizedInstances() { + if (hasFinalizationListenerStopped()) { + return + } + var reference: java.lang.ref.WeakReference? + while ((referenceQueue.poll() as java.lang.ref.WeakReference?).also { reference = it } != + null) { + val identifier = weakReferencesToIdentifiers.remove(reference) + if (identifier != null) { + weakInstances.remove(identifier) + strongInstances.remove(identifier) + finalizationListener.onFinalize(identifier) + } + } + handler.postDelayed({ releaseAllFinalizedInstances() }, clearFinalizedWeakReferencesInterval) + } + + private fun addInstance(instance: Any, identifier: Long) { + require(identifier >= 0) { "Identifier must be >= 0: $identifier" } + require(!weakInstances.containsKey(identifier)) { + "Identifier has already been added: $identifier" + } + val weakReference = java.lang.ref.WeakReference(instance, referenceQueue) + identifiers[instance] = identifier + weakInstances[identifier] = weakReference + weakReferencesToIdentifiers[weakReference] = identifier + strongInstances[identifier] = instance + } + + private fun logWarningIfFinalizationListenerHasStopped() { + if (hasFinalizationListenerStopped()) { + Log.w( + tag, + "The manager was used after calls to the PigeonFinalizationListener have been stopped.") + } + } +} + +/** Generated API for managing the Dart and native `PigeonInstanceManager`s. */ +class PigeonInstanceManagerApi(internal val binaryMessenger: BinaryMessenger) { + companion object { + /** The codec used by PigeonInstanceManagerApi. */ + private val codec: MessageCodec by lazy { StandardMessageCodec() } + + /** + * Sets up an instance of `PigeonInstanceManagerApi` to handle messages from the + * `binaryMessenger`. + */ + fun setUpMessageHandlers( + binaryMessenger: BinaryMessenger, + instanceManager: PigeonInstanceManager + ) { + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.PigeonInstanceManagerApi.removeStrongReference", + codec) + channel.setMessageHandler { message, reply -> + val identifier = message as Number + val wrapped: List = + try { + instanceManager.remove(identifier.toLong()) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.PigeonInstanceManagerApi.clear", + codec) + channel.setMessageHandler { _, reply -> + val wrapped: List = + try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } + } + } + + fun removeStrongReference(identifier: Long, callback: (Result) -> Unit) { + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.PigeonInstanceManagerApi.removeStrongReference" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(identifier) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } +} + +abstract class PigeonProxyApiBaseCodec( + val binaryMessenger: BinaryMessenger, + val instanceManager: PigeonInstanceManager +) : StandardMessageCodec() { + /** + * An implementation of [PigeonApiProxyApiTestClass] used to add a new Dart instance of + * `ProxyApiTestClass` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiProxyApiTestClass(): PigeonApiProxyApiTestClass + + /** + * An implementation of [PigeonApiProxyApiSuperClass] used to add a new Dart instance of + * `ProxyApiSuperClass` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiProxyApiSuperClass(): PigeonApiProxyApiSuperClass + + /** + * An implementation of [PigeonApiProxyApiInterface] used to add a new Dart instance of + * `ProxyApiInterface` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiProxyApiInterface(): PigeonApiProxyApiInterface + + fun setUpMessageHandlers() { + PigeonApiProxyApiTestClass.setUpMessageHandlers( + binaryMessenger, getPigeonApiProxyApiTestClass()) + PigeonApiProxyApiSuperClass.setUpMessageHandlers( + binaryMessenger, getPigeonApiProxyApiSuperClass()) + } + + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 128.toByte() -> { + return instanceManager.getInstance( + readValue(buffer).let { if (it is Int) it.toLong() else it as Long }) + } + else -> super.readValueOfType(type, buffer) + } + } + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + if (value is ProxyApiTestClass) { + getPigeonApiProxyApiTestClass().pigeon_newInstance(value) {} + } else if (value is ProxyApiSuperClass) { + getPigeonApiProxyApiSuperClass().pigeon_newInstance(value) {} + } else if (value is ProxyApiInterface) { + getPigeonApiProxyApiInterface().pigeon_newInstance(value) {} + } + + when { + instanceManager.containsInstance(value) -> { + stream.write(128) + writeValue(stream, instanceManager.getIdentifierForStrongReference(value)) + } + else -> super.writeValue(stream, value) + } + } +} + +enum class ProxyApiTestEnum(val raw: Int) { + ONE(0), + TWO(1), + THREE(2); + + companion object { + fun ofRaw(raw: Int): ProxyApiTestEnum? { + return values().firstOrNull { it.raw == raw } + } + } +} +/** + * The core ProxyApi test class that each supported host language must implement in platform_tests + * integration tests. + */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiProxyApiTestClass(val codec: PigeonProxyApiBaseCodec) { + abstract fun pigeon_defaultConstructor( + aBool: Boolean, + anInt: Long, + aDouble: Double, + aString: String, + aUint8List: ByteArray, + aList: List, + aMap: Map, + anEnum: ProxyApiTestEnum, + aProxyApi: ProxyApiSuperClass, + aNullableBool: Boolean?, + aNullableInt: Long?, + aNullableDouble: Double?, + aNullableString: String?, + aNullableUint8List: ByteArray?, + aNullableList: List?, + aNullableMap: Map?, + aNullableEnum: ProxyApiTestEnum?, + aNullableProxyApi: ProxyApiSuperClass?, + boolParam: Boolean, + intParam: Long, + doubleParam: Double, + stringParam: String, + aUint8ListParam: ByteArray, + listParam: List, + mapParam: Map, + enumParam: ProxyApiTestEnum, + proxyApiParam: ProxyApiSuperClass, + nullableBoolParam: Boolean?, + nullableIntParam: Long?, + nullableDoubleParam: Double?, + nullableStringParam: String?, + nullableUint8ListParam: ByteArray?, + nullableListParam: List?, + nullableMapParam: Map?, + nullableEnumParam: ProxyApiTestEnum?, + nullableProxyApiParam: ProxyApiSuperClass? + ): ProxyApiTestClass + + abstract fun attachedField(pigeon_instance: ProxyApiTestClass): ProxyApiSuperClass + + abstract fun staticAttachedField(): ProxyApiSuperClass + + abstract fun aBool(pigeon_instance: ProxyApiTestClass): Boolean + + abstract fun anInt(pigeon_instance: ProxyApiTestClass): Long + + abstract fun aDouble(pigeon_instance: ProxyApiTestClass): Double + + abstract fun aString(pigeon_instance: ProxyApiTestClass): String + + abstract fun aUint8List(pigeon_instance: ProxyApiTestClass): ByteArray + + abstract fun aList(pigeon_instance: ProxyApiTestClass): List + + abstract fun aMap(pigeon_instance: ProxyApiTestClass): Map + + abstract fun anEnum(pigeon_instance: ProxyApiTestClass): ProxyApiTestEnum + + abstract fun aProxyApi(pigeon_instance: ProxyApiTestClass): ProxyApiSuperClass + + abstract fun aNullableBool(pigeon_instance: ProxyApiTestClass): Boolean? + + abstract fun aNullableInt(pigeon_instance: ProxyApiTestClass): Long? + + abstract fun aNullableDouble(pigeon_instance: ProxyApiTestClass): Double? + + abstract fun aNullableString(pigeon_instance: ProxyApiTestClass): String? + + abstract fun aNullableUint8List(pigeon_instance: ProxyApiTestClass): ByteArray? + + abstract fun aNullableList(pigeon_instance: ProxyApiTestClass): List? + + abstract fun aNullableMap(pigeon_instance: ProxyApiTestClass): Map? + + abstract fun aNullableEnum(pigeon_instance: ProxyApiTestClass): ProxyApiTestEnum? + + abstract fun aNullableProxyApi(pigeon_instance: ProxyApiTestClass): ProxyApiSuperClass? + + /** A no-op function taking no arguments and returning no value, to sanity test basic calling. */ + abstract fun noop(pigeon_instance: ProxyApiTestClass) + + /** Returns an error, to test error handling. */ + abstract fun throwError(pigeon_instance: ProxyApiTestClass): Any? + + /** Returns an error from a void function, to test error handling. */ + abstract fun throwErrorFromVoid(pigeon_instance: ProxyApiTestClass) + + /** Returns a Flutter error, to test error handling. */ + abstract fun throwFlutterError(pigeon_instance: ProxyApiTestClass): Any? + + /** Returns passed in int. */ + abstract fun echoInt(pigeon_instance: ProxyApiTestClass, anInt: Long): Long + + /** Returns passed in double. */ + abstract fun echoDouble(pigeon_instance: ProxyApiTestClass, aDouble: Double): Double + + /** Returns the passed in boolean. */ + abstract fun echoBool(pigeon_instance: ProxyApiTestClass, aBool: Boolean): Boolean + + /** Returns the passed in string. */ + abstract fun echoString(pigeon_instance: ProxyApiTestClass, aString: String): String + + /** Returns the passed in Uint8List. */ + abstract fun echoUint8List(pigeon_instance: ProxyApiTestClass, aUint8List: ByteArray): ByteArray + + /** Returns the passed in generic Object. */ + abstract fun echoObject(pigeon_instance: ProxyApiTestClass, anObject: Any): Any + + /** Returns the passed list, to test serialization and deserialization. */ + abstract fun echoList(pigeon_instance: ProxyApiTestClass, aList: List): List + + /** Returns the passed list with ProxyApis, to test serialization and deserialization. */ + abstract fun echoProxyApiList( + pigeon_instance: ProxyApiTestClass, + aList: List + ): List + + /** Returns the passed map, to test serialization and deserialization. */ + abstract fun echoMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map + ): Map + + /** Returns the passed map with ProxyApis, to test serialization and deserialization. */ + abstract fun echoProxyApiMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map + ): Map + + /** Returns the passed enum to test serialization and deserialization. */ + abstract fun echoEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum + ): ProxyApiTestEnum + + /** Returns the passed ProxyApi to test serialization and deserialization. */ + abstract fun echoProxyApi( + pigeon_instance: ProxyApiTestClass, + aProxyApi: ProxyApiSuperClass + ): ProxyApiSuperClass + + /** Returns passed in int. */ + abstract fun echoNullableInt(pigeon_instance: ProxyApiTestClass, aNullableInt: Long?): Long? + + /** Returns passed in double. */ + abstract fun echoNullableDouble( + pigeon_instance: ProxyApiTestClass, + aNullableDouble: Double? + ): Double? + + /** Returns the passed in boolean. */ + abstract fun echoNullableBool( + pigeon_instance: ProxyApiTestClass, + aNullableBool: Boolean? + ): Boolean? + + /** Returns the passed in string. */ + abstract fun echoNullableString( + pigeon_instance: ProxyApiTestClass, + aNullableString: String? + ): String? + + /** Returns the passed in Uint8List. */ + abstract fun echoNullableUint8List( + pigeon_instance: ProxyApiTestClass, + aNullableUint8List: ByteArray? + ): ByteArray? + + /** Returns the passed in generic Object. */ + abstract fun echoNullableObject(pigeon_instance: ProxyApiTestClass, aNullableObject: Any?): Any? + + /** Returns the passed list, to test serialization and deserialization. */ + abstract fun echoNullableList( + pigeon_instance: ProxyApiTestClass, + aNullableList: List? + ): List? + + /** Returns the passed map, to test serialization and deserialization. */ + abstract fun echoNullableMap( + pigeon_instance: ProxyApiTestClass, + aNullableMap: Map? + ): Map? + + abstract fun echoNullableEnum( + pigeon_instance: ProxyApiTestClass, + aNullableEnum: ProxyApiTestEnum? + ): ProxyApiTestEnum? + + /** Returns the passed ProxyApi to test serialization and deserialization. */ + abstract fun echoNullableProxyApi( + pigeon_instance: ProxyApiTestClass, + aNullableProxyApi: ProxyApiSuperClass? + ): ProxyApiSuperClass? + + /** + * A no-op function taking no arguments and returning no value, to sanity test basic asynchronous + * calling. + */ + abstract fun noopAsync(pigeon_instance: ProxyApiTestClass, callback: (Result) -> Unit) + + /** Returns passed in int asynchronously. */ + abstract fun echoAsyncInt( + pigeon_instance: ProxyApiTestClass, + anInt: Long, + callback: (Result) -> Unit + ) + + /** Returns passed in double asynchronously. */ + abstract fun echoAsyncDouble( + pigeon_instance: ProxyApiTestClass, + aDouble: Double, + callback: (Result) -> Unit + ) + + /** Returns the passed in boolean asynchronously. */ + abstract fun echoAsyncBool( + pigeon_instance: ProxyApiTestClass, + aBool: Boolean, + callback: (Result) -> Unit + ) + + /** Returns the passed string asynchronously. */ + abstract fun echoAsyncString( + pigeon_instance: ProxyApiTestClass, + aString: String, + callback: (Result) -> Unit + ) + + /** Returns the passed in Uint8List asynchronously. */ + abstract fun echoAsyncUint8List( + pigeon_instance: ProxyApiTestClass, + aUint8List: ByteArray, + callback: (Result) -> Unit + ) + + /** Returns the passed in generic Object asynchronously. */ + abstract fun echoAsyncObject( + pigeon_instance: ProxyApiTestClass, + anObject: Any, + callback: (Result) -> Unit + ) + + /** Returns the passed list, to test asynchronous serialization and deserialization. */ + abstract fun echoAsyncList( + pigeon_instance: ProxyApiTestClass, + aList: List, + callback: (Result>) -> Unit + ) + + /** Returns the passed map, to test asynchronous serialization and deserialization. */ + abstract fun echoAsyncMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map, + callback: (Result>) -> Unit + ) + + /** Returns the passed enum, to test asynchronous serialization and deserialization. */ + abstract fun echoAsyncEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum, + callback: (Result) -> Unit + ) + + /** Responds with an error from an async function returning a value. */ + abstract fun throwAsyncError(pigeon_instance: ProxyApiTestClass, callback: (Result) -> Unit) + + /** Responds with an error from an async void function. */ + abstract fun throwAsyncErrorFromVoid( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) + + /** Responds with a Flutter error from an async function returning a value. */ + abstract fun throwAsyncFlutterError( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) + + /** Returns passed in int asynchronously. */ + abstract fun echoAsyncNullableInt( + pigeon_instance: ProxyApiTestClass, + anInt: Long?, + callback: (Result) -> Unit + ) + + /** Returns passed in double asynchronously. */ + abstract fun echoAsyncNullableDouble( + pigeon_instance: ProxyApiTestClass, + aDouble: Double?, + callback: (Result) -> Unit + ) + + /** Returns the passed in boolean asynchronously. */ + abstract fun echoAsyncNullableBool( + pigeon_instance: ProxyApiTestClass, + aBool: Boolean?, + callback: (Result) -> Unit + ) + + /** Returns the passed string asynchronously. */ + abstract fun echoAsyncNullableString( + pigeon_instance: ProxyApiTestClass, + aString: String?, + callback: (Result) -> Unit + ) + + /** Returns the passed in Uint8List asynchronously. */ + abstract fun echoAsyncNullableUint8List( + pigeon_instance: ProxyApiTestClass, + aUint8List: ByteArray?, + callback: (Result) -> Unit + ) + + /** Returns the passed in generic Object asynchronously. */ + abstract fun echoAsyncNullableObject( + pigeon_instance: ProxyApiTestClass, + anObject: Any?, + callback: (Result) -> Unit + ) + + /** Returns the passed list, to test asynchronous serialization and deserialization. */ + abstract fun echoAsyncNullableList( + pigeon_instance: ProxyApiTestClass, + aList: List?, + callback: (Result?>) -> Unit + ) + + /** Returns the passed map, to test asynchronous serialization and deserialization. */ + abstract fun echoAsyncNullableMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map?, + callback: (Result?>) -> Unit + ) + + /** Returns the passed enum, to test asynchronous serialization and deserialization. */ + abstract fun echoAsyncNullableEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum?, + callback: (Result) -> Unit + ) + + abstract fun staticNoop() + + abstract fun echoStaticString(aString: String): String + + abstract fun staticAsyncNoop(callback: (Result) -> Unit) + + abstract fun callFlutterNoop(pigeon_instance: ProxyApiTestClass, callback: (Result) -> Unit) + + abstract fun callFlutterThrowError( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) + + abstract fun callFlutterThrowErrorFromVoid( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoBool( + pigeon_instance: ProxyApiTestClass, + aBool: Boolean, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoInt( + pigeon_instance: ProxyApiTestClass, + anInt: Long, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoDouble( + pigeon_instance: ProxyApiTestClass, + aDouble: Double, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoString( + pigeon_instance: ProxyApiTestClass, + aString: String, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoUint8List( + pigeon_instance: ProxyApiTestClass, + aUint8List: ByteArray, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoList( + pigeon_instance: ProxyApiTestClass, + aList: List, + callback: (Result>) -> Unit + ) + + abstract fun callFlutterEchoProxyApiList( + pigeon_instance: ProxyApiTestClass, + aList: List, + callback: (Result>) -> Unit + ) + + abstract fun callFlutterEchoMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map, + callback: (Result>) -> Unit + ) + + abstract fun callFlutterEchoProxyApiMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map, + callback: (Result>) -> Unit + ) + + abstract fun callFlutterEchoEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoProxyApi( + pigeon_instance: ProxyApiTestClass, + aProxyApi: ProxyApiSuperClass, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoNullableBool( + pigeon_instance: ProxyApiTestClass, + aBool: Boolean?, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoNullableInt( + pigeon_instance: ProxyApiTestClass, + anInt: Long?, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoNullableDouble( + pigeon_instance: ProxyApiTestClass, + aDouble: Double?, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoNullableString( + pigeon_instance: ProxyApiTestClass, + aString: String?, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoNullableUint8List( + pigeon_instance: ProxyApiTestClass, + aUint8List: ByteArray?, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoNullableList( + pigeon_instance: ProxyApiTestClass, + aList: List?, + callback: (Result?>) -> Unit + ) + + abstract fun callFlutterEchoNullableMap( + pigeon_instance: ProxyApiTestClass, + aMap: Map?, + callback: (Result?>) -> Unit + ) + + abstract fun callFlutterEchoNullableEnum( + pigeon_instance: ProxyApiTestClass, + anEnum: ProxyApiTestEnum?, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoNullableProxyApi( + pigeon_instance: ProxyApiTestClass, + aProxyApi: ProxyApiSuperClass?, + callback: (Result) -> Unit + ) + + abstract fun callFlutterNoopAsync( + pigeon_instance: ProxyApiTestClass, + callback: (Result) -> Unit + ) + + abstract fun callFlutterEchoAsyncString( + pigeon_instance: ProxyApiTestClass, + aString: String, + callback: (Result) -> Unit + ) + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiProxyApiTestClass?) { + val codec = api?.codec ?: StandardMessageCodec() + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.pigeon_defaultConstructor", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0].let { if (it is Int) it.toLong() else it as Long } + val aBoolArg = args[1] as Boolean + val anIntArg = args[2].let { if (it is Int) it.toLong() else it as Long } + val aDoubleArg = args[3] as Double + val aStringArg = args[4] as String + val aUint8ListArg = args[5] as ByteArray + val aListArg = args[6] as List + val aMapArg = args[7] as Map + val anEnumArg = ProxyApiTestEnum.ofRaw(args[8] as Int)!! + val aProxyApiArg = args[9] as ProxyApiSuperClass + val aNullableBoolArg = args[10] as Boolean? + val aNullableIntArg = args[11].let { if (it is Int) it.toLong() else it as Long? } + val aNullableDoubleArg = args[12] as Double? + val aNullableStringArg = args[13] as String? + val aNullableUint8ListArg = args[14] as ByteArray? + val aNullableListArg = args[15] as List? + val aNullableMapArg = args[16] as Map? + val aNullableEnumArg = + if (args[17] == null) null else ProxyApiTestEnum.ofRaw(args[17] as Int) + val aNullableProxyApiArg = args[18] as ProxyApiSuperClass? + val boolParamArg = args[19] as Boolean + val intParamArg = args[20].let { if (it is Int) it.toLong() else it as Long } + val doubleParamArg = args[21] as Double + val stringParamArg = args[22] as String + val aUint8ListParamArg = args[23] as ByteArray + val listParamArg = args[24] as List + val mapParamArg = args[25] as Map + val enumParamArg = ProxyApiTestEnum.ofRaw(args[26] as Int)!! + val proxyApiParamArg = args[27] as ProxyApiSuperClass + val nullableBoolParamArg = args[28] as Boolean? + val nullableIntParamArg = args[29].let { if (it is Int) it.toLong() else it as Long? } + val nullableDoubleParamArg = args[30] as Double? + val nullableStringParamArg = args[31] as String? + val nullableUint8ListParamArg = args[32] as ByteArray? + val nullableListParamArg = args[33] as List? + val nullableMapParamArg = args[34] as Map? + val nullableEnumParamArg = + if (args[35] == null) null else ProxyApiTestEnum.ofRaw(args[35] as Int) + val nullableProxyApiParamArg = args[36] as ProxyApiSuperClass? + var wrapped: List + try { + api.codec.instanceManager.addDartCreatedInstance( + api.pigeon_defaultConstructor( + aBoolArg, + anIntArg, + aDoubleArg, + aStringArg, + aUint8ListArg, + aListArg, + aMapArg, + anEnumArg, + aProxyApiArg, + aNullableBoolArg, + aNullableIntArg, + aNullableDoubleArg, + aNullableStringArg, + aNullableUint8ListArg, + aNullableListArg, + aNullableMapArg, + aNullableEnumArg, + aNullableProxyApiArg, + boolParamArg, + intParamArg, + doubleParamArg, + stringParamArg, + aUint8ListParamArg, + listParamArg, + mapParamArg, + enumParamArg, + proxyApiParamArg, + nullableBoolParamArg, + nullableIntParamArg, + nullableDoubleParamArg, + nullableStringParamArg, + nullableUint8ListParamArg, + nullableListParamArg, + nullableMapParamArg, + nullableEnumParamArg, + nullableProxyApiParamArg), + pigeon_identifierArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.attachedField", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val pigeon_identifierArg = args[1].let { if (it is Int) it.toLong() else it as Long } + var wrapped: List + try { + api.codec.instanceManager.addDartCreatedInstance( + api.attachedField(pigeon_instanceArg), pigeon_identifierArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.staticAttachedField", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0].let { if (it is Int) it.toLong() else it as Long } + var wrapped: List + try { + api.codec.instanceManager.addDartCreatedInstance( + api.staticAttachedField(), pigeon_identifierArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.noop", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + var wrapped: List + try { + api.noop(pigeon_instanceArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.throwError", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + var wrapped: List + try { + wrapped = listOf(api.throwError(pigeon_instanceArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.throwErrorFromVoid", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + var wrapped: List + try { + api.throwErrorFromVoid(pigeon_instanceArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.throwFlutterError", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + var wrapped: List + try { + wrapped = listOf(api.throwFlutterError(pigeon_instanceArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoInt", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anIntArg = args[1].let { if (it is Int) it.toLong() else it as Long } + var wrapped: List + try { + wrapped = listOf(api.echoInt(pigeon_instanceArg, anIntArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoDouble", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aDoubleArg = args[1] as Double + var wrapped: List + try { + wrapped = listOf(api.echoDouble(pigeon_instanceArg, aDoubleArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoBool", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aBoolArg = args[1] as Boolean + var wrapped: List + try { + wrapped = listOf(api.echoBool(pigeon_instanceArg, aBoolArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoString", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aStringArg = args[1] as String + var wrapped: List + try { + wrapped = listOf(api.echoString(pigeon_instanceArg, aStringArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoUint8List", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aUint8ListArg = args[1] as ByteArray + var wrapped: List + try { + wrapped = listOf(api.echoUint8List(pigeon_instanceArg, aUint8ListArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoObject", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anObjectArg = args[1] as Any + var wrapped: List + try { + wrapped = listOf(api.echoObject(pigeon_instanceArg, anObjectArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoList", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aListArg = args[1] as List + var wrapped: List + try { + wrapped = listOf(api.echoList(pigeon_instanceArg, aListArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoProxyApiList", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aListArg = args[1] as List + var wrapped: List + try { + wrapped = listOf(api.echoProxyApiList(pigeon_instanceArg, aListArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoMap", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aMapArg = args[1] as Map + var wrapped: List + try { + wrapped = listOf(api.echoMap(pigeon_instanceArg, aMapArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoProxyApiMap", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aMapArg = args[1] as Map + var wrapped: List + try { + wrapped = listOf(api.echoProxyApiMap(pigeon_instanceArg, aMapArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoEnum", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anEnumArg = ProxyApiTestEnum.ofRaw(args[1] as Int)!! + var wrapped: List + try { + wrapped = listOf(api.echoEnum(pigeon_instanceArg, anEnumArg).raw) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoProxyApi", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aProxyApiArg = args[1] as ProxyApiSuperClass + var wrapped: List + try { + wrapped = listOf(api.echoProxyApi(pigeon_instanceArg, aProxyApiArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableInt", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableIntArg = args[1].let { if (it is Int) it.toLong() else it as Long? } + var wrapped: List + try { + wrapped = listOf(api.echoNullableInt(pigeon_instanceArg, aNullableIntArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableDouble", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableDoubleArg = args[1] as Double? + var wrapped: List + try { + wrapped = listOf(api.echoNullableDouble(pigeon_instanceArg, aNullableDoubleArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableBool", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableBoolArg = args[1] as Boolean? + var wrapped: List + try { + wrapped = listOf(api.echoNullableBool(pigeon_instanceArg, aNullableBoolArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableString", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableStringArg = args[1] as String? + var wrapped: List + try { + wrapped = listOf(api.echoNullableString(pigeon_instanceArg, aNullableStringArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableUint8List", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableUint8ListArg = args[1] as ByteArray? + var wrapped: List + try { + wrapped = + listOf(api.echoNullableUint8List(pigeon_instanceArg, aNullableUint8ListArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableObject", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableObjectArg = args[1] + var wrapped: List + try { + wrapped = listOf(api.echoNullableObject(pigeon_instanceArg, aNullableObjectArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableList", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableListArg = args[1] as List? + var wrapped: List + try { + wrapped = listOf(api.echoNullableList(pigeon_instanceArg, aNullableListArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableMap", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableMapArg = args[1] as Map? + var wrapped: List + try { + wrapped = listOf(api.echoNullableMap(pigeon_instanceArg, aNullableMapArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableEnum", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableEnumArg = + if (args[1] == null) null else ProxyApiTestEnum.ofRaw(args[1] as Int) + var wrapped: List + try { + wrapped = + listOf(api.echoNullableEnum(pigeon_instanceArg, aNullableEnumArg)?.raw) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoNullableProxyApi", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aNullableProxyApiArg = args[1] as ProxyApiSuperClass? + var wrapped: List + try { + wrapped = + listOf(api.echoNullableProxyApi(pigeon_instanceArg, aNullableProxyApiArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.noopAsync", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + api.noopAsync(pigeon_instanceArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + reply.reply(wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncInt", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anIntArg = args[1].let { if (it is Int) it.toLong() else it as Long } + api.echoAsyncInt(pigeon_instanceArg, anIntArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncDouble", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aDoubleArg = args[1] as Double + api.echoAsyncDouble(pigeon_instanceArg, aDoubleArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncBool", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aBoolArg = args[1] as Boolean + api.echoAsyncBool(pigeon_instanceArg, aBoolArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncString", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aStringArg = args[1] as String + api.echoAsyncString(pigeon_instanceArg, aStringArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncUint8List", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aUint8ListArg = args[1] as ByteArray + api.echoAsyncUint8List(pigeon_instanceArg, aUint8ListArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncObject", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anObjectArg = args[1] as Any + api.echoAsyncObject(pigeon_instanceArg, anObjectArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncList", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aListArg = args[1] as List + api.echoAsyncList(pigeon_instanceArg, aListArg) { result: Result> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncMap", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aMapArg = args[1] as Map + api.echoAsyncMap(pigeon_instanceArg, aMapArg) { result: Result> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncEnum", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anEnumArg = ProxyApiTestEnum.ofRaw(args[1] as Int)!! + api.echoAsyncEnum(pigeon_instanceArg, anEnumArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data!!.raw)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.throwAsyncError", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + api.throwAsyncError(pigeon_instanceArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.throwAsyncErrorFromVoid", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + api.throwAsyncErrorFromVoid(pigeon_instanceArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + reply.reply(wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.throwAsyncFlutterError", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + api.throwAsyncFlutterError(pigeon_instanceArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableInt", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anIntArg = args[1].let { if (it is Int) it.toLong() else it as Long? } + api.echoAsyncNullableInt(pigeon_instanceArg, anIntArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableDouble", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aDoubleArg = args[1] as Double? + api.echoAsyncNullableDouble(pigeon_instanceArg, aDoubleArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableBool", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aBoolArg = args[1] as Boolean? + api.echoAsyncNullableBool(pigeon_instanceArg, aBoolArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableString", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aStringArg = args[1] as String? + api.echoAsyncNullableString(pigeon_instanceArg, aStringArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableUint8List", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aUint8ListArg = args[1] as ByteArray? + api.echoAsyncNullableUint8List(pigeon_instanceArg, aUint8ListArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableObject", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anObjectArg = args[1] + api.echoAsyncNullableObject(pigeon_instanceArg, anObjectArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableList", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aListArg = args[1] as List? + api.echoAsyncNullableList(pigeon_instanceArg, aListArg) { result: Result?> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableMap", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aMapArg = args[1] as Map? + api.echoAsyncNullableMap(pigeon_instanceArg, aMapArg) { + result: Result?> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoAsyncNullableEnum", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anEnumArg = if (args[1] == null) null else ProxyApiTestEnum.ofRaw(args[1] as Int) + api.echoAsyncNullableEnum(pigeon_instanceArg, anEnumArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data?.raw)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.staticNoop", + codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + var wrapped: List + try { + api.staticNoop() + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoStaticString", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val aStringArg = args[0] as String + var wrapped: List + try { + wrapped = listOf(api.echoStaticString(aStringArg)) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.staticAsyncNoop", + codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + api.staticAsyncNoop() { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + reply.reply(wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterNoop", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + api.callFlutterNoop(pigeon_instanceArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + reply.reply(wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterThrowError", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + api.callFlutterThrowError(pigeon_instanceArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterThrowErrorFromVoid", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + api.callFlutterThrowErrorFromVoid(pigeon_instanceArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + reply.reply(wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoBool", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aBoolArg = args[1] as Boolean + api.callFlutterEchoBool(pigeon_instanceArg, aBoolArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoInt", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anIntArg = args[1].let { if (it is Int) it.toLong() else it as Long } + api.callFlutterEchoInt(pigeon_instanceArg, anIntArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoDouble", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aDoubleArg = args[1] as Double + api.callFlutterEchoDouble(pigeon_instanceArg, aDoubleArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoString", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aStringArg = args[1] as String + api.callFlutterEchoString(pigeon_instanceArg, aStringArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoUint8List", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aUint8ListArg = args[1] as ByteArray + api.callFlutterEchoUint8List(pigeon_instanceArg, aUint8ListArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoList", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aListArg = args[1] as List + api.callFlutterEchoList(pigeon_instanceArg, aListArg) { result: Result> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoProxyApiList", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aListArg = args[1] as List + api.callFlutterEchoProxyApiList(pigeon_instanceArg, aListArg) { + result: Result> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoMap", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aMapArg = args[1] as Map + api.callFlutterEchoMap(pigeon_instanceArg, aMapArg) { result: Result> + -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoProxyApiMap", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aMapArg = args[1] as Map + api.callFlutterEchoProxyApiMap(pigeon_instanceArg, aMapArg) { + result: Result> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoEnum", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anEnumArg = ProxyApiTestEnum.ofRaw(args[1] as Int)!! + api.callFlutterEchoEnum(pigeon_instanceArg, anEnumArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data!!.raw)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoProxyApi", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aProxyApiArg = args[1] as ProxyApiSuperClass + api.callFlutterEchoProxyApi(pigeon_instanceArg, aProxyApiArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableBool", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aBoolArg = args[1] as Boolean? + api.callFlutterEchoNullableBool(pigeon_instanceArg, aBoolArg) { result: Result + -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableInt", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anIntArg = args[1].let { if (it is Int) it.toLong() else it as Long? } + api.callFlutterEchoNullableInt(pigeon_instanceArg, anIntArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableDouble", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aDoubleArg = args[1] as Double? + api.callFlutterEchoNullableDouble(pigeon_instanceArg, aDoubleArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableString", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aStringArg = args[1] as String? + api.callFlutterEchoNullableString(pigeon_instanceArg, aStringArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableUint8List", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aUint8ListArg = args[1] as ByteArray? + api.callFlutterEchoNullableUint8List(pigeon_instanceArg, aUint8ListArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableList", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aListArg = args[1] as List? + api.callFlutterEchoNullableList(pigeon_instanceArg, aListArg) { + result: Result?> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableMap", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aMapArg = args[1] as Map? + api.callFlutterEchoNullableMap(pigeon_instanceArg, aMapArg) { + result: Result?> -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableEnum", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val anEnumArg = if (args[1] == null) null else ProxyApiTestEnum.ofRaw(args[1] as Int) + api.callFlutterEchoNullableEnum(pigeon_instanceArg, anEnumArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data?.raw)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoNullableProxyApi", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aProxyApiArg = args[1] as ProxyApiSuperClass? + api.callFlutterEchoNullableProxyApi(pigeon_instanceArg, aProxyApiArg) { + result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterNoopAsync", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + api.callFlutterNoopAsync(pigeon_instanceArg) { result: Result -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + reply.reply(wrapResult(null)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.callFlutterEchoAsyncString", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiTestClass + val aStringArg = args[1] as String + api.callFlutterEchoAsyncString(pigeon_instanceArg, aStringArg) { result: Result + -> + val error = result.exceptionOrNull() + if (error != null) { + reply.reply(wrapError(error)) + } else { + val data = result.getOrNull() + reply.reply(wrapResult(data)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of ProxyApiTestClass and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: ProxyApiTestClass, callback: (Result) -> Unit) { + if (codec.instanceManager.containsInstance(pigeon_instanceArg)) { + Result.success(Unit) + return + } + val pigeon_identifierArg = codec.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val aBoolArg = aBool(pigeon_instanceArg) + val anIntArg = anInt(pigeon_instanceArg) + val aDoubleArg = aDouble(pigeon_instanceArg) + val aStringArg = aString(pigeon_instanceArg) + val aUint8ListArg = aUint8List(pigeon_instanceArg) + val aListArg = aList(pigeon_instanceArg) + val aMapArg = aMap(pigeon_instanceArg) + val anEnumArg = anEnum(pigeon_instanceArg) + val aProxyApiArg = aProxyApi(pigeon_instanceArg) + val aNullableBoolArg = aNullableBool(pigeon_instanceArg) + val aNullableIntArg = aNullableInt(pigeon_instanceArg) + val aNullableDoubleArg = aNullableDouble(pigeon_instanceArg) + val aNullableStringArg = aNullableString(pigeon_instanceArg) + val aNullableUint8ListArg = aNullableUint8List(pigeon_instanceArg) + val aNullableListArg = aNullableList(pigeon_instanceArg) + val aNullableMapArg = aNullableMap(pigeon_instanceArg) + val aNullableEnumArg = aNullableEnum(pigeon_instanceArg) + val aNullableProxyApiArg = aNullableProxyApi(pigeon_instanceArg) + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send( + listOf( + pigeon_identifierArg, + aBoolArg, + anIntArg, + aDoubleArg, + aStringArg, + aUint8ListArg, + aListArg, + aMapArg, + anEnumArg.raw, + aProxyApiArg, + aNullableBoolArg, + aNullableIntArg, + aNullableDoubleArg, + aNullableStringArg, + aNullableUint8ListArg, + aNullableListArg, + aNullableMapArg, + aNullableEnumArg?.raw, + aNullableProxyApiArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** A no-op function taking no arguments and returning no value, to sanity test basic calling. */ + fun flutterNoop(pigeon_instanceArg: ProxyApiTestClass, callback: (Result) -> Unit) { + val binaryMessenger = codec.binaryMessenger + val channelName = "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterNoop" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Responds with an error from an async function returning a value. */ + fun flutterThrowError(pigeon_instanceArg: ProxyApiTestClass, callback: (Result) -> Unit) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterThrowError" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0] + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Responds with an error from an async void function. */ + fun flutterThrowErrorFromVoid( + pigeon_instanceArg: ProxyApiTestClass, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterThrowErrorFromVoid" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed boolean, to test serialization and deserialization. */ + fun flutterEchoBool( + pigeon_instanceArg: ProxyApiTestClass, + aBoolArg: Boolean, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoBool" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aBoolArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as Boolean + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed int, to test serialization and deserialization. */ + fun flutterEchoInt( + pigeon_instanceArg: ProxyApiTestClass, + anIntArg: Long, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoInt" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, anIntArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0].let { if (it is Int) it.toLong() else it as Long } + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed double, to test serialization and deserialization. */ + fun flutterEchoDouble( + pigeon_instanceArg: ProxyApiTestClass, + aDoubleArg: Double, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoDouble" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aDoubleArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as Double + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed string, to test serialization and deserialization. */ + fun flutterEchoString( + pigeon_instanceArg: ProxyApiTestClass, + aStringArg: String, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoString" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aStringArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as String + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed byte list, to test serialization and deserialization. */ + fun flutterEchoUint8List( + pigeon_instanceArg: ProxyApiTestClass, + aListArg: ByteArray, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoUint8List" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aListArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as ByteArray + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed list, to test serialization and deserialization. */ + fun flutterEchoList( + pigeon_instanceArg: ProxyApiTestClass, + aListArg: List, + callback: (Result>) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoList" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aListArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as List + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed list with ProxyApis, to test serialization and deserialization. */ + fun flutterEchoProxyApiList( + pigeon_instanceArg: ProxyApiTestClass, + aListArg: List, + callback: (Result>) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoProxyApiList" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aListArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as List + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed map, to test serialization and deserialization. */ + fun flutterEchoMap( + pigeon_instanceArg: ProxyApiTestClass, + aMapArg: Map, + callback: (Result>) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoMap" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aMapArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as Map + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed map with ProxyApis, to test serialization and deserialization. */ + fun flutterEchoProxyApiMap( + pigeon_instanceArg: ProxyApiTestClass, + aMapArg: Map, + callback: (Result>) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoProxyApiMap" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aMapArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as Map + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed enum to test serialization and deserialization. */ + fun flutterEchoEnum( + pigeon_instanceArg: ProxyApiTestClass, + anEnumArg: ProxyApiTestEnum, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoEnum" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, anEnumArg.raw)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = ProxyApiTestEnum.ofRaw(it[0] as Int)!! + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed ProxyApi to test serialization and deserialization. */ + fun flutterEchoProxyApi( + pigeon_instanceArg: ProxyApiTestClass, + aProxyApiArg: ProxyApiSuperClass, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoProxyApi" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aProxyApiArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as ProxyApiSuperClass + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed boolean, to test serialization and deserialization. */ + fun flutterEchoNullableBool( + pigeon_instanceArg: ProxyApiTestClass, + aBoolArg: Boolean?, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableBool" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aBoolArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0] as Boolean? + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed int, to test serialization and deserialization. */ + fun flutterEchoNullableInt( + pigeon_instanceArg: ProxyApiTestClass, + anIntArg: Long?, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableInt" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, anIntArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0].let { if (it is Int) it.toLong() else it as Long? } + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed double, to test serialization and deserialization. */ + fun flutterEchoNullableDouble( + pigeon_instanceArg: ProxyApiTestClass, + aDoubleArg: Double?, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableDouble" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aDoubleArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0] as Double? + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed string, to test serialization and deserialization. */ + fun flutterEchoNullableString( + pigeon_instanceArg: ProxyApiTestClass, + aStringArg: String?, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableString" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aStringArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0] as String? + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed byte list, to test serialization and deserialization. */ + fun flutterEchoNullableUint8List( + pigeon_instanceArg: ProxyApiTestClass, + aListArg: ByteArray?, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableUint8List" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aListArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0] as ByteArray? + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed list, to test serialization and deserialization. */ + fun flutterEchoNullableList( + pigeon_instanceArg: ProxyApiTestClass, + aListArg: List?, + callback: (Result?>) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableList" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aListArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0] as List? + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed map, to test serialization and deserialization. */ + fun flutterEchoNullableMap( + pigeon_instanceArg: ProxyApiTestClass, + aMapArg: Map?, + callback: (Result?>) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableMap" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aMapArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0] as Map? + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed enum to test serialization and deserialization. */ + fun flutterEchoNullableEnum( + pigeon_instanceArg: ProxyApiTestClass, + anEnumArg: ProxyApiTestEnum?, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableEnum" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, anEnumArg?.raw)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = (it[0] as Int?)?.let { ProxyApiTestEnum.ofRaw(it) } + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed ProxyApi to test serialization and deserialization. */ + fun flutterEchoNullableProxyApi( + pigeon_instanceArg: ProxyApiTestClass, + aProxyApiArg: ProxyApiSuperClass?, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableProxyApi" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aProxyApiArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + val output = it[0] as ProxyApiSuperClass? + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** + * A no-op function taking no arguments and returning no value, to sanity test basic asynchronous + * calling. + */ + fun flutterNoopAsync(pigeon_instanceArg: ProxyApiTestClass, callback: (Result) -> Unit) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterNoopAsync" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + /** Returns the passed in generic Object asynchronously. */ + fun flutterEchoAsyncString( + pigeon_instanceArg: ProxyApiTestClass, + aStringArg: String, + callback: (Result) -> Unit + ) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoAsyncString" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, aStringArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else if (it[0] == null) { + callback( + Result.failure( + ProxyApiTestsError( + "null-error", + "Flutter api returned null value for non-null return value.", + ""))) + } else { + val output = it[0] as String + callback(Result.success(output)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + @Suppress("FunctionName") + /** An implementation of [PigeonApiProxyApiSuperClass] used to access callback methods */ + fun pigeon_getPigeonApiProxyApiSuperClass(): PigeonApiProxyApiSuperClass { + return codec.getPigeonApiProxyApiSuperClass() + } + + @Suppress("FunctionName") + /** An implementation of [PigeonApiProxyApiInterface] used to access callback methods */ + fun pigeon_getPigeonApiProxyApiInterface(): PigeonApiProxyApiInterface { + return codec.getPigeonApiProxyApiInterface() + } +} +/** ProxyApi to serve as a super class to the core ProxyApi class. */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiProxyApiSuperClass(val codec: PigeonProxyApiBaseCodec) { + abstract fun pigeon_defaultConstructor(): ProxyApiSuperClass + + abstract fun aSuperMethod(pigeon_instance: ProxyApiSuperClass) + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiProxyApiSuperClass?) { + val codec = api?.codec ?: StandardMessageCodec() + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiSuperClass.pigeon_defaultConstructor", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0].let { if (it is Int) it.toLong() else it as Long } + var wrapped: List + try { + api.codec.instanceManager.addDartCreatedInstance( + api.pigeon_defaultConstructor(), pigeon_identifierArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiSuperClass.aSuperMethod", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ProxyApiSuperClass + var wrapped: List + try { + api.aSuperMethod(pigeon_instanceArg) + wrapped = listOf(null) + } catch (exception: Throwable) { + wrapped = wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of ProxyApiSuperClass and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: ProxyApiSuperClass, callback: (Result) -> Unit) { + if (codec.instanceManager.containsInstance(pigeon_instanceArg)) { + Result.success(Unit) + return + } + val pigeon_identifierArg = codec.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiSuperClass.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } +} +/** ProxyApi to serve as an interface to the core ProxyApi class. */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiProxyApiInterface(val codec: PigeonProxyApiBaseCodec) { + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of ProxyApiInterface and attaches it to [pigeon_instanceArg]. */ + fun pigeon_newInstance(pigeon_instanceArg: ProxyApiInterface, callback: (Result) -> Unit) { + if (codec.instanceManager.containsInstance(pigeon_instanceArg)) { + Result.success(Unit) + return + } + val pigeon_identifierArg = codec.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiInterface.pigeon_newInstance" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_identifierArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } + + fun anInterfaceMethod(pigeon_instanceArg: ProxyApiInterface, callback: (Result) -> Unit) { + val binaryMessenger = codec.binaryMessenger + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiInterface.anInterfaceMethod" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg)) { + if (it is List<*>) { + if (it.size > 1) { + callback( + Result.failure( + ProxyApiTestsError(it[0] as String, it[1] as String, it[2] as String?))) + } else { + callback(Result.success(Unit)) + } + } else { + callback(Result.failure(createConnectionError(channelName))) + } + } + } +} diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/TestPlugin.kt b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/TestPlugin.kt index 8b4e8bc4fb1..a3fd8446e04 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/TestPlugin.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/TestPlugin.kt @@ -10,10 +10,17 @@ import io.flutter.embedding.engine.plugins.FlutterPlugin /** This plugin handles the native side of the integration tests in example/integration_test/. */ class TestPlugin : FlutterPlugin, HostIntegrationCoreApi { var flutterApi: FlutterIntegrationCoreApi? = null + private var instanceManager: PigeonInstanceManager? = null override fun onAttachedToEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) { HostIntegrationCoreApi.setUp(binding.getBinaryMessenger(), this) flutterApi = FlutterIntegrationCoreApi(binding.getBinaryMessenger()) + + val instanceManagerApi = PigeonInstanceManagerApi(binding.binaryMessenger) + instanceManager = PigeonInstanceManager.create(instanceManagerApi) + + val codec = ProxyApiCodec(binding.binaryMessenger, instanceManager!!) + codec.setUpMessageHandlers() } override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {} diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/InstanceManagerTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/InstanceManagerTest.kt new file mode 100644 index 00000000000..d1b9b783e28 --- /dev/null +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/InstanceManagerTest.kt @@ -0,0 +1,129 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package com.example.test_plugin + +import junit.framework.TestCase.assertEquals +import junit.framework.TestCase.assertFalse +import junit.framework.TestCase.assertNotNull +import junit.framework.TestCase.assertNull +import junit.framework.TestCase.assertTrue +import org.junit.Test + +class InstanceManagerTest { + @Test + fun addDartCreatedInstance() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + val testObject = Any() + instanceManager.addDartCreatedInstance(testObject, 0) + + assertEquals(testObject, instanceManager.getInstance(0)) + assertEquals(0L, instanceManager.getIdentifierForStrongReference(testObject)) + assertTrue(instanceManager.containsInstance(testObject)) + + instanceManager.stopFinalizationListener() + } + + @Test + fun addHostCreatedInstance() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + val testObject = Any() + val identifier: Long = instanceManager.addHostCreatedInstance(testObject) + + assertNotNull(instanceManager.getInstance(identifier)) + assertEquals(testObject, instanceManager.getInstance(identifier)) + assertTrue(instanceManager.containsInstance(testObject)) + + instanceManager.stopFinalizationListener() + } + + @Test + fun remove() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + var testObject: Any? = Any() + instanceManager.addDartCreatedInstance(testObject!!, 0) + assertEquals(testObject, instanceManager.remove(0)) + + // To allow for object to be garbage collected. + @Suppress("UNUSED_VALUE") + testObject = null + Runtime.getRuntime().gc() + assertNull(instanceManager.getInstance(0)) + + instanceManager.stopFinalizationListener() + } + + @Test + fun clear() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + val instance = Any() + instanceManager.addDartCreatedInstance(instance, 0) + + assertTrue(instanceManager.containsInstance(instance)) + instanceManager.clear() + assertFalse(instanceManager.containsInstance(instance)) + + instanceManager.stopFinalizationListener() + } + + @Test + fun canAddSameObjectWithAddDartCreatedInstance() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + val instance = Any() + instanceManager.addDartCreatedInstance(instance, 0) + instanceManager.addDartCreatedInstance(instance, 1) + + assertTrue(instanceManager.containsInstance(instance)) + assertEquals(instanceManager.getInstance(0), instance) + assertEquals(instanceManager.getInstance(1), instance) + + instanceManager.stopFinalizationListener() + } + + @Test(expected = IllegalArgumentException::class) + fun cannotAddSameObjectsWithAddHostCreatedInstance() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + val instance = Any() + instanceManager.addHostCreatedInstance(instance) + instanceManager.addHostCreatedInstance(instance) + + instanceManager.stopFinalizationListener() + } + + @Test(expected = IllegalArgumentException::class) + fun cannotUseIdentifierLessThanZero() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + instanceManager.addDartCreatedInstance(Any(), -1) + instanceManager.stopFinalizationListener() + } + + @Test(expected = IllegalArgumentException::class) + fun identifiersMustBeUnique() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + instanceManager.addDartCreatedInstance(Any(), 0) + instanceManager.addDartCreatedInstance(Any(), 0) + + instanceManager.stopFinalizationListener() + } + + @Test + fun managerIsUsableWhileListenerHasStopped() { + val instanceManager: PigeonInstanceManager = createInstanceManager() + instanceManager.stopFinalizationListener() + val instance = Any() + val identifier: Long = 0 + instanceManager.addDartCreatedInstance(instance, identifier) + + assertEquals(instanceManager.getInstance(identifier), instance) + assertEquals(instanceManager.getIdentifierForStrongReference(instance), identifier) + assertTrue(instanceManager.containsInstance(instance)) + } + + private fun createInstanceManager(): PigeonInstanceManager { + return PigeonInstanceManager.create( + object : PigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) {} + }) + } +} diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index d5b579405d4..fef2b8e8574 100644 --- a/packages/pigeon/pubspec.yaml +++ b/packages/pigeon/pubspec.yaml @@ -2,7 +2,7 @@ name: pigeon description: Code generator tool to make communication between Flutter and the host platform type-safe and easier. repository: https://github.com/flutter/packages/tree/main/packages/pigeon issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+pigeon%22 -version: 17.2.0 # This must match the version in lib/generator_tools.dart +version: 17.3.0 # This must match the version in lib/generator_tools.dart environment: sdk: ^3.1.0 @@ -13,6 +13,7 @@ dependencies: code_builder: ^4.10.0 collection: ^1.15.0 dart_style: ^2.3.4 + graphs: ^2.3.1 meta: ^1.9.0 path: ^1.8.0 yaml: ^3.1.1 diff --git a/packages/pigeon/test/kotlin/proxy_api_test.dart b/packages/pigeon/test/kotlin/proxy_api_test.dart new file mode 100644 index 00000000000..f4b6642c58c --- /dev/null +++ b/packages/pigeon/test/kotlin/proxy_api_test.dart @@ -0,0 +1,931 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:pigeon/ast.dart'; +import 'package:pigeon/kotlin_generator.dart'; +import 'package:test/test.dart'; + +const String DEFAULT_PACKAGE_NAME = 'test_package'; + +void main() { + group('ProxyApi', () { + test('one api', () { + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + kotlinOptions: const KotlinProxyApiOptions( + fullClassName: 'my.library.Api', + ), + constructors: [ + Constructor( + name: 'name', + parameters: [ + Parameter( + type: const TypeDeclaration( + baseName: 'Input', + isNullable: false, + ), + name: 'input', + ), + ], + ), + ], + fields: [ + ApiField( + name: 'someField', + type: const TypeDeclaration( + baseName: 'int', + isNullable: false, + ), + ) + ], + methods: [ + Method( + name: 'doSomething', + location: ApiLocation.host, + parameters: [ + Parameter( + type: const TypeDeclaration( + baseName: 'Input', + isNullable: false, + ), + name: 'input', + ) + ], + returnType: const TypeDeclaration( + baseName: 'String', + isNullable: false, + ), + ), + Method( + name: 'doSomethingElse', + location: ApiLocation.flutter, + isRequired: false, + parameters: [ + Parameter( + type: const TypeDeclaration( + baseName: 'Input', + isNullable: false, + ), + name: 'input', + ), + ], + returnType: const TypeDeclaration( + baseName: 'String', + isNullable: false, + ), + ), + ], + ) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + + // Instance Manager + expect(code, contains(r'class PigeonInstanceManager')); + expect(code, contains(r'class PigeonInstanceManagerApi')); + + // Codec and class + expect(code, contains('class PigeonProxyApiBaseCodec')); + expect( + code, + contains( + r'abstract class PigeonApiApi(val codec: PigeonProxyApiBaseCodec)', + ), + ); + + // Constructors + expect( + collapsedCode, + contains( + r'abstract fun name(someField: Long, input: Input)', + ), + ); + expect( + collapsedCode, + contains( + r'fun pigeon_newInstance(pigeon_instanceArg: my.library.Api, callback: (Result) -> Unit)', + ), + ); + + // Field + expect( + code, + contains( + 'abstract fun someField(pigeon_instance: my.library.Api): Long', + ), + ); + + // Dart -> Host method + expect( + collapsedCode, + contains('api.doSomething(pigeon_instanceArg, inputArg)'), + ); + + // Host -> Dart method + expect( + code, + contains( + r'fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiApi?)', + ), + ); + expect( + code, + contains( + 'fun doSomethingElse(pigeon_instanceArg: my.library.Api, inputArg: Input, callback: (Result) -> Unit)', + ), + ); + }); + + group('inheritance', () { + test('extends', () { + final AstProxyApi api2 = AstProxyApi( + name: 'Api2', + constructors: [], + fields: [], + methods: [], + ); + final Root root = Root(apis: [ + AstProxyApi( + name: 'Api', + constructors: [], + fields: [], + methods: [], + superClass: TypeDeclaration( + baseName: api2.name, + isNullable: false, + associatedProxyApi: api2, + ), + ), + api2, + ], classes: [], enums: []); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + expect( + collapsedCode, + contains('fun pigeon_getPigeonApiApi2(): PigeonApiApi2'), + ); + }); + + test('implements', () { + final AstProxyApi api2 = AstProxyApi( + name: 'Api2', + constructors: [], + fields: [], + methods: [], + ); + final Root root = Root(apis: [ + AstProxyApi( + name: 'Api', + constructors: [], + fields: [], + methods: [], + interfaces: { + TypeDeclaration( + baseName: api2.name, + isNullable: false, + associatedProxyApi: api2, + ) + }, + ), + api2, + ], classes: [], enums: []); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + expect(code, contains('fun pigeon_getPigeonApiApi2(): PigeonApiApi2')); + }); + + test('implements 2 ProxyApis', () { + final AstProxyApi api2 = AstProxyApi( + name: 'Api2', + constructors: [], + fields: [], + methods: [], + ); + final AstProxyApi api3 = AstProxyApi( + name: 'Api3', + constructors: [], + fields: [], + methods: [], + ); + final Root root = Root(apis: [ + AstProxyApi( + name: 'Api', + constructors: [], + fields: [], + methods: [], + interfaces: { + TypeDeclaration( + baseName: api2.name, + isNullable: false, + associatedProxyApi: api2, + ), + TypeDeclaration( + baseName: api3.name, + isNullable: false, + associatedProxyApi: api3, + ), + }, + ), + api2, + api3, + ], classes: [], enums: []); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + expect(code, contains('fun pigeon_getPigeonApiApi2(): PigeonApiApi2')); + expect(code, contains('fun pigeon_getPigeonApiApi3(): PigeonApiApi3')); + }); + }); + + group('Constructors', () { + test('empty name and no params constructor', () { + final Root root = Root( + apis: [ + AstProxyApi(name: 'Api', constructors: [ + Constructor( + name: '', + parameters: [], + ) + ], fields: [], methods: []), + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + expect( + code, + contains( + 'abstract class PigeonApiApi(val codec: PigeonProxyApiBaseCodec) ', + ), + ); + expect( + collapsedCode, + contains('abstract fun pigeon_defaultConstructor(): Api'), + ); + expect( + collapsedCode, + contains( + r'val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.test_package.Api.pigeon_defaultConstructor"', + ), + ); + expect( + collapsedCode, + contains( + r'api.codec.instanceManager.addDartCreatedInstance(api.pigeon_defaultConstructor(', + ), + ); + }); + + test('multiple params constructor', () { + final Enum anEnum = Enum( + name: 'AnEnum', + members: [EnumMember(name: 'one')], + ); + final Root root = Root( + apis: [ + AstProxyApi(name: 'Api', constructors: [ + Constructor( + name: 'name', + parameters: [ + Parameter( + type: const TypeDeclaration( + isNullable: false, + baseName: 'int', + ), + name: 'validType', + ), + Parameter( + type: TypeDeclaration( + isNullable: false, + baseName: 'AnEnum', + associatedEnum: anEnum, + ), + name: 'enumType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: false, + baseName: 'Api2', + ), + name: 'proxyApiType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: true, + baseName: 'int', + ), + name: 'nullableValidType', + ), + Parameter( + type: TypeDeclaration( + isNullable: true, + baseName: 'AnEnum', + associatedEnum: anEnum, + ), + name: 'nullableEnumType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: true, + baseName: 'Api2', + ), + name: 'nullableProxyApiType', + ), + ], + ) + ], fields: [], methods: []), + AstProxyApi( + name: 'Api2', + constructors: [], + fields: [], + methods: [], + ), + ], + classes: [], + enums: [anEnum], + ); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + expect( + code, + contains( + 'abstract class PigeonApiApi(val codec: PigeonProxyApiBaseCodec) ', + ), + ); + expect( + collapsedCode, + contains( + 'abstract fun name(validType: Long, enumType: AnEnum, ' + 'proxyApiType: Api2, nullableValidType: Long?, ' + 'nullableEnumType: AnEnum?, nullableProxyApiType: Api2?): Api', + ), + ); + expect( + collapsedCode, + contains( + r'api.codec.instanceManager.addDartCreatedInstance(api.name(' + r'validTypeArg,enumTypeArg,proxyApiTypeArg,nullableValidTypeArg,' + r'nullableEnumTypeArg,nullableProxyApiTypeArg), pigeon_identifierArg)', + ), + ); + }); + }); + + group('Fields', () { + test('constructor with fields', () { + final Enum anEnum = Enum( + name: 'AnEnum', + members: [EnumMember(name: 'one')], + ); + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + constructors: [ + Constructor( + name: 'name', + parameters: [], + ) + ], + fields: [ + ApiField( + type: const TypeDeclaration( + isNullable: false, + baseName: 'int', + ), + name: 'validType', + ), + ApiField( + type: TypeDeclaration( + isNullable: false, + baseName: 'AnEnum', + associatedEnum: anEnum, + ), + name: 'enumType', + ), + ApiField( + type: const TypeDeclaration( + isNullable: false, + baseName: 'Api2', + ), + name: 'proxyApiType', + ), + ApiField( + type: const TypeDeclaration( + isNullable: true, + baseName: 'int', + ), + name: 'nullableValidType', + ), + ApiField( + type: TypeDeclaration( + isNullable: true, + baseName: 'AnEnum', + associatedEnum: anEnum, + ), + name: 'nullableEnumType', + ), + ApiField( + type: const TypeDeclaration( + isNullable: true, + baseName: 'Api2', + ), + name: 'nullableProxyApiType', + ), + ], + methods: [], + ), + AstProxyApi( + name: 'Api2', + constructors: [], + fields: [], + methods: [], + ), + ], + classes: [], + enums: [anEnum], + ); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + expect( + collapsedCode, + contains( + 'abstract fun name(validType: Long, enumType: AnEnum, ' + 'proxyApiType: Api2, nullableValidType: Long?, ' + 'nullableEnumType: AnEnum?, nullableProxyApiType: Api2?): Api', + ), + ); + expect( + collapsedCode, + contains( + r'api.codec.instanceManager.addDartCreatedInstance(api.name(' + r'validTypeArg,enumTypeArg,proxyApiTypeArg,nullableValidTypeArg,' + r'nullableEnumTypeArg,nullableProxyApiTypeArg), pigeon_identifierArg)', + ), + ); + expect( + collapsedCode, + contains( + 'channel.send(listOf(pigeon_identifierArg, validTypeArg, ' + 'enumTypeArg.raw, proxyApiTypeArg, nullableValidTypeArg, ' + 'nullableEnumTypeArg?.raw, nullableProxyApiTypeArg))', + ), + ); + expect( + code, + contains(r'abstract fun validType(pigeon_instance: Api): Long'), + ); + expect( + code, + contains(r'abstract fun enumType(pigeon_instance: Api): AnEnum'), + ); + expect( + code, + contains(r'abstract fun proxyApiType(pigeon_instance: Api): Api2'), + ); + expect( + code, + contains( + r'abstract fun nullableValidType(pigeon_instance: Api): Long?', + ), + ); + expect( + code, + contains( + r'abstract fun nullableEnumType(pigeon_instance: Api): AnEnum?', + ), + ); + expect( + code, + contains( + r'abstract fun nullableProxyApiType(pigeon_instance: Api): Api2?', + ), + ); + }); + + test('attached field', () { + final AstProxyApi api2 = AstProxyApi( + name: 'Api2', + constructors: [], + fields: [], + methods: [], + ); + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + constructors: [], + fields: [ + ApiField( + name: 'aField', + isAttached: true, + type: TypeDeclaration( + baseName: 'Api2', + isNullable: false, + associatedProxyApi: api2, + ), + ), + ], + methods: [], + ), + api2, + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + expect( + code, + contains(r'abstract fun aField(pigeon_instance: Api): Api2'), + ); + expect( + code, + contains( + r'api.codec.instanceManager.addDartCreatedInstance(api.aField(pigeon_instanceArg), pigeon_identifierArg)', + ), + ); + }); + + test('static attached field', () { + final AstProxyApi api2 = AstProxyApi( + name: 'Api2', + constructors: [], + fields: [], + methods: [], + ); + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + constructors: [], + fields: [ + ApiField( + name: 'aField', + isStatic: true, + isAttached: true, + type: TypeDeclaration( + baseName: 'Api2', + isNullable: false, + associatedProxyApi: api2, + ), + ), + ], + methods: [], + ), + api2, + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + expect( + code, + contains(r'abstract fun aField(): Api2'), + ); + expect( + code, + contains( + r'api.codec.instanceManager.addDartCreatedInstance(api.aField(), pigeon_identifierArg)', + ), + ); + }); + }); + + group('Host methods', () { + test('multiple params method', () { + final Enum anEnum = Enum( + name: 'AnEnum', + members: [EnumMember(name: 'one')], + ); + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + constructors: [], + fields: [], + methods: [ + Method( + name: 'doSomething', + location: ApiLocation.host, + parameters: [ + Parameter( + type: const TypeDeclaration( + isNullable: false, + baseName: 'int', + ), + name: 'validType', + ), + Parameter( + type: TypeDeclaration( + isNullable: false, + baseName: 'AnEnum', + associatedEnum: anEnum, + ), + name: 'enumType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: false, + baseName: 'Api2', + ), + name: 'proxyApiType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: true, + baseName: 'int', + ), + name: 'nullableValidType', + ), + Parameter( + type: TypeDeclaration( + isNullable: true, + baseName: 'AnEnum', + associatedEnum: anEnum, + ), + name: 'nullableEnumType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: true, + baseName: 'Api2', + ), + name: 'nullableProxyApiType', + ), + ], + returnType: const TypeDeclaration.voidDeclaration(), + ), + ], + ), + AstProxyApi( + name: 'Api2', + constructors: [], + fields: [], + methods: [], + ), + ], + classes: [], + enums: [anEnum], + ); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + expect( + collapsedCode, + contains( + 'abstract fun doSomething(pigeon_instance: Api, validType: Long, ' + 'enumType: AnEnum, proxyApiType: Api2, nullableValidType: Long?, ' + 'nullableEnumType: AnEnum?, nullableProxyApiType: Api2?)', + ), + ); + expect( + collapsedCode, + contains( + r'api.doSomething(pigeon_instanceArg, validTypeArg, enumTypeArg, ' + r'proxyApiTypeArg, nullableValidTypeArg, nullableEnumTypeArg, ' + r'nullableProxyApiTypeArg)', + ), + ); + }); + + test('static method', () { + final Root root = Root( + apis: [ + AstProxyApi( + name: 'Api', + constructors: [], + fields: [], + methods: [ + Method( + name: 'doSomething', + location: ApiLocation.host, + isStatic: true, + parameters: [], + returnType: const TypeDeclaration.voidDeclaration(), + ), + ], + ), + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + expect(collapsedCode, contains('abstract fun doSomething()')); + expect(collapsedCode, contains(r'api.doSomething()')); + }); + }); + + group('Flutter methods', () { + test('multiple params flutter method', () { + final Enum anEnum = Enum( + name: 'AnEnum', + members: [EnumMember(name: 'one')], + ); + final Root root = Root(apis: [ + AstProxyApi( + name: 'Api', + constructors: [], + fields: [], + methods: [ + Method( + name: 'doSomething', + location: ApiLocation.flutter, + parameters: [ + Parameter( + type: const TypeDeclaration( + isNullable: false, + baseName: 'int', + ), + name: 'validType', + ), + Parameter( + type: TypeDeclaration( + isNullable: false, + baseName: 'AnEnum', + associatedEnum: anEnum, + ), + name: 'enumType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: false, + baseName: 'Api2', + ), + name: 'proxyApiType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: true, + baseName: 'int', + ), + name: 'nullableValidType', + ), + Parameter( + type: TypeDeclaration( + isNullable: true, + baseName: 'AnEnum', + associatedEnum: anEnum, + ), + name: 'nullableEnumType', + ), + Parameter( + type: const TypeDeclaration( + isNullable: true, + baseName: 'Api2', + ), + name: 'nullableProxyApiType', + ), + ], + returnType: const TypeDeclaration.voidDeclaration(), + ) + ]) + ], classes: [], enums: [ + anEnum + ]); + final StringBuffer sink = StringBuffer(); + const KotlinGenerator generator = KotlinGenerator(); + generator.generate( + const KotlinOptions(), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + expect( + collapsedCode, + contains( + 'fun doSomething(pigeon_instanceArg: Api, validTypeArg: Long, ' + 'enumTypeArg: AnEnum, proxyApiTypeArg: Api2, nullableValidTypeArg: Long?, ' + 'nullableEnumTypeArg: AnEnum?, nullableProxyApiTypeArg: Api2?, ' + 'callback: (Result) -> Unit)', + ), + ); + expect( + collapsedCode, + contains( + r'channel.send(listOf(pigeon_instanceArg, validTypeArg, enumTypeArg.raw, ' + r'proxyApiTypeArg, nullableValidTypeArg, nullableEnumTypeArg?.raw, ' + r'nullableProxyApiTypeArg))', + ), + ); + }); + }); + }); +} + +/// Replaces a new line and the indentation with a single white space +/// +/// This +/// +/// ```dart +/// void method( +/// int param1, +/// int param2, +/// ) +/// ``` +/// +/// converts to +/// +/// ```dart +/// void method( int param1, int param2, ) +/// ``` +String _collapseNewlineAndIndentation(String string) { + final StringBuffer result = StringBuffer(); + for (final String line in string.split('\n')) { + result.write('${line.trimLeft()} '); + } + return result.toString().trim(); +} diff --git a/script/configs/allowed_unpinned_deps.yaml b/script/configs/allowed_unpinned_deps.yaml index 84ff94a1101..5aab97d9a25 100644 --- a/script/configs/allowed_unpinned_deps.yaml +++ b/script/configs/allowed_unpinned_deps.yaml @@ -33,6 +33,7 @@ - fake_async - ffi - gcloud +- graphs - html - http - intl