diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index 4a3bb8cc2b69..d6e641feeea1 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,3 +1,7 @@ +## 22.2.0 + +* [kotlin] Adds implementation for `@ProxyApi`. + ## 22.1.0 * Allows generation of classes that aren't referenced in an API. diff --git a/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt b/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt index ec916c5292c9..cc56f5bb3b21 100644 --- a/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt +++ b/packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt @@ -84,7 +84,7 @@ data class MessageData( } } -private object MessagesPigeonCodec : StandardMessageCodec() { +private open class MessagesPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 129.toByte() -> { @@ -122,7 +122,7 @@ interface ExampleHostApi { companion object { /** The codec used by ExampleHostApi. */ - val codec: MessageCodec by lazy { MessagesPigeonCodec } + val codec: MessageCodec by lazy { MessagesPigeonCodec() } /** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */ @JvmOverloads fun setUp( @@ -209,7 +209,7 @@ class MessageFlutterApi( ) { companion object { /** The codec used by MessageFlutterApi. */ - val codec: MessageCodec by lazy { MessagesPigeonCodec } + val codec: MessageCodec by lazy { MessagesPigeonCodec() } } fun flutterMethod(aStringArg: String?, callback: (Result) -> Unit) { diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index eeb3b696eae8..981c428a1594 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -4,7 +4,9 @@ import 'package:collection/collection.dart' show ListEquality; import 'package:meta/meta.dart'; + import 'generator_tools.dart'; +import 'kotlin_generator.dart' show KotlinProxyApiOptions; import 'pigeon_lib.dart'; typedef _ListEquals = bool Function(List, List); @@ -140,6 +142,7 @@ class AstProxyApi extends Api { required this.fields, this.superClass, this.interfaces = const {}, + this.kotlinOptions, }); /// List of constructors inside the API. @@ -154,6 +157,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, @@ -253,7 +260,7 @@ class AstProxyApi extends Api { } } - /// Whether the api has a method that callbacks to Dart to add a new instance + /// Whether the API has a method that callbacks to Dart to add a new instance /// to the InstanceManager. /// /// This is possible as long as no callback methods are required to @@ -265,6 +272,21 @@ class AstProxyApi extends Api { .every((Method method) => !method.isRequired); } + /// Whether the API has any message calls from Dart to host. + bool hasAnyHostMessageCalls() => + constructors.isNotEmpty || + attachedFields.isNotEmpty || + hostMethods.isNotEmpty; + + /// Whether the API has any message calls from host to Dart. + bool hasAnyFlutterMessageCalls() => + hasCallbackConstructor() || flutterMethods.isNotEmpty; + + /// Whether the host proxy API class will have methods that need to be + /// implemented. + bool hasMethodsRequiringImplementation() => + hasAnyHostMessageCalls() || unattachedFields.isNotEmpty; + // Recursively search for all the interfaces apis from a list of names of // interfaces. // diff --git a/packages/pigeon/lib/dart/templates.dart b/packages/pigeon/lib/dart/templates.dart index 48c5859dc3d5..c78c4f566d22 100644 --- a/packages/pigeon/lib/dart/templates.dart +++ b/packages/pigeon/lib/dart/templates.dart @@ -4,6 +4,20 @@ import '../generator_tools.dart'; +/// Name for the generated InstanceManager for ProxyApis. +/// +/// This lowers the chances of variable name collisions with user defined +/// parameters. +const String dartInstanceManagerClassName = + '${proxyApiClassNamePrefix}InstanceManager'; + +/// Name for the generated InstanceManager API for ProxyApis. +/// +/// This lowers the chances of variable name collisions with user defined +/// parameters. +const String dartInstanceManagerApiClassName = + '_${classNamePrefix}InstanceManagerApi'; + /// Creates the `InstanceManager` with the passed string values. String instanceManagerTemplate({ required Iterable allProxyApiNames, @@ -30,9 +44,9 @@ String instanceManagerTemplate({ /// is added as a weak reference with the same identifier. This prevents a /// scenario where the weak referenced instance was released and then later /// returned by the host platform. -class $instanceManagerClassName { - /// Constructs a [$instanceManagerClassName]. - $instanceManagerClassName({required void Function(int) onWeakReferenceRemoved}) { +class $dartInstanceManagerClassName { + /// Constructs a [$dartInstanceManagerClassName]. + $dartInstanceManagerClassName({required void Function(int) onWeakReferenceRemoved}) { this.onWeakReferenceRemoved = (int identifier) { _weakInstances.remove(identifier); onWeakReferenceRemoved(identifier); @@ -46,12 +60,12 @@ class $instanceManagerClassName { // 0 <= n < 2^16. static const int _maxDartCreatedIdentifier = 65536; - /// The default [$instanceManagerClassName] used by ProxyApis. + /// The default [$dartInstanceManagerClassName] used by ProxyApis. /// /// On creation, this manager makes a call to clear the native /// InstanceManager. This is to prevent identifier conflicts after a host /// restart. - static final $instanceManagerClassName instance = _initInstance(); + static final $dartInstanceManagerClassName instance = _initInstance(); // Expando is used because it doesn't prevent its keys from becoming // inaccessible. This allows the manager to efficiently retrieve an identifier @@ -72,17 +86,17 @@ class $instanceManagerClassName { /// or becomes inaccessible. late final void Function(int) onWeakReferenceRemoved; - static $instanceManagerClassName _initInstance() { + static $dartInstanceManagerClassName _initInstance() { WidgetsFlutterBinding.ensureInitialized(); - final _${instanceManagerClassName}Api api = _${instanceManagerClassName}Api(); - // Clears the native `$instanceManagerClassName` on the initial use of the Dart one. + final $dartInstanceManagerApiClassName api = $dartInstanceManagerApiClassName(); + // Clears the native `$dartInstanceManagerClassName` on the initial use of the Dart one. api.clear(); - final $instanceManagerClassName instanceManager = $instanceManagerClassName( + final $dartInstanceManagerClassName instanceManager = $dartInstanceManagerClassName( onWeakReferenceRemoved: (int identifier) { api.removeStrongReference(identifier); }, ); - _${instanceManagerClassName}Api.setUpMessageHandlers(instanceManager: instanceManager); + $dartInstanceManagerApiClassName.setUpMessageHandlers(instanceManager: instanceManager); ${apiHandlerSetUps.join('\n\t\t')} return instanceManager; } @@ -229,9 +243,9 @@ abstract class $proxyApiBaseClassName { /// Construct a [$proxyApiBaseClassName]. $proxyApiBaseClassName({ this.$_proxyApiBaseClassMessengerVarName, - $instanceManagerClassName? $_proxyApiBaseClassInstanceManagerVarName, + $dartInstanceManagerClassName? $_proxyApiBaseClassInstanceManagerVarName, }) : $_proxyApiBaseClassInstanceManagerVarName = - $_proxyApiBaseClassInstanceManagerVarName ?? $instanceManagerClassName.instance; + $_proxyApiBaseClassInstanceManagerVarName ?? $dartInstanceManagerClassName.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -242,12 +256,12 @@ abstract class $proxyApiBaseClassName { /// Maintains instances stored to communicate with native language objects. @protected - final $instanceManagerClassName $_proxyApiBaseClassInstanceManagerVarName; + final $dartInstanceManagerClassName $_proxyApiBaseClassInstanceManagerVarName; /// Instantiates and returns a functionally identical object to oneself. /// /// Outside of tests, this method should only ever be called by - /// [$instanceManagerClassName]. + /// [$dartInstanceManagerClassName]. /// /// Subclasses should always override their parent's implementation of this /// method. @@ -264,11 +278,11 @@ abstract class $proxyApiBaseClassName { const String proxyApiBaseCodec = ''' class $_proxyApiCodecName extends _PigeonCodec { const $_proxyApiCodecName(this.instanceManager); - final $instanceManagerClassName instanceManager; + final $dartInstanceManagerClassName instanceManager; @override void writeValue(WriteBuffer buffer, Object? value) { if (value is $proxyApiBaseClassName) { - buffer.putUint8(128); + buffer.putUint8($proxyApiCodecInstanceManagerKey); writeValue(buffer, instanceManager.getIdentifier(value)); } else { super.writeValue(buffer, value); @@ -277,7 +291,7 @@ class $_proxyApiCodecName extends _PigeonCodec { @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case $proxyApiCodecInstanceManagerKey: return instanceManager .getInstanceWithWeakReference(readValue(buffer)! as int); default: diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index e2d745657ea8..1746a120240b 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -539,8 +539,6 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; Indent indent, { required String dartPackageName, }) { - const String apiName = '${instanceManagerClassName}Api'; - final cb.Parameter binaryMessengerParameter = cb.Parameter( (cb.ParameterBuilder builder) => builder ..name = 'binaryMessenger' @@ -555,23 +553,18 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; ..modifier = cb.FieldModifier.final$, ); - final String removeStrongReferenceName = makeChannelNameWithStrings( - apiName: apiName, - methodName: 'removeStrongReference', - dartPackageName: dartPackageName, - ); - final cb.Class instanceManagerApi = cb.Class( (cb.ClassBuilder builder) => builder - ..name = '_$apiName' + ..name = dartInstanceManagerApiClassName ..docs.add( - '/// Generated API for managing the Dart and native `$instanceManagerClassName`s.', + '/// Generated API for managing the Dart and native `$dartInstanceManagerClassName`s.', ) ..constructors.add( cb.Constructor( (cb.ConstructorBuilder builder) { builder - ..docs.add('/// Constructor for [_$apiName].') + ..docs.add( + '/// Constructor for [$dartInstanceManagerApiClassName].') ..optionalParameters.add(binaryMessengerParameter) ..initializers.add( cb.Code( @@ -591,7 +584,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; ..type = cb.refer('MessageCodec') ..static = true ..modifier = cb.FieldModifier.constant - ..assignment = const cb.Code('StandardMessageCodec()'); + ..assignment = const cb.Code('$_pigeonCodec()'); }, ) ], @@ -616,7 +609,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; (cb.ParameterBuilder builder) => builder ..name = 'instanceManager' ..named = true - ..type = cb.refer('$instanceManagerClassName?'), + ..type = cb.refer('$dartInstanceManagerClassName?'), ), ]) ..body = cb.Block.of( @@ -636,7 +629,9 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; ) ], returnType: const TypeDeclaration.voidDeclaration(), - channelName: removeStrongReferenceName, + channelName: makeRemoveStrongReferenceChannelName( + dartPackageName, + ), isMockHandler: false, isAsynchronous: false, nullHandlerExpression: @@ -646,7 +641,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; Iterable parameters, Iterable safeArgumentNames, ) { - return '(instanceManager ?? $instanceManagerClassName.instance).remove(${safeArgumentNames.single})'; + return '(instanceManager ?? $dartInstanceManagerClassName.instance).remove(${safeArgumentNames.single})'; }, ); builder.statements.add( @@ -679,7 +674,8 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; _writeHostMethodMessageCall( Indent(messageCallSink), addSuffixVariable: false, - channelName: removeStrongReferenceName, + channelName: makeRemoveStrongReferenceChannelName( + dartPackageName), parameters: [ Parameter( name: 'identifier', @@ -705,7 +701,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; ..returns = cb.refer('Future') ..modifier = cb.MethodModifier.async ..docs.addAll([ - '/// Clear the native `$instanceManagerClassName`.', + '/// Clear the native `$dartInstanceManagerClassName`.', '///', '/// This is typically called after a hot restart.', ]) @@ -715,11 +711,7 @@ final BinaryMessenger? ${varNamePrefix}binaryMessenger; _writeHostMethodMessageCall( Indent(messageCallSink), addSuffixVariable: false, - channelName: makeChannelNameWithStrings( - apiName: apiName, - methodName: 'clear', - dartPackageName: dartPackageName, - ), + channelName: makeClearChannelName(dartPackageName), parameters: [], returnType: const TypeDeclaration.voidDeclaration(), ); @@ -1428,7 +1420,7 @@ if (${varNamePrefix}replyList == null) { '/// Constructs [$apiName] without creating the associated native object.', '///', '/// This should only be used by subclasses created by this library or to', - '/// create copies for an [$instanceManagerClassName].', + '/// create copies for an [$dartInstanceManagerClassName].', ]) ..annotations.add(cb.refer('protected')) ..optionalParameters.addAll([ @@ -1535,7 +1527,7 @@ if (${varNamePrefix}replyList == null) { ');', '```', '', - 'Alternatively, [$instanceManagerClassName.removeWeakReference] can be used to', + 'Alternatively, [$dartInstanceManagerClassName.removeWeakReference] can be used to', 'release the associated Native object manually.', ], ], @@ -1681,7 +1673,7 @@ if (${varNamePrefix}replyList == null) { (cb.ParameterBuilder builder) => builder ..name = _instanceManagerVarName ..named = true - ..type = cb.refer('$instanceManagerClassName?'), + ..type = cb.refer('$dartInstanceManagerClassName?'), ), if (hasCallbackConstructor) cb.Parameter( @@ -1732,7 +1724,7 @@ if (${varNamePrefix}replyList == null) { ..body = cb.Block.of([ if (hasAnyMessageHandlers) ...[ cb.Code( - 'final $codecName $_pigeonChannelCodec = $codecName($_instanceManagerVarName ?? $instanceManagerClassName.instance);', + 'final $codecName $_pigeonChannelCodec = $codecName($_instanceManagerVarName ?? $dartInstanceManagerClassName.instance);', ), const cb.Code( 'final BinaryMessenger? binaryMessenger = ${classMemberNamePrefix}binaryMessenger;', @@ -1780,7 +1772,7 @@ if (${varNamePrefix}replyList == null) { return '${parameter.name}: $safeArgName,\n'; }, ).skip(1).join(); - return '($_instanceManagerVarName ?? $instanceManagerClassName.instance)\n' + return '($_instanceManagerVarName ?? $dartInstanceManagerClassName.instance)\n' ' .addHostCreatedInstance(\n' ' $methodName?.call(${safeArgumentNames.skip(1).join(',')}) ??\n' ' $apiName.${classMemberNamePrefix}detached(' @@ -1916,13 +1908,13 @@ if (${varNamePrefix}replyList == null) { 'final $type $instanceName = $type.${classMemberNamePrefix}detached();', ), cb.Code( - 'final $codecName $_pigeonChannelCodec = $codecName($instanceManagerClassName.instance);', + 'final $codecName $_pigeonChannelCodec = $codecName($dartInstanceManagerClassName.instance);', ), const cb.Code( 'final BinaryMessenger ${varNamePrefix}binaryMessenger = ServicesBinding.instance.defaultBinaryMessenger;', ), const cb.Code( - 'final int $identifierInstanceName = $instanceManagerClassName.instance.addDartCreatedInstance($instanceName);', + 'final int $identifierInstanceName = $dartInstanceManagerClassName.instance.addDartCreatedInstance($instanceName);', ), ], const cb.Code('() async {'), @@ -1983,7 +1975,7 @@ if (${varNamePrefix}replyList == null) { cb.Parameter( (cb.ParameterBuilder builder) => builder ..name = _instanceManagerVarName - ..type = cb.refer('$instanceManagerClassName?'), + ..type = cb.refer('$dartInstanceManagerClassName?'), ), ], ]) @@ -2017,7 +2009,7 @@ if (${varNamePrefix}replyList == null) { ' $codecInstanceName;') else cb.Code( - 'final $codecName $_pigeonChannelCodec = $codecName($_instanceManagerVarName ?? $instanceManagerClassName.instance);', + 'final $codecName $_pigeonChannelCodec = $codecName($_instanceManagerVarName ?? $dartInstanceManagerClassName.instance);', ), const cb.Code( 'final BinaryMessenger? ${varNamePrefix}binaryMessenger = ${classMemberNamePrefix}binaryMessenger;', diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index 6e35ad47051d..249b1089781f 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -4,6 +4,7 @@ import 'dart:convert'; import 'dart:io'; +import 'dart:math'; import 'dart:mirrors'; import 'package:yaml/yaml.dart' as yaml; @@ -13,7 +14,7 @@ import 'ast.dart'; /// The current version of pigeon. /// /// This must match the version in pubspec.yaml. -const String pigeonVersion = '22.1.0'; +const String pigeonVersion = '22.2.0'; /// Read all the content from [stdin] to a String. String readStdin() { @@ -70,11 +71,29 @@ class Indent { } /// Replaces the newlines and tabs of input and adds it to the stream. - void format(String input, - {bool leadingSpace = true, bool trailingNewline = true}) { + /// + /// [trimIndentation] flag finds the line with the fewest leading empty + /// spaces and trims the beginning of all lines by this number. + void format( + String input, { + bool leadingSpace = true, + bool trailingNewline = true, + bool trimIndentation = true, + }) { final List lines = input.split('\n'); + + final int indentationToRemove = !trimIndentation + ? 0 + : lines + .where((String line) => line.trim().isNotEmpty) + .map((String line) => line.length - line.trimLeft().length) + .reduce(min); + for (int i = 0; i < lines.length; ++i) { - final String line = lines[i]; + final String line = lines[i].length >= indentationToRemove + ? lines[i].substring(indentationToRemove) + : lines[i]; + if (i == 0 && !leadingSpace) { add(line.replaceAll('\t', tab)); } else if (line.isNotEmpty) { @@ -297,11 +316,17 @@ const String seeAlsoWarning = 'See also: https://pub.dev/packages/pigeon'; /// parameters. const String classNamePrefix = 'PigeonInternal'; -/// Name for the generated InstanceManager for ProxyApis. +/// Prefix for classes generated to use with ProxyApis. /// /// This lowers the chances of variable name collisions with user defined /// parameters. -const String instanceManagerClassName = '${classNamePrefix}InstanceManager'; +const String proxyApiClassNamePrefix = '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 hostProxyApiPrefix = '${proxyApiClassNamePrefix}Api'; /// Prefix for class member names not defined by the user. /// @@ -309,7 +334,7 @@ const String instanceManagerClassName = '${classNamePrefix}InstanceManager'; /// parameters. const String classMemberNamePrefix = 'pigeon_'; -/// Prefix for variable names not defined by the user. +/// Prefix for variable names not defined by the user. /// /// This lowers the chances of variable name collisions with user defined /// parameters. @@ -319,6 +344,8 @@ const String varNamePrefix = 'pigeonVar_'; const List disallowedPrefixes = [ classNamePrefix, classMemberNamePrefix, + hostProxyApiPrefix, + proxyApiClassNamePrefix, varNamePrefix, 'pigeonChannelCodec' ]; @@ -422,9 +449,19 @@ const List validTypes = [ 'Object', ]; +/// The dedicated key for accessing an InstanceManager in ProxyApi base codecs. +/// +/// Generated codecs override the `StandardMessageCodec` which reserves the byte +/// keys of 0-127, so this value is chosen because it is the lowest available +/// key. +/// +/// See https://api.flutter.dev/flutter/services/StandardMessageCodec/writeValue.html +/// for more information on keys in MessageCodecs. +const int proxyApiCodecInstanceManagerKey = 128; + /// Custom codecs' custom types are enumerations begin at this number to /// avoid collisions with the StandardMessageCodec. -const int minimumCodecFieldKey = 129; +const int minimumCodecFieldKey = proxyApiCodecInstanceManagerKey + 1; /// The maximum codec enumeration allowed. const int maximumCodecFieldKey = 255; @@ -515,6 +552,48 @@ Map> getReferencedTypes( return references.map; } +/// Find the [TypeDeclaration] that has the highest API requirement and its +/// version, [T]. +/// +/// [T] depends on the language. For example, Android uses an int while iOS uses +/// semantic versioning. +({TypeDeclaration type, T version})? + findHighestApiRequirement( + Iterable types, { + required T? Function(TypeDeclaration) onGetApiRequirement, + required Comparator onCompare, +}) { + Iterable addAllRecursive(TypeDeclaration type) sync* { + yield type; + if (type.typeArguments.isNotEmpty) { + for (final TypeDeclaration typeArg in type.typeArguments) { + yield* addAllRecursive(typeArg); + } + } + } + + final Iterable allReferencedTypes = types + .expand(addAllRecursive) + .where((TypeDeclaration type) => onGetApiRequirement(type) != null); + + if (allReferencedTypes.isEmpty) { + return null; + } + + final TypeDeclaration typeWithHighestRequirement = allReferencedTypes.reduce( + (TypeDeclaration one, TypeDeclaration two) { + return onCompare(onGetApiRequirement(one)!, onGetApiRequirement(two)!) > 0 + ? one + : two; + }, + ); + + return ( + type: typeWithHighestRequirement, + version: onGetApiRequirement(typeWithHighestRequirement)!, + ); +} + /// All custom definable data types. enum CustomTypes { /// A custom Class. @@ -729,3 +808,26 @@ String toScreamingSnakeCase(String string) { RegExp(r'(?<=[a-z])[A-Z]'), (Match m) => '_${m.group(0)}') .toUpperCase(); } + +/// The channel name for the `removeStrongReference` method of the +/// `InstanceManager` API. +/// +/// This ensures the channel name is the same for all languages. +String makeRemoveStrongReferenceChannelName(String dartPackageName) { + return makeChannelNameWithStrings( + apiName: '${classNamePrefix}InstanceManager', + methodName: 'removeStrongReference', + dartPackageName: dartPackageName, + ); +} + +/// The channel name for the `clear` method of the `InstanceManager` API. +/// +/// This ensures the channel name is the same for all languages. +String makeClearChannelName(String dartPackageName) { + return makeChannelNameWithStrings( + apiName: '${classNamePrefix}InstanceManager', + methodName: 'clear', + dartPackageName: dartPackageName, + ); +} diff --git a/packages/pigeon/lib/kotlin/templates.dart b/packages/pigeon/lib/kotlin/templates.dart new file mode 100644 index 000000000000..5f85078588be --- /dev/null +++ b/packages/pigeon/lib/kotlin/templates.dart @@ -0,0 +1,240 @@ +// 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'; +import '../kotlin_generator.dart'; + +/// Name of the Kotlin `InstanceManager`. +String kotlinInstanceManagerClassName(KotlinOptions options) => + '${options.fileSpecificClassNameComponent ?? ''}${proxyApiClassNamePrefix}InstanceManager'; + +/// The name of the registrar containing all the ProxyApi implementations. +String proxyApiRegistrarName(KotlinOptions options) => + '${options.fileSpecificClassNameComponent ?? ''}${proxyApiClassNamePrefix}ProxyApiRegistrar'; + +/// The name of the codec that handles ProxyApis. +String proxyApiCodecName(KotlinOptions options) => + '${options.fileSpecificClassNameComponent ?? ''}${proxyApiClassNamePrefix}ProxyApiBaseCodec'; + +/// The Kotlin `InstanceManager`. +String instanceManagerTemplate(KotlinOptions options) { + return ''' +/** + * 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.onFinalize` is called 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") +class ${kotlinInstanceManagerClassName(options)}(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 + + /** + * Modifies the time interval used to define how often this instance removes garbage collected + * weak references to native Android objects that this instance was managing. + */ + var clearFinalizedWeakReferencesInterval: Long = 3000 + set(value) { + handler.removeCallbacks { this.releaseAllFinalizedInstances() } + field = value + releaseAllFinalizedInstances() + } + + 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 tag = "${proxyApiClassNamePrefix}InstanceManager" + + /** + * Instantiate a new manager with a listener for garbage collected weak + * references. + * + * When the manager is no longer needed, [stopFinalizationListener] must be called. + */ + fun create(finalizationListener: $_finalizationListenerClassName): ${kotlinInstanceManagerClassName(options)} { + return ${kotlinInstanceManagerClassName(options)}(finalizationListener) + } + } + + /** + * Removes `identifier` and return its associated strongly referenced instance, if present, + * from the manager. + */ + fun remove(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + return strongInstances.remove(identifier) as T? + } + + /** + * Retrieves the identifier paired with an instance, if present, otherwise `null`. + * + * + * 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 + * `${kotlinInstanceManagerClassName(options)}` to have, or recreate, a weak reference to the Dart instance the + * identifier is associated with. + */ + 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. + * + * [identifier] must be >= 0 and unique. + */ + fun addDartCreatedInstance(instance: Any, identifier: Long) { + logWarningIfFinalizationListenerHasStopped() + addInstance(instance, identifier) + } + + /** + * Adds a new unique instance that was instantiated from the host platform. + * + * [identifier] must be >= 0 and unique. + */ + 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, if present, otherwise `null`. */ + 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`. */ + fun containsInstance(instance: Any?): Boolean { + logWarningIfFinalizationListenerHasStopped() + return identifiers.containsKey(instance) + } + + /** + * Stops 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 has been stopped." + ) + } + } +} +'''; +} + +const String _finalizationListenerClassName = + '${proxyApiClassNamePrefix}FinalizationListener'; diff --git a/packages/pigeon/lib/kotlin_generator.dart b/packages/pigeon/lib/kotlin_generator.dart index 1e3444ce34c0..3b5ff62aa822 100644 --- a/packages/pigeon/lib/kotlin_generator.dart +++ b/packages/pigeon/lib/kotlin_generator.dart @@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +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. @@ -92,6 +95,23 @@ class KotlinOptions { } } +/// Options that control how Kotlin code will be generated for a specific +/// ProxyApi. +class KotlinProxyApiOptions { + /// Construct a [KotlinProxyApiOptions]. + const KotlinProxyApiOptions({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. @@ -368,7 +388,7 @@ class KotlinGenerator extends StructuredGenerator { } indent.write( - 'private object ${generatorOptions.fileSpecificClassNameComponent}$_codecName : StandardMessageCodec() '); + 'private open class ${generatorOptions.fileSpecificClassNameComponent}$_codecName : StandardMessageCodec() '); indent.addScoped('{', '}', () { indent.write( 'override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? '); @@ -506,7 +526,7 @@ if (wrapped == null) { indent.write('val codec: MessageCodec by lazy '); indent.addScoped('{', '}', () { indent.writeln( - '${generatorOptions.fileSpecificClassNameComponent}$_codecName'); + '${generatorOptions.fileSpecificClassNameComponent}$_codecName()'); }); }); @@ -520,6 +540,24 @@ if (wrapped == null) { channelName: makeChannelName(api, method, dartPackageName), documentationComments: method.documentationComments, dartPackageName: dartPackageName, + onWriteBody: ( + Indent indent, { + required List parameters, + required TypeDeclaration returnType, + required String channelName, + required String errorClassName, + }) { + indent.writeln( + r'val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""', + ); + _writeFlutterMethodMessageCall( + indent, + parameters: parameters, + returnType: returnType, + channelName: '$channelName\$separatedMessageChannelSuffix', + errorClassName: errorClassName, + ); + }, ); } }); @@ -570,7 +608,7 @@ if (wrapped == null) { indent.write('val codec: MessageCodec by lazy '); indent.addScoped('{', '}', () { indent.writeln( - '${generatorOptions.fileSpecificClassNameComponent}$_codecName'); + '${generatorOptions.fileSpecificClassNameComponent}$_codecName()'); }); indent.writeln( '/** Sets up an instance of `$apiName` to handle messages through the `binaryMessenger`. */'); @@ -583,9 +621,9 @@ if (wrapped == null) { for (final Method method in api.methods) { _writeHostMethodMessageHandler( indent, - api: api, name: method.name, - channelName: makeChannelName(api, method, dartPackageName), + channelName: + '${makeChannelName(api, method, dartPackageName)}\$separatedMessageChannelSuffix', taskQueueType: method.taskQueueType, parameters: method.parameters, returnType: method.returnType, @@ -597,6 +635,355 @@ if (wrapped == null) { }); } + @override + void writeInstanceManager( + KotlinOptions generatorOptions, + Root root, + Indent indent, { + required String dartPackageName, + }) { + indent.format(instanceManagerTemplate(generatorOptions)); + indent.newln(); + } + + @override + void writeInstanceManagerApi( + KotlinOptions generatorOptions, + Root root, + Indent indent, { + required String dartPackageName, + }) { + final String instanceManagerApiName = + '${kotlinInstanceManagerClassName(generatorOptions)}Api'; + + addDocumentationComments( + indent, + [ + ' Generated API for managing the Dart and native `InstanceManager`s.', + ], + _docCommentSpec, + ); + indent.writeScoped( + 'private class $instanceManagerApiName(val binaryMessenger: BinaryMessenger) {', + '}', + () { + indent.writeScoped('companion object {', '}', () { + addDocumentationComments( + indent, + [' The codec used by $instanceManagerApiName.'], + _docCommentSpec, + ); + indent.writeScoped( + 'val codec: MessageCodec by lazy {', + '}', + () { + indent.writeln( + '${generatorOptions.fileSpecificClassNameComponent}$_codecName()', + ); + }, + ); + indent.newln(); + + addDocumentationComments( + indent, + [ + ' Sets up an instance of `$instanceManagerApiName` to handle messages from the', + ' `binaryMessenger`.', + ], + _docCommentSpec, + ); + indent.writeScoped( + 'fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, instanceManager: ${kotlinInstanceManagerClassName(generatorOptions)}?) {', + '}', + () { + const String setHandlerCondition = 'instanceManager != null'; + _writeHostMethodMessageHandler( + indent, + name: 'removeStrongReference', + channelName: + makeRemoveStrongReferenceChannelName(dartPackageName), + taskQueueType: TaskQueueType.serial, + parameters: [ + Parameter( + name: 'identifier', + type: const TypeDeclaration( + baseName: 'int', + isNullable: false, + ), + ), + ], + returnType: const TypeDeclaration.voidDeclaration(), + setHandlerCondition: setHandlerCondition, + onCreateCall: ( + List safeArgNames, { + required String apiVarName, + }) { + return 'instanceManager.remove(${safeArgNames.single})'; + }, + ); + _writeHostMethodMessageHandler( + indent, + name: 'clear', + channelName: makeClearChannelName(dartPackageName), + taskQueueType: TaskQueueType.serial, + parameters: [], + returnType: const TypeDeclaration.voidDeclaration(), + setHandlerCondition: setHandlerCondition, + onCreateCall: ( + List safeArgNames, { + required String apiVarName, + }) { + return 'instanceManager.clear()'; + }, + ); + }, + ); + }); + indent.newln(); + + _writeFlutterMethod( + indent, + generatorOptions: generatorOptions, + name: 'removeStrongReference', + parameters: [ + Parameter( + name: 'identifier', + type: const TypeDeclaration(baseName: 'int', isNullable: false), + ) + ], + returnType: const TypeDeclaration.voidDeclaration(), + channelName: makeRemoveStrongReferenceChannelName(dartPackageName), + dartPackageName: dartPackageName, + ); + }, + ); + } + + @override + void writeProxyApiBaseCodec( + KotlinOptions generatorOptions, + Root root, + Indent indent, + ) { + final Iterable allProxyApis = + root.apis.whereType(); + + _writeProxyApiRegistrar( + indent, + generatorOptions: generatorOptions, + allProxyApis: allProxyApis, + ); + + // 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) { + return [ + if (api.superClass?.associatedProxyApi != null) + api.superClass!.associatedProxyApi!, + ...api.interfaces.map( + (TypeDeclaration interface) => interface.associatedProxyApi!, + ), + ]; + }, + ); + + indent.writeScoped( + 'private class ${proxyApiCodecName(generatorOptions)}(val registrar: ${proxyApiRegistrarName(generatorOptions)}) : ' + '${generatorOptions.fileSpecificClassNameComponent}$_codecName() {', + '}', + () { + indent.format( + ''' + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + $proxyApiCodecInstanceManagerKey.toByte() -> { + return registrar.instanceManager.getInstance(readValue(buffer) as Long) + } + else -> super.readValueOfType(type, buffer) + } + }''', + ); + indent.newln(); + + indent.writeScoped( + 'override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {', + '}', + () { + final List nonProxyApiTypes = [ + 'Boolean', + 'ByteArray', + 'Double', + 'DoubleArray', + 'FloatArray', + 'Int', + 'IntArray', + 'List<*>', + 'Long', + 'LongArray', + 'Map<*, *>', + 'String', + ...root.enums.map((Enum anEnum) => anEnum.name), + ]; + final String isSupportedExpression = nonProxyApiTypes + .map((String kotlinType) => 'value is $kotlinType') + .followedBy(['value == null']).join(' || '); + // Non ProxyApi types are checked first to handle the scenario + // where a client wraps the `Object` class which all the + // classes above extend. + indent.writeScoped('if ($isSupportedExpression) {', '}', () { + indent.writeln('super.writeValue(stream, value)'); + indent.writeln('return'); + }); + indent.newln(); + + 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) { + registrar.get$hostProxyApiPrefix${api.name}().${classMemberNamePrefix}newInstance(value) { } + }''', + ); + }, + ); + indent.newln(); + + indent.format( + ''' + when { + registrar.instanceManager.containsInstance(value) -> { + stream.write($proxyApiCodecInstanceManagerKey) + writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) + } + else -> throw IllegalArgumentException("Unsupported value: '\$value' of type '\${value.javaClass.name}'") + }''', + ); + }, + ); + }, + ); + } + + @override + void writeProxyApi( + KotlinOptions generatorOptions, + Root root, + Indent indent, + AstProxyApi api, { + required String dartPackageName, + }) { + final String kotlinApiName = '$hostProxyApiPrefix${api.name}'; + + addDocumentationComments( + indent, + api.documentationComments, + _docCommentSpec, + ); + indent.writeln('@Suppress("UNCHECKED_CAST")'); + // The API only needs to be abstract if there are methods to override. + final String classModifier = + api.hasMethodsRequiringImplementation() ? 'abstract' : 'open'; + indent.writeScoped( + '$classModifier class $kotlinApiName(open val pigeonRegistrar: ${proxyApiRegistrarName(generatorOptions)}) {', + '}', + () { + final String fullKotlinClassName = + api.kotlinOptions?.fullClassName ?? api.name; + + 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, + generatorOptions: generatorOptions, + ); + }); + indent.newln(); + } + + _writeProxyApiNewInstanceMethod( + indent, + api, + generatorOptions: generatorOptions, + apiAsTypeDeclaration: apiAsTypeDeclaration, + newInstanceMethodName: '${classMemberNamePrefix}newInstance', + dartPackageName: dartPackageName, + ); + + _writeProxyApiFlutterMethods( + indent, + api, + generatorOptions: generatorOptions, + apiAsTypeDeclaration: apiAsTypeDeclaration, + dartPackageName: dartPackageName, + ); + + _writeProxyApiInheritedApiMethods(indent, api); + }, + ); + } + void _writeWrapResult(Indent indent) { indent.newln(); indent.write('private fun wrapResult(result: Any?): List '); @@ -673,12 +1060,13 @@ if (wrapped == null) { 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) { @@ -694,6 +1082,7 @@ if (wrapped == null) { List documentationComments = const [], int? minApiRequirement, bool isAsynchronous = false, + bool isOpen = false, bool isAbstract = false, String Function(int index, NamedType type) getArgumentName = _getArgumentName, @@ -726,28 +1115,33 @@ if (wrapped == null) { ); } + final String openKeyword = isOpen ? 'open ' : ''; final String abstractKeyword = isAbstract ? 'abstract ' : ''; if (isAsynchronous) { argSignature.add('callback: (Result<$resultType>) -> Unit'); - indent.writeln('${abstractKeyword}fun $name(${argSignature.join(', ')})'); + indent.writeln( + '$openKeyword${abstractKeyword}fun $name(${argSignature.join(', ')})', + ); } else if (returnType.isVoid) { - indent.writeln('${abstractKeyword}fun $name(${argSignature.join(', ')})'); + indent.writeln( + '$openKeyword${abstractKeyword}fun $name(${argSignature.join(', ')})', + ); } else { indent.writeln( - '${abstractKeyword}fun $name(${argSignature.join(', ')}): $returnTypeString', + '$openKeyword${abstractKeyword}fun $name(${argSignature.join(', ')}): $returnTypeString', ); } } void _writeHostMethodMessageHandler( Indent indent, { - required Api api, required String name, required String channelName, required TaskQueueType taskQueueType, required List parameters, required TypeDeclaration returnType, + String setHandlerCondition = 'api != null', bool isAsynchronous = false, String Function(List safeArgNames, {required String apiVarName})? onCreateCall, @@ -760,8 +1154,10 @@ if (wrapped == null) { indent.writeln( 'val $taskQueue = binaryMessenger.makeBackgroundTaskQueue()'); } + indent.write( - 'val channel = BasicMessageChannel(binaryMessenger, "$channelName\$separatedMessageChannelSuffix", codec'); + 'val channel = BasicMessageChannel(binaryMessenger, "$channelName", codec', + ); if (taskQueue != null) { indent.addln(', $taskQueue)'); @@ -769,7 +1165,7 @@ if (wrapped == null) { indent.addln(')'); } - indent.write('if (api != null) '); + indent.write('if ($setHandlerCondition) '); indent.addScoped('{', '}', () { final String messageVarName = parameters.isNotEmpty ? 'message' : '_'; @@ -842,6 +1238,13 @@ if (wrapped == null) { required String dartPackageName, List documentationComments = const [], int? minApiRequirement, + void Function( + Indent indent, { + required List parameters, + required TypeDeclaration returnType, + required String channelName, + required String errorClassName, + }) onWriteBody = _writeFlutterMethodMessageCall, }) { _writeMethodDeclaration( indent, @@ -856,7 +1259,7 @@ if (wrapped == null) { final String errorClassName = _getErrorClassName(generatorOptions); indent.addScoped('{', '}', () { - _writeFlutterMethodMessageCall( + onWriteBody( indent, parameters: parameters, returnType: returnType, @@ -886,10 +1289,7 @@ if (wrapped == null) { } const String channel = 'channel'; - indent.writeln( - r'val separatedMessageChannelSuffix = if (messageChannelSuffix.isNotEmpty()) ".$messageChannelSuffix" else ""'); - indent.writeln( - 'val channelName = "$channelName\$separatedMessageChannelSuffix"'); + indent.writeln('val channelName = "$channelName"'); indent.writeln( 'val $channel = BasicMessageChannel(binaryMessenger, channelName, codec)'); indent.writeScoped('$channel.send($sendArgument) {', '}', () { @@ -921,6 +1321,664 @@ if (wrapped == null) { }); }); } + + void _writeProxyApiRegistrar( + Indent indent, { + required KotlinOptions generatorOptions, + required Iterable allProxyApis, + }) { + final String registrarName = proxyApiRegistrarName(generatorOptions); + final String instanceManagerName = kotlinInstanceManagerClassName( + generatorOptions, + ); + final String instanceManagerApiName = '${instanceManagerName}Api'; + + addDocumentationComments( + indent, + [ + ' Provides implementations for each ProxyApi implementation and provides access to resources', + ' needed by any implementation.', + ], + _docCommentSpec, + ); + indent.writeScoped( + 'abstract class $registrarName(val binaryMessenger: BinaryMessenger) {', + '}', + () { + addDocumentationComments( + indent, + [' Whether APIs should ignore calling to Dart.'], + _docCommentSpec, + ); + indent.writeln('public var ignoreCallsToDart = false'); + indent.format( + ''' + val instanceManager: $instanceManagerName + private var _codec: MessageCodec? = null + val codec: MessageCodec + get() { + if (_codec == null) { + _codec = ${proxyApiCodecName(generatorOptions)}(this) + } + return _codec!! + } + + init { + val api = $instanceManagerApiName(binaryMessenger) + instanceManager = $instanceManagerName.create( + object : $instanceManagerName.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "${proxyApiClassNamePrefix}ProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: \$identifier" + ) + } + } + } + } + ) + }''', + ); + for (final AstProxyApi api in allProxyApis) { + _writeMethodDeclaration( + indent, + name: 'get$hostProxyApiPrefix${api.name}', + isAbstract: + api.hasAnyHostMessageCalls() || api.unattachedFields.isNotEmpty, + isOpen: + !api.hasAnyHostMessageCalls() && api.unattachedFields.isEmpty, + documentationComments: [ + ' An implementation of [$hostProxyApiPrefix${api.name}] used to add a new Dart instance of', + ' `${api.name}` to the Dart `InstanceManager`.' + ], + returnType: TypeDeclaration( + baseName: '$hostProxyApiPrefix${api.name}', + isNullable: false, + ), + parameters: [], + ); + + // Use the default API implementation if this API does not have any + // methods to implement. + if (!api.hasMethodsRequiringImplementation()) { + indent.writeScoped('{', '}', () { + indent.writeln('return $hostProxyApiPrefix${api.name}(this)'); + }); + } + indent.newln(); + } + + indent.writeScoped('fun setUp() {', '}', () { + indent.writeln( + '$instanceManagerApiName.setUpMessageHandlers(binaryMessenger, instanceManager)', + ); + for (final AstProxyApi api in allProxyApis) { + final bool hasHostMessageCalls = api.constructors.isNotEmpty || + api.attachedFields.isNotEmpty || + api.hostMethods.isNotEmpty; + if (hasHostMessageCalls) { + indent.writeln( + '$hostProxyApiPrefix${api.name}.setUpMessageHandlers(binaryMessenger, get$hostProxyApiPrefix${api.name}())', + ); + } + } + }); + + indent.writeScoped('fun tearDown() {', '}', () { + indent.writeln( + '$instanceManagerApiName.setUpMessageHandlers(binaryMessenger, null)', + ); + for (final AstProxyApi api in allProxyApis) { + if (api.hasAnyHostMessageCalls()) { + indent.writeln( + '$hostProxyApiPrefix${api.name}.setUpMessageHandlers(binaryMessenger, null)', + ); + } + } + }); + }, + ); + } + + // 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: _findAndroidHighestApiRequirement([ + apiAsTypeDeclaration, + ...constructor.parameters.map( + (Parameter parameter) => parameter.type, + ), + ])?.version, + 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: _findAndroidHighestApiRequirement([ + apiAsTypeDeclaration, + field.type, + ])?.version, + 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: _findAndroidHighestApiRequirement([ + apiAsTypeDeclaration, + field.type, + ])?.version, + 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: _findAndroidHighestApiRequirement( + [ + if (!method.isStatic) apiAsTypeDeclaration, + method.returnType, + ...method.parameters.map((Parameter p) => p.type), + ], + )?.version, + 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, + required KotlinOptions generatorOptions, + }) { + indent.writeln('@Suppress("LocalVariableName")'); + indent.writeScoped( + 'fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: $kotlinApiName?) {', + '}', + () { + indent.writeln( + 'val codec = api?.pigeonRegistrar?.codec ?: ${generatorOptions.fileSpecificClassNameComponent}$_codecName()', + ); + void writeWithApiCheckIfNecessary( + List types, { + required String channelName, + required void Function() onWrite, + }) { + final ({TypeDeclaration type, int version})? typeWithRequirement = + _findAndroidHighestApiRequirement(types); + if (typeWithRequirement != null) { + final int apiRequirement = typeWithRequirement.version; + indent.writeScoped( + 'if (android.os.Build.VERSION.SDK_INT >= $apiRequirement) {', + '}', + onWrite, + addTrailingNewline: false, + ); + indent.writeScoped(' else {', '}', () { + final String className = typeWithRequirement + .type.associatedProxyApi!.kotlinOptions?.fullClassName ?? + typeWithRequirement.type.baseName; + indent.format( + ''' + val channel = BasicMessageChannel( + binaryMessenger, + "$channelName", + codec + ) + if (api != null) { + channel.setMessageHandler { _, reply -> + reply.reply(wrapError(UnsupportedOperationException( + "Call references class `$className`, which requires api version $apiRequirement." + ))) + } + } else { + channel.setMessageHandler(null) + }''', + ); + }); + } 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, + name: name, + channelName: channelName, + taskQueueType: TaskQueueType.serial, + returnType: const TypeDeclaration.voidDeclaration(), + onCreateCall: ( + List methodParameters, { + required String apiVarName, + }) { + return '$apiVarName.pigeonRegistrar.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, + 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.pigeonRegistrar.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, + 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: _findAndroidHighestApiRequirement([ + apiAsTypeDeclaration, + ...api.unattachedFields.map((ApiField field) => field.type), + ])?.version, + 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 (pigeonRegistrar.ignoreCallsToDart) {', + '}', + () { + indent.format( + ''' + callback( + Result.failure( + $errorClassName("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return''', + ); + }, + ); + indent.writeScoped( + 'if (pigeonRegistrar.instanceManager.containsInstance(${classMemberNamePrefix}instanceArg)) {', + '}', + () { + indent.writeln('Result.success(Unit)'); + indent.writeln('return'); + }, + ); + if (api.hasCallbackConstructor()) { + indent.writeln( + 'val ${classMemberNamePrefix}identifierArg = pigeonRegistrar.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 = pigeonRegistrar.binaryMessenger'); + indent.writeln('val codec = pigeonRegistrar.codec'); + _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: _findAndroidHighestApiRequirement([ + apiAsTypeDeclaration, + method.returnType, + ...method.parameters.map((Parameter parameter) => parameter.type), + ])?.version, + 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.writeScoped( + 'if (pigeonRegistrar.ignoreCallsToDart) {', + '}', + () { + indent.format( + ''' + callback( + Result.failure( + $errorClassName("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return''', + ); + }, + ); + indent + .writeln('val binaryMessenger = pigeonRegistrar.binaryMessenger'); + indent.writeln('val codec = pigeonRegistrar.codec'); + _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 = '$hostProxyApiPrefix$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 pigeonRegistrar.get$apiName()'); + }); + indent.newln(); + } + } +} + +({TypeDeclaration type, int version})? _findAndroidHighestApiRequirement( + Iterable types, +) { + return findHighestApiRequirement( + types, + onGetApiRequirement: (TypeDeclaration type) { + return type.associatedProxyApi?.kotlinOptions?.minAndroidApi; + }, + onCompare: (int first, int second) => first.compareTo(second), + ); } String _getErrorClassName(KotlinOptions generatorOptions) => @@ -994,8 +2052,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 53087ae7877a..e9aa09922263 100644 --- a/packages/pigeon/lib/pigeon.dart +++ b/packages/pigeon/lib/pigeon.dart @@ -8,7 +8,7 @@ export 'cpp_generator.dart' show CppOptions; export 'dart_generator.dart' show DartOptions; export 'gobject_generator.dart' show GObjectOptions; 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 c0d6658aefdf..d4db52c55c2c 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -139,7 +139,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. /// @@ -149,6 +149,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. @@ -1686,6 +1690,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: [], @@ -1693,6 +1707,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/pigeons/proxy_api_tests.dart b/packages/pigeon/pigeons/proxy_api_tests.dart index 699e5dfaed86..fe6fb73fcfd2 100644 --- a/packages/pigeon/pigeons/proxy_api_tests.dart +++ b/packages/pigeon/pigeons/proxy_api_tests.dart @@ -455,7 +455,11 @@ abstract class ProxyApiTestClass extends ProxyApiSuperClass } /// ProxyApi to serve as a super class to the core ProxyApi class. -@ProxyApi() +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions( + fullClassName: 'com.example.test_plugin.ProxyApiSuperClass', + ), +) abstract class ProxyApiSuperClass { ProxyApiSuperClass(); @@ -467,3 +471,12 @@ abstract class ProxyApiSuperClass { abstract class ProxyApiInterface { late void Function()? anInterfaceMethod; } + +@ProxyApi( + kotlinOptions: KotlinProxyApiOptions(minAndroidApi: 25), +) +abstract class ClassWithApiRequirement { + ClassWithApiRequirement(); + + void aMethod(); +} 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 31aff33a3f36..b7861ee4d574 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 4b0752acc9c1..a26ffda8ad6d 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 @@ -8,7 +8,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:integration_test/integration_test.dart'; import 'generated.dart'; -import 'src/generated/core_tests.gen.dart'; const int _biggerThanBigInt = 3000000000; const int _regularInt = 42; @@ -2070,6 +2069,656 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) { }); }); + 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); + expect(await api.echoNullableInt(1), 1); + }); + + testWidgets('echoNullableDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableDouble(null), null); + expect(await api.echoNullableDouble(1.0), 1.0); + }); + + testWidgets('echoNullableBool', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableBool(null), null); + expect(await api.echoNullableBool(false), false); + }); + + testWidgets('echoNullableString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableString(null), null); + expect(await api.echoNullableString('aString'), 'aString'); + }); + + testWidgets('echoNullableUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableUint8List(null), null); + expect(await api.echoNullableUint8List(Uint8List(0)), Uint8List(0)); + }); + + testWidgets('echoNullableObject', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableObject(null), null); + expect(await api.echoNullableObject('aString'), 'aString'); + }); + + testWidgets('echoNullableList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableList(null), null); + expect(await api.echoNullableList([1]), [1]); + }); + + testWidgets('echoNullableMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableMap(null), null); + expect( + await api.echoNullableMap({'value': 1}), + {'value': 1}, + ); + }); + + testWidgets('echoNullableEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableEnum(null), null); + expect( + await api.echoNullableEnum(ProxyApiTestEnum.one), + ProxyApiTestEnum.one, + ); + }); + + testWidgets('echoNullableProxyApi', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoNullableProxyApi(null), null); + + final ProxyApiSuperClass proxyApi = ProxyApiSuperClass(); + expect( + await api.echoNullableProxyApi(proxyApi), + proxyApi, + ); + }); + + 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); + expect(await api.echoAsyncNullableInt(1), 1); + }); + + testWidgets('echoAsyncNullableDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableDouble(null), null); + expect(await api.echoAsyncNullableDouble(2.0), 2.0); + }); + + testWidgets('echoAsyncNullableBool', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableBool(null), null); + expect(await api.echoAsyncNullableBool(true), true); + }); + + testWidgets('echoAsyncNullableString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableString(null), null); + expect(await api.echoAsyncNullableString('aString'), 'aString'); + }); + + testWidgets('echoAsyncNullableUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableUint8List(null), null); + expect( + await api.echoAsyncNullableUint8List(Uint8List(0)), + Uint8List(0), + ); + }); + + testWidgets('echoAsyncNullableObject', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableObject(null), null); + expect(await api.echoAsyncNullableObject(1), 1); + }); + + testWidgets('echoAsyncNullableList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableList(null), null); + expect(await api.echoAsyncNullableList([1]), [1]); + }); + + testWidgets('echoAsyncNullableMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableMap(null), null); + expect( + await api.echoAsyncNullableMap({'banana': 1}), + {'banana': 1}, + ); + }); + + testWidgets('echoAsyncNullableEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass(); + expect(await api.echoAsyncNullableEnum(null), null); + expect( + await api.echoAsyncNullableEnum(ProxyApiTestEnum.one), + ProxyApiTestEnum.one, + ); + }); + + 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); + expect(await api.callFlutterEchoNullableBool(true), true); + }); + + testWidgets('callFlutterEchoNullableInt', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableInt: (_, int? anInt) => anInt, + ); + expect(await api.callFlutterEchoNullableInt(null), null); + expect(await api.callFlutterEchoNullableInt(1), 1); + }); + + testWidgets('callFlutterEchoNullableDouble', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableDouble: (_, double? aDouble) => aDouble, + ); + expect(await api.callFlutterEchoNullableDouble(null), null); + expect(await api.callFlutterEchoNullableDouble(1.0), 1.0); + }); + + testWidgets('callFlutterEchoNullableString', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableString: (_, String? aString) => aString, + ); + expect(await api.callFlutterEchoNullableString(null), null); + expect(await api.callFlutterEchoNullableString('aString'), 'aString'); + }); + + testWidgets('callFlutterEchoNullableUint8List', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableUint8List: (_, Uint8List? aUint8List) => aUint8List, + ); + expect(await api.callFlutterEchoNullableUint8List(null), null); + expect( + await api.callFlutterEchoNullableUint8List(Uint8List(0)), + Uint8List(0), + ); + }); + + testWidgets('callFlutterEchoNullableList', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableList: (_, List? aList) => aList, + ); + expect(await api.callFlutterEchoNullableList(null), null); + expect(await api.callFlutterEchoNullableList([0]), [0]); + }); + + testWidgets('callFlutterEchoNullableMap', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableMap: (_, Map? aMap) => aMap, + ); + expect(await api.callFlutterEchoNullableMap(null), null); + expect( + await api.callFlutterEchoNullableMap({'str': 0}), + {'str': 0}, + ); + }); + + testWidgets('callFlutterEchoNullableEnum', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableEnum: (_, ProxyApiTestEnum? anEnum) => anEnum, + ); + expect(await api.callFlutterEchoNullableEnum(null), null); + expect( + await api.callFlutterEchoNullableEnum(ProxyApiTestEnum.two), + ProxyApiTestEnum.two, + ); + }); + + testWidgets('callFlutterEchoNullableProxyApi', (_) async { + final ProxyApiTestClass api = _createGenericProxyApiTestClass( + flutterEchoNullableProxyApi: (_, ProxyApiSuperClass? aProxyApi) => + aProxyApi, + ); + + expect(await api.callFlutterEchoNullableProxyApi(null), null); + + final ProxyApiSuperClass proxyApi = ProxyApiSuperClass(); + expect(await api.callFlutterEchoNullableProxyApi(proxyApi), proxyApi); + }); + + 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); + }); + }); + group('Flutter API with suffix', () { setUp(() { FlutterSmallApi.setUp( @@ -2235,3 +2884,142 @@ class _SmallFlutterApi implements FlutterSmallApi { return msg; } } + +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/shared_test_plugin_code/lib/src/generated/proxy_api_tests.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/proxy_api_tests.gen.dart index c0634e08ed41..eb40693a844b 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/proxy_api_tests.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/proxy_api_tests.gen.dart @@ -42,9 +42,9 @@ abstract class PigeonInternalProxyApiBaseClass { /// Construct a [PigeonInternalProxyApiBaseClass]. PigeonInternalProxyApiBaseClass({ this.pigeon_binaryMessenger, - PigeonInternalInstanceManager? pigeon_instanceManager, + PigeonInstanceManager? pigeon_instanceManager, }) : pigeon_instanceManager = - pigeon_instanceManager ?? PigeonInternalInstanceManager.instance; + pigeon_instanceManager ?? PigeonInstanceManager.instance; /// Sends and receives binary data across the Flutter platform barrier. /// @@ -55,12 +55,12 @@ abstract class PigeonInternalProxyApiBaseClass { /// Maintains instances stored to communicate with native language objects. @protected - final PigeonInternalInstanceManager pigeon_instanceManager; + final PigeonInstanceManager pigeon_instanceManager; /// Instantiates and returns a functionally identical object to oneself. /// /// Outside of tests, this method should only ever be called by - /// [PigeonInternalInstanceManager]. + /// [PigeonInstanceManager]. /// /// Subclasses should always override their parent's implementation of this /// method. @@ -83,10 +83,9 @@ abstract class PigeonInternalProxyApiBaseClass { /// is added as a weak reference with the same identifier. This prevents a /// scenario where the weak referenced instance was released and then later /// returned by the host platform. -class PigeonInternalInstanceManager { - /// Constructs a [PigeonInternalInstanceManager]. - PigeonInternalInstanceManager( - {required void Function(int) onWeakReferenceRemoved}) { +class PigeonInstanceManager { + /// Constructs a [PigeonInstanceManager]. + PigeonInstanceManager({required void Function(int) onWeakReferenceRemoved}) { this.onWeakReferenceRemoved = (int identifier) { _weakInstances.remove(identifier); onWeakReferenceRemoved(identifier); @@ -100,12 +99,12 @@ class PigeonInternalInstanceManager { // 0 <= n < 2^16. static const int _maxDartCreatedIdentifier = 65536; - /// The default [PigeonInternalInstanceManager] used by ProxyApis. + /// The default [PigeonInstanceManager] used by ProxyApis. /// /// On creation, this manager makes a call to clear the native /// InstanceManager. This is to prevent identifier conflicts after a host /// restart. - static final PigeonInternalInstanceManager instance = _initInstance(); + static final PigeonInstanceManager instance = _initInstance(); // Expando is used because it doesn't prevent its keys from becoming // inaccessible. This allows the manager to efficiently retrieve an identifier @@ -127,14 +126,13 @@ class PigeonInternalInstanceManager { /// or becomes inaccessible. late final void Function(int) onWeakReferenceRemoved; - static PigeonInternalInstanceManager _initInstance() { + static PigeonInstanceManager _initInstance() { WidgetsFlutterBinding.ensureInitialized(); final _PigeonInternalInstanceManagerApi api = _PigeonInternalInstanceManagerApi(); - // Clears the native `PigeonInternalInstanceManager` on the initial use of the Dart one. + // Clears the native `PigeonInstanceManager` on the initial use of the Dart one. api.clear(); - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager( + final PigeonInstanceManager instanceManager = PigeonInstanceManager( onWeakReferenceRemoved: (int identifier) { api.removeStrongReference(identifier); }, @@ -147,6 +145,8 @@ class PigeonInternalInstanceManager { pigeon_instanceManager: instanceManager); ProxyApiInterface.pigeon_setUpMessageHandlers( pigeon_instanceManager: instanceManager); + ClassWithApiRequirement.pigeon_setUpMessageHandlers( + pigeon_instanceManager: instanceManager); return instanceManager; } @@ -284,7 +284,7 @@ class PigeonInternalInstanceManager { } } -/// Generated API for managing the Dart and native `PigeonInternalInstanceManager`s. +/// Generated API for managing the Dart and native `PigeonInstanceManager`s. class _PigeonInternalInstanceManagerApi { /// Constructor for [_PigeonInternalInstanceManagerApi]. _PigeonInternalInstanceManagerApi({BinaryMessenger? binaryMessenger}) @@ -292,19 +292,18 @@ class _PigeonInternalInstanceManagerApi { final BinaryMessenger? pigeonVar_binaryMessenger; - static const MessageCodec pigeonChannelCodec = - StandardMessageCodec(); + static const MessageCodec pigeonChannelCodec = _PigeonCodec(); static void setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? binaryMessenger, - PigeonInternalInstanceManager? instanceManager, + PigeonInstanceManager? instanceManager, }) { { final BasicMessageChannel< Object?> pigeonVar_channel = BasicMessageChannel< Object?>( - 'dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManagerApi.removeStrongReference', + 'dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManager.removeStrongReference', pigeonChannelCodec, binaryMessenger: binaryMessenger); if (pigeon_clearHandlers) { @@ -312,13 +311,13 @@ class _PigeonInternalInstanceManagerApi { } else { pigeonVar_channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManagerApi.removeStrongReference was null.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManager.removeStrongReference was null.'); final List args = (message as List?)!; final int? arg_identifier = (args[0] as int?); assert(arg_identifier != null, - 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManagerApi.removeStrongReference was null, expected non-null int.'); + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManager.removeStrongReference was null, expected non-null int.'); try { - (instanceManager ?? PigeonInternalInstanceManager.instance) + (instanceManager ?? PigeonInstanceManager.instance) .remove(arg_identifier!); return wrapResponse(empty: true); } on PlatformException catch (e) { @@ -334,7 +333,7 @@ class _PigeonInternalInstanceManagerApi { Future removeStrongReference(int identifier) async { const String pigeonVar_channelName = - 'dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManagerApi.removeStrongReference'; + 'dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManager.removeStrongReference'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, @@ -356,12 +355,12 @@ class _PigeonInternalInstanceManagerApi { } } - /// Clear the native `PigeonInternalInstanceManager`. + /// Clear the native `PigeonInstanceManager`. /// /// This is typically called after a hot restart. Future clear() async { const String pigeonVar_channelName = - 'dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManagerApi.clear'; + 'dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManager.clear'; final BasicMessageChannel pigeonVar_channel = BasicMessageChannel( pigeonVar_channelName, @@ -386,7 +385,7 @@ class _PigeonInternalInstanceManagerApi { class _PigeonInternalProxyApiBaseCodec extends _PigeonCodec { const _PigeonInternalProxyApiBaseCodec(this.instanceManager); - final PigeonInternalInstanceManager instanceManager; + final PigeonInstanceManager instanceManager; @override void writeValue(WriteBuffer buffer, Object? value) { if (value is PigeonInternalProxyApiBaseClass) { @@ -583,7 +582,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// Constructs [ProxyApiTestClass] without creating the associated native object. /// /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInternalInstanceManager]. + /// create copies for an [PigeonInstanceManager]. @protected ProxyApiTestClass.pigeon_detached({ super.pigeon_binaryMessenger, @@ -692,7 +691,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final void Function(ProxyApiTestClass pigeon_instance)? flutterNoop; @@ -713,7 +712,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final Object? Function(ProxyApiTestClass pigeon_instance)? flutterThrowError; @@ -734,7 +733,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final void Function(ProxyApiTestClass pigeon_instance)? flutterThrowErrorFromVoid; @@ -756,7 +755,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final bool Function( ProxyApiTestClass pigeon_instance, @@ -780,7 +779,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final int Function( ProxyApiTestClass pigeon_instance, @@ -804,7 +803,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final double Function( ProxyApiTestClass pigeon_instance, @@ -828,7 +827,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final String Function( ProxyApiTestClass pigeon_instance, @@ -852,7 +851,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final Uint8List Function( ProxyApiTestClass pigeon_instance, @@ -876,7 +875,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final List Function( ProxyApiTestClass pigeon_instance, @@ -901,7 +900,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final List Function( ProxyApiTestClass pigeon_instance, @@ -925,7 +924,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final Map Function( ProxyApiTestClass pigeon_instance, @@ -950,7 +949,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final Map Function( ProxyApiTestClass pigeon_instance, @@ -974,7 +973,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final ProxyApiTestEnum Function( ProxyApiTestClass pigeon_instance, @@ -998,7 +997,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final ProxyApiSuperClass Function( ProxyApiTestClass pigeon_instance, @@ -1022,7 +1021,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final bool? Function( ProxyApiTestClass pigeon_instance, @@ -1046,7 +1045,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final int? Function( ProxyApiTestClass pigeon_instance, @@ -1070,7 +1069,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final double? Function( ProxyApiTestClass pigeon_instance, @@ -1094,7 +1093,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final String? Function( ProxyApiTestClass pigeon_instance, @@ -1118,7 +1117,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final Uint8List? Function( ProxyApiTestClass pigeon_instance, @@ -1142,7 +1141,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final List? Function( ProxyApiTestClass pigeon_instance, @@ -1166,7 +1165,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final Map? Function( ProxyApiTestClass pigeon_instance, @@ -1190,7 +1189,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final ProxyApiTestEnum? Function( ProxyApiTestClass pigeon_instance, @@ -1214,7 +1213,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final ProxyApiSuperClass? Function( ProxyApiTestClass pigeon_instance, @@ -1239,7 +1238,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final Future Function(ProxyApiTestClass pigeon_instance)? flutterNoopAsync; @@ -1261,7 +1260,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final Future Function( ProxyApiTestClass pigeon_instance, @@ -1279,7 +1278,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, - PigeonInternalInstanceManager? pigeon_instanceManager, + PigeonInstanceManager? pigeon_instanceManager, ProxyApiTestClass Function( bool aBool, int anInt, @@ -1391,7 +1390,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInternalInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final BasicMessageChannel< @@ -1454,7 +1453,7 @@ class ProxyApiTestClass extends ProxyApiSuperClass final ProxyApiSuperClass? arg_aNullableProxyApi = (args[18] as ProxyApiSuperClass?); try { - (pigeon_instanceManager ?? PigeonInternalInstanceManager.instance) + (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( pigeon_newInstance?.call( arg_aBool!, @@ -2431,12 +2430,10 @@ class ProxyApiTestClass extends ProxyApiSuperClass final ProxyApiSuperClass pigeonVar_instance = ProxyApiSuperClass.pigeon_detached(); final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = - _PigeonInternalProxyApiBaseCodec( - PigeonInternalInstanceManager.instance); + _PigeonInternalProxyApiBaseCodec(PigeonInstanceManager.instance); final BinaryMessenger pigeonVar_binaryMessenger = ServicesBinding.instance.defaultBinaryMessenger; - final int pigeonVar_instanceIdentifier = PigeonInternalInstanceManager - .instance + final int pigeonVar_instanceIdentifier = PigeonInstanceManager.instance .addDartCreatedInstance(pigeonVar_instance); () async { const String pigeonVar_channelName = @@ -3932,11 +3929,11 @@ class ProxyApiTestClass extends ProxyApiSuperClass static Future staticNoop({ BinaryMessenger? pigeon_binaryMessenger, - PigeonInternalInstanceManager? pigeon_instanceManager, + PigeonInstanceManager? pigeon_instanceManager, }) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInternalInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const String pigeonVar_channelName = 'dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.staticNoop'; @@ -3964,11 +3961,11 @@ class ProxyApiTestClass extends ProxyApiSuperClass static Future echoStaticString( String aString, { BinaryMessenger? pigeon_binaryMessenger, - PigeonInternalInstanceManager? pigeon_instanceManager, + PigeonInstanceManager? pigeon_instanceManager, }) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInternalInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const String pigeonVar_channelName = 'dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.echoStaticString'; @@ -4000,11 +3997,11 @@ class ProxyApiTestClass extends ProxyApiSuperClass static Future staticAsyncNoop({ BinaryMessenger? pigeon_binaryMessenger, - PigeonInternalInstanceManager? pigeon_instanceManager, + PigeonInstanceManager? pigeon_instanceManager, }) async { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInternalInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; const String pigeonVar_channelName = 'dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.staticAsyncNoop'; @@ -4869,7 +4866,7 @@ class ProxyApiSuperClass extends PigeonInternalProxyApiBaseClass { /// Constructs [ProxyApiSuperClass] without creating the associated native object. /// /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInternalInstanceManager]. + /// create copies for an [PigeonInstanceManager]. @protected ProxyApiSuperClass.pigeon_detached({ super.pigeon_binaryMessenger, @@ -4883,12 +4880,12 @@ class ProxyApiSuperClass extends PigeonInternalProxyApiBaseClass { static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, - PigeonInternalInstanceManager? pigeon_instanceManager, + PigeonInstanceManager? pigeon_instanceManager, ProxyApiSuperClass Function()? pigeon_newInstance, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInternalInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final BasicMessageChannel< @@ -4908,7 +4905,7 @@ class ProxyApiSuperClass extends PigeonInternalProxyApiBaseClass { assert(arg_pigeon_instanceIdentifier != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.ProxyApiSuperClass.pigeon_newInstance was null, expected non-null int.'); try { - (pigeon_instanceManager ?? PigeonInternalInstanceManager.instance) + (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( pigeon_newInstance?.call() ?? ProxyApiSuperClass.pigeon_detached( @@ -4970,7 +4967,7 @@ class ProxyApiInterface extends PigeonInternalProxyApiBaseClass { /// Constructs [ProxyApiInterface] without creating the associated native object. /// /// This should only be used by subclasses created by this library or to - /// create copies for an [PigeonInternalInstanceManager]. + /// create copies for an [PigeonInstanceManager]. @protected ProxyApiInterface.pigeon_detached({ super.pigeon_binaryMessenger, @@ -4995,20 +4992,20 @@ class ProxyApiInterface extends PigeonInternalProxyApiBaseClass { /// ); /// ``` /// - /// Alternatively, [PigeonInternalInstanceManager.removeWeakReference] can be used to + /// Alternatively, [PigeonInstanceManager.removeWeakReference] can be used to /// release the associated Native object manually. final void Function(ProxyApiInterface pigeon_instance)? anInterfaceMethod; static void pigeon_setUpMessageHandlers({ bool pigeon_clearHandlers = false, BinaryMessenger? pigeon_binaryMessenger, - PigeonInternalInstanceManager? pigeon_instanceManager, + PigeonInstanceManager? pigeon_instanceManager, ProxyApiInterface Function()? pigeon_newInstance, void Function(ProxyApiInterface pigeon_instance)? anInterfaceMethod, }) { final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = _PigeonInternalProxyApiBaseCodec( - pigeon_instanceManager ?? PigeonInternalInstanceManager.instance); + pigeon_instanceManager ?? PigeonInstanceManager.instance); final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; { final BasicMessageChannel< @@ -5028,7 +5025,7 @@ class ProxyApiInterface extends PigeonInternalProxyApiBaseClass { assert(arg_pigeon_instanceIdentifier != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.ProxyApiInterface.pigeon_newInstance was null, expected non-null int.'); try { - (pigeon_instanceManager ?? PigeonInternalInstanceManager.instance) + (pigeon_instanceManager ?? PigeonInstanceManager.instance) .addHostCreatedInstance( pigeon_newInstance?.call() ?? ProxyApiInterface.pigeon_detached( @@ -5090,3 +5087,137 @@ class ProxyApiInterface extends PigeonInternalProxyApiBaseClass { ); } } + +class ClassWithApiRequirement extends PigeonInternalProxyApiBaseClass { + ClassWithApiRequirement({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }) { + final int pigeonVar_instanceIdentifier = + pigeon_instanceManager.addDartCreatedInstance(this); + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecClassWithApiRequirement; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + () async { + const String pigeonVar_channelName = + 'dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.pigeon_defaultConstructor'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = await pigeonVar_channel + .send([pigeonVar_instanceIdentifier]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + }(); + } + + /// Constructs [ClassWithApiRequirement] without creating the associated native object. + /// + /// This should only be used by subclasses created by this library or to + /// create copies for an [PigeonInstanceManager]. + @protected + ClassWithApiRequirement.pigeon_detached({ + super.pigeon_binaryMessenger, + super.pigeon_instanceManager, + }); + + late final _PigeonInternalProxyApiBaseCodec + _pigeonVar_codecClassWithApiRequirement = + _PigeonInternalProxyApiBaseCodec(pigeon_instanceManager); + + static void pigeon_setUpMessageHandlers({ + bool pigeon_clearHandlers = false, + BinaryMessenger? pigeon_binaryMessenger, + PigeonInstanceManager? pigeon_instanceManager, + ClassWithApiRequirement Function()? pigeon_newInstance, + }) { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _PigeonInternalProxyApiBaseCodec( + pigeon_instanceManager ?? PigeonInstanceManager.instance); + final BinaryMessenger? binaryMessenger = pigeon_binaryMessenger; + { + final BasicMessageChannel< + Object?> pigeonVar_channel = BasicMessageChannel< + Object?>( + 'dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.pigeon_newInstance', + pigeonChannelCodec, + binaryMessenger: binaryMessenger); + if (pigeon_clearHandlers) { + pigeonVar_channel.setMessageHandler(null); + } else { + pigeonVar_channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.pigeon_newInstance was null.'); + final List args = (message as List?)!; + final int? arg_pigeon_instanceIdentifier = (args[0] as int?); + assert(arg_pigeon_instanceIdentifier != null, + 'Argument for dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.pigeon_newInstance was null, expected non-null int.'); + try { + (pigeon_instanceManager ?? PigeonInstanceManager.instance) + .addHostCreatedInstance( + pigeon_newInstance?.call() ?? + ClassWithApiRequirement.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ), + arg_pigeon_instanceIdentifier!, + ); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } + }); + } + } + } + + Future aMethod() async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecClassWithApiRequirement; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.aMethod'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final List? pigeonVar_replyList = + await pigeonVar_channel.send([this]) as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + + @override + ClassWithApiRequirement pigeon_copy() { + return ClassWithApiRequirement.pigeon_detached( + pigeon_binaryMessenger: pigeon_binaryMessenger, + pigeon_instanceManager: pigeon_instanceManager, + ); + } +} diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/test/instance_manager_test.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/instance_manager_test.dart index 1b64950e0a97..f28cb077dea0 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/test/instance_manager_test.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/instance_manager_test.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// This file specifically tests the test PigeonInternalInstanceManager generated by core_tests. +// This file specifically tests the test PigeonInstanceManager generated by core_tests. import 'package:flutter_test/flutter_test.dart'; import 'package:shared_test_plugin_code/src/generated/proxy_api_tests.gen.dart'; @@ -10,8 +10,8 @@ import 'package:shared_test_plugin_code/src/generated/proxy_api_tests.gen.dart'; void main() { group('InstanceManager', () { test('addHostCreatedInstance', () { - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager(onWeakReferenceRemoved: (_) {}); + final PigeonInstanceManager instanceManager = + PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); final CopyableObject object = CopyableObject( pigeon_instanceManager: instanceManager, @@ -27,8 +27,8 @@ void main() { }); test('addHostCreatedInstance prevents already used objects and ids', () { - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager(onWeakReferenceRemoved: (_) {}); + final PigeonInstanceManager instanceManager = + PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); final CopyableObject object = CopyableObject( pigeon_instanceManager: instanceManager, @@ -51,8 +51,8 @@ void main() { }); test('addFlutterCreatedInstance', () { - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager(onWeakReferenceRemoved: (_) {}); + final PigeonInstanceManager instanceManager = + PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); final CopyableObject object = CopyableObject( pigeon_instanceManager: instanceManager, @@ -70,9 +70,8 @@ void main() { test('removeWeakReference', () { int? weakInstanceId; - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager( - onWeakReferenceRemoved: (int instanceId) { + final PigeonInstanceManager instanceManager = + PigeonInstanceManager(onWeakReferenceRemoved: (int instanceId) { weakInstanceId = instanceId; }); @@ -91,8 +90,8 @@ void main() { }); test('removeWeakReference removes only weak reference', () { - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager(onWeakReferenceRemoved: (_) {}); + final PigeonInstanceManager instanceManager = + PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); final CopyableObject object = CopyableObject( pigeon_instanceManager: instanceManager, @@ -108,8 +107,8 @@ void main() { }); test('removeStrongReference', () { - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager(onWeakReferenceRemoved: (_) {}); + final PigeonInstanceManager instanceManager = + PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); final CopyableObject object = CopyableObject( pigeon_instanceManager: instanceManager, @@ -122,8 +121,8 @@ void main() { }); test('removeStrongReference removes only strong reference', () { - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager(onWeakReferenceRemoved: (_) {}); + final PigeonInstanceManager instanceManager = + PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); final CopyableObject object = CopyableObject( pigeon_instanceManager: instanceManager, @@ -138,8 +137,8 @@ void main() { }); test('getInstance can add a new weak reference', () { - final PigeonInternalInstanceManager instanceManager = - PigeonInternalInstanceManager(onWeakReferenceRemoved: (_) {}); + final PigeonInstanceManager instanceManager = + PigeonInstanceManager(onWeakReferenceRemoved: (_) {}); final CopyableObject object = CopyableObject( pigeon_instanceManager: instanceManager, 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 a870aa16cae1..5f3fcaf31604 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,9 @@ # such as a flag to suppress version stamp generation. *.kt !TestPlugin.kt -!CoreTests.gen.kt \ No newline at end of file +!CoreTests.gen.kt +# This contains the declaration of the test classes wrapped by the ProxyApi tests and the +# implemetations of their APIs. +!ProxyApiTestApiImpls.kt +# Including this makes it easier to review code generation changes. +!ProxyApiTests.gen.kt diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt index d8d50f1a88e4..cf0d55b8be52 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/CoreTests.gen.kt @@ -442,7 +442,7 @@ data class TestMessage(val testList: List? = null) { } } -private object CoreTestsPigeonCodec : StandardMessageCodec() { +private open class CoreTestsPigeonCodec : StandardMessageCodec() { override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { return when (type) { 129.toByte() -> { @@ -799,7 +799,7 @@ interface HostIntegrationCoreApi { companion object { /** The codec used by HostIntegrationCoreApi. */ - val codec: MessageCodec by lazy { CoreTestsPigeonCodec } + val codec: MessageCodec by lazy { CoreTestsPigeonCodec() } /** * Sets up an instance of `HostIntegrationCoreApi` to handle messages through the * `binaryMessenger`. @@ -3214,7 +3214,7 @@ class FlutterIntegrationCoreApi( ) { companion object { /** The codec used by FlutterIntegrationCoreApi. */ - val codec: MessageCodec by lazy { CoreTestsPigeonCodec } + val codec: MessageCodec by lazy { CoreTestsPigeonCodec() } } /** A no-op function taking no arguments and returning no value, to sanity test basic calling. */ fun noop(callback: (Result) -> Unit) { @@ -4008,7 +4008,7 @@ interface HostTrivialApi { companion object { /** The codec used by HostTrivialApi. */ - val codec: MessageCodec by lazy { CoreTestsPigeonCodec } + val codec: MessageCodec by lazy { CoreTestsPigeonCodec() } /** Sets up an instance of `HostTrivialApi` to handle messages through the `binaryMessenger`. */ @JvmOverloads fun setUp( @@ -4054,7 +4054,7 @@ interface HostSmallApi { companion object { /** The codec used by HostSmallApi. */ - val codec: MessageCodec by lazy { CoreTestsPigeonCodec } + val codec: MessageCodec by lazy { CoreTestsPigeonCodec() } /** Sets up an instance of `HostSmallApi` to handle messages through the `binaryMessenger`. */ @JvmOverloads fun setUp( @@ -4123,7 +4123,7 @@ class FlutterSmallApi( ) { companion object { /** The codec used by FlutterSmallApi. */ - val codec: MessageCodec by lazy { CoreTestsPigeonCodec } + val codec: MessageCodec by lazy { CoreTestsPigeonCodec() } } fun echoWrappedList(msgArg: TestMessage, callback: (Result) -> Unit) { 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 000000000000..bfe6e4257e79 --- /dev/null +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/ProxyApiTestApiImpls.kt @@ -0,0 +1,699 @@ +// 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 androidx.annotation.RequiresApi +import io.flutter.plugin.common.BinaryMessenger + +class ProxyApiTestClass : ProxyApiSuperClass(), ProxyApiInterface + +open class ProxyApiSuperClass + +interface ProxyApiInterface + +@RequiresApi(25) class ClassWithApiRequirement + +class ProxyApiRegistrar(binaryMessenger: BinaryMessenger) : + ProxyApiTestsPigeonProxyApiRegistrar(binaryMessenger) { + override fun getPigeonApiProxyApiTestClass(): PigeonApiProxyApiTestClass { + return ProxyApiTestClassApi(this) + } + + override fun getPigeonApiProxyApiSuperClass(): PigeonApiProxyApiSuperClass { + return ProxyApiSuperClassApi(this) + } + + override fun getPigeonApiClassWithApiRequirement(): PigeonApiClassWithApiRequirement { + return ClassWithApiRequirementApi(this) + } +} + +class ProxyApiTestClassApi(override val pigeonRegistrar: ProxyApiRegistrar) : + PigeonApiProxyApiTestClass(pigeonRegistrar) { + + 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(override val pigeonRegistrar: ProxyApiRegistrar) : + PigeonApiProxyApiSuperClass(pigeonRegistrar) { + override fun pigeon_defaultConstructor(): ProxyApiSuperClass { + return ProxyApiSuperClass() + } + + override fun aSuperMethod(pigeon_instance: ProxyApiSuperClass) {} +} + +class ClassWithApiRequirementApi(override val pigeonRegistrar: ProxyApiRegistrar) : + PigeonApiClassWithApiRequirement(pigeonRegistrar) { + @RequiresApi(25) + override fun pigeon_defaultConstructor(): ClassWithApiRequirement { + return ClassWithApiRequirement() + } + + override fun aMethod(pigeon_instance: ClassWithApiRequirement) { + // Do nothing + } +} 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 000000000000..184a5b00f599 --- /dev/null +++ b/packages/pigeon/platform_tests/test_plugin/android/src/main/kotlin/com/example/test_plugin/ProxyApiTests.gen.kt @@ -0,0 +1,4291 @@ +// 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 +@file:Suppress("UNCHECKED_CAST", "ArrayInDataClass") + +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 { + return if (exception is ProxyApiTestsError) { + listOf(exception.code, exception.message, exception.details) + } else { + 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.onFinalize` is called 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") +class ProxyApiTestsPigeonInstanceManager( + 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 + + /** + * Modifies the time interval used to define how often this instance removes garbage collected + * weak references to native Android objects that this instance was managing. + */ + var clearFinalizedWeakReferencesInterval: Long = 3000 + set(value) { + handler.removeCallbacks { this.releaseAllFinalizedInstances() } + field = value + releaseAllFinalizedInstances() + } + + 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 tag = "PigeonInstanceManager" + + /** + * Instantiate a new manager with a listener for garbage collected weak references. + * + * When the manager is no longer needed, [stopFinalizationListener] must be called. + */ + fun create( + finalizationListener: PigeonFinalizationListener + ): ProxyApiTestsPigeonInstanceManager { + return ProxyApiTestsPigeonInstanceManager(finalizationListener) + } + } + + /** + * Removes `identifier` and return its associated strongly referenced instance, if present, from + * the manager. + */ + fun remove(identifier: Long): T? { + logWarningIfFinalizationListenerHasStopped() + return strongInstances.remove(identifier) as T? + } + + /** + * Retrieves the identifier paired with an instance, if present, otherwise `null`. + * + * 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 + * `ProxyApiTestsPigeonInstanceManager` to have, or recreate, a weak reference to the Dart + * instance the identifier is associated with. + */ + 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. + * + * [identifier] must be >= 0 and unique. + */ + fun addDartCreatedInstance(instance: Any, identifier: Long) { + logWarningIfFinalizationListenerHasStopped() + addInstance(instance, identifier) + } + + /** + * Adds a new unique instance that was instantiated from the host platform. + * + * [identifier] must be >= 0 and unique. + */ + 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, if present, otherwise `null`. */ + 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`. */ + fun containsInstance(instance: Any?): Boolean { + logWarningIfFinalizationListenerHasStopped() + return identifiers.containsKey(instance) + } + + /** + * Stops 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 has been stopped.") + } + } +} + +/** Generated API for managing the Dart and native `InstanceManager`s. */ +private class ProxyApiTestsPigeonInstanceManagerApi(val binaryMessenger: BinaryMessenger) { + companion object { + /** The codec used by ProxyApiTestsPigeonInstanceManagerApi. */ + val codec: MessageCodec by lazy { ProxyApiTestsPigeonCodec() } + + /** + * Sets up an instance of `ProxyApiTestsPigeonInstanceManagerApi` to handle messages from the + * `binaryMessenger`. + */ + fun setUpMessageHandlers( + binaryMessenger: BinaryMessenger, + instanceManager: ProxyApiTestsPigeonInstanceManager? + ) { + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManager.removeStrongReference", + codec) + if (instanceManager != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val identifierArg = args[0] as Long + val wrapped: List = + try { + instanceManager.remove(identifierArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManager.clear", + codec) + if (instanceManager != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = + try { + instanceManager.clear() + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + fun removeStrongReference(identifierArg: Long, callback: (Result) -> Unit) { + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.PigeonInternalInstanceManager.removeStrongReference" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(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))) + } + } + } +} +/** + * Provides implementations for each ProxyApi implementation and provides access to resources needed + * by any implementation. + */ +abstract class ProxyApiTestsPigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger) { + /** Whether APIs should ignore calling to Dart. */ + public var ignoreCallsToDart = false + val instanceManager: ProxyApiTestsPigeonInstanceManager + private var _codec: MessageCodec? = null + val codec: MessageCodec + get() { + if (_codec == null) { + _codec = ProxyApiTestsPigeonProxyApiBaseCodec(this) + } + return _codec!! + } + + init { + val api = ProxyApiTestsPigeonInstanceManagerApi(binaryMessenger) + instanceManager = + ProxyApiTestsPigeonInstanceManager.create( + object : ProxyApiTestsPigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) { + api.removeStrongReference(identifier) { + if (it.isFailure) { + Log.e( + "PigeonProxyApiRegistrar", + "Failed to remove Dart strong reference with identifier: $identifier") + } + } + } + }) + } + /** + * 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`. + */ + open fun getPigeonApiProxyApiInterface(): PigeonApiProxyApiInterface { + return PigeonApiProxyApiInterface(this) + } + + /** + * An implementation of [PigeonApiClassWithApiRequirement] used to add a new Dart instance of + * `ClassWithApiRequirement` to the Dart `InstanceManager`. + */ + abstract fun getPigeonApiClassWithApiRequirement(): PigeonApiClassWithApiRequirement + + fun setUp() { + ProxyApiTestsPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, instanceManager) + PigeonApiProxyApiTestClass.setUpMessageHandlers( + binaryMessenger, getPigeonApiProxyApiTestClass()) + PigeonApiProxyApiSuperClass.setUpMessageHandlers( + binaryMessenger, getPigeonApiProxyApiSuperClass()) + PigeonApiClassWithApiRequirement.setUpMessageHandlers( + binaryMessenger, getPigeonApiClassWithApiRequirement()) + } + + fun tearDown() { + ProxyApiTestsPigeonInstanceManagerApi.setUpMessageHandlers(binaryMessenger, null) + PigeonApiProxyApiTestClass.setUpMessageHandlers(binaryMessenger, null) + PigeonApiProxyApiSuperClass.setUpMessageHandlers(binaryMessenger, null) + PigeonApiClassWithApiRequirement.setUpMessageHandlers(binaryMessenger, null) + } +} + +private class ProxyApiTestsPigeonProxyApiBaseCodec( + val registrar: ProxyApiTestsPigeonProxyApiRegistrar +) : ProxyApiTestsPigeonCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 128.toByte() -> { + return registrar.instanceManager.getInstance(readValue(buffer) as Long) + } + else -> super.readValueOfType(type, buffer) + } + } + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + if (value is Boolean || + value is ByteArray || + value is Double || + value is DoubleArray || + value is FloatArray || + value is Int || + value is IntArray || + value is List<*> || + value is Long || + value is LongArray || + value is Map<*, *> || + value is String || + value is ProxyApiTestEnum || + value == null) { + super.writeValue(stream, value) + return + } + + if (value is ProxyApiTestClass) { + registrar.getPigeonApiProxyApiTestClass().pigeon_newInstance(value) {} + } else if (value is com.example.test_plugin.ProxyApiSuperClass) { + registrar.getPigeonApiProxyApiSuperClass().pigeon_newInstance(value) {} + } else if (value is ProxyApiInterface) { + registrar.getPigeonApiProxyApiInterface().pigeon_newInstance(value) {} + } else if (android.os.Build.VERSION.SDK_INT >= 25 && value is ClassWithApiRequirement) { + registrar.getPigeonApiClassWithApiRequirement().pigeon_newInstance(value) {} + } + + when { + registrar.instanceManager.containsInstance(value) -> { + stream.write(128) + writeValue(stream, registrar.instanceManager.getIdentifierForStrongReference(value)) + } + else -> + throw IllegalArgumentException( + "Unsupported value: '$value' of type '${value.javaClass.name}'") + } + } +} + +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 } + } + } +} + +private open class ProxyApiTestsPigeonCodec : StandardMessageCodec() { + override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? { + return when (type) { + 129.toByte() -> { + return (readValue(buffer) as Long?)?.let { ProxyApiTestEnum.ofRaw(it.toInt()) } + } + else -> super.readValueOfType(type, buffer) + } + } + + override fun writeValue(stream: ByteArrayOutputStream, value: Any?) { + when (value) { + is ProxyApiTestEnum -> { + stream.write(129) + writeValue(stream, value.raw) + } + else -> super.writeValue(stream, value) + } + } +} + +/** + * The core ProxyApi test class that each supported host language must implement in platform_tests + * integration tests. + */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiProxyApiTestClass( + open val pigeonRegistrar: ProxyApiTestsPigeonProxyApiRegistrar +) { + abstract fun pigeon_defaultConstructor( + aBool: Boolean, + anInt: Long, + aDouble: Double, + aString: String, + aUint8List: ByteArray, + aList: List, + aMap: Map, + anEnum: ProxyApiTestEnum, + aProxyApi: com.example.test_plugin.ProxyApiSuperClass, + aNullableBool: Boolean?, + aNullableInt: Long?, + aNullableDouble: Double?, + aNullableString: String?, + aNullableUint8List: ByteArray?, + aNullableList: List?, + aNullableMap: Map?, + aNullableEnum: ProxyApiTestEnum?, + aNullableProxyApi: com.example.test_plugin.ProxyApiSuperClass?, + boolParam: Boolean, + intParam: Long, + doubleParam: Double, + stringParam: String, + aUint8ListParam: ByteArray, + listParam: List, + mapParam: Map, + enumParam: ProxyApiTestEnum, + proxyApiParam: com.example.test_plugin.ProxyApiSuperClass, + nullableBoolParam: Boolean?, + nullableIntParam: Long?, + nullableDoubleParam: Double?, + nullableStringParam: String?, + nullableUint8ListParam: ByteArray?, + nullableListParam: List?, + nullableMapParam: Map?, + nullableEnumParam: ProxyApiTestEnum?, + nullableProxyApiParam: com.example.test_plugin.ProxyApiSuperClass? + ): ProxyApiTestClass + + abstract fun attachedField( + pigeon_instance: ProxyApiTestClass + ): com.example.test_plugin.ProxyApiSuperClass + + abstract fun staticAttachedField(): com.example.test_plugin.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 + ): com.example.test_plugin.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 + ): com.example.test_plugin.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: com.example.test_plugin.ProxyApiSuperClass + ): com.example.test_plugin.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: com.example.test_plugin.ProxyApiSuperClass? + ): com.example.test_plugin.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: com.example.test_plugin.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: com.example.test_plugin.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?.pigeonRegistrar?.codec ?: ProxyApiTestsPigeonCodec() + 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] as Long + val aBoolArg = args[1] as Boolean + val anIntArg = args[2] 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 = args[8] as ProxyApiTestEnum + val aProxyApiArg = args[9] as com.example.test_plugin.ProxyApiSuperClass + val aNullableBoolArg = args[10] as Boolean? + val aNullableIntArg = args[11] 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 = args[17] as ProxyApiTestEnum? + val aNullableProxyApiArg = args[18] as com.example.test_plugin.ProxyApiSuperClass? + val boolParamArg = args[19] as Boolean + val intParamArg = args[20] 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 = args[26] as ProxyApiTestEnum + val proxyApiParamArg = args[27] as com.example.test_plugin.ProxyApiSuperClass + val nullableBoolParamArg = args[28] as Boolean? + val nullableIntParamArg = args[29] 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 = args[35] as ProxyApiTestEnum? + val nullableProxyApiParamArg = args[36] as com.example.test_plugin.ProxyApiSuperClass? + val wrapped: List = + try { + api.pigeonRegistrar.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) + listOf(null) + } catch (exception: Throwable) { + 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] as Long + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.attachedField(pigeon_instanceArg), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + 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] as Long + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.staticAttachedField(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + api.noop(pigeon_instanceArg) + listOf(null) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.throwError(pigeon_instanceArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + api.throwErrorFromVoid(pigeon_instanceArg) + listOf(null) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.throwFlutterError(pigeon_instanceArg)) + } catch (exception: Throwable) { + 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] as Long + val wrapped: List = + try { + listOf(api.echoInt(pigeon_instanceArg, anIntArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoDouble(pigeon_instanceArg, aDoubleArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoBool(pigeon_instanceArg, aBoolArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoString(pigeon_instanceArg, aStringArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoUint8List(pigeon_instanceArg, aUint8ListArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoObject(pigeon_instanceArg, anObjectArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoList(pigeon_instanceArg, aListArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoProxyApiList(pigeon_instanceArg, aListArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoMap(pigeon_instanceArg, aMapArg)) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoProxyApiMap(pigeon_instanceArg, aMapArg)) + } catch (exception: Throwable) { + 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 = args[1] as ProxyApiTestEnum + val wrapped: List = + try { + listOf(api.echoEnum(pigeon_instanceArg, anEnumArg)) + } catch (exception: Throwable) { + 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 com.example.test_plugin.ProxyApiSuperClass + val wrapped: List = + try { + listOf(api.echoProxyApi(pigeon_instanceArg, aProxyApiArg)) + } catch (exception: Throwable) { + 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] as Long? + val wrapped: List = + try { + listOf(api.echoNullableInt(pigeon_instanceArg, aNullableIntArg)) + } catch (exception: Throwable) { + 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? + val wrapped: List = + try { + listOf(api.echoNullableDouble(pigeon_instanceArg, aNullableDoubleArg)) + } catch (exception: Throwable) { + 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? + val wrapped: List = + try { + listOf(api.echoNullableBool(pigeon_instanceArg, aNullableBoolArg)) + } catch (exception: Throwable) { + 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? + val wrapped: List = + try { + listOf(api.echoNullableString(pigeon_instanceArg, aNullableStringArg)) + } catch (exception: Throwable) { + 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? + val wrapped: List = + try { + listOf(api.echoNullableUint8List(pigeon_instanceArg, aNullableUint8ListArg)) + } catch (exception: Throwable) { + 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] + val wrapped: List = + try { + listOf(api.echoNullableObject(pigeon_instanceArg, aNullableObjectArg)) + } catch (exception: Throwable) { + 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? + val wrapped: List = + try { + listOf(api.echoNullableList(pigeon_instanceArg, aNullableListArg)) + } catch (exception: Throwable) { + 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? + val wrapped: List = + try { + listOf(api.echoNullableMap(pigeon_instanceArg, aNullableMapArg)) + } catch (exception: Throwable) { + 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 = args[1] as ProxyApiTestEnum? + val wrapped: List = + try { + listOf(api.echoNullableEnum(pigeon_instanceArg, aNullableEnumArg)) + } catch (exception: Throwable) { + 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 com.example.test_plugin.ProxyApiSuperClass? + val wrapped: List = + try { + listOf(api.echoNullableProxyApi(pigeon_instanceArg, aNullableProxyApiArg)) + } catch (exception: Throwable) { + 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] 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 = args[1] as ProxyApiTestEnum + 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)) + } + } + } + } 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] 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 = args[1] as ProxyApiTestEnum? + 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)) + } + } + } + } else { + channel.setMessageHandler(null) + } + } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.staticNoop", + codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + val wrapped: List = + try { + api.staticNoop() + listOf(null) + } catch (exception: Throwable) { + 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 + val wrapped: List = + try { + listOf(api.echoStaticString(aStringArg)) + } catch (exception: Throwable) { + 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] 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 = args[1] as ProxyApiTestEnum + 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)) + } + } + } + } 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 com.example.test_plugin.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] 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 = args[1] as ProxyApiTestEnum? + 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)) + } + } + } + } 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 com.example.test_plugin.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 (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + Result.success(Unit) + return + } + val pigeon_identifierArg = + pigeonRegistrar.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 = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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, + aProxyApiArg, + aNullableBoolArg, + aNullableIntArg, + aNullableDoubleArg, + aNullableStringArg, + aNullableUint8ListArg, + aNullableListArg, + aNullableMapArg, + aNullableEnumArg, + 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) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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] 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoEnum" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, anEnumArg)) { + 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 ProxyApiTestEnum + 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: com.example.test_plugin.ProxyApiSuperClass, + callback: (Result) -> Unit + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 com.example.test_plugin.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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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] 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ProxyApiTestClass.flutterEchoNullableEnum" + val channel = BasicMessageChannel(binaryMessenger, channelName, codec) + channel.send(listOf(pigeon_instanceArg, anEnumArg)) { + 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 ProxyApiTestEnum? + 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: com.example.test_plugin.ProxyApiSuperClass?, + callback: (Result) -> Unit + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 com.example.test_plugin.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) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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 pigeonRegistrar.getPigeonApiProxyApiSuperClass() + } + + @Suppress("FunctionName") + /** An implementation of [PigeonApiProxyApiInterface] used to access callback methods */ + fun pigeon_getPigeonApiProxyApiInterface(): PigeonApiProxyApiInterface { + return pigeonRegistrar.getPigeonApiProxyApiInterface() + } +} +/** ProxyApi to serve as a super class to the core ProxyApi class. */ +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiProxyApiSuperClass( + open val pigeonRegistrar: ProxyApiTestsPigeonProxyApiRegistrar +) { + abstract fun pigeon_defaultConstructor(): com.example.test_plugin.ProxyApiSuperClass + + abstract fun aSuperMethod(pigeon_instance: com.example.test_plugin.ProxyApiSuperClass) + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiProxyApiSuperClass?) { + val codec = api?.pigeonRegistrar?.codec ?: ProxyApiTestsPigeonCodec() + 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] as Long + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.pigeon_defaultConstructor(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + 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 com.example.test_plugin.ProxyApiSuperClass + val wrapped: List = + try { + api.aSuperMethod(pigeon_instanceArg) + listOf(null) + } catch (exception: Throwable) { + 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: com.example.test_plugin.ProxyApiSuperClass, + callback: (Result) -> Unit + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + Result.success(Unit) + return + } + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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") +open class PigeonApiProxyApiInterface( + open val pigeonRegistrar: ProxyApiTestsPigeonProxyApiRegistrar +) { + @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 (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + Result.success(Unit) + return + } + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + 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))) + } + } + } +} + +@Suppress("UNCHECKED_CAST") +abstract class PigeonApiClassWithApiRequirement( + open val pigeonRegistrar: ProxyApiTestsPigeonProxyApiRegistrar +) { + @androidx.annotation.RequiresApi(api = 25) + abstract fun pigeon_defaultConstructor(): ClassWithApiRequirement + + @androidx.annotation.RequiresApi(api = 25) + abstract fun aMethod(pigeon_instance: ClassWithApiRequirement) + + companion object { + @Suppress("LocalVariableName") + fun setUpMessageHandlers( + binaryMessenger: BinaryMessenger, + api: PigeonApiClassWithApiRequirement? + ) { + val codec = api?.pigeonRegistrar?.codec ?: ProxyApiTestsPigeonCodec() + if (android.os.Build.VERSION.SDK_INT >= 25) { + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.pigeon_defaultConstructor", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_identifierArg = args[0] as Long + val wrapped: List = + try { + api.pigeonRegistrar.instanceManager.addDartCreatedInstance( + api.pigeon_defaultConstructor(), pigeon_identifierArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } else { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.pigeon_defaultConstructor", + codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + reply.reply( + wrapError( + UnsupportedOperationException( + "Call references class `ClassWithApiRequirement`, which requires api version 25."))) + } + } else { + channel.setMessageHandler(null) + } + } + if (android.os.Build.VERSION.SDK_INT >= 25) { + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.aMethod", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as ClassWithApiRequirement + val wrapped: List = + try { + api.aMethod(pigeon_instanceArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } + } else { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.aMethod", + codec) + if (api != null) { + channel.setMessageHandler { _, reply -> + reply.reply( + wrapError( + UnsupportedOperationException( + "Call references class `ClassWithApiRequirement`, which requires api version 25."))) + } + } else { + channel.setMessageHandler(null) + } + } + } + } + + @Suppress("LocalVariableName", "FunctionName") + /** Creates a Dart instance of ClassWithApiRequirement and attaches it to [pigeon_instanceArg]. */ + @androidx.annotation.RequiresApi(api = 25) + fun pigeon_newInstance( + pigeon_instanceArg: ClassWithApiRequirement, + callback: (Result) -> Unit + ) { + if (pigeonRegistrar.ignoreCallsToDart) { + callback( + Result.failure( + ProxyApiTestsError("ignore-calls-error", "Calls to Dart are being ignored.", ""))) + return + } + if (pigeonRegistrar.instanceManager.containsInstance(pigeon_instanceArg)) { + Result.success(Unit) + return + } + val pigeon_identifierArg = + pigeonRegistrar.instanceManager.addHostCreatedInstance(pigeon_instanceArg) + val binaryMessenger = pigeonRegistrar.binaryMessenger + val codec = pigeonRegistrar.codec + val channelName = + "dev.flutter.pigeon.pigeon_integration_tests.ClassWithApiRequirement.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))) + } + } + } +} 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 658468c351a0..ff7e0a6969cb 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 @@ -12,6 +12,7 @@ class TestPlugin : FlutterPlugin, HostIntegrationCoreApi { private var flutterApi: FlutterIntegrationCoreApi? = null private var flutterSmallApiOne: FlutterSmallApi? = null private var flutterSmallApiTwo: FlutterSmallApi? = null + private var proxyApiRegistrar: ProxyApiRegistrar? = null override fun onAttachedToEngine(binding: FlutterPluginBinding) { HostIntegrationCoreApi.setUp(binding.binaryMessenger, this) @@ -22,9 +23,14 @@ class TestPlugin : FlutterPlugin, HostIntegrationCoreApi { flutterApi = FlutterIntegrationCoreApi(binding.binaryMessenger) flutterSmallApiOne = FlutterSmallApi(binding.binaryMessenger, "suffixOne") flutterSmallApiTwo = FlutterSmallApi(binding.binaryMessenger, "suffixTwo") + + proxyApiRegistrar = ProxyApiRegistrar(binding.binaryMessenger) + proxyApiRegistrar!!.setUp() } - override fun onDetachedFromEngine(binding: FlutterPluginBinding) {} + override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + proxyApiRegistrar?.tearDown() + } // HostIntegrationCoreApi 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 000000000000..438ccfd1f444 --- /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: ProxyApiTestsPigeonInstanceManager = 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: ProxyApiTestsPigeonInstanceManager = 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: ProxyApiTestsPigeonInstanceManager = 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: ProxyApiTestsPigeonInstanceManager = 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: ProxyApiTestsPigeonInstanceManager = 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: ProxyApiTestsPigeonInstanceManager = createInstanceManager() + val instance = Any() + instanceManager.addHostCreatedInstance(instance) + instanceManager.addHostCreatedInstance(instance) + + instanceManager.stopFinalizationListener() + } + + @Test(expected = IllegalArgumentException::class) + fun cannotUseIdentifierLessThanZero() { + val instanceManager: ProxyApiTestsPigeonInstanceManager = createInstanceManager() + instanceManager.addDartCreatedInstance(Any(), -1) + instanceManager.stopFinalizationListener() + } + + @Test(expected = IllegalArgumentException::class) + fun identifiersMustBeUnique() { + val instanceManager: ProxyApiTestsPigeonInstanceManager = createInstanceManager() + instanceManager.addDartCreatedInstance(Any(), 0) + instanceManager.addDartCreatedInstance(Any(), 0) + + instanceManager.stopFinalizationListener() + } + + @Test + fun managerIsUsableWhileListenerHasStopped() { + val instanceManager: ProxyApiTestsPigeonInstanceManager = 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(): ProxyApiTestsPigeonInstanceManager { + return ProxyApiTestsPigeonInstanceManager.create( + object : ProxyApiTestsPigeonInstanceManager.PigeonFinalizationListener { + override fun onFinalize(identifier: Long) {} + }) + } +} diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index 12bc071beb49..c065809a7f1f 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: 22.1.0 # This must match the version in lib/generator_tools.dart +version: 22.2.0 # This must match the version in lib/generator_tools.dart environment: sdk: ^3.3.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/dart/proxy_api_test.dart b/packages/pigeon/test/dart/proxy_api_test.dart index 8e7f230f7ed3..fd1d887189e3 100644 --- a/packages/pigeon/test/dart/proxy_api_test.dart +++ b/packages/pigeon/test/dart/proxy_api_test.dart @@ -80,7 +80,7 @@ void main() { final String collapsedCode = _collapseNewlineAndIndentation(code); // Instance Manager - expect(code, contains(r'class PigeonInternalInstanceManager')); + expect(code, contains(r'class PigeonInstanceManager')); expect(code, contains(r'class _PigeonInternalInstanceManagerApi')); // Base Api class @@ -158,13 +158,13 @@ void main() { expect( code, contains( - 'dev.flutter.pigeon.$DEFAULT_PACKAGE_NAME.PigeonInternalInstanceManagerApi.removeStrongReference', + 'dev.flutter.pigeon.$DEFAULT_PACKAGE_NAME.PigeonInternalInstanceManager.removeStrongReference', ), ); expect( collapsedCode, contains( - '(instanceManager ?? PigeonInternalInstanceManager.instance) .remove(arg_identifier!);', + '(instanceManager ?? PigeonInstanceManager.instance) .remove(arg_identifier!);', ), ); @@ -172,7 +172,7 @@ void main() { expect( code, contains( - 'dev.flutter.pigeon.$DEFAULT_PACKAGE_NAME.PigeonInternalInstanceManagerApi.clear', + 'dev.flutter.pigeon.$DEFAULT_PACKAGE_NAME.PigeonInternalInstanceManager.clear', ), ); }); @@ -890,7 +890,7 @@ void main() { collapsedCode, contains( r'static Future doSomething({ BinaryMessenger? pigeon_binaryMessenger, ' - r'PigeonInternalInstanceManager? pigeon_instanceManager, })', + r'PigeonInstanceManager? pigeon_instanceManager, })', ), ); expect( diff --git a/packages/pigeon/test/generator_tools_test.dart b/packages/pigeon/test/generator_tools_test.dart index d7c49e37154f..2ed9239b0a25 100644 --- a/packages/pigeon/test/generator_tools_test.dart +++ b/packages/pigeon/test/generator_tools_test.dart @@ -387,4 +387,81 @@ void main() { expect(() => a.apisOfInterfaces(), throwsArgumentError); }); + + test('findHighestApiRequirement', () { + final TypeDeclaration typeWithoutMinApi = TypeDeclaration( + baseName: 'TypeWithoutMinApi', + isNullable: false, + associatedProxyApi: AstProxyApi( + name: 'TypeWithoutMinApi', + methods: [], + constructors: [], + fields: [], + ), + ); + + final TypeDeclaration typeWithMinApi = TypeDeclaration( + baseName: 'TypeWithMinApi', + isNullable: false, + associatedProxyApi: AstProxyApi( + name: 'TypeWithMinApi', + methods: [], + constructors: [], + fields: [], + ), + ); + + final TypeDeclaration typeWithHighestMinApi = TypeDeclaration( + baseName: 'TypeWithHighestMinApi', + isNullable: false, + associatedProxyApi: AstProxyApi( + name: 'TypeWithHighestMinApi', + methods: [], + constructors: [], + fields: [], + ), + ); + + final ({TypeDeclaration type, int version})? result = + findHighestApiRequirement( + [ + typeWithoutMinApi, + typeWithMinApi, + typeWithHighestMinApi, + ], + onGetApiRequirement: (TypeDeclaration type) { + if (type == typeWithMinApi) { + return 1; + } else if (type == typeWithHighestMinApi) { + return 2; + } + + return null; + }, + onCompare: (int one, int two) => one.compareTo(two), + ); + + expect(result?.type, typeWithHighestMinApi); + expect(result?.version, 2); + }); + + test('Indent.format trims indentation', () { + final StringBuffer buffer = StringBuffer(); + final Indent indent = Indent(buffer); + + indent.format( + ''' + void myMethod() { + + print('hello'); + }''', + ); + + expect(buffer.toString(), ''' +void myMethod() { + + print('hello'); +} +'''); + }); } 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 000000000000..d6ddd35377bf --- /dev/null +++ b/packages/pigeon/test/kotlin/proxy_api_test.dart @@ -0,0 +1,944 @@ +// 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(fileSpecificClassNameComponent: 'MyFile'), + root, + sink, + dartPackageName: DEFAULT_PACKAGE_NAME, + ); + final String code = sink.toString(); + final String collapsedCode = _collapseNewlineAndIndentation(code); + + // Instance Manager + expect(code, contains(r'class MyFilePigeonInstanceManager')); + expect(code, contains(r'class MyFilePigeonInstanceManagerApi')); + + // API registrar + expect( + code, + contains( + 'abstract class MyFilePigeonProxyApiRegistrar(val binaryMessenger: BinaryMessenger)', + ), + ); + + // Codec + expect( + code, + contains( + 'private class MyFilePigeonProxyApiBaseCodec(val registrar: MyFilePigeonProxyApiRegistrar) : MyFilePigeonCodec()')); + + // Proxy API class + expect( + code, + contains( + r'abstract class PigeonApiApi(open val pigeonRegistrar: MyFilePigeonProxyApiRegistrar)', + ), + ); + + // 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(open val pigeonRegistrar: PigeonProxyApiRegistrar) ', + ), + ); + 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.pigeonRegistrar.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(open val pigeonRegistrar: PigeonProxyApiRegistrar) ', + ), + ); + expect( + collapsedCode, + contains( + 'abstract fun name(validType: Long, enumType: AnEnum, ' + 'proxyApiType: Api2, nullableValidType: Long?, ' + 'nullableEnumType: AnEnum?, nullableProxyApiType: Api2?): Api', + ), + ); + expect( + collapsedCode, + contains( + r'api.pigeonRegistrar.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.pigeonRegistrar.instanceManager.addDartCreatedInstance(api.name(' + r'validTypeArg,enumTypeArg,proxyApiTypeArg,nullableValidTypeArg,' + r'nullableEnumTypeArg,nullableProxyApiTypeArg), pigeon_identifierArg)', + ), + ); + expect( + collapsedCode, + contains( + 'channel.send(listOf(pigeon_identifierArg, validTypeArg, ' + 'enumTypeArg, proxyApiTypeArg, nullableValidTypeArg, ' + 'nullableEnumTypeArg, 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.pigeonRegistrar.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.pigeonRegistrar.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, ' + r'proxyApiTypeArg, nullableValidTypeArg, nullableEnumTypeArg, ' + 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 fa23bb48c910..b3cd4f193de7 100644 --- a/script/configs/allowed_unpinned_deps.yaml +++ b/script/configs/allowed_unpinned_deps.yaml @@ -32,6 +32,7 @@ - fake_async - ffi - gcloud +- graphs - html - http - intl