diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index a49c57acdd1..a1cf6d0f1e3 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -1,3 +1,16 @@ +## 12.0.0 + +* Adds error handling on Flutter API methods. +* **Breaking Change** [kotlin] Flutter API methods now return `Result`. +* **Breaking Change** [swift] Flutter API methods now return `Result`. +* **Breaking Change** [java] Removes `Reply` class from all method returns and replaces it with `Result`. + * Changes required: Replace all `Reply` callbacks with `Result` classes that contain both `success` and `failure` methods. +* **Breaking Change** [java] Adds `NullableResult` class for all nullable method returns. + * Changes required: Any method that returns a nullable type will need to be updated to return `NullableResult` rather than `Result`. +* **Breaking Change** [java] Renames Host API `setup` method to `setUp`. +* **Breaking Change** [objc] Boxes all enum returns to allow for `nil` response on error. +* **Breaking Change** [objc] Renames `Setup` to `SetUp`. + ## 11.0.1 * Adds pub topics to package metadata. @@ -5,9 +18,9 @@ ## 11.0.0 * Adds primitive enum support. -* Fixes Objective-C nullable enums. -* **Breaking Change** Changes all nullable enums in Objective-C to be wrapped in custom classes. -* **Breaking Change** Changes all enums names in Objective-C to have class prefix. +* [objc] Fixes nullable enums. +* **Breaking Change** [objc] Changes all nullable enums to be boxed in custom classes. +* **Breaking Change** [objc] Changes all enums names to have class prefix. * Updates minimum supported SDK version to Flutter 3.7/Dart 2.19. ## 10.1.6 @@ -16,7 +29,7 @@ ## 10.1.5 -* Fixes import in generated Dart test output when overriding package name. +* [dart] Fixes import in generated test output when overriding package name. ## 10.1.4 @@ -45,11 +58,11 @@ ## 10.0.0 -* [swift] Avoids using `Any` to represent `Optional` in Swift. +* [swift] Avoids using `Any` to represent `Optional`. * [swift] **Breaking Change** A raw `List` (without generic type argument) in Dart will be - translated into `[Any?]` (rather than `[Any]`) in Swift. + translated into `[Any?]` (rather than `[Any]`). * [swift] **Breaking Change** A raw `Map` (without generic type argument) in Dart will be - translated into `[AnyHashable:Any?]` (rather than `[AnyHashable:Any]`) in Swift. + translated into `[AnyHashable:Any?]` (rather than `[AnyHashable:Any]`). * Adds an example application that uses Pigeon directly, rather than in a plugin. ## 9.2.5 @@ -275,7 +288,7 @@ ## 4.2.10 -* Changes generated Java enum field to be final. +* [java] Changes generated enum field to be final. ## 4.2.9 @@ -457,11 +470,11 @@ ## 2.0.3 -* Makes the generated Java Builder class final. +* [java] Makes the generated Builder class final. ## 2.0.2 -* Fixes Java crash for nullable nested type. +* [java] Fixes crash for nullable nested type. ## 2.0.1 @@ -583,8 +596,8 @@ * [generators] Moved Pigeon to using a custom codec which allows collection types to contain custom classes. * [java] Fixed NPE in Java generated code for nested types. -* [objc] **BREAKING CHANGE:** logic for generating Objective-C selectors has - changed. `void add(Input value)` will now translate to +* [objc] **BREAKING CHANGE:** logic for generating selectors has changed. + `void add(Input value)` will now translate to `-(void)addValue:(Input*)value`, methods with no arguments will translate to `...WithError:` or `...WithCompletion:`. * [objc] Added `@ObjCSelector` for specifying custom objc selectors. diff --git a/packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java b/packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java index 25bcda1c6db..ac3186ee573 100644 --- a/packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java +++ b/packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java @@ -15,6 +15,7 @@ import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collections; +import java.util.List; import java.util.Map; /** Generated class from Pigeon. */ @@ -180,10 +181,20 @@ ArrayList toList() { } } + /** Asynchronous error handling return type for non-nullable API method returns. */ public interface Result { - @SuppressWarnings("UnknownNullness") - void success(T result); + /** Success case callback method for handling returns. */ + void success(@NonNull T result); + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for nullable API method returns. */ + public interface NullableResult { + /** Success case callback method for handling returns. */ + void success(@Nullable T result); + + /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } @@ -229,7 +240,7 @@ public interface ExampleHostApi { return ExampleHostApiCodec.INSTANCE; } /** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */ - static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable ExampleHostApi api) { + static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable ExampleHostApi api) { { BasicMessageChannel channel = new BasicMessageChannel<>( @@ -324,16 +335,12 @@ public MessageFlutterApi(@NonNull BinaryMessenger argBinaryMessenger) { } /** Public interface for sending reply. */ - @SuppressWarnings("UnknownNullness") - public interface Reply { - void reply(T reply); - } /** The codec used by MessageFlutterApi. */ static @NonNull MessageCodec getCodec() { return new StandardMessageCodec(); } - public void flutterMethod(@Nullable String aStringArg, @NonNull Reply callback) { + public void flutterMethod(@Nullable String aStringArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -342,9 +349,30 @@ public void flutterMethod(@Nullable String aStringArg, @NonNull Reply ca channel.send( new ArrayList(Collections.singletonList(aStringArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - String output = (String) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + String output = (String) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } } 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 e0dc8a49cbc..4fb36eedd17 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 @@ -188,11 +188,21 @@ class MessageFlutterApi(private val binaryMessenger: BinaryMessenger) { StandardMessageCodec() } } - fun flutterMethod(aStringArg: String?, callback: (String) -> Unit) { + fun flutterMethod(aStringArg: String?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod", codec) channel.send(listOf(aStringArg)) { - val result = it as String - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } } diff --git a/packages/pigeon/example/app/ios/Runner/Messages.g.swift b/packages/pigeon/example/app/ios/Runner/Messages.g.swift index 9c12267c489..3c0433a7425 100644 --- a/packages/pigeon/example/app/ios/Runner/Messages.g.swift +++ b/packages/pigeon/example/app/ios/Runner/Messages.g.swift @@ -179,11 +179,24 @@ class MessageFlutterApi { init(binaryMessenger: FlutterBinaryMessenger){ self.binaryMessenger = binaryMessenger } - func flutterMethod(aString aStringArg: String?, completion: @escaping (String) -> Void) { + func flutterMethod(aString aStringArg: String?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod", binaryMessenger: binaryMessenger) channel.sendMessage([aStringArg] as [Any?]) { response in - let result = response as! String - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! String + completion(.success(result)) + } } } } diff --git a/packages/pigeon/example/app/lib/src/messages.g.dart b/packages/pigeon/example/app/lib/src/messages.g.dart index 201b1fd6b26..52d40138f0f 100644 --- a/packages/pigeon/example/app/lib/src/messages.g.dart +++ b/packages/pigeon/example/app/lib/src/messages.g.dart @@ -11,6 +11,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + enum Code { one, two, @@ -188,8 +199,15 @@ abstract class MessageFlutterApi { 'Argument for dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod was null.'); final List args = (message as List?)!; final String? arg_aString = (args[0] as String?); - final String output = api.flutterMethod(arg_aString); - return output; + try { + final String output = api.flutterMethod(arg_aString); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/example/app/macos/Runner/messages.g.h b/packages/pigeon/example/app/macos/Runner/messages.g.h index 64cf6e2ee56..834fc1bc5d0 100644 --- a/packages/pigeon/example/app/macos/Runner/messages.g.h +++ b/packages/pigeon/example/app/macos/Runner/messages.g.h @@ -53,7 +53,7 @@ NSObject *PGNExampleHostApiGetCodec(void); completion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion; @end -extern void PGNExampleHostApiSetup(id binaryMessenger, +extern void SetUpPGNExampleHostApi(id binaryMessenger, NSObject *_Nullable api); /// The codec used by PGNMessageFlutterApi. diff --git a/packages/pigeon/example/app/macos/Runner/messages.g.m b/packages/pigeon/example/app/macos/Runner/messages.g.m index 6610097ee67..45c7058736a 100644 --- a/packages/pigeon/example/app/macos/Runner/messages.g.m +++ b/packages/pigeon/example/app/macos/Runner/messages.g.m @@ -127,7 +127,7 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { return sSharedObject; } -void PGNExampleHostApiSetup(id binaryMessenger, +void SetUpPGNExampleHostApi(id binaryMessenger, NSObject *api) { { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] @@ -220,9 +220,22 @@ - (void)flutterMethodAString:(nullable NSString *)arg_aString binaryMessenger:self.binaryMessenger codec:PGNMessageFlutterApiGetCodec()]; [channel sendMessage:@[ arg_aString ?: [NSNull null] ] - reply:^(id reply) { - NSString *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSString *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } @end diff --git a/packages/pigeon/example/app/windows/runner/messages.g.cpp b/packages/pigeon/example/app/windows/runner/messages.g.cpp index ab8ccddd46b..3e065a5a9b7 100644 --- a/packages/pigeon/example/app/windows/runner/messages.g.cpp +++ b/packages/pigeon/example/app/windows/runner/messages.g.cpp @@ -271,17 +271,31 @@ void MessageFlutterApi::FlutterMethod( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ a_string_arg ? EncodableValue(*a_string_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = - std::get(encodable_return_value); + std::get(list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } } // namespace pigeon_example diff --git a/packages/pigeon/lib/cpp_generator.dart b/packages/pigeon/lib/cpp_generator.dart index 67b7f506668..4853e3b963f 100644 --- a/packages/pigeon/lib/cpp_generator.dart +++ b/packages/pigeon/lib/cpp_generator.dart @@ -878,26 +878,40 @@ class CppSourceGenerator extends StructuredGenerator { '[on_success = std::move(on_success), on_error = std::move(on_error)]' '(const uint8_t* reply, size_t reply_size) '); indent.addScoped('{', '});', () { - final String successCallbackArgument; - if (func.returnType.isVoid) { - successCallbackArgument = ''; - } else { - successCallbackArgument = 'return_value'; - final String encodedReplyName = - 'encodable_$successCallbackArgument'; + String successCallbackArgument; + successCallbackArgument = 'return_value'; + final String encodedReplyName = 'encodable_$successCallbackArgument'; + final String listReplyName = 'list_$successCallbackArgument'; + indent.writeln( + 'std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size);'); + indent.writeln('const auto& $encodedReplyName = *response;'); + indent.writeln( + 'const auto* $listReplyName = std::get_if(&$encodedReplyName);'); + indent.writeScoped('if ($listReplyName) {', '} ', () { + indent.writeScoped('if ($listReplyName->size() > 1) {', '} ', () { + indent.writeln( + 'on_error(FlutterError( std::get($listReplyName->at(0)), std::get($listReplyName->at(1)), $listReplyName->at(2)));'); + }, addTrailingNewline: false); + indent.addScoped('else {', '}', () { + if (func.returnType.isVoid) { + successCallbackArgument = ''; + } else { + _writeEncodableValueArgumentUnwrapping( + indent, + root, + returnType, + argName: successCallbackArgument, + encodableArgName: '$listReplyName->at(0)', + apiType: ApiType.flutter, + ); + } + indent.writeln('on_success($successCallbackArgument);'); + }); + }, addTrailingNewline: false); + indent.addScoped('else {', '} ', () { indent.writeln( - 'std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size);'); - indent.writeln('const auto& $encodedReplyName = *response;'); - _writeEncodableValueArgumentUnwrapping( - indent, - root, - returnType, - argName: successCallbackArgument, - encodableArgName: encodedReplyName, - apiType: ApiType.flutter, - ); - } - indent.writeln('on_success($successCallbackArgument);'); + 'on_error(FlutterError("channel-error", "Unable to establish connection on channel.", EncodableValue("")));'); + }); }); }); } @@ -1344,20 +1358,17 @@ ${prefix}reply(EncodableValue(std::move(wrapped)));'''; indent.writeln( 'const auto* $argName = std::get_if<${hostType.datatype}>(&$encodableArgName);'); } else if (hostType.isEnum) { - if (hostType.isNullable) { - final String valueVarName = '${argName}_value'; + final String valueVarName = '${argName}_value'; + indent.writeln( + 'const int64_t $valueVarName = $encodableArgName.IsNull() ? 0 : $encodableArgName.LongValue();'); + if (apiType == ApiType.flutter) { indent.writeln( - 'const int64_t $valueVarName = $encodableArgName.IsNull() ? 0 : $encodableArgName.LongValue();'); - if (apiType == ApiType.flutter) { - indent.writeln( - 'const auto* $argName = $encodableArgName.IsNull() ? nullptr : &(${hostType.datatype})$valueVarName;'); - } else { - indent.writeln( - 'const auto $argName = $encodableArgName.IsNull() ? std::nullopt : std::make_optional<${hostType.datatype}>(static_cast<${hostType.datatype}>(${argName}_value));'); - } + 'const ${hostType.datatype} enum_$argName = (${hostType.datatype})$valueVarName;'); + indent.writeln( + 'const auto* $argName = $encodableArgName.IsNull() ? nullptr : &enum_$argName;'); } else { indent.writeln( - 'const auto* $argName = &((${hostType.datatype})std::get($encodableArgName));'); + 'const auto $argName = $encodableArgName.IsNull() ? std::nullopt : std::make_optional<${hostType.datatype}>(static_cast<${hostType.datatype}>(${argName}_value));'); } } else { indent.writeln( diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index fe13c75148e..cff3a7b0fd2 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -384,14 +384,10 @@ $resultAt != null final String returnType = _addGenericTypesNullable(func.returnType); final bool isAsync = func.isAsynchronous; - final String emptyReturnStatement = isMockHandler - ? 'return [];' - : func.returnType.isVoid - ? 'return;' - : 'return null;'; + const String emptyReturnStatement = + 'return wrapResponse(empty: true);'; String call; if (func.arguments.isEmpty) { - indent.writeln('// ignore message'); call = 'api.${func.name}()'; } else { indent.writeln('assert(message != null,'); @@ -429,30 +425,41 @@ $resultAt != null }); call = 'api.${func.name}(${argNames.join(', ')})'; } - if (func.returnType.isVoid) { - if (isAsync) { - indent.writeln('await $call;'); - } else { - indent.writeln('$call;'); - } - indent.writeln(emptyReturnStatement); - } else { - if (isAsync) { - indent.writeln('final $returnType output = await $call;'); + indent.writeScoped('try {', '} ', () { + if (func.returnType.isVoid) { + if (isAsync) { + indent.writeln('await $call;'); + } else { + indent.writeln('$call;'); + } + indent.writeln(emptyReturnStatement); } else { - indent.writeln('final $returnType output = $call;'); + if (isAsync) { + indent.writeln('final $returnType output = await $call;'); + } else { + indent.writeln('final $returnType output = $call;'); + } + + const String returnExpression = 'output'; + final String nullability = + func.returnType.isNullable ? '?' : ''; + final String valueExtraction = isEnum(root, func.returnType) + ? '$nullability.index' + : ''; + final String returnStatement = isMockHandler + ? 'return [$returnExpression$valueExtraction];' + : 'return wrapResponse(result: $returnExpression$valueExtraction);'; + indent.writeln(returnStatement); } + }, addTrailingNewline: false); + indent.addScoped('on PlatformException catch (e) {', '}', () { + indent.writeln('return wrapResponse(error: e);'); + }, addTrailingNewline: false); - const String returnExpression = 'output'; - final String nullability = - func.returnType.isNullable ? '?' : ''; - final String valueExtraction = - isEnum(root, func.returnType) ? '$nullability.index' : ''; - final String returnStatement = isMockHandler - ? 'return [$returnExpression$valueExtraction];' - : 'return $returnExpression$valueExtraction;'; - indent.writeln(returnStatement); - } + indent.writeScoped('catch (e) {', '}', () { + indent.writeln( + "return wrapResponse(error: PlatformException(code: 'error', message: e.toString()));"); + }); }); }); }); @@ -690,6 +697,32 @@ if (replyList == null) { indent.writeln("import 'package:flutter_test/flutter_test.dart';"); indent.newln(); } + + @override + void writeGeneralUtilities( + DartOptions generatorOptions, + Root root, + Indent indent, { + required String dartPackageName, + }) { + _writeWrapResponse(generatorOptions, root, indent); + } + + /// Writes [wrapResponse] method. + void _writeWrapResponse(DartOptions opt, Root root, Indent indent) { + indent.writeScoped( + 'List wrapResponse({Object? result, PlatformException? error, bool empty = false}) {', + '}', () { + indent.writeScoped('if (empty) {', '}', () { + indent.writeln('return [];'); + }); + indent.writeScoped('if (error == null) {', '}', () { + indent.writeln('return [result];'); + }); + indent.writeln( + 'return [error.code, error.message, error.details];'); + }); + } } String _escapeForDartSingleQuotedString(String raw) { diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index bf00a4e072c..3dfd1141bc8 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -13,7 +13,7 @@ import 'ast.dart'; /// The current version of pigeon. /// /// This must match the version in pubspec.yaml. -const String pigeonVersion = '11.0.1'; +const String pigeonVersion = '12.0.0'; /// Read all the content from [stdin] to a String. String readStdin() { diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 8d58f37f231..6569e84bba4 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -396,10 +396,10 @@ class JavaGenerator extends StructuredGenerator { /// Example: /// public static final class Foo { /// public Foo(BinaryMessenger argBinaryMessenger) {...} - /// public interface Reply { + /// public interface Result { /// void reply(T reply); /// } - /// public int add(int x, int y, Reply callback) {...} + /// public int add(int x, int y, Result result) {...} /// } @override void writeFlutterApi( @@ -409,6 +409,17 @@ class JavaGenerator extends StructuredGenerator { Api api, { required String dartPackageName, }) { + /// Returns an argument name that can be used in a context where it is possible to collide + /// and append `.index` to enums. + String getEnumSafeArgumentExpression(int count, NamedType argument) { + if (isEnum(root, argument.type)) { + return argument.type.isNullable + ? '${_getArgumentName(count, argument)}Arg == null ? null : ${_getArgumentName(count, argument)}Arg.index' + : '${_getArgumentName(count, argument)}Arg.index'; + } + return '${_getArgumentName(count, argument)}Arg'; + } + assert(api.location == ApiLocation.flutter); if (getCodecClasses(api, root).isNotEmpty) { _writeCodec(indent, api, root); @@ -430,16 +441,6 @@ class JavaGenerator extends StructuredGenerator { }); indent.newln(); indent.writeln('/** Public interface for sending reply. */ '); - // This warning can't be fixed without a breaking change, and the next - // breaking change to this part of the code should be eliminating Reply - // entirely in favor of using Result for - // https://github.com/flutter/flutter/issues/118243 - // See also the comment on the Result code. - indent.writeln('@SuppressWarnings("UnknownNullness")'); - indent.write('public interface Reply '); - indent.addScoped('{', '}', () { - indent.writeln('void reply(T reply);'); - }); final String codecName = _getCodecName(api); indent.writeln('/** The codec used by ${api.name}. */'); indent.write('static @NonNull MessageCodec getCodec() '); @@ -452,18 +453,9 @@ class JavaGenerator extends StructuredGenerator { } }); - /// Returns an argument name that can be used in a context where it is possible to collide - /// and append `.index` to enums. - String getEnumSafeArgumentExpression(int count, NamedType argument) { - if (isEnum(root, argument.type)) { - return argument.type.isNullable - ? '${_getArgumentName(count, argument)}Arg == null ? null : ${_getArgumentName(count, argument)}Arg.index' - : '${_getArgumentName(count, argument)}Arg.index'; - } - return '${_getArgumentName(count, argument)}Arg'; - } - for (final Method func in api.methods) { + final String resultType = + func.returnType.isNullable ? 'NullableResult' : 'Result'; final String channelName = makeChannelName(api, func, dartPackageName); final String returnType = func.returnType.isVoid ? 'Void' @@ -473,7 +465,7 @@ class JavaGenerator extends StructuredGenerator { indent, func.documentationComments, _docCommentSpec); if (func.arguments.isEmpty) { indent.write( - 'public void ${func.name}(@NonNull Reply<$returnType> callback) '); + 'public void ${func.name}(@NonNull $resultType<$returnType> result) '); sendArgument = 'null'; } else { final Iterable argTypes = func.arguments @@ -493,7 +485,7 @@ class JavaGenerator extends StructuredGenerator { map2(argTypes, argNames, (String x, String y) => '$x $y') .join(', '); indent.write( - 'public void ${func.name}($argsSignature, @NonNull Reply<$returnType> callback) '); + 'public void ${func.name}($argsSignature, @NonNull $resultType<$returnType> result) '); } indent.addScoped('{', '}', () { const String channel = 'channel'; @@ -508,30 +500,54 @@ class JavaGenerator extends StructuredGenerator { indent.nest(2, () { indent.writeln('$sendArgument,'); indent.write('channelReply -> '); - if (func.returnType.isVoid) { - indent.addln('callback.reply(null));'); - } else { - indent.addScoped('{', '});', () { - const String output = 'output'; - indent.writeln('@SuppressWarnings("ConstantConditions")'); - if (func.returnType.baseName == 'int') { + indent.addScoped('{', '});', () { + indent.writeScoped('if (channelReply instanceof List) {', '} ', + () { + indent.writeln( + 'List listReply = (List) channelReply;'); + indent.writeScoped('if (listReply.size() > 1) {', '} ', () { indent.writeln( - '$returnType $output = channelReply == null ? null : ((Number) channelReply).longValue();'); - } else if (isEnum(root, func.returnType)) { - if (func.returnType.isNullable) { + 'result.error(new FlutterError((String) listReply.get(0), (String) listReply.get(1), (String) listReply.get(2)));'); + }, addTrailingNewline: false); + if (!func.returnType.isNullable && !func.returnType.isVoid) { + indent.addScoped('else if (listReply.get(0) == null) {', '} ', + () { indent.writeln( - '$returnType $output = channelReply == null ? null : $returnType.values()[(int) channelReply];'); + 'result.error(new FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""));'); + }, addTrailingNewline: false); + } + indent.addScoped('else {', '}', () { + if (func.returnType.isVoid) { + indent.writeln('result.success(null);'); } else { - indent.writeln( - '$returnType $output = $returnType.values()[(int) channelReply];'); + const String output = 'output'; + final String outputExpression; + indent.writeln('@SuppressWarnings("ConstantConditions")'); + if (func.returnType.baseName == 'int') { + outputExpression = + 'listReply.get(0) == null ? null : ((Number) listReply.get(0)).longValue();'; + } else if (isEnum(root, func.returnType)) { + if (func.returnType.isNullable) { + outputExpression = + 'listReply.get(0) == null ? null : $returnType.values()[(int) listReply.get(0)];'; + } else { + outputExpression = + '$returnType.values()[(int) listReply.get(0)];'; + } + } else { + outputExpression = + '${_cast('listReply.get(0)', javaType: returnType)};'; + } + indent.writeln('$returnType $output = $outputExpression'); + indent.writeln('result.success($output);'); } - } else { - indent.writeln( - '$returnType $output = ${_cast('channelReply', javaType: returnType)};'); - } - indent.writeln('callback.reply($output);'); + }); + }, addTrailingNewline: false); + indent.addScoped(' else {', '} ', () { + indent.writeln( + 'result.error(new FlutterError("channel-error", "Unable to establish connection on channel.", ""));'); }); - } + }); }); }); } @@ -547,9 +563,10 @@ class JavaGenerator extends StructuredGenerator { }) { if (root.apis.any((Api api) => api.location == ApiLocation.host && - api.methods.any((Method it) => it.isAsynchronous))) { + api.methods.any((Method it) => it.isAsynchronous) || + api.location == ApiLocation.flutter)) { indent.newln(); - _writeResultInterface(indent); + _writeResultInterfaces(indent); } super.writeApis(generatorOptions, root, indent, dartPackageName: dartPackageName); @@ -559,7 +576,7 @@ class JavaGenerator extends StructuredGenerator { /// Example: /// public interface Foo { /// int add(int x, int y); - /// static void setup(BinaryMessenger binaryMessenger, Foo api) {...} + /// static void setUp(BinaryMessenger binaryMessenger, Foo api) {...} /// } @override void writeHostApi( @@ -600,10 +617,10 @@ class JavaGenerator extends StructuredGenerator { indent.writeln( '${_docCommentPrefix}Sets up an instance of `${api.name}` to handle messages through the `binaryMessenger`.$_docCommentSuffix'); indent.write( - 'static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable ${api.name} api) '); + 'static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable ${api.name} api) '); indent.addScoped('{', '}', () { for (final Method method in api.methods) { - _writeMethodSetup( + _writeMethodSetUp( generatorOptions, root, indent, @@ -621,6 +638,8 @@ class JavaGenerator extends StructuredGenerator { /// int add(int x, int y); void _writeInterfaceMethod(JavaOptions generatorOptions, Root root, Indent indent, Api api, final Method method) { + final String resultType = + method.returnType.isNullable ? 'NullableResult' : 'Result'; final String nullableType = method.isAsynchronous ? '' : _nullabilityAnnotationFromType(method.returnType); @@ -639,10 +658,10 @@ class JavaGenerator extends StructuredGenerator { })); } if (method.isAsynchronous) { - final String resultType = method.returnType.isVoid + final String returnType = method.returnType.isVoid ? 'Void' : _javaTypeForDartType(method.returnType); - argSignature.add('@NonNull Result<$resultType> result'); + argSignature.add('@NonNull $resultType<$returnType> result'); } if (method.documentationComments.isNotEmpty) { addDocumentationComments( @@ -656,10 +675,10 @@ class JavaGenerator extends StructuredGenerator { indent.writeln('$returnType ${method.name}(${argSignature.join(', ')});'); } - /// Write a static setup function in the interface. + /// Write a static setUp function in the interface. /// Example: - /// static void setup(BinaryMessenger binaryMessenger, Foo api) {...} - void _writeMethodSetup( + /// static void setUp(BinaryMessenger binaryMessenger, Foo api) {...} + void _writeMethodSetUp( JavaOptions generatorOptions, Root root, Indent indent, @@ -734,10 +753,12 @@ class JavaGenerator extends StructuredGenerator { ? ' == null ? null : $resultValue.index' : '.index'; } + final String resultType = + method.returnType.isNullable ? 'NullableResult' : 'Result'; const String resultName = 'resultCallback'; indent.format(''' -Result<$returnType> $resultName = -\t\tnew Result<$returnType>() { +$resultType<$returnType> $resultName = +\t\tnew $resultType<$returnType>() { \t\t\tpublic void success($returnType result) { \t\t\t\twrapped.add(0, $resultValue$enumTag); \t\t\t\treply.reply(wrapped); @@ -853,15 +874,30 @@ Result<$returnType> $resultName = indent.newln(); } - void _writeResultInterface(Indent indent) { + void _writeResultInterfaces(Indent indent) { + indent.writeln( + '/** Asynchronous error handling return type for non-nullable API method returns. */'); indent.write('public interface Result '); indent.addScoped('{', '}', () { - // TODO(stuartmorgan): Add a `NullableResult`, and annotate each with - // the correct nullability here. See - // https://github.com/flutter/flutter/issues/124268 - indent.writeln('@SuppressWarnings("UnknownNullness")'); - indent.writeln('void success(T result);'); + indent + .writeln('/** Success case callback method for handling returns. */'); + indent.writeln('void success(@NonNull T result);'); + indent.newln(); + indent + .writeln('/** Failure case callback method for handling errors. */'); + indent.writeln('void error(@NonNull Throwable error);'); + }); + + indent.writeln( + '/** Asynchronous error handling return type for nullable API method returns. */'); + indent.write('public interface NullableResult '); + indent.addScoped('{', '}', () { + indent + .writeln('/** Success case callback method for handling returns. */'); + indent.writeln('void success(@Nullable T result);'); indent.newln(); + indent + .writeln('/** Failure case callback method for handling errors. */'); indent.writeln('void error(@NonNull Throwable error);'); }); } diff --git a/packages/pigeon/lib/kotlin_generator.dart b/packages/pigeon/lib/kotlin_generator.dart index da6faf40470..8370927631e 100644 --- a/packages/pigeon/lib/kotlin_generator.dart +++ b/packages/pigeon/lib/kotlin_generator.dart @@ -257,11 +257,6 @@ class KotlinGenerator extends StructuredGenerator { (int index, final NamedType field) { final HostDatatype hostDatatype = _getHostDatatype(root, field); - // The StandardMessageCodec can give us [Integer, Long] for - // a Dart 'int'. To keep things simple we just use 64bit - // longs in Pigeon with Kotlin. - final bool isInt = field.type.baseName == 'int'; - final String listValue = 'list[$index]'; final String fieldType = _kotlinTypeForDartType(field.type); @@ -280,10 +275,6 @@ class KotlinGenerator extends StructuredGenerator { indent.addScoped('{', '}', () { indent.writeln('$fieldType.ofRaw(it)'); }); - } else if (isInt) { - indent.write('val ${field.name} = $listValue'); - indent.addln( - '.let { ${_cast(root, indent, listValue, type: field.type)} }'); } else { indent.writeln( 'val ${field.name} = ${_cast(root, indent, listValue, type: field.type)}'); @@ -297,10 +288,6 @@ class KotlinGenerator extends StructuredGenerator { customEnumNames.contains(field.type.baseName)) { indent.writeln( 'val ${field.name} = $fieldType.ofRaw($listValue as Int)!!'); - } else if (isInt) { - indent.write('val ${field.name} = $listValue'); - indent.addln( - '.let { ${_cast(root, indent, listValue, type: field.type)} }'); } else { indent.writeln( 'val ${field.name} = ${_cast(root, indent, listValue, type: field.type)}'); @@ -390,7 +377,7 @@ class KotlinGenerator extends StructuredGenerator { for (final Method func in api.methods) { final String channelName = makeChannelName(api, func, dartPackageName); final String returnType = func.returnType.isVoid - ? '' + ? 'Unit' : _nullsafeKotlinTypeForDartType(func.returnType); String sendArgument; @@ -398,7 +385,8 @@ class KotlinGenerator extends StructuredGenerator { indent, func.documentationComments, _docCommentSpec); if (func.arguments.isEmpty) { - indent.write('fun ${func.name}(callback: ($returnType) -> Unit) '); + indent.write( + 'fun ${func.name}(callback: (Result<$returnType>) -> Unit) '); sendArgument = 'null'; } else { final Iterable argTypes = func.arguments @@ -412,37 +400,50 @@ class KotlinGenerator extends StructuredGenerator { sendArgument = 'listOf(${enumSafeArgNames.join(', ')})'; final String argsSignature = map2(argTypes, argNames, (String type, String name) => '$name: $type').join(', '); - if (func.returnType.isVoid) { - indent.write( - 'fun ${func.name}($argsSignature, callback: () -> Unit) '); - } else { - indent.write( - 'fun ${func.name}($argsSignature, callback: ($returnType) -> Unit) '); - } + indent.write( + 'fun ${func.name}($argsSignature, callback: (Result<$returnType>) -> Unit) '); } indent.addScoped('{', '}', () { const String channel = 'channel'; indent.writeln( 'val $channel = BasicMessageChannel(binaryMessenger, "$channelName", codec)'); - indent.write('$channel.send($sendArgument) '); - if (func.returnType.isVoid) { - indent.addScoped('{', '}', () { - indent.writeln('callback()'); - }); - } else { - indent.addScoped('{', '}', () { - // Nullable enums require special handling. - if (isEnum(root, func.returnType) && func.returnType.isNullable) { - indent.writeScoped('val result = (it as Int?)?.let {', '}', () { - indent.writeln('${func.returnType.baseName}.ofRaw(it)'); - }); - } else { + indent.writeScoped('$channel.send($sendArgument) {', '}', () { + indent.writeScoped('if (it is List<*>) {', '} ', () { + indent.writeScoped('if (it.size > 1) {', '} ', () { indent.writeln( - 'val result = ${_cast(root, indent, 'it', type: func.returnType)}'); + 'callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?)));'); + }, addTrailingNewline: false); + if (!func.returnType.isNullable && !func.returnType.isVoid) { + indent.addScoped('else if (it[0] == null) {', '} ', () { + indent.writeln( + 'callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", "")));'); + }, addTrailingNewline: false); } - indent.writeln('callback(result)'); + indent.addScoped('else {', '}', () { + if (func.returnType.isVoid) { + indent.writeln('callback(Result.success(Unit));'); + } else { + const String output = 'output'; + // Nullable enums require special handling. + if (isEnum(root, func.returnType) && + func.returnType.isNullable) { + indent.writeScoped( + 'val $output = (it[0] as Int?)?.let {', '}', () { + indent.writeln('${func.returnType.baseName}.ofRaw(it)'); + }); + } else { + indent.writeln( + 'val $output = ${_cast(root, indent, 'it[0]', type: func.returnType)}'); + } + indent.writeln('callback(Result.success($output));'); + } + }); + }, addTrailingNewline: false); + indent.addScoped('else {', '} ', () { + indent.writeln( + 'callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", "")));'); }); - } + }); }); } }); @@ -785,14 +786,7 @@ String _castForceUnwrap( type.isNullable ? 'if ($value == null) null else ' : ''; return '$nullableConditionPrefix${_kotlinTypeForDartType(type)}.ofRaw($value as Int)$forceUnwrap'; } else { - // The StandardMessageCodec can give us [Integer, Long] for - // a Dart 'int'. To keep things simple we just use 64bit - // longs in Pigeon with Kotlin. - if (type.baseName == 'int') { - return '$value.let { ${_cast(root, indent, value, type: type)} }'; - } else { - return _cast(root, indent, value, type: type); - } + return _cast(root, indent, value, type: type); } } @@ -865,7 +859,7 @@ String _cast(Root root, Indent indent, String variable, return variable; } if (typeString == 'Int' || typeString == 'Long') { - return _castInt(type.isNullable); + return '$variable${_castInt(type.isNullable)}'; } if (isEnum(root, type)) { if (type.isNullable) { @@ -880,5 +874,5 @@ String _cast(Root root, Indent indent, String variable, String _castInt(bool isNullable) { final String nullability = isNullable ? '?' : ''; - return 'if (it is Int) it.toLong() else it as Long$nullability'; + return '.let { if (it is Int) it.toLong() else it as Long$nullability }'; } diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index baac4e34579..2638a0f0ef6 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -362,9 +362,9 @@ class ObjcHeaderGenerator extends StructuredGenerator { String? returnType; final String enumReturnType = _enumName( returnTypeName.baseName, - suffix: func.returnType.isNullable ? ' *_Nullable' : '', + suffix: ' *_Nullable', prefix: generatorOptions.prefix, - box: func.returnType.isNullable, + box: true, ); if (func.isAsynchronous) { returnType = 'void'; @@ -413,7 +413,7 @@ class ObjcHeaderGenerator extends StructuredGenerator { indent.writeln('@end'); indent.newln(); indent.writeln( - 'extern void ${apiName}Setup(id binaryMessenger, NSObject<$apiName> *_Nullable api);'); + 'extern void SetUp$apiName(id binaryMessenger, NSObject<$apiName> *_Nullable api);'); indent.newln(); } } @@ -593,7 +593,7 @@ class ObjcSourceGenerator extends StructuredGenerator { indent.writeln( 'NSNumber *${field.name}AsNumber = GetNullableObjectAtIndex(list, $index);'); indent.writeln( - '${_enumName(field.type.baseName, suffix: ' *', prefix: generatorOptions.prefix, box: true)}${field.name} = ${field.name}AsNumber == nil ? nil : [[${_enumName(field.type.baseName, prefix: generatorOptions.prefix, box: true)} alloc] initWithValue: [${field.name}AsNumber integerValue]];'); + '${_enumName(field.type.baseName, suffix: ' *', prefix: generatorOptions.prefix, box: true)}${field.name} = ${field.name}AsNumber == nil ? nil : [[${_enumName(field.type.baseName, prefix: generatorOptions.prefix, box: true)} alloc] initWithValue:[${field.name}AsNumber integerValue]];'); indent.writeln('$resultName.${field.name} = ${field.name};'); } else { indent.writeln( @@ -674,7 +674,7 @@ class ObjcSourceGenerator extends StructuredGenerator { const String channelName = 'channel'; indent.write( - 'void ${apiName}Setup(id binaryMessenger, NSObject<$apiName> *api) '); + 'void SetUp$apiName(id binaryMessenger, NSObject<$apiName> *api) '); indent.addScoped('{', '}', () { for (final Method func in api.methods) { addDocumentationComments( @@ -724,7 +724,7 @@ class ObjcSourceGenerator extends StructuredGenerator { indent.writeln( 'NSNumber *${argName}AsNumber = GetNullableObjectAtIndex(args, $count);'); indent.writeln( - '${_enumName(arg.type.baseName, suffix: ' *', prefix: '', box: true)}$argName = ${argName}AsNumber == nil ? nil : [[${_enumName(arg.type.baseName, prefix: generatorOptions.prefix, box: true)} alloc] initWithValue: [${argName}AsNumber integerValue]];'); + '${_enumName(arg.type.baseName, suffix: ' *', prefix: '', box: true)}$argName = ${argName}AsNumber == nil ? nil : [[${_enumName(arg.type.baseName, prefix: generatorOptions.prefix, box: true)} alloc] initWithValue:[${argName}AsNumber integerValue]];'); } else { indent.writeln( '$className $argName = [GetNullableObjectAtIndex(args, $count) integerValue];'); @@ -760,16 +760,12 @@ class ObjcSourceGenerator extends StructuredGenerator { const String callback = 'callback(wrapResult(output, error));'; String returnTypeString = '${returnType.withPtr}_Nullable output'; const String numberOutput = 'NSNumber *output ='; - final String enumConversionExpression = func.returnType.isNullable - ? 'enumValue == nil ? nil : [NSNumber numberWithInteger:enumValue.value];' - : '[NSNumber numberWithInteger:enumValue];'; + const String enumConversionExpression = + 'enumValue == nil ? nil : [NSNumber numberWithInteger:enumValue.value];'; + if (isEnum(root, func.returnType)) { - if (func.returnType.isNullable) { - returnTypeString = - '${_enumName(returnType.baseName, suffix: ' *_Nullable', prefix: generatorOptions.prefix, box: true)} enumValue'; - } else { - returnTypeString = '${returnType.baseName} enumValue'; - } + returnTypeString = + '${_enumName(returnType.baseName, suffix: ' *_Nullable', prefix: generatorOptions.prefix, box: true)} enumValue'; } if (func.arguments.isEmpty) { indent.writeScoped( @@ -800,16 +796,10 @@ class ObjcSourceGenerator extends StructuredGenerator { indent.writeln('callback(wrapResult(nil, error));'); } else { if (isEnum(root, func.returnType)) { - if (func.returnType.isNullable) { - indent.writeln( - '${_enumName(func.returnType.baseName, suffix: ' *', prefix: generatorOptions.prefix, box: true)} enumBox = $call;'); - indent.writeln( - 'NSNumber *output = enumBox == nil ? nil : [NSNumber numberWithInteger:enumBox.value];'); - } else { - indent.writeln('${returnType.baseName} enumValue = $call;'); - indent.writeln( - 'NSNumber *output = [NSNumber numberWithInteger:enumValue];'); - } + indent.writeln( + '${_enumName(func.returnType.baseName, suffix: ' *', prefix: generatorOptions.prefix, box: true)} enumBox = $call;'); + indent.writeln( + 'NSNumber *output = enumBox == nil ? nil : [NSNumber numberWithInteger:enumBox.value];'); } else { indent.writeln('${returnType.withPtr}output = $call;'); } @@ -1104,26 +1094,38 @@ static id GetNullableObjectAtIndex(NSArray *array, NSInteger key) { indent.addln('];'); }); }); - indent.write('[channel sendMessage:$sendArgument reply:^(id reply) '); + final String valueOnErrorResponse = func.returnType.isVoid ? '' : 'nil, '; + indent.write( + '[channel sendMessage:$sendArgument reply:^(NSArray *reply) '); indent.addScoped('{', '}];', () { - if (func.returnType.isVoid) { - indent.writeln('completion(nil);'); - } else { - if (isEnum(root, func.returnType)) { - if (func.returnType.isNullable) { - indent.writeln( - 'NSNumber *outputAsNumber = reply == [NSNull null] ? nil : reply;'); - indent.writeln( - '${_enumName(returnType.baseName, suffix: ' *', prefix: languageOptions.prefix, box: true)}output = outputAsNumber == nil ? nil : [[${_enumName(returnType.baseName, prefix: languageOptions.prefix, box: true)} alloc] initWithValue: [outputAsNumber integerValue]];'); + indent.writeScoped('if (reply != nil) {', '} ', () { + indent.writeScoped('if (reply.count > 1) {', '} ', () { + indent.writeln( + 'completion($valueOnErrorResponse[FlutterError errorWithCode:reply[0] message:reply[1] details:reply[2]]);'); + }, addTrailingNewline: false); + indent.addScoped('else {', '}', () { + const String nullCheck = + 'reply[0] == [NSNull null] ? nil : reply[0]'; + if (func.returnType.isVoid) { + indent.writeln('completion(nil);'); } else { - indent.writeln( - '${returnType.baseName} output = [reply integerValue];'); + if (isEnum(root, func.returnType)) { + final String enumName = _enumName(returnType.baseName, + prefix: languageOptions.prefix, box: true); + indent.writeln('NSNumber *outputAsNumber = $nullCheck;'); + indent.writeln( + '$enumName *output = outputAsNumber == nil ? nil : [[$enumName alloc] initWithValue:[outputAsNumber integerValue]];'); + } else { + indent.writeln('${returnType.withPtr}output = $nullCheck;'); + } + indent.writeln('completion(output, nil);'); } - } else { - indent.writeln('${returnType.withPtr}output = reply;'); - } - indent.writeln('completion(output, nil);'); - } + }); + }, addTrailingNewline: false); + indent.addScoped('else {', '} ', () { + indent.writeln( + 'completion($valueOnErrorResponse[FlutterError errorWithCode:@"channel-error" message:@"Unable to establish connection on channel." details:@""]);'); + }); }); }); } @@ -1188,10 +1190,7 @@ String _callbackForType( if (type.isVoid) { return 'void (^)(FlutterError *_Nullable)'; } else if (isEnum(root, type)) { - if (type.isNullable) { - return 'void (^)(${_enumName(objcType.baseName, suffix: ' *_Nullable', prefix: options.prefix, box: true)}, FlutterError *_Nullable)'; - } - return 'void (^)(${_enumName(objcType.baseName, prefix: options.prefix)}, FlutterError *_Nullable)'; + return 'void (^)(${_enumName(objcType.baseName, suffix: ' *_Nullable', prefix: options.prefix, box: true)}, FlutterError *_Nullable)'; } else { return 'void (^)(${objcType.withPtr}_Nullable, FlutterError *_Nullable)'; } diff --git a/packages/pigeon/lib/swift_generator.dart b/packages/pigeon/lib/swift_generator.dart index d382fffacb9..d558c877b2b 100644 --- a/packages/pigeon/lib/swift_generator.dart +++ b/packages/pigeon/lib/swift_generator.dart @@ -319,7 +319,7 @@ import FlutterMacOS final String channelName = makeChannelName(api, func, dartPackageName); final String returnType = func.returnType.isVoid - ? '' + ? 'Void' : _nullsafeSwiftTypeForDartType(func.returnType); String sendArgument; addDocumentationComments( @@ -327,7 +327,7 @@ import FlutterMacOS if (func.arguments.isEmpty) { indent.write( - 'func ${func.name}(completion: @escaping ($returnType) -> Void) '); + 'func ${func.name}(completion: @escaping (Result<$returnType, FlutterError>) -> Void) '); sendArgument = 'nil'; } else { final Iterable argTypes = func.arguments @@ -351,13 +351,8 @@ import FlutterMacOS argNames, (String type, String label, String name) => '$label $name: $type').join(', '); - if (func.returnType.isVoid) { - indent.write( - 'func ${components.name}($argsSignature, completion: @escaping () -> Void) '); - } else { - indent.write( - 'func ${components.name}($argsSignature, completion: @escaping ($returnType) -> Void) '); - } + indent.write( + 'func ${components.name}($argsSignature, completion: @escaping (Result<$returnType, FlutterError>) -> Void) '); } indent.addScoped('{', '}', () { const String channel = 'channel'; @@ -366,18 +361,43 @@ import FlutterMacOS indent.write('$channel.sendMessage($sendArgument) '); if (func.returnType.isVoid) { indent.addScoped('{ _ in', '}', () { - indent.writeln('completion()'); + indent.writeln('completion(.success(Void()))'); }); } else { indent.addScoped('{ response in', '}', () { - _writeDecodeCasting( - root: root, - indent: indent, - value: 'response', - variableName: 'result', - type: func.returnType, - ); - indent.writeln('completion(result)'); + indent.writeScoped( + 'guard let listResponse = response as? [Any?] else {', '}', + () { + indent.writeln( + 'completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: "")))'); + indent.writeln('return'); + }); + indent.writeScoped('if (listResponse.count > 1) {', '} ', () { + indent.writeln('let code: String = listResponse[0] as! String'); + indent.writeln( + 'let message: String? = nilOrValue(listResponse[1])'); + indent.writeln( + 'let details: String? = nilOrValue(listResponse[2])'); + indent.writeln( + 'completion(.failure(FlutterError(code: code, message: message, details: details)));'); + }, addTrailingNewline: false); + if (!func.returnType.isNullable && !func.returnType.isVoid) { + indent.addScoped('else if (listResponse[0] == nil) {', '} ', + () { + indent.writeln( + 'completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: "")))'); + }, addTrailingNewline: false); + } + indent.addScoped('else {', '}', () { + _writeDecodeCasting( + root: root, + indent: indent, + value: 'listResponse[0]', + variableName: 'result', + type: func.returnType, + ); + indent.writeln('completion(.success(result))'); + }); }); } }); diff --git a/packages/pigeon/pigeons/nullable_returns.dart b/packages/pigeon/pigeons/nullable_returns.dart index 548e159452a..04d807809e7 100644 --- a/packages/pigeon/pigeons/nullable_returns.dart +++ b/packages/pigeon/pigeons/nullable_returns.dart @@ -24,7 +24,7 @@ abstract class NullableArgHostApi { @FlutterApi() abstract class NullableArgFlutterApi { - int doit(int? x); + int? doit(int? x); } @HostApi() diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java index 08d1a93eaeb..694bbcaff9c 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/AlternateLanguageTestPlugin.java @@ -12,6 +12,7 @@ import com.example.alternate_language_test_plugin.CoreTests.AnEnum; import com.example.alternate_language_test_plugin.CoreTests.FlutterIntegrationCoreApi; import com.example.alternate_language_test_plugin.CoreTests.HostIntegrationCoreApi; +import com.example.alternate_language_test_plugin.CoreTests.NullableResult; import com.example.alternate_language_test_plugin.CoreTests.Result; import io.flutter.embedding.engine.plugins.FlutterPlugin; import java.util.List; @@ -23,7 +24,7 @@ public class AlternateLanguageTestPlugin implements FlutterPlugin, HostIntegrati @Override public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) { - HostIntegrationCoreApi.setup(binding.getBinaryMessenger(), this); + HostIntegrationCoreApi.setUp(binding.getBinaryMessenger(), this); flutterApi = new FlutterIntegrationCoreApi(binding.getBinaryMessenger()); } @@ -187,7 +188,7 @@ public void noopAsync(@NonNull Result result) { } @Override - public void throwAsyncError(@NonNull Result result) { + public void throwAsyncError(@NonNull NullableResult result) { result.error(new RuntimeException("An error")); } @@ -197,7 +198,7 @@ public void throwAsyncErrorFromVoid(@NonNull Result result) { } @Override - public void throwAsyncFlutterError(@NonNull Result result) { + public void throwAsyncFlutterError(@NonNull NullableResult result) { result.error(new CoreTests.FlutterError("code", "message", "details")); } @@ -208,7 +209,7 @@ public void echoAsyncAllTypes(@NonNull AllTypes everything, @NonNull Result result) { + @Nullable AllNullableTypes everything, @NonNull NullableResult result) { result.success(everything); } @@ -259,109 +260,83 @@ public void echoAsyncEnum(@NonNull AnEnum anEnum, @NonNull Result result } @Override - public void echoAsyncNullableInt(@Nullable Long anInt, @NonNull Result result) { + public void echoAsyncNullableInt(@Nullable Long anInt, @NonNull NullableResult result) { result.success(anInt); } @Override - public void echoAsyncNullableDouble(@Nullable Double aDouble, @NonNull Result result) { + public void echoAsyncNullableDouble( + @Nullable Double aDouble, @NonNull NullableResult result) { result.success(aDouble); } @Override - public void echoAsyncNullableBool(@Nullable Boolean aBool, @NonNull Result result) { + public void echoAsyncNullableBool( + @Nullable Boolean aBool, @NonNull NullableResult result) { result.success(aBool); } @Override - public void echoAsyncNullableString(@Nullable String aString, @NonNull Result result) { + public void echoAsyncNullableString( + @Nullable String aString, @NonNull NullableResult result) { result.success(aString); } @Override public void echoAsyncNullableUint8List( - @Nullable byte[] aUint8List, @NonNull Result result) { + @Nullable byte[] aUint8List, @NonNull NullableResult result) { result.success(aUint8List); } @Override - public void echoAsyncNullableObject(@Nullable Object anObject, @NonNull Result result) { + public void echoAsyncNullableObject( + @Nullable Object anObject, @NonNull NullableResult result) { result.success(anObject); } @Override public void echoAsyncNullableList( - @Nullable List aList, @NonNull Result> result) { + @Nullable List aList, @NonNull NullableResult> result) { result.success(aList); } @Override public void echoAsyncNullableMap( - @Nullable Map aMap, @NonNull Result> result) { + @Nullable Map aMap, @NonNull NullableResult> result) { result.success(aMap); } @Override - public void echoAsyncNullableEnum(@Nullable AnEnum anEnum, @NonNull Result result) { + public void echoAsyncNullableEnum( + @Nullable AnEnum anEnum, @NonNull NullableResult result) { result.success(anEnum); } @Override public void callFlutterNoop(@NonNull Result result) { - flutterApi.noop( - new FlutterIntegrationCoreApi.Reply() { - public void reply(Void value) { - result.success(value); - } - }); + flutterApi.noop(result); } @Override - public void callFlutterThrowError(@NonNull Result result) { - flutterApi.throwError( - new FlutterIntegrationCoreApi.Reply() { - public void reply(Object value) { - // TODO: (tarrinneal) Once flutter api error handling is added, - // update error handling tests to properly recieve and handle errors. - // See issue https://github.com/flutter/flutter/issues/118243 - } - }); + public void callFlutterThrowError(@NonNull NullableResult result) { + flutterApi.throwError(result); } @Override public void callFlutterThrowErrorFromVoid(@NonNull Result result) { - flutterApi.throwErrorFromVoid( - new FlutterIntegrationCoreApi.Reply() { - public void reply(Void value) { - // TODO: (tarrinneal) Once flutter api error handling is added, - // update error handling tests to properly recieve and handle errors. - // See issue https://github.com/flutter/flutter/issues/118243 - } - }); + flutterApi.throwErrorFromVoid(result); } @Override public void callFlutterEchoAllTypes( @NonNull AllTypes everything, @NonNull Result result) { - flutterApi.echoAllTypes( - everything, - new FlutterIntegrationCoreApi.Reply() { - public void reply(AllTypes value) { - result.success(value); - } - }); + flutterApi.echoAllTypes(everything, result); } @Override public void callFlutterEchoAllNullableTypes( - @Nullable AllNullableTypes everything, @NonNull Result result) { - flutterApi.echoAllNullableTypes( - everything, - new FlutterIntegrationCoreApi.Reply() { - public void reply(AllNullableTypes value) { - result.success(value); - } - }); + @Nullable AllNullableTypes everything, @NonNull NullableResult result) { + flutterApi.echoAllNullableTypes(everything, result); } @Override @@ -370,198 +345,96 @@ public void callFlutterSendMultipleNullableTypes( @Nullable Long aNullableInt, @Nullable String aNullableString, @NonNull Result result) { - flutterApi.sendMultipleNullableTypes( - aNullableBool, - aNullableInt, - aNullableString, - new FlutterIntegrationCoreApi.Reply() { - public void reply(AllNullableTypes value) { - result.success(value); - } - }); + flutterApi.sendMultipleNullableTypes(aNullableBool, aNullableInt, aNullableString, result); } @Override public void callFlutterEchoBool(@NonNull Boolean aBool, @NonNull Result result) { - flutterApi.echoBool( - aBool, - new FlutterIntegrationCoreApi.Reply() { - public void reply(Boolean value) { - result.success(value); - } - }); + flutterApi.echoBool(aBool, result); } @Override public void callFlutterEchoInt(@NonNull Long anInt, @NonNull Result result) { - flutterApi.echoInt( - anInt, - new FlutterIntegrationCoreApi.Reply() { - public void reply(Long value) { - result.success(value); - } - }); + flutterApi.echoInt(anInt, result); } @Override public void callFlutterEchoDouble(@NonNull Double aDouble, @NonNull Result result) { - flutterApi.echoDouble( - aDouble, - new FlutterIntegrationCoreApi.Reply() { - public void reply(Double value) { - result.success(value); - } - }); + flutterApi.echoDouble(aDouble, result); } @Override public void callFlutterEchoString(@NonNull String aString, @NonNull Result result) { - flutterApi.echoString( - aString, - new FlutterIntegrationCoreApi.Reply() { - public void reply(String value) { - result.success(value); - } - }); + flutterApi.echoString(aString, result); } @Override public void callFlutterEchoUint8List(@NonNull byte[] aList, @NonNull Result result) { - flutterApi.echoUint8List( - aList, - new FlutterIntegrationCoreApi.Reply() { - public void reply(byte[] value) { - result.success(value); - } - }); + flutterApi.echoUint8List(aList, result); } @Override public void callFlutterEchoList( @NonNull List aList, @NonNull Result> result) { - flutterApi.echoList( - aList, - new FlutterIntegrationCoreApi.Reply>() { - public void reply(List value) { - result.success(value); - } - }); + flutterApi.echoList(aList, result); } @Override public void callFlutterEchoMap( @NonNull Map aMap, @NonNull Result> result) { - flutterApi.echoMap( - aMap, - new FlutterIntegrationCoreApi.Reply>() { - public void reply(Map value) { - result.success(value); - } - }); + flutterApi.echoMap(aMap, result); } @Override public void callFlutterEchoEnum(@NonNull AnEnum anEnum, @NonNull Result result) { - flutterApi.echoEnum( - anEnum, - new FlutterIntegrationCoreApi.Reply() { - public void reply(AnEnum value) { - result.success(value); - } - }); + flutterApi.echoEnum(anEnum, result); } @Override public void callFlutterEchoNullableBool( - @Nullable Boolean aBool, @NonNull Result result) { - flutterApi.echoNullableBool( - aBool, - new FlutterIntegrationCoreApi.Reply() { - public void reply(Boolean value) { - result.success(value); - } - }); + @Nullable Boolean aBool, @NonNull NullableResult result) { + flutterApi.echoNullableBool(aBool, result); } @Override - public void callFlutterEchoNullableInt(@Nullable Long anInt, @NonNull Result result) { - flutterApi.echoNullableInt( - anInt, - new FlutterIntegrationCoreApi.Reply() { - public void reply(Long value) { - result.success(value); - } - }); + public void callFlutterEchoNullableInt( + @Nullable Long anInt, @NonNull NullableResult result) { + flutterApi.echoNullableInt(anInt, result); } @Override public void callFlutterEchoNullableDouble( - @Nullable Double aDouble, @NonNull Result result) { - flutterApi.echoNullableDouble( - aDouble, - new FlutterIntegrationCoreApi.Reply() { - public void reply(Double value) { - result.success(value); - } - }); + @Nullable Double aDouble, @NonNull NullableResult result) { + flutterApi.echoNullableDouble(aDouble, result); } @Override public void callFlutterEchoNullableString( - @Nullable String aString, @NonNull Result result) { - flutterApi.echoNullableString( - aString, - new FlutterIntegrationCoreApi.Reply() { - public void reply(String value) { - result.success(value); - } - }); + @Nullable String aString, @NonNull NullableResult result) { + flutterApi.echoNullableString(aString, result); } @Override public void callFlutterEchoNullableUint8List( - @Nullable byte[] aList, @NonNull Result result) { - flutterApi.echoNullableUint8List( - aList, - new FlutterIntegrationCoreApi.Reply() { - public void reply(byte[] value) { - result.success(value); - } - }); + @Nullable byte[] aList, @NonNull NullableResult result) { + flutterApi.echoNullableUint8List(aList, result); } @Override public void callFlutterEchoNullableList( - @Nullable List aList, @NonNull Result> result) { - flutterApi.echoNullableList( - aList, - new FlutterIntegrationCoreApi.Reply>() { - public void reply(List value) { - result.success(value); - } - }); + @Nullable List aList, @NonNull NullableResult> result) { + flutterApi.echoNullableList(aList, result); } @Override public void callFlutterEchoNullableMap( - @Nullable Map aMap, @NonNull Result> result) { - flutterApi.echoNullableMap( - aMap, - new FlutterIntegrationCoreApi.Reply>() { - public void reply(Map value) { - result.success(value); - } - }); - } - - @Override - public void callFlutterEchoNullableEnum(@Nullable AnEnum anEnum, @NonNull Result result) { - flutterApi.echoNullableEnum( - anEnum, - new FlutterIntegrationCoreApi.Reply() { - public void reply(AnEnum value) { - result.success(value); - } - }); + @Nullable Map aMap, @NonNull NullableResult> result) { + flutterApi.echoNullableMap(aMap, result); + } + + @Override + public void callFlutterEchoNullableEnum( + @Nullable AnEnum anEnum, @NonNull NullableResult result) { + flutterApi.echoNullableEnum(anEnum, result); } } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java index fd32aad89be..2eaaa7c3594 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/main/java/com/example/alternate_language_test_plugin/CoreTests.java @@ -917,10 +917,20 @@ ArrayList toList() { } } + /** Asynchronous error handling return type for non-nullable API method returns. */ public interface Result { - @SuppressWarnings("UnknownNullness") - void success(T result); + /** Success case callback method for handling returns. */ + void success(@NonNull T result); + /** Failure case callback method for handling errors. */ + void error(@NonNull Throwable error); + } + /** Asynchronous error handling return type for nullable API method returns. */ + public interface NullableResult { + /** Success case callback method for handling returns. */ + void success(@Nullable T result); + + /** Failure case callback method for handling errors. */ void error(@NonNull Throwable error); } @@ -1088,46 +1098,48 @@ void echoAsyncMap( /** Returns the passed enum, to test asynchronous serialization and deserialization. */ void echoAsyncEnum(@NonNull AnEnum anEnum, @NonNull Result result); /** Responds with an error from an async function returning a value. */ - void throwAsyncError(@NonNull Result result); + void throwAsyncError(@NonNull NullableResult result); /** Responds with an error from an async void function. */ void throwAsyncErrorFromVoid(@NonNull Result result); /** Responds with a Flutter error from an async function returning a value. */ - void throwAsyncFlutterError(@NonNull Result result); + void throwAsyncFlutterError(@NonNull NullableResult result); /** Returns the passed object, to test async serialization and deserialization. */ void echoAsyncAllTypes(@NonNull AllTypes everything, @NonNull Result result); /** Returns the passed object, to test serialization and deserialization. */ void echoAsyncNullableAllNullableTypes( - @Nullable AllNullableTypes everything, @NonNull Result result); + @Nullable AllNullableTypes everything, @NonNull NullableResult result); /** Returns passed in int asynchronously. */ - void echoAsyncNullableInt(@Nullable Long anInt, @NonNull Result result); + void echoAsyncNullableInt(@Nullable Long anInt, @NonNull NullableResult result); /** Returns passed in double asynchronously. */ - void echoAsyncNullableDouble(@Nullable Double aDouble, @NonNull Result result); + void echoAsyncNullableDouble(@Nullable Double aDouble, @NonNull NullableResult result); /** Returns the passed in boolean asynchronously. */ - void echoAsyncNullableBool(@Nullable Boolean aBool, @NonNull Result result); + void echoAsyncNullableBool(@Nullable Boolean aBool, @NonNull NullableResult result); /** Returns the passed string asynchronously. */ - void echoAsyncNullableString(@Nullable String aString, @NonNull Result result); + void echoAsyncNullableString(@Nullable String aString, @NonNull NullableResult result); /** Returns the passed in Uint8List asynchronously. */ - void echoAsyncNullableUint8List(@Nullable byte[] aUint8List, @NonNull Result result); + void echoAsyncNullableUint8List( + @Nullable byte[] aUint8List, @NonNull NullableResult result); /** Returns the passed in generic Object asynchronously. */ - void echoAsyncNullableObject(@Nullable Object anObject, @NonNull Result result); + void echoAsyncNullableObject(@Nullable Object anObject, @NonNull NullableResult result); /** Returns the passed list, to test asynchronous serialization and deserialization. */ - void echoAsyncNullableList(@Nullable List aList, @NonNull Result> result); + void echoAsyncNullableList( + @Nullable List aList, @NonNull NullableResult> result); /** Returns the passed map, to test asynchronous serialization and deserialization. */ void echoAsyncNullableMap( - @Nullable Map aMap, @NonNull Result> result); + @Nullable Map aMap, @NonNull NullableResult> result); /** Returns the passed enum, to test asynchronous serialization and deserialization. */ - void echoAsyncNullableEnum(@Nullable AnEnum anEnum, @NonNull Result result); + void echoAsyncNullableEnum(@Nullable AnEnum anEnum, @NonNull NullableResult result); void callFlutterNoop(@NonNull Result result); - void callFlutterThrowError(@NonNull Result result); + void callFlutterThrowError(@NonNull NullableResult result); void callFlutterThrowErrorFromVoid(@NonNull Result result); void callFlutterEchoAllTypes(@NonNull AllTypes everything, @NonNull Result result); void callFlutterEchoAllNullableTypes( - @Nullable AllNullableTypes everything, @NonNull Result result); + @Nullable AllNullableTypes everything, @NonNull NullableResult result); void callFlutterSendMultipleNullableTypes( @Nullable Boolean aNullableBool, @@ -1152,23 +1164,28 @@ void callFlutterEchoMap( void callFlutterEchoEnum(@NonNull AnEnum anEnum, @NonNull Result result); - void callFlutterEchoNullableBool(@Nullable Boolean aBool, @NonNull Result result); + void callFlutterEchoNullableBool( + @Nullable Boolean aBool, @NonNull NullableResult result); - void callFlutterEchoNullableInt(@Nullable Long anInt, @NonNull Result result); + void callFlutterEchoNullableInt(@Nullable Long anInt, @NonNull NullableResult result); - void callFlutterEchoNullableDouble(@Nullable Double aDouble, @NonNull Result result); + void callFlutterEchoNullableDouble( + @Nullable Double aDouble, @NonNull NullableResult result); - void callFlutterEchoNullableString(@Nullable String aString, @NonNull Result result); + void callFlutterEchoNullableString( + @Nullable String aString, @NonNull NullableResult result); - void callFlutterEchoNullableUint8List(@Nullable byte[] aList, @NonNull Result result); + void callFlutterEchoNullableUint8List( + @Nullable byte[] aList, @NonNull NullableResult result); void callFlutterEchoNullableList( - @Nullable List aList, @NonNull Result> result); + @Nullable List aList, @NonNull NullableResult> result); void callFlutterEchoNullableMap( - @Nullable Map aMap, @NonNull Result> result); + @Nullable Map aMap, @NonNull NullableResult> result); - void callFlutterEchoNullableEnum(@Nullable AnEnum anEnum, @NonNull Result result); + void callFlutterEchoNullableEnum( + @Nullable AnEnum anEnum, @NonNull NullableResult result); /** The codec used by HostIntegrationCoreApi. */ static @NonNull MessageCodec getCodec() { @@ -1178,7 +1195,7 @@ void callFlutterEchoNullableMap( * Sets up an instance of `HostIntegrationCoreApi` to handle messages through the * `binaryMessenger`. */ - static void setup( + static void setUp( @NonNull BinaryMessenger binaryMessenger, @Nullable HostIntegrationCoreApi api) { { BasicMessageChannel channel = @@ -2198,8 +2215,8 @@ public void error(Throwable error) { channel.setMessageHandler( (message, reply) -> { ArrayList wrapped = new ArrayList(); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Object result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2256,8 +2273,8 @@ public void error(Throwable error) { channel.setMessageHandler( (message, reply) -> { ArrayList wrapped = new ArrayList(); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Object result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2318,8 +2335,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; AllNullableTypes everythingArg = (AllNullableTypes) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(AllNullableTypes result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2349,8 +2366,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Number anIntArg = (Number) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Long result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2381,8 +2398,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Double aDoubleArg = (Double) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Double result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2412,8 +2429,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Boolean aBoolArg = (Boolean) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Boolean result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2443,8 +2460,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; String aStringArg = (String) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(String result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2474,8 +2491,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; byte[] aUint8ListArg = (byte[]) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(byte[] result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2505,8 +2522,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Object anObjectArg = args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Object result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2536,8 +2553,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; List aListArg = (List) args.get(0); - Result> resultCallback = - new Result>() { + NullableResult> resultCallback = + new NullableResult>() { public void success(List result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2567,8 +2584,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Map aMapArg = (Map) args.get(0); - Result> resultCallback = - new Result>() { + NullableResult> resultCallback = + new NullableResult>() { public void success(Map result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2598,8 +2615,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; AnEnum anEnumArg = args.get(0) == null ? null : AnEnum.values()[(int) args.get(0)]; - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(AnEnum result) { wrapped.add(0, result == null ? null : result.index); reply.reply(wrapped); @@ -2656,8 +2673,8 @@ public void error(Throwable error) { channel.setMessageHandler( (message, reply) -> { ArrayList wrapped = new ArrayList(); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Object result) { wrapped.add(0, result); reply.reply(wrapped); @@ -2747,8 +2764,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; AllNullableTypes everythingArg = (AllNullableTypes) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(AllNullableTypes result) { wrapped.add(0, result); reply.reply(wrapped); @@ -3064,8 +3081,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Boolean aBoolArg = (Boolean) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Boolean result) { wrapped.add(0, result); reply.reply(wrapped); @@ -3095,8 +3112,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Number anIntArg = (Number) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Long result) { wrapped.add(0, result); reply.reply(wrapped); @@ -3127,8 +3144,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Double aDoubleArg = (Double) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(Double result) { wrapped.add(0, result); reply.reply(wrapped); @@ -3158,8 +3175,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; String aStringArg = (String) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(String result) { wrapped.add(0, result); reply.reply(wrapped); @@ -3189,8 +3206,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; byte[] aListArg = (byte[]) args.get(0); - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(byte[] result) { wrapped.add(0, result); reply.reply(wrapped); @@ -3220,8 +3237,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; List aListArg = (List) args.get(0); - Result> resultCallback = - new Result>() { + NullableResult> resultCallback = + new NullableResult>() { public void success(List result) { wrapped.add(0, result); reply.reply(wrapped); @@ -3251,8 +3268,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; Map aMapArg = (Map) args.get(0); - Result> resultCallback = - new Result>() { + NullableResult> resultCallback = + new NullableResult>() { public void success(Map result) { wrapped.add(0, result); reply.reply(wrapped); @@ -3282,8 +3299,8 @@ public void error(Throwable error) { ArrayList wrapped = new ArrayList(); ArrayList args = (ArrayList) message; AnEnum anEnumArg = args.get(0) == null ? null : AnEnum.values()[(int) args.get(0)]; - Result resultCallback = - new Result() { + NullableResult resultCallback = + new NullableResult() { public void success(AnEnum result) { wrapped.add(0, result == null ? null : result.index); reply.reply(wrapped); @@ -3360,10 +3377,6 @@ public FlutterIntegrationCoreApi(@NonNull BinaryMessenger argBinaryMessenger) { } /** Public interface for sending reply. */ - @SuppressWarnings("UnknownNullness") - public interface Reply { - void reply(T reply); - } /** The codec used by FlutterIntegrationCoreApi. */ static @NonNull MessageCodec getCodec() { return FlutterIntegrationCoreApiCodec.INSTANCE; @@ -3371,16 +3384,35 @@ public interface Reply { /** * A no-op function taking no arguments and returning no value, to sanity test basic calling. */ - public void noop(@NonNull Reply callback) { + public void noop(@NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noop", getCodec()); - channel.send(null, channelReply -> callback.reply(null)); + channel.send( + null, + channelReply -> { + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + result.success(null); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } + }); } /** Responds with an error from an async function returning a value. */ - public void throwError(@NonNull Reply callback) { + public void throwError(@NonNull NullableResult result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3389,22 +3421,56 @@ public void throwError(@NonNull Reply callback) { channel.send( null, channelReply -> { - @SuppressWarnings("ConstantConditions") - Object output = channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + Object output = listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Responds with an error from an async void function. */ - public void throwErrorFromVoid(@NonNull Reply callback) { + public void throwErrorFromVoid(@NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.throwErrorFromVoid", getCodec()); - channel.send(null, channelReply -> callback.reply(null)); + channel.send( + null, + channelReply -> { + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + result.success(null); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } + }); } /** Returns the passed object, to test serialization and deserialization. */ - public void echoAllTypes(@NonNull AllTypes everythingArg, @NonNull Reply callback) { + public void echoAllTypes(@NonNull AllTypes everythingArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3413,14 +3479,36 @@ public void echoAllTypes(@NonNull AllTypes everythingArg, @NonNull Reply(Collections.singletonList(everythingArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - AllTypes output = (AllTypes) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + AllTypes output = (AllTypes) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed object, to test serialization and deserialization. */ public void echoAllNullableTypes( - @Nullable AllNullableTypes everythingArg, @NonNull Reply callback) { + @Nullable AllNullableTypes everythingArg, + @NonNull NullableResult result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3429,9 +3517,24 @@ public void echoAllNullableTypes( channel.send( new ArrayList(Collections.singletonList(everythingArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - AllNullableTypes output = (AllNullableTypes) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + AllNullableTypes output = (AllNullableTypes) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** @@ -3443,7 +3546,7 @@ public void sendMultipleNullableTypes( @Nullable Boolean aNullableBoolArg, @Nullable Long aNullableIntArg, @Nullable String aNullableStringArg, - @NonNull Reply callback) { + @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3453,13 +3556,34 @@ public void sendMultipleNullableTypes( new ArrayList( Arrays.asList(aNullableBoolArg, aNullableIntArg, aNullableStringArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - AllNullableTypes output = (AllNullableTypes) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + AllNullableTypes output = (AllNullableTypes) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed boolean, to test serialization and deserialization. */ - public void echoBool(@NonNull Boolean aBoolArg, @NonNull Reply callback) { + public void echoBool(@NonNull Boolean aBoolArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3468,13 +3592,34 @@ public void echoBool(@NonNull Boolean aBoolArg, @NonNull Reply callback channel.send( new ArrayList(Collections.singletonList(aBoolArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - Boolean output = (Boolean) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + Boolean output = (Boolean) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed int, to test serialization and deserialization. */ - public void echoInt(@NonNull Long anIntArg, @NonNull Reply callback) { + public void echoInt(@NonNull Long anIntArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3483,13 +3628,35 @@ public void echoInt(@NonNull Long anIntArg, @NonNull Reply callback) { channel.send( new ArrayList(Collections.singletonList(anIntArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - Long output = channelReply == null ? null : ((Number) channelReply).longValue(); - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + Long output = + listReply.get(0) == null ? null : ((Number) listReply.get(0)).longValue(); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed double, to test serialization and deserialization. */ - public void echoDouble(@NonNull Double aDoubleArg, @NonNull Reply callback) { + public void echoDouble(@NonNull Double aDoubleArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3498,13 +3665,34 @@ public void echoDouble(@NonNull Double aDoubleArg, @NonNull Reply callba channel.send( new ArrayList(Collections.singletonList(aDoubleArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - Double output = (Double) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + Double output = (Double) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed string, to test serialization and deserialization. */ - public void echoString(@NonNull String aStringArg, @NonNull Reply callback) { + public void echoString(@NonNull String aStringArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3513,13 +3701,34 @@ public void echoString(@NonNull String aStringArg, @NonNull Reply callba channel.send( new ArrayList(Collections.singletonList(aStringArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - String output = (String) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + String output = (String) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed byte list, to test serialization and deserialization. */ - public void echoUint8List(@NonNull byte[] aListArg, @NonNull Reply callback) { + public void echoUint8List(@NonNull byte[] aListArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3528,13 +3737,34 @@ public void echoUint8List(@NonNull byte[] aListArg, @NonNull Reply callb channel.send( new ArrayList(Collections.singletonList(aListArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - byte[] output = (byte[]) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + byte[] output = (byte[]) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed list, to test serialization and deserialization. */ - public void echoList(@NonNull List aListArg, @NonNull Reply> callback) { + public void echoList(@NonNull List aListArg, @NonNull Result> result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3543,14 +3773,35 @@ public void echoList(@NonNull List aListArg, @NonNull Reply channel.send( new ArrayList(Collections.singletonList(aListArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - List output = (List) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + List output = (List) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed map, to test serialization and deserialization. */ public void echoMap( - @NonNull Map aMapArg, @NonNull Reply> callback) { + @NonNull Map aMapArg, @NonNull Result> result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3559,13 +3810,34 @@ public void echoMap( channel.send( new ArrayList(Collections.singletonList(aMapArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - Map output = (Map) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + Map output = (Map) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed enum to test serialization and deserialization. */ - public void echoEnum(@NonNull AnEnum anEnumArg, @NonNull Reply callback) { + public void echoEnum(@NonNull AnEnum anEnumArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3574,13 +3846,35 @@ public void echoEnum(@NonNull AnEnum anEnumArg, @NonNull Reply callback) channel.send( new ArrayList(Collections.singletonList(anEnumArg.index)), channelReply -> { - @SuppressWarnings("ConstantConditions") - AnEnum output = AnEnum.values()[(int) channelReply]; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + AnEnum output = AnEnum.values()[(int) listReply.get(0)]; + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed boolean, to test serialization and deserialization. */ - public void echoNullableBool(@Nullable Boolean aBoolArg, @NonNull Reply callback) { + public void echoNullableBool( + @Nullable Boolean aBoolArg, @NonNull NullableResult result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3589,13 +3883,28 @@ public void echoNullableBool(@Nullable Boolean aBoolArg, @NonNull Reply channel.send( new ArrayList(Collections.singletonList(aBoolArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - Boolean output = (Boolean) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + Boolean output = (Boolean) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed int, to test serialization and deserialization. */ - public void echoNullableInt(@Nullable Long anIntArg, @NonNull Reply callback) { + public void echoNullableInt(@Nullable Long anIntArg, @NonNull NullableResult result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3604,13 +3913,30 @@ public void echoNullableInt(@Nullable Long anIntArg, @NonNull Reply callba channel.send( new ArrayList(Collections.singletonList(anIntArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - Long output = channelReply == null ? null : ((Number) channelReply).longValue(); - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + Long output = + listReply.get(0) == null ? null : ((Number) listReply.get(0)).longValue(); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed double, to test serialization and deserialization. */ - public void echoNullableDouble(@Nullable Double aDoubleArg, @NonNull Reply callback) { + public void echoNullableDouble( + @Nullable Double aDoubleArg, @NonNull NullableResult result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3619,13 +3945,29 @@ public void echoNullableDouble(@Nullable Double aDoubleArg, @NonNull Reply(Collections.singletonList(aDoubleArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - Double output = (Double) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + Double output = (Double) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed string, to test serialization and deserialization. */ - public void echoNullableString(@Nullable String aStringArg, @NonNull Reply callback) { + public void echoNullableString( + @Nullable String aStringArg, @NonNull NullableResult result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3634,13 +3976,29 @@ public void echoNullableString(@Nullable String aStringArg, @NonNull Reply(Collections.singletonList(aStringArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - String output = (String) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + String output = (String) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed byte list, to test serialization and deserialization. */ - public void echoNullableUint8List(@Nullable byte[] aListArg, @NonNull Reply callback) { + public void echoNullableUint8List( + @Nullable byte[] aListArg, @NonNull NullableResult result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3649,14 +4007,29 @@ public void echoNullableUint8List(@Nullable byte[] aListArg, @NonNull Reply(Collections.singletonList(aListArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - byte[] output = (byte[]) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + byte[] output = (byte[]) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed list, to test serialization and deserialization. */ public void echoNullableList( - @Nullable List aListArg, @NonNull Reply> callback) { + @Nullable List aListArg, @NonNull NullableResult> result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3665,14 +4038,30 @@ public void echoNullableList( channel.send( new ArrayList(Collections.singletonList(aListArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - List output = (List) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + List output = (List) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed map, to test serialization and deserialization. */ public void echoNullableMap( - @Nullable Map aMapArg, @NonNull Reply> callback) { + @Nullable Map aMapArg, + @NonNull NullableResult> result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3681,13 +4070,29 @@ public void echoNullableMap( channel.send( new ArrayList(Collections.singletonList(aMapArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - Map output = (Map) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + Map output = (Map) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** Returns the passed enum to test serialization and deserialization. */ - public void echoNullableEnum(@Nullable AnEnum anEnumArg, @NonNull Reply callback) { + public void echoNullableEnum( + @Nullable AnEnum anEnumArg, @NonNull NullableResult result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3697,25 +4102,60 @@ public void echoNullableEnum(@Nullable AnEnum anEnumArg, @NonNull Reply new ArrayList( Collections.singletonList(anEnumArg == null ? null : anEnumArg.index)), channelReply -> { - @SuppressWarnings("ConstantConditions") - AnEnum output = channelReply == null ? null : AnEnum.values()[(int) channelReply]; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + @SuppressWarnings("ConstantConditions") + AnEnum output = + listReply.get(0) == null ? null : AnEnum.values()[(int) listReply.get(0)]; + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } /** * A no-op function taking no arguments and returning no value, to sanity test basic * asynchronous calling. */ - public void noopAsync(@NonNull Reply callback) { + public void noopAsync(@NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noopAsync", getCodec()); - channel.send(null, channelReply -> callback.reply(null)); + channel.send( + null, + channelReply -> { + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else { + result.success(null); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } + }); } /** Returns the passed in generic Object asynchronously. */ - public void echoAsyncString(@NonNull String aStringArg, @NonNull Reply callback) { + public void echoAsyncString(@NonNull String aStringArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3724,9 +4164,30 @@ public void echoAsyncString(@NonNull String aStringArg, @NonNull Reply c channel.send( new ArrayList(Collections.singletonList(aStringArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - String output = (String) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + String output = (String) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } } @@ -3744,7 +4205,7 @@ public interface HostTrivialApi { return new StandardMessageCodec(); } /** Sets up an instance of `HostTrivialApi` to handle messages through the `binaryMessenger`. */ - static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable HostTrivialApi api) { + static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable HostTrivialApi api) { { BasicMessageChannel channel = new BasicMessageChannel<>( @@ -3786,7 +4247,7 @@ public interface HostSmallApi { return new StandardMessageCodec(); } /** Sets up an instance of `HostSmallApi` to handle messages through the `binaryMessenger`. */ - static void setup(@NonNull BinaryMessenger binaryMessenger, @Nullable HostSmallApi api) { + static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable HostSmallApi api) { { BasicMessageChannel channel = new BasicMessageChannel<>( @@ -3889,16 +4350,12 @@ public FlutterSmallApi(@NonNull BinaryMessenger argBinaryMessenger) { } /** Public interface for sending reply. */ - @SuppressWarnings("UnknownNullness") - public interface Reply { - void reply(T reply); - } /** The codec used by FlutterSmallApi. */ static @NonNull MessageCodec getCodec() { return FlutterSmallApiCodec.INSTANCE; } - public void echoWrappedList(@NonNull TestMessage msgArg, @NonNull Reply callback) { + public void echoWrappedList(@NonNull TestMessage msgArg, @NonNull Result result) { BasicMessageChannel channel = new BasicMessageChannel<>( binaryMessenger, @@ -3907,9 +4364,30 @@ public void echoWrappedList(@NonNull TestMessage msgArg, @NonNull Reply(Collections.singletonList(msgArg)), channelReply -> { - @SuppressWarnings("ConstantConditions") - TestMessage output = (TestMessage) channelReply; - callback.reply(output); + if (channelReply instanceof List) { + List listReply = (List) channelReply; + if (listReply.size() > 1) { + result.error( + new FlutterError( + (String) listReply.get(0), + (String) listReply.get(1), + (String) listReply.get(2))); + } else if (listReply.get(0) == null) { + result.error( + new FlutterError( + "null-error", + "Flutter api returned null value for non-null return value.", + "")); + } else { + @SuppressWarnings("ConstantConditions") + TestMessage output = (TestMessage) listReply.get(0); + result.success(output); + } + } else { + result.error( + new FlutterError( + "channel-error", "Unable to establish connection on channel.", "")); + } }); } } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AllDatatypesTest.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AllDatatypesTest.java index 4e735d92d0e..6f2fdf16e90 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AllDatatypesTest.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AllDatatypesTest.java @@ -83,8 +83,7 @@ public void nullValues() { @SuppressWarnings("unchecked") ArrayList args = (ArrayList) FlutterIntegrationCoreApi.getCodec().decodeMessage(message); - ByteBuffer replyData = - FlutterIntegrationCoreApi.getCodec().encodeMessage(args.get(0)); + ByteBuffer replyData = FlutterIntegrationCoreApi.getCodec().encodeMessage(args); replyData.position(0); reply.reply(replyData); return null; @@ -95,19 +94,25 @@ public void nullValues() { boolean[] didCall = {false}; api.echoAllNullableTypes( everything, - (result) -> { - didCall[0] = true; - assertNull(everything.getANullableBool()); - assertNull(everything.getANullableInt()); - assertNull(everything.getANullableDouble()); - assertNull(everything.getANullableString()); - assertNull(everything.getANullableByteArray()); - assertNull(everything.getANullable4ByteArray()); - assertNull(everything.getANullable8ByteArray()); - assertNull(everything.getANullableFloatArray()); - assertNull(everything.getANullableList()); - assertNull(everything.getANullableMap()); - assertNull(everything.getNullableMapWithObject()); + new CoreTests.NullableResult() { + public void success(AllNullableTypes result) { + didCall[0] = true; + assertNull(everything.getANullableBool()); + assertNull(everything.getANullableInt()); + assertNull(everything.getANullableDouble()); + assertNull(everything.getANullableString()); + assertNull(everything.getANullableByteArray()); + assertNull(everything.getANullable4ByteArray()); + assertNull(everything.getANullable8ByteArray()); + assertNull(everything.getANullableFloatArray()); + assertNull(everything.getANullableList()); + assertNull(everything.getANullableMap()); + assertNull(everything.getNullableMapWithObject()); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } @@ -180,8 +185,7 @@ public void hasValues() { @SuppressWarnings("unchecked") ArrayList args = (ArrayList) FlutterIntegrationCoreApi.getCodec().decodeMessage(message); - ByteBuffer replyData = - FlutterIntegrationCoreApi.getCodec().encodeMessage(args.get(0)); + ByteBuffer replyData = FlutterIntegrationCoreApi.getCodec().encodeMessage(args); replyData.position(0); reply.reply(replyData); return null; @@ -192,9 +196,15 @@ public void hasValues() { boolean[] didCall = {false}; api.echoAllNullableTypes( everything, - (result) -> { - didCall[0] = true; - compareAllNullableTypes(everything, result); + new CoreTests.NullableResult() { + public void success(AllNullableTypes result) { + didCall[0] = true; + compareAllNullableTypes(everything, result); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AsyncTest.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AsyncTest.java index 01f6ef55645..3eefea01e9d 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AsyncTest.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/AsyncTest.java @@ -45,7 +45,7 @@ public void voidVoid(Result result) { public void asyncSuccess() { Success api = new Success(); BinaryMessenger binaryMessenger = mock(BinaryMessenger.class); - HostSmallApi.setup(binaryMessenger, api); + HostSmallApi.setUp(binaryMessenger, api); ArgumentCaptor handler = ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class); verify(binaryMessenger) @@ -76,7 +76,7 @@ public void asyncSuccess() { public void asyncError() { Error api = new Error(); BinaryMessenger binaryMessenger = mock(BinaryMessenger.class); - HostSmallApi.setup(binaryMessenger, api); + HostSmallApi.setUp(binaryMessenger, api); ArgumentCaptor handler = ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class); verify(binaryMessenger) diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/ListTest.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/ListTest.java index 9594f576d91..720826d7b97 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/ListTest.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/ListTest.java @@ -31,7 +31,7 @@ public void listInList() { @SuppressWarnings("unchecked") ArrayList args = (ArrayList) FlutterSmallApi.getCodec().decodeMessage(message); - ByteBuffer replyData = FlutterSmallApi.getCodec().encodeMessage(args.get(0)); + ByteBuffer replyData = FlutterSmallApi.getCodec().encodeMessage(args); replyData.position(0); reply.reply(replyData); return null; @@ -42,12 +42,18 @@ public void listInList() { boolean[] didCall = {false}; api.echoWrappedList( top, - (result) -> { - didCall[0] = true; - assertEquals(result.getTestList().size(), 1); - assertTrue(result.getTestList().get(0) instanceof TestMessage); - TestMessage readInside = (TestMessage) result.getTestList().get(0); - assertEquals(readInside.getTestList().size(), 3); + new CoreTests.Result() { + public void success(TestMessage result) { + didCall[0] = true; + assertEquals(result.getTestList().size(), 1); + assertTrue(result.getTestList().get(0) instanceof TestMessage); + TestMessage readInside = (TestMessage) result.getTestList().get(0); + assertEquals(readInside.getTestList().size(), 3); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/MultipleArityTest.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/MultipleArityTest.java index 36f172a0bf5..aded84bf6b8 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/MultipleArityTest.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/MultipleArityTest.java @@ -27,7 +27,13 @@ public void subtract() { (ArrayList) MultipleArityFlutterApi.getCodec().decodeMessage(message); Long arg0 = (Long) args.get(0); Long arg1 = (Long) args.get(1); - ByteBuffer replyData = MultipleArityFlutterApi.getCodec().encodeMessage(arg0 - arg1); + + Long output = arg0 - arg1; + + ArrayList wrapped = new ArrayList(); + wrapped.add(0, output); + + ByteBuffer replyData = MultipleArityFlutterApi.getCodec().encodeMessage(wrapped); replyData.position(0); reply.reply(replyData); return null; @@ -39,8 +45,14 @@ public void subtract() { api.subtract( 30L, 20L, - (Long result) -> { - assertEquals(10L, (long) result); + new MultipleArity.Result() { + public void success(Long result) { + assertEquals(10L, (long) result); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); } } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/NullableReturnsTest.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/NullableReturnsTest.java index 640a8ef9123..672b4e0db9b 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/NullableReturnsTest.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/NullableReturnsTest.java @@ -19,7 +19,7 @@ public class NullableReturnsTest { public void nullArgHostApi() { NullableReturns.NullableArgHostApi mockApi = mock(NullableReturns.NullableArgHostApi.class); BinaryMessenger binaryMessenger = mock(BinaryMessenger.class); - NullableReturns.NullableArgHostApi.setup(binaryMessenger, mockApi); + NullableReturns.NullableArgHostApi.setUp(binaryMessenger, mockApi); ArgumentCaptor handler = ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class); verify(binaryMessenger).setMessageHandler(anyString(), handler.capture()); @@ -58,7 +58,14 @@ public void nullArgFlutterApi() { NullableReturns.NullableArgFlutterApi.getCodec().decodeMessage(message); assertNull(args.get(0)); ByteBuffer replyData = - NullableReturns.NullableArgFlutterApi.getCodec().encodeMessage(args.get(0)); + NullableReturns.NullableArgFlutterApi.getCodec() + .encodeMessage( + new ArrayList() { + { + add(args.get(0)); + } + }); + replyData.rewind(); reply.reply(replyData); return null; }) @@ -69,9 +76,15 @@ public void nullArgFlutterApi() { boolean[] didCall = {false}; api.doit( null, - (Long result) -> { - didCall[0] = true; - assertNull(result); + new NullableReturns.NullableResult() { + public void success(Long result) { + didCall[0] = true; + assertNull(result); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/PigeonTest.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/PigeonTest.java index a9dbc3ee64a..abc16de8c65 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/PigeonTest.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/PigeonTest.java @@ -17,10 +17,10 @@ public class PigeonTest { public void clearsHandler() { HostSmallApi mockApi = mock(HostSmallApi.class); BinaryMessenger binaryMessenger = mock(BinaryMessenger.class); - HostSmallApi.setup(binaryMessenger, mockApi); + HostSmallApi.setUp(binaryMessenger, mockApi); ArgumentCaptor channelName = ArgumentCaptor.forClass(String.class); verify(binaryMessenger, atLeast(1)).setMessageHandler(channelName.capture(), isNotNull()); - HostSmallApi.setup(binaryMessenger, null); + HostSmallApi.setUp(binaryMessenger, null); verify(binaryMessenger, atLeast(1)).setMessageHandler(eq(channelName.getValue()), isNull()); } } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/PrimitiveTest.java b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/PrimitiveTest.java index d45970196aa..fc96adc2cb4 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/PrimitiveTest.java +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/android/src/test/java/com/example/alternate_language_test_plugin/PrimitiveTest.java @@ -40,7 +40,9 @@ private static BinaryMessenger makeMockBinaryMessenger() { arg = Integer.valueOf(longArg.intValue()); } } - ByteBuffer replyData = PrimitiveFlutterApi.getCodec().encodeMessage(arg); + ArrayList wrapped = new ArrayList(); + wrapped.add(0, arg); + ByteBuffer replyData = PrimitiveFlutterApi.getCodec().encodeMessage(wrapped); replyData.position(0); reply.reply(replyData); return null; @@ -57,9 +59,15 @@ public void primitiveInt() { boolean[] didCall = {false}; api.anInt( 1L, - (Long result) -> { - didCall[0] = true; - assertEquals(result, (Long) 1L); + new Primitive.Result() { + public void success(Long result) { + didCall[0] = true; + assertEquals(result, (Long) 1L); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } @@ -71,9 +79,15 @@ public void primitiveLongInt() { boolean[] didCall = {false}; api.anInt( 1L << 50, - (Long result) -> { - didCall[0] = true; - assertEquals(result.longValue(), 1L << 50); + new Primitive.Result() { + public void success(Long result) { + didCall[0] = true; + assertEquals(result.longValue(), 1L << 50); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } @@ -83,7 +97,7 @@ public void primitiveIntHostApi() { PrimitiveHostApi mockApi = mock(PrimitiveHostApi.class); when(mockApi.anInt(1L)).thenReturn(1L); BinaryMessenger binaryMessenger = mock(BinaryMessenger.class); - PrimitiveHostApi.setup(binaryMessenger, mockApi); + PrimitiveHostApi.setUp(binaryMessenger, mockApi); ArgumentCaptor handler = ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class); verify(binaryMessenger) @@ -114,9 +128,15 @@ public void primitiveBool() { boolean[] didCall = {false}; api.aBool( true, - (Boolean result) -> { - didCall[0] = true; - assertEquals(result, (Boolean) true); + new Primitive.Result() { + public void success(Boolean result) { + didCall[0] = true; + assertEquals(result, (Boolean) true); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } @@ -128,9 +148,15 @@ public void primitiveString() { boolean[] didCall = {false}; api.aString( "hello", - (String result) -> { - didCall[0] = true; - assertEquals(result, "hello"); + new Primitive.Result() { + public void success(String result) { + didCall[0] = true; + assertEquals(result, "hello"); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } @@ -142,9 +168,15 @@ public void primitiveDouble() { boolean[] didCall = {false}; api.aDouble( 1.5, - (Double result) -> { - didCall[0] = true; - assertEquals(result, 1.5, 0.01); + new Primitive.Result() { + public void success(Double result) { + didCall[0] = true; + assertEquals(result, 1.5, 0.01); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } @@ -156,9 +188,15 @@ public void primitiveMap() { boolean[] didCall = {false}; api.aMap( Collections.singletonMap("hello", 1), - (Map result) -> { - didCall[0] = true; - assertEquals(result, Collections.singletonMap("hello", 1)); + new Primitive.Result>() { + public void success(Map result) { + didCall[0] = true; + assertEquals(result, Collections.singletonMap("hello", 1)); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } @@ -170,9 +208,15 @@ public void primitiveList() { boolean[] didCall = {false}; api.aList( Collections.singletonList("hello"), - (List result) -> { - didCall[0] = true; - assertEquals(result, Collections.singletonList("hello")); + new Primitive.Result>() { + public void success(List result) { + didCall[0] = true; + assertEquals(result, Collections.singletonList("hello")); + } + + public void error(Throwable error) { + assertEquals(error, null); + } }); assertTrue(didCall[0]); } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/AsyncHandlersTest.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/AsyncHandlersTest.m index 14aec3e94aa..7034618a239 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/AsyncHandlersTest.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/AsyncHandlersTest.m @@ -60,7 +60,7 @@ - (void)testAsyncFlutter2HostVoidVoid { MockBinaryMessenger *binaryMessenger = [[MockBinaryMessenger alloc] initWithCodec:HostSmallApiGetCodec()]; MockHostSmallApi *mockHostSmallApi = [[MockHostSmallApi alloc] init]; - HostSmallApiSetup(binaryMessenger, mockHostSmallApi); + SetUpHostSmallApi(binaryMessenger, mockHostSmallApi); NSString *channelName = @"dev.flutter.pigeon.pigeon_integration_tests.HostSmallApi.voidVoid"; XCTAssertNotNil(binaryMessenger.handlers[channelName]); @@ -80,7 +80,7 @@ - (void)testAsyncFlutter2HostVoidVoidError { mockHostSmallApi.voidVoidError = [FlutterError errorWithCode:@"code" message:@"message" details:nil]; - HostSmallApiSetup(binaryMessenger, mockHostSmallApi); + SetUpHostSmallApi(binaryMessenger, mockHostSmallApi); NSString *channelName = @"dev.flutter.pigeon.pigeon_integration_tests.HostSmallApi.voidVoid"; XCTAssertNotNil(binaryMessenger.handlers[channelName]); @@ -100,7 +100,7 @@ - (void)testAsyncFlutter2Host { MockHostSmallApi *mockHostSmallApi = [[MockHostSmallApi alloc] init]; NSString *value = @"Test"; mockHostSmallApi.output = value; - HostSmallApiSetup(binaryMessenger, mockHostSmallApi); + SetUpHostSmallApi(binaryMessenger, mockHostSmallApi); NSString *channelName = @"dev.flutter.pigeon.pigeon_integration_tests.HostSmallApi.echo"; XCTAssertNotNil(binaryMessenger.handlers[channelName]); @@ -119,7 +119,7 @@ - (void)testAsyncFlutter2HostError { MockBinaryMessenger *binaryMessenger = [[MockBinaryMessenger alloc] initWithCodec:HostSmallApiGetCodec()]; MockHostSmallApi *mockHostSmallApi = [[MockHostSmallApi alloc] init]; - HostSmallApiSetup(binaryMessenger, mockHostSmallApi); + SetUpHostSmallApi(binaryMessenger, mockHostSmallApi); NSString *channelName = @"dev.flutter.pigeon.pigeon_integration_tests.HostSmallApi.echo"; XCTAssertNotNil(binaryMessenger.handlers[channelName]); diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/EchoMessenger.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/EchoMessenger.m index b7b3342765c..95db64e8cee 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/EchoMessenger.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/EchoMessenger.m @@ -30,8 +30,7 @@ - (void)sendOnChannel:(nonnull NSString *)channel message:(NSData *_Nullable)message binaryReply:(FlutterBinaryReply _Nullable)callback { NSArray *args = [self.codec decode:message]; - id firstArg = args[0]; - callback([self.codec encode:firstArg]); + callback([self.codec encode:args]); } - (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(nonnull NSString *)channel diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/MockBinaryMessenger.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/MockBinaryMessenger.m index 7b9e9fda530..bd84c74c860 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/MockBinaryMessenger.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/MockBinaryMessenger.m @@ -25,7 +25,7 @@ - (void)sendOnChannel:(nonnull NSString *)channel message:(NSData *_Nullable)message binaryReply:(FlutterBinaryReply _Nullable)callback { if (self.result) { - callback([_codec encode:self.result]); + callback([_codec encode:@[ self.result ]]); } } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/MultipleArityTest.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/MultipleArityTest.m index 3bef8582e88..5161c185962 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/MultipleArityTest.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/MultipleArityTest.m @@ -17,11 +17,11 @@ @interface MultipleAritytest : XCTestCase @implementation MultipleAritytest - (void)testSimple { - HandlerBinaryMessenger *binaryMessenger = - [[HandlerBinaryMessenger alloc] initWithCodec:MultipleArityHostApiGetCodec() - handler:^id _Nullable(NSArray *_Nonnull args) { - return @([args[0] intValue] - [args[1] intValue]); - }]; + HandlerBinaryMessenger *binaryMessenger = [[HandlerBinaryMessenger alloc] + initWithCodec:MultipleArityHostApiGetCodec() + handler:^id _Nullable(NSArray *_Nonnull args) { + return @[ @([args[0] intValue] - [args[1] intValue]) ]; + }]; MultipleArityFlutterApi *api = [[MultipleArityFlutterApi alloc] initWithBinaryMessenger:binaryMessenger]; XCTestExpectation *expectation = [self expectationWithDescription:@"subtraction"]; diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/NullableReturnsTest.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/NullableReturnsTest.m index a1fb114cf6e..3cd45e6fbc4 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/NullableReturnsTest.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/NullableReturnsTest.m @@ -52,7 +52,7 @@ - (void)testNullableParameterWithHostApi { MockBinaryMessenger *binaryMessenger = [[MockBinaryMessenger alloc] initWithCodec:NullableArgHostApiGetCodec()]; NSString *channel = @"dev.flutter.pigeon.pigeon_integration_tests.NullableArgHostApi.doit"; - NullableArgHostApiSetup(binaryMessenger, api); + SetUpNullableArgHostApi(binaryMessenger, api); XCTAssertNotNil(binaryMessenger.handlers[channel]); XCTestExpectation *expectation = [self expectationWithDescription:@"callback"]; NSData *arguments = [NullableArgHostApiGetCodec() encode:@[ [NSNull null] ]]; diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/PrimitiveTest.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/PrimitiveTest.m index 19a48350a3e..ec109458bd0 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/PrimitiveTest.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/example/ios/RunnerTests/PrimitiveTest.m @@ -49,11 +49,11 @@ - (void)testDoublePrimitive { PrimitiveFlutterApi *api = [[PrimitiveFlutterApi alloc] initWithBinaryMessenger:binaryMessenger]; XCTestExpectation *expectation = [self expectationWithDescription:@"callback"]; NSNumber *arg = @(1.5); - [api aBoolValue:arg - completion:^(NSNumber *_Nonnull result, FlutterError *_Nullable err) { - XCTAssertEqualObjects(arg, result); - [expectation fulfill]; - }]; + [api aDoubleValue:arg + completion:^(NSNumber *_Nonnull result, FlutterError *_Nullable err) { + XCTAssertEqualObjects(arg, result); + [expectation fulfill]; + }]; [self waitForExpectations:@[ expectation ] timeout:1.0]; } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/AlternateLanguageTestPlugin.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/AlternateLanguageTestPlugin.m index 3423d53f5e0..a66e9e77178 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/AlternateLanguageTestPlugin.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/AlternateLanguageTestPlugin.m @@ -16,7 +16,7 @@ @interface AlternateLanguageTestPlugin () @implementation AlternateLanguageTestPlugin + (void)registerWithRegistrar:(NSObject *)registrar { AlternateLanguageTestPlugin *plugin = [[AlternateLanguageTestPlugin alloc] init]; - HostIntegrationCoreApiSetup([registrar messenger], plugin); + SetUpHostIntegrationCoreApi([registrar messenger], plugin); plugin.flutterAPI = [[FlutterIntegrationCoreApi alloc] initWithBinaryMessenger:[registrar messenger]]; } @@ -92,8 +92,8 @@ - (nullable AllClassesWrapper *)echoClassWrapper:(AllClassesWrapper *)wrapper return wrapper; } -- (AnEnum)echoEnum:(AnEnum)anEnum error:(FlutterError *_Nullable *_Nonnull)error { - return anEnum; +- (AnEnumBox *_Nullable)echoEnum:(AnEnum)anEnum error:(FlutterError *_Nullable *_Nonnull)error { + return [[AnEnumBox alloc] initWithValue:anEnum]; } - (nullable NSString *)extractNestedNullableStringFrom:(AllClassesWrapper *)wrapper @@ -239,8 +239,8 @@ - (void)echoAsyncMap:(NSDictionary *)aMap } - (void)echoAsyncEnum:(AnEnum)anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion { - completion(anEnum, nil); + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion { + completion([[AnEnumBox alloc] initWithValue:anEnum], nil); } - (void)echoAsyncNullableInt:(nullable NSNumber *)anInt @@ -390,9 +390,9 @@ - (void)callFlutterEchoMap:(NSDictionary *)aMap } - (void)callFlutterEchoEnum:(AnEnum)anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion { + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion { [self.flutterAPI echoEnum:anEnum - completion:^(AnEnum value, FlutterError *error) { + completion:^(AnEnumBox *value, FlutterError *error) { completion(value, error); }]; } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.h b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.h index 1b558e4f6a8..d2fac067fea 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.h +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.h @@ -186,7 +186,7 @@ NSObject *HostIntegrationCoreApiGetCodec(void); /// Returns the passed enum to test serialization and deserialization. /// /// @return `nil` only when `error != nil`. -- (AnEnum)echoEnum:(AnEnum)anEnum error:(FlutterError *_Nullable *_Nonnull)error; +- (AnEnumBox *_Nullable)echoEnum:(AnEnum)anEnum error:(FlutterError *_Nullable *_Nonnull)error; /// Returns the passed object, to test serialization and deserialization. - (nullable AllNullableTypes *)echoAllNullableTypes:(nullable AllNullableTypes *)everything error:(FlutterError *_Nullable *_Nonnull)error; @@ -268,7 +268,7 @@ NSObject *HostIntegrationCoreApiGetCodec(void); FlutterError *_Nullable))completion; /// Returns the passed enum, to test asynchronous serialization and deserialization. - (void)echoAsyncEnum:(AnEnum)anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion; + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion; /// Responds with an error from an async function returning a value. - (void)throwAsyncErrorWithCompletion:(void (^)(id _Nullable, FlutterError *_Nullable))completion; /// Responds with an error from an async void function. @@ -343,7 +343,7 @@ NSObject *HostIntegrationCoreApiGetCodec(void); completion:(void (^)(NSDictionary *_Nullable, FlutterError *_Nullable))completion; - (void)callFlutterEchoEnum:(AnEnum)anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion; + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion; - (void)callFlutterEchoNullableBool:(nullable NSNumber *)aBool completion: (void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion; @@ -370,7 +370,7 @@ NSObject *HostIntegrationCoreApiGetCodec(void); (void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion; @end -extern void HostIntegrationCoreApiSetup(id binaryMessenger, +extern void SetUpHostIntegrationCoreApi(id binaryMessenger, NSObject *_Nullable api); /// The codec used by FlutterIntegrationCoreApi. @@ -426,7 +426,8 @@ NSObject *FlutterIntegrationCoreApiGetCodec(void); completion: (void (^)(NSDictionary *_Nullable, FlutterError *_Nullable))completion; /// Returns the passed enum to test serialization and deserialization. -- (void)echoEnum:(AnEnum)anEnum completion:(void (^)(AnEnum, FlutterError *_Nullable))completion; +- (void)echoEnum:(AnEnum)anEnum + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion; /// Returns the passed boolean, to test serialization and deserialization. - (void)echoNullableBool:(nullable NSNumber *)aBool completion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion; @@ -469,7 +470,7 @@ NSObject *HostTrivialApiGetCodec(void); - (void)noopWithError:(FlutterError *_Nullable *_Nonnull)error; @end -extern void HostTrivialApiSetup(id binaryMessenger, +extern void SetUpHostTrivialApi(id binaryMessenger, NSObject *_Nullable api); /// The codec used by HostSmallApi. @@ -482,7 +483,7 @@ NSObject *HostSmallApiGetCodec(void); - (void)voidVoidWithCompletion:(void (^)(FlutterError *_Nullable))completion; @end -extern void HostSmallApiSetup(id binaryMessenger, +extern void SetUpHostSmallApi(id binaryMessenger, NSObject *_Nullable api); /// The codec used by FlutterSmallApi. diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.m index f68ecd87931..634c3e5503b 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/ios/Classes/CoreTests.gen.m @@ -344,7 +344,7 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { return sSharedObject; } -void HostIntegrationCoreApiSetup(id binaryMessenger, +void SetUpHostIntegrationCoreApi(id binaryMessenger, NSObject *api) { /// A no-op function taking no arguments and returning no value, to sanity /// test basic calling. @@ -667,8 +667,8 @@ void HostIntegrationCoreApiSetup(id binaryMessenger, NSArray *args = message; AnEnum arg_anEnum = [GetNullableObjectAtIndex(args, 0) integerValue]; FlutterError *error; - AnEnum enumValue = [api echoEnum:arg_anEnum error:&error]; - NSNumber *output = [NSNumber numberWithInteger:enumValue]; + AnEnumBox *enumBox = [api echoEnum:arg_anEnum error:&error]; + NSNumber *output = enumBox == nil ? nil : [NSNumber numberWithInteger:enumBox.value]; callback(wrapResult(output, error)); }]; } else { @@ -1220,8 +1220,9 @@ void HostIntegrationCoreApiSetup(id binaryMessenger, NSArray *args = message; AnEnum arg_anEnum = [GetNullableObjectAtIndex(args, 0) integerValue]; [api echoAsyncEnum:arg_anEnum - completion:^(AnEnum enumValue, FlutterError *_Nullable error) { - NSNumber *output = [NSNumber numberWithInteger:enumValue]; + completion:^(AnEnumBox *_Nullable enumValue, FlutterError *_Nullable error) { + NSNumber *output = + enumValue == nil ? nil : [NSNumber numberWithInteger:enumValue.value]; callback(wrapResult(output, error)); }]; }]; @@ -1882,8 +1883,9 @@ void HostIntegrationCoreApiSetup(id binaryMessenger, NSArray *args = message; AnEnum arg_anEnum = [GetNullableObjectAtIndex(args, 0) integerValue]; [api callFlutterEchoEnum:arg_anEnum - completion:^(AnEnum enumValue, FlutterError *_Nullable error) { - NSNumber *output = [NSNumber numberWithInteger:enumValue]; + completion:^(AnEnumBox *_Nullable enumValue, FlutterError *_Nullable error) { + NSNumber *output = + enumValue == nil ? nil : [NSNumber numberWithInteger:enumValue.value]; callback(wrapResult(output, error)); }]; }]; @@ -2173,10 +2175,23 @@ - (void)noopWithCompletion:(void (^)(FlutterError *_Nullable))completion { @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noop" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:nil - reply:^(id reply) { - completion(nil); - }]; + [channel + sendMessage:nil + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion([FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + completion(nil); + } + } else { + completion([FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)throwErrorWithCompletion:(void (^)(id _Nullable, FlutterError *_Nullable))completion { FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel @@ -2185,9 +2200,22 @@ - (void)throwErrorWithCompletion:(void (^)(id _Nullable, FlutterError *_Nullable binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:nil - reply:^(id reply) { - id output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + id output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)throwErrorFromVoidWithCompletion:(void (^)(FlutterError *_Nullable))completion { @@ -2196,10 +2224,23 @@ - (void)throwErrorFromVoidWithCompletion:(void (^)(FlutterError *_Nullable))comp @"FlutterIntegrationCoreApi.throwErrorFromVoid" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:nil - reply:^(id reply) { - completion(nil); - }]; + [channel + sendMessage:nil + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion([FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + completion(nil); + } + } else { + completion([FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoAllTypes:(AllTypes *)arg_everything completion:(void (^)(AllTypes *_Nullable, FlutterError *_Nullable))completion { @@ -2209,9 +2250,22 @@ - (void)echoAllTypes:(AllTypes *)arg_everything binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_everything ?: [NSNull null] ] - reply:^(id reply) { - AllTypes *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + AllTypes *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoAllNullableTypes:(nullable AllNullableTypes *)arg_everything @@ -2223,9 +2277,22 @@ - (void)echoAllNullableTypes:(nullable AllNullableTypes *)arg_everything binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_everything ?: [NSNull null] ] - reply:^(id reply) { - AllNullableTypes *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + AllNullableTypes *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)sendMultipleNullableTypesABool:(nullable NSNumber *)arg_aNullableBool @@ -2242,9 +2309,22 @@ - (void)sendMultipleNullableTypesABool:(nullable NSNumber *)arg_aNullableBool arg_aNullableBool ?: [NSNull null], arg_aNullableInt ?: [NSNull null], arg_aNullableString ?: [NSNull null] ] - reply:^(id reply) { - AllNullableTypes *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + AllNullableTypes *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoBool:(NSNumber *)arg_aBool @@ -2255,9 +2335,22 @@ - (void)echoBool:(NSNumber *)arg_aBool binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aBool ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoInt:(NSNumber *)arg_anInt @@ -2268,9 +2361,22 @@ - (void)echoInt:(NSNumber *)arg_anInt binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_anInt ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoDouble:(NSNumber *)arg_aDouble @@ -2281,9 +2387,22 @@ - (void)echoDouble:(NSNumber *)arg_aDouble binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aDouble ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoString:(NSString *)arg_aString @@ -2294,9 +2413,22 @@ - (void)echoString:(NSString *)arg_aString binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aString ?: [NSNull null] ] - reply:^(id reply) { - NSString *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSString *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoUint8List:(FlutterStandardTypedData *)arg_aList @@ -2307,11 +2439,25 @@ - (void)echoUint8List:(FlutterStandardTypedData *)arg_aList @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoUint8List" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:@[ arg_aList ?: [NSNull null] ] - reply:^(id reply) { - FlutterStandardTypedData *output = reply; - completion(output, nil); - }]; + [channel + sendMessage:@[ arg_aList ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + FlutterStandardTypedData *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, + [FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoList:(NSArray *)arg_aList completion:(void (^)(NSArray *_Nullable, FlutterError *_Nullable))completion { @@ -2321,9 +2467,22 @@ - (void)echoList:(NSArray *)arg_aList binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aList ?: [NSNull null] ] - reply:^(id reply) { - NSArray *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSArray *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoMap:(NSDictionary *)arg_aMap @@ -2334,23 +2493,54 @@ - (void)echoMap:(NSDictionary *)arg_aMap @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoMap" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:@[ arg_aMap ?: [NSNull null] ] - reply:^(id reply) { - NSDictionary *output = reply; - completion(output, nil); - }]; + [channel + sendMessage:@[ arg_aMap ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSDictionary *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, + [FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoEnum:(AnEnum)arg_anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion { + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion { FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel messageChannelWithName: @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoEnum" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ [NSNumber numberWithInteger:arg_anEnum] ] - reply:^(id reply) { - AnEnum output = [reply integerValue]; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *outputAsNumber = reply[0] == [NSNull null] ? nil : reply[0]; + AnEnumBox *output = + outputAsNumber == nil + ? nil + : [[AnEnumBox alloc] initWithValue:[outputAsNumber integerValue]]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableBool:(nullable NSNumber *)arg_aBool @@ -2361,9 +2551,22 @@ - (void)echoNullableBool:(nullable NSNumber *)arg_aBool binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aBool ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableInt:(nullable NSNumber *)arg_anInt @@ -2374,9 +2577,22 @@ - (void)echoNullableInt:(nullable NSNumber *)arg_anInt binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_anInt ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableDouble:(nullable NSNumber *)arg_aDouble @@ -2387,9 +2603,22 @@ - (void)echoNullableDouble:(nullable NSNumber *)arg_aDouble binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aDouble ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableString:(nullable NSString *)arg_aString @@ -2400,9 +2629,22 @@ - (void)echoNullableString:(nullable NSString *)arg_aString binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aString ?: [NSNull null] ] - reply:^(id reply) { - NSString *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSString *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableUint8List:(nullable FlutterStandardTypedData *)arg_aList @@ -2413,11 +2655,25 @@ - (void)echoNullableUint8List:(nullable FlutterStandardTypedData *)arg_aList @"FlutterIntegrationCoreApi.echoNullableUint8List" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:@[ arg_aList ?: [NSNull null] ] - reply:^(id reply) { - FlutterStandardTypedData *output = reply; - completion(output, nil); - }]; + [channel + sendMessage:@[ arg_aList ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + FlutterStandardTypedData *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, + [FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoNullableList:(nullable NSArray *)arg_aList completion:(void (^)(NSArray *_Nullable, FlutterError *_Nullable))completion { @@ -2427,9 +2683,22 @@ - (void)echoNullableList:(nullable NSArray *)arg_aList binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aList ?: [NSNull null] ] - reply:^(id reply) { - NSArray *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSArray *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableMap:(nullable NSDictionary *)arg_aMap @@ -2440,11 +2709,25 @@ - (void)echoNullableMap:(nullable NSDictionary *)arg_aMap @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableMap" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:@[ arg_aMap ?: [NSNull null] ] - reply:^(id reply) { - NSDictionary *output = reply; - completion(output, nil); - }]; + [channel + sendMessage:@[ arg_aMap ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSDictionary *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, + [FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoNullableEnum:(nullable AnEnumBox *)arg_anEnum completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion { @@ -2455,13 +2738,26 @@ - (void)echoNullableEnum:(nullable AnEnumBox *)arg_anEnum codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_anEnum == nil ? [NSNull null] : [NSNumber numberWithInteger:arg_anEnum.value] ] - reply:^(id reply) { - NSNumber *outputAsNumber = reply == [NSNull null] ? nil : reply; - AnEnumBox *output = - outputAsNumber == nil - ? nil - : [[AnEnumBox alloc] initWithValue:[outputAsNumber integerValue]]; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *outputAsNumber = reply[0] == [NSNull null] ? nil : reply[0]; + AnEnumBox *output = + outputAsNumber == nil + ? nil + : [[AnEnumBox alloc] initWithValue:[outputAsNumber integerValue]]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)noopAsyncWithCompletion:(void (^)(FlutterError *_Nullable))completion { @@ -2470,10 +2766,23 @@ - (void)noopAsyncWithCompletion:(void (^)(FlutterError *_Nullable))completion { @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noopAsync" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:nil - reply:^(id reply) { - completion(nil); - }]; + [channel + sendMessage:nil + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion([FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + completion(nil); + } + } else { + completion([FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoAsyncString:(NSString *)arg_aString completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { @@ -2483,9 +2792,22 @@ - (void)echoAsyncString:(NSString *)arg_aString binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aString ?: [NSNull null] ] - reply:^(id reply) { - NSString *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSString *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } @end @@ -2496,7 +2818,7 @@ - (void)echoAsyncString:(NSString *)arg_aString return sSharedObject; } -void HostTrivialApiSetup(id binaryMessenger, +void SetUpHostTrivialApi(id binaryMessenger, NSObject *api) { { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] @@ -2522,7 +2844,7 @@ void HostTrivialApiSetup(id binaryMessenger, return sSharedObject; } -void HostSmallApiSetup(id binaryMessenger, NSObject *api) { +void SetUpHostSmallApi(id binaryMessenger, NSObject *api) { { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] initWithName:@"dev.flutter.pigeon.pigeon_integration_tests.HostSmallApi.echo" @@ -2631,9 +2953,22 @@ - (void)echoWrappedList:(TestMessage *)arg_msg binaryMessenger:self.binaryMessenger codec:FlutterSmallApiGetCodec()]; [channel sendMessage:@[ arg_msg ?: [NSNull null] ] - reply:^(id reply) { - TestMessage *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + TestMessage *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } @end diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/AlternateLanguageTestPlugin.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/AlternateLanguageTestPlugin.m index 335913bee5c..a4fe6b86d9f 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/AlternateLanguageTestPlugin.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/AlternateLanguageTestPlugin.m @@ -16,7 +16,7 @@ @interface AlternateLanguageTestPlugin () @implementation AlternateLanguageTestPlugin + (void)registerWithRegistrar:(NSObject *)registrar { AlternateLanguageTestPlugin *plugin = [[AlternateLanguageTestPlugin alloc] init]; - HostIntegrationCoreApiSetup(registrar.messenger, plugin); + SetUpHostIntegrationCoreApi(registrar.messenger, plugin); plugin.flutterAPI = [[FlutterIntegrationCoreApi alloc] initWithBinaryMessenger:registrar.messenger]; } @@ -92,8 +92,8 @@ - (nullable AllClassesWrapper *)echoClassWrapper:(AllClassesWrapper *)wrapper return wrapper; } -- (AnEnum)echoEnum:(AnEnum)anEnum error:(FlutterError *_Nullable *_Nonnull)error { - return anEnum; +- (AnEnumBox *_Nullable)echoEnum:(AnEnum)anEnum error:(FlutterError *_Nullable *_Nonnull)error { + return [[AnEnumBox alloc] initWithValue:anEnum]; } - (nullable NSString *)extractNestedNullableStringFrom:(AllClassesWrapper *)wrapper @@ -239,8 +239,8 @@ - (void)echoAsyncMap:(NSDictionary *)aMap } - (void)echoAsyncEnum:(AnEnum)anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion { - completion(anEnum, nil); + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion { + completion([[AnEnumBox alloc] initWithValue:anEnum], nil); } - (void)echoAsyncNullableInt:(nullable NSNumber *)anInt @@ -390,9 +390,9 @@ - (void)callFlutterEchoMap:(NSDictionary *)aMap } - (void)callFlutterEchoEnum:(AnEnum)anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion { + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion { [self.flutterAPI echoEnum:anEnum - completion:^(AnEnum value, FlutterError *error) { + completion:^(AnEnumBox *value, FlutterError *error) { completion(value, error); }]; } diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/CoreTests.gen.h b/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/CoreTests.gen.h index 1b558e4f6a8..d2fac067fea 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/CoreTests.gen.h +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/CoreTests.gen.h @@ -186,7 +186,7 @@ NSObject *HostIntegrationCoreApiGetCodec(void); /// Returns the passed enum to test serialization and deserialization. /// /// @return `nil` only when `error != nil`. -- (AnEnum)echoEnum:(AnEnum)anEnum error:(FlutterError *_Nullable *_Nonnull)error; +- (AnEnumBox *_Nullable)echoEnum:(AnEnum)anEnum error:(FlutterError *_Nullable *_Nonnull)error; /// Returns the passed object, to test serialization and deserialization. - (nullable AllNullableTypes *)echoAllNullableTypes:(nullable AllNullableTypes *)everything error:(FlutterError *_Nullable *_Nonnull)error; @@ -268,7 +268,7 @@ NSObject *HostIntegrationCoreApiGetCodec(void); FlutterError *_Nullable))completion; /// Returns the passed enum, to test asynchronous serialization and deserialization. - (void)echoAsyncEnum:(AnEnum)anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion; + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion; /// Responds with an error from an async function returning a value. - (void)throwAsyncErrorWithCompletion:(void (^)(id _Nullable, FlutterError *_Nullable))completion; /// Responds with an error from an async void function. @@ -343,7 +343,7 @@ NSObject *HostIntegrationCoreApiGetCodec(void); completion:(void (^)(NSDictionary *_Nullable, FlutterError *_Nullable))completion; - (void)callFlutterEchoEnum:(AnEnum)anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion; + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion; - (void)callFlutterEchoNullableBool:(nullable NSNumber *)aBool completion: (void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion; @@ -370,7 +370,7 @@ NSObject *HostIntegrationCoreApiGetCodec(void); (void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion; @end -extern void HostIntegrationCoreApiSetup(id binaryMessenger, +extern void SetUpHostIntegrationCoreApi(id binaryMessenger, NSObject *_Nullable api); /// The codec used by FlutterIntegrationCoreApi. @@ -426,7 +426,8 @@ NSObject *FlutterIntegrationCoreApiGetCodec(void); completion: (void (^)(NSDictionary *_Nullable, FlutterError *_Nullable))completion; /// Returns the passed enum to test serialization and deserialization. -- (void)echoEnum:(AnEnum)anEnum completion:(void (^)(AnEnum, FlutterError *_Nullable))completion; +- (void)echoEnum:(AnEnum)anEnum + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion; /// Returns the passed boolean, to test serialization and deserialization. - (void)echoNullableBool:(nullable NSNumber *)aBool completion:(void (^)(NSNumber *_Nullable, FlutterError *_Nullable))completion; @@ -469,7 +470,7 @@ NSObject *HostTrivialApiGetCodec(void); - (void)noopWithError:(FlutterError *_Nullable *_Nonnull)error; @end -extern void HostTrivialApiSetup(id binaryMessenger, +extern void SetUpHostTrivialApi(id binaryMessenger, NSObject *_Nullable api); /// The codec used by HostSmallApi. @@ -482,7 +483,7 @@ NSObject *HostSmallApiGetCodec(void); - (void)voidVoidWithCompletion:(void (^)(FlutterError *_Nullable))completion; @end -extern void HostSmallApiSetup(id binaryMessenger, +extern void SetUpHostSmallApi(id binaryMessenger, NSObject *_Nullable api); /// The codec used by FlutterSmallApi. diff --git a/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/CoreTests.gen.m b/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/CoreTests.gen.m index f68ecd87931..634c3e5503b 100644 --- a/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/CoreTests.gen.m +++ b/packages/pigeon/platform_tests/alternate_language_test_plugin/macos/Classes/CoreTests.gen.m @@ -344,7 +344,7 @@ - (FlutterStandardReader *)readerWithData:(NSData *)data { return sSharedObject; } -void HostIntegrationCoreApiSetup(id binaryMessenger, +void SetUpHostIntegrationCoreApi(id binaryMessenger, NSObject *api) { /// A no-op function taking no arguments and returning no value, to sanity /// test basic calling. @@ -667,8 +667,8 @@ void HostIntegrationCoreApiSetup(id binaryMessenger, NSArray *args = message; AnEnum arg_anEnum = [GetNullableObjectAtIndex(args, 0) integerValue]; FlutterError *error; - AnEnum enumValue = [api echoEnum:arg_anEnum error:&error]; - NSNumber *output = [NSNumber numberWithInteger:enumValue]; + AnEnumBox *enumBox = [api echoEnum:arg_anEnum error:&error]; + NSNumber *output = enumBox == nil ? nil : [NSNumber numberWithInteger:enumBox.value]; callback(wrapResult(output, error)); }]; } else { @@ -1220,8 +1220,9 @@ void HostIntegrationCoreApiSetup(id binaryMessenger, NSArray *args = message; AnEnum arg_anEnum = [GetNullableObjectAtIndex(args, 0) integerValue]; [api echoAsyncEnum:arg_anEnum - completion:^(AnEnum enumValue, FlutterError *_Nullable error) { - NSNumber *output = [NSNumber numberWithInteger:enumValue]; + completion:^(AnEnumBox *_Nullable enumValue, FlutterError *_Nullable error) { + NSNumber *output = + enumValue == nil ? nil : [NSNumber numberWithInteger:enumValue.value]; callback(wrapResult(output, error)); }]; }]; @@ -1882,8 +1883,9 @@ void HostIntegrationCoreApiSetup(id binaryMessenger, NSArray *args = message; AnEnum arg_anEnum = [GetNullableObjectAtIndex(args, 0) integerValue]; [api callFlutterEchoEnum:arg_anEnum - completion:^(AnEnum enumValue, FlutterError *_Nullable error) { - NSNumber *output = [NSNumber numberWithInteger:enumValue]; + completion:^(AnEnumBox *_Nullable enumValue, FlutterError *_Nullable error) { + NSNumber *output = + enumValue == nil ? nil : [NSNumber numberWithInteger:enumValue.value]; callback(wrapResult(output, error)); }]; }]; @@ -2173,10 +2175,23 @@ - (void)noopWithCompletion:(void (^)(FlutterError *_Nullable))completion { @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noop" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:nil - reply:^(id reply) { - completion(nil); - }]; + [channel + sendMessage:nil + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion([FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + completion(nil); + } + } else { + completion([FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)throwErrorWithCompletion:(void (^)(id _Nullable, FlutterError *_Nullable))completion { FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel @@ -2185,9 +2200,22 @@ - (void)throwErrorWithCompletion:(void (^)(id _Nullable, FlutterError *_Nullable binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:nil - reply:^(id reply) { - id output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + id output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)throwErrorFromVoidWithCompletion:(void (^)(FlutterError *_Nullable))completion { @@ -2196,10 +2224,23 @@ - (void)throwErrorFromVoidWithCompletion:(void (^)(FlutterError *_Nullable))comp @"FlutterIntegrationCoreApi.throwErrorFromVoid" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:nil - reply:^(id reply) { - completion(nil); - }]; + [channel + sendMessage:nil + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion([FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + completion(nil); + } + } else { + completion([FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoAllTypes:(AllTypes *)arg_everything completion:(void (^)(AllTypes *_Nullable, FlutterError *_Nullable))completion { @@ -2209,9 +2250,22 @@ - (void)echoAllTypes:(AllTypes *)arg_everything binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_everything ?: [NSNull null] ] - reply:^(id reply) { - AllTypes *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + AllTypes *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoAllNullableTypes:(nullable AllNullableTypes *)arg_everything @@ -2223,9 +2277,22 @@ - (void)echoAllNullableTypes:(nullable AllNullableTypes *)arg_everything binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_everything ?: [NSNull null] ] - reply:^(id reply) { - AllNullableTypes *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + AllNullableTypes *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)sendMultipleNullableTypesABool:(nullable NSNumber *)arg_aNullableBool @@ -2242,9 +2309,22 @@ - (void)sendMultipleNullableTypesABool:(nullable NSNumber *)arg_aNullableBool arg_aNullableBool ?: [NSNull null], arg_aNullableInt ?: [NSNull null], arg_aNullableString ?: [NSNull null] ] - reply:^(id reply) { - AllNullableTypes *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + AllNullableTypes *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoBool:(NSNumber *)arg_aBool @@ -2255,9 +2335,22 @@ - (void)echoBool:(NSNumber *)arg_aBool binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aBool ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoInt:(NSNumber *)arg_anInt @@ -2268,9 +2361,22 @@ - (void)echoInt:(NSNumber *)arg_anInt binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_anInt ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoDouble:(NSNumber *)arg_aDouble @@ -2281,9 +2387,22 @@ - (void)echoDouble:(NSNumber *)arg_aDouble binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aDouble ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoString:(NSString *)arg_aString @@ -2294,9 +2413,22 @@ - (void)echoString:(NSString *)arg_aString binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aString ?: [NSNull null] ] - reply:^(id reply) { - NSString *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSString *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoUint8List:(FlutterStandardTypedData *)arg_aList @@ -2307,11 +2439,25 @@ - (void)echoUint8List:(FlutterStandardTypedData *)arg_aList @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoUint8List" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:@[ arg_aList ?: [NSNull null] ] - reply:^(id reply) { - FlutterStandardTypedData *output = reply; - completion(output, nil); - }]; + [channel + sendMessage:@[ arg_aList ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + FlutterStandardTypedData *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, + [FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoList:(NSArray *)arg_aList completion:(void (^)(NSArray *_Nullable, FlutterError *_Nullable))completion { @@ -2321,9 +2467,22 @@ - (void)echoList:(NSArray *)arg_aList binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aList ?: [NSNull null] ] - reply:^(id reply) { - NSArray *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSArray *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoMap:(NSDictionary *)arg_aMap @@ -2334,23 +2493,54 @@ - (void)echoMap:(NSDictionary *)arg_aMap @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoMap" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:@[ arg_aMap ?: [NSNull null] ] - reply:^(id reply) { - NSDictionary *output = reply; - completion(output, nil); - }]; + [channel + sendMessage:@[ arg_aMap ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSDictionary *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, + [FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoEnum:(AnEnum)arg_anEnum - completion:(void (^)(AnEnum, FlutterError *_Nullable))completion { + completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion { FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel messageChannelWithName: @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoEnum" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ [NSNumber numberWithInteger:arg_anEnum] ] - reply:^(id reply) { - AnEnum output = [reply integerValue]; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *outputAsNumber = reply[0] == [NSNull null] ? nil : reply[0]; + AnEnumBox *output = + outputAsNumber == nil + ? nil + : [[AnEnumBox alloc] initWithValue:[outputAsNumber integerValue]]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableBool:(nullable NSNumber *)arg_aBool @@ -2361,9 +2551,22 @@ - (void)echoNullableBool:(nullable NSNumber *)arg_aBool binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aBool ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableInt:(nullable NSNumber *)arg_anInt @@ -2374,9 +2577,22 @@ - (void)echoNullableInt:(nullable NSNumber *)arg_anInt binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_anInt ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableDouble:(nullable NSNumber *)arg_aDouble @@ -2387,9 +2603,22 @@ - (void)echoNullableDouble:(nullable NSNumber *)arg_aDouble binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aDouble ?: [NSNull null] ] - reply:^(id reply) { - NSNumber *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableString:(nullable NSString *)arg_aString @@ -2400,9 +2629,22 @@ - (void)echoNullableString:(nullable NSString *)arg_aString binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aString ?: [NSNull null] ] - reply:^(id reply) { - NSString *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSString *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableUint8List:(nullable FlutterStandardTypedData *)arg_aList @@ -2413,11 +2655,25 @@ - (void)echoNullableUint8List:(nullable FlutterStandardTypedData *)arg_aList @"FlutterIntegrationCoreApi.echoNullableUint8List" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:@[ arg_aList ?: [NSNull null] ] - reply:^(id reply) { - FlutterStandardTypedData *output = reply; - completion(output, nil); - }]; + [channel + sendMessage:@[ arg_aList ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + FlutterStandardTypedData *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, + [FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoNullableList:(nullable NSArray *)arg_aList completion:(void (^)(NSArray *_Nullable, FlutterError *_Nullable))completion { @@ -2427,9 +2683,22 @@ - (void)echoNullableList:(nullable NSArray *)arg_aList binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aList ?: [NSNull null] ] - reply:^(id reply) { - NSArray *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSArray *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)echoNullableMap:(nullable NSDictionary *)arg_aMap @@ -2440,11 +2709,25 @@ - (void)echoNullableMap:(nullable NSDictionary *)arg_aMap @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableMap" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:@[ arg_aMap ?: [NSNull null] ] - reply:^(id reply) { - NSDictionary *output = reply; - completion(output, nil); - }]; + [channel + sendMessage:@[ arg_aMap ?: [NSNull null] ] + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSDictionary *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, + [FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoNullableEnum:(nullable AnEnumBox *)arg_anEnum completion:(void (^)(AnEnumBox *_Nullable, FlutterError *_Nullable))completion { @@ -2455,13 +2738,26 @@ - (void)echoNullableEnum:(nullable AnEnumBox *)arg_anEnum codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_anEnum == nil ? [NSNull null] : [NSNumber numberWithInteger:arg_anEnum.value] ] - reply:^(id reply) { - NSNumber *outputAsNumber = reply == [NSNull null] ? nil : reply; - AnEnumBox *output = - outputAsNumber == nil - ? nil - : [[AnEnumBox alloc] initWithValue:[outputAsNumber integerValue]]; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSNumber *outputAsNumber = reply[0] == [NSNull null] ? nil : reply[0]; + AnEnumBox *output = + outputAsNumber == nil + ? nil + : [[AnEnumBox alloc] initWithValue:[outputAsNumber integerValue]]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } - (void)noopAsyncWithCompletion:(void (^)(FlutterError *_Nullable))completion { @@ -2470,10 +2766,23 @@ - (void)noopAsyncWithCompletion:(void (^)(FlutterError *_Nullable))completion { @"dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noopAsync" binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; - [channel sendMessage:nil - reply:^(id reply) { - completion(nil); - }]; + [channel + sendMessage:nil + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion([FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + completion(nil); + } + } else { + completion([FlutterError errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } + }]; } - (void)echoAsyncString:(NSString *)arg_aString completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion { @@ -2483,9 +2792,22 @@ - (void)echoAsyncString:(NSString *)arg_aString binaryMessenger:self.binaryMessenger codec:FlutterIntegrationCoreApiGetCodec()]; [channel sendMessage:@[ arg_aString ?: [NSNull null] ] - reply:^(id reply) { - NSString *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + NSString *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } @end @@ -2496,7 +2818,7 @@ - (void)echoAsyncString:(NSString *)arg_aString return sSharedObject; } -void HostTrivialApiSetup(id binaryMessenger, +void SetUpHostTrivialApi(id binaryMessenger, NSObject *api) { { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] @@ -2522,7 +2844,7 @@ void HostTrivialApiSetup(id binaryMessenger, return sSharedObject; } -void HostSmallApiSetup(id binaryMessenger, NSObject *api) { +void SetUpHostSmallApi(id binaryMessenger, NSObject *api) { { FlutterBasicMessageChannel *channel = [[FlutterBasicMessageChannel alloc] initWithName:@"dev.flutter.pigeon.pigeon_integration_tests.HostSmallApi.echo" @@ -2631,9 +2953,22 @@ - (void)echoWrappedList:(TestMessage *)arg_msg binaryMessenger:self.binaryMessenger codec:FlutterSmallApiGetCodec()]; [channel sendMessage:@[ arg_msg ?: [NSNull null] ] - reply:^(id reply) { - TestMessage *output = reply; - completion(output, nil); + reply:^(NSArray *reply) { + if (reply != nil) { + if (reply.count > 1) { + completion(nil, [FlutterError errorWithCode:reply[0] + message:reply[1] + details:reply[2]]); + } else { + TestMessage *output = reply[0] == [NSNull null] ? nil : reply[0]; + completion(output, nil); + } + } else { + completion(nil, [FlutterError + errorWithCode:@"channel-error" + message:@"Unable to establish connection on channel." + details:@""]); + } }]; } @end 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 954ed8e1da1..9daa7c9317f 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 @@ -1030,10 +1030,7 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) { expect(() async { await api.callFlutterThrowError(); }, throwsA(isA())); - }, - // TODO(tarrinneal): Once flutter api error handling is added, enable these tests. - // See: https://github.com/flutter/flutter/issues/118243 - skip: true); + }); testWidgets('errors are returned from void methods correctly', (WidgetTester _) async { @@ -1042,10 +1039,7 @@ void runPigeonIntegrationTests(TargetGenerator targetGenerator) { expect(() async { await api.callFlutterThrowErrorFromVoid(); }, throwsA(isA())); - }, - // TODO(tarrinneal): Once flutter api error handling is added, enable these tests. - // See: https://github.com/flutter/flutter/issues/118243 - skip: true); + }); testWidgets('all datatypes serialize and deserialize correctly', (WidgetTester _) async { diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart index 8b4a04e9e9e..84365208216 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/background_platform_channels.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + class BackgroundApi2Host { /// Constructor for [BackgroundApi2Host]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart index 08b223cb192..0ec2bcd8a44 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/core_tests.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + enum AnEnum { one, two, @@ -2376,9 +2387,15 @@ abstract class FlutterIntegrationCoreApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - // ignore message - api.noop(); - return; + try { + api.noop(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2391,9 +2408,15 @@ abstract class FlutterIntegrationCoreApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - // ignore message - final Object? output = api.throwError(); - return output; + try { + final Object? output = api.throwError(); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2406,9 +2429,15 @@ abstract class FlutterIntegrationCoreApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - // ignore message - api.throwErrorFromVoid(); - return; + try { + api.throwErrorFromVoid(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2427,8 +2456,15 @@ abstract class FlutterIntegrationCoreApi { final AllTypes? arg_everything = (args[0] as AllTypes?); assert(arg_everything != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAllTypes was null, expected non-null AllTypes.'); - final AllTypes output = api.echoAllTypes(arg_everything!); - return output; + try { + final AllTypes output = api.echoAllTypes(arg_everything!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2446,9 +2482,16 @@ abstract class FlutterIntegrationCoreApi { final List args = (message as List?)!; final AllNullableTypes? arg_everything = (args[0] as AllNullableTypes?); - final AllNullableTypes? output = - api.echoAllNullableTypes(arg_everything); - return output; + try { + final AllNullableTypes? output = + api.echoAllNullableTypes(arg_everything); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2467,9 +2510,16 @@ abstract class FlutterIntegrationCoreApi { final bool? arg_aNullableBool = (args[0] as bool?); final int? arg_aNullableInt = (args[1] as int?); final String? arg_aNullableString = (args[2] as String?); - final AllNullableTypes output = api.sendMultipleNullableTypes( - arg_aNullableBool, arg_aNullableInt, arg_aNullableString); - return output; + try { + final AllNullableTypes output = api.sendMultipleNullableTypes( + arg_aNullableBool, arg_aNullableInt, arg_aNullableString); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2488,8 +2538,15 @@ abstract class FlutterIntegrationCoreApi { final bool? arg_aBool = (args[0] as bool?); assert(arg_aBool != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoBool was null, expected non-null bool.'); - final bool output = api.echoBool(arg_aBool!); - return output; + try { + final bool output = api.echoBool(arg_aBool!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2508,8 +2565,15 @@ abstract class FlutterIntegrationCoreApi { final int? arg_anInt = (args[0] as int?); assert(arg_anInt != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoInt was null, expected non-null int.'); - final int output = api.echoInt(arg_anInt!); - return output; + try { + final int output = api.echoInt(arg_anInt!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2528,8 +2592,15 @@ abstract class FlutterIntegrationCoreApi { final double? arg_aDouble = (args[0] as double?); assert(arg_aDouble != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoDouble was null, expected non-null double.'); - final double output = api.echoDouble(arg_aDouble!); - return output; + try { + final double output = api.echoDouble(arg_aDouble!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2548,8 +2619,15 @@ abstract class FlutterIntegrationCoreApi { final String? arg_aString = (args[0] as String?); assert(arg_aString != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoString was null, expected non-null String.'); - final String output = api.echoString(arg_aString!); - return output; + try { + final String output = api.echoString(arg_aString!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2568,8 +2646,15 @@ abstract class FlutterIntegrationCoreApi { final Uint8List? arg_aList = (args[0] as Uint8List?); assert(arg_aList != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoUint8List was null, expected non-null Uint8List.'); - final Uint8List output = api.echoUint8List(arg_aList!); - return output; + try { + final Uint8List output = api.echoUint8List(arg_aList!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2589,8 +2674,15 @@ abstract class FlutterIntegrationCoreApi { (args[0] as List?)?.cast(); assert(arg_aList != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoList was null, expected non-null List.'); - final List output = api.echoList(arg_aList!); - return output; + try { + final List output = api.echoList(arg_aList!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2610,8 +2702,15 @@ abstract class FlutterIntegrationCoreApi { (args[0] as Map?)?.cast(); assert(arg_aMap != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoMap was null, expected non-null Map.'); - final Map output = api.echoMap(arg_aMap!); - return output; + try { + final Map output = api.echoMap(arg_aMap!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2631,8 +2730,15 @@ abstract class FlutterIntegrationCoreApi { args[0] == null ? null : AnEnum.values[args[0]! as int]; assert(arg_anEnum != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoEnum was null, expected non-null AnEnum.'); - final AnEnum output = api.echoEnum(arg_anEnum!); - return output.index; + try { + final AnEnum output = api.echoEnum(arg_anEnum!); + return wrapResponse(result: output.index); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2649,8 +2755,15 @@ abstract class FlutterIntegrationCoreApi { 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableBool was null.'); final List args = (message as List?)!; final bool? arg_aBool = (args[0] as bool?); - final bool? output = api.echoNullableBool(arg_aBool); - return output; + try { + final bool? output = api.echoNullableBool(arg_aBool); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2667,8 +2780,15 @@ abstract class FlutterIntegrationCoreApi { 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableInt was null.'); final List args = (message as List?)!; final int? arg_anInt = (args[0] as int?); - final int? output = api.echoNullableInt(arg_anInt); - return output; + try { + final int? output = api.echoNullableInt(arg_anInt); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2685,8 +2805,15 @@ abstract class FlutterIntegrationCoreApi { 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableDouble was null.'); final List args = (message as List?)!; final double? arg_aDouble = (args[0] as double?); - final double? output = api.echoNullableDouble(arg_aDouble); - return output; + try { + final double? output = api.echoNullableDouble(arg_aDouble); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2703,8 +2830,15 @@ abstract class FlutterIntegrationCoreApi { 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableString was null.'); final List args = (message as List?)!; final String? arg_aString = (args[0] as String?); - final String? output = api.echoNullableString(arg_aString); - return output; + try { + final String? output = api.echoNullableString(arg_aString); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2721,8 +2855,15 @@ abstract class FlutterIntegrationCoreApi { 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableUint8List was null.'); final List args = (message as List?)!; final Uint8List? arg_aList = (args[0] as Uint8List?); - final Uint8List? output = api.echoNullableUint8List(arg_aList); - return output; + try { + final Uint8List? output = api.echoNullableUint8List(arg_aList); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2740,8 +2881,15 @@ abstract class FlutterIntegrationCoreApi { final List args = (message as List?)!; final List? arg_aList = (args[0] as List?)?.cast(); - final List? output = api.echoNullableList(arg_aList); - return output; + try { + final List? output = api.echoNullableList(arg_aList); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2759,8 +2907,15 @@ abstract class FlutterIntegrationCoreApi { final List args = (message as List?)!; final Map? arg_aMap = (args[0] as Map?)?.cast(); - final Map? output = api.echoNullableMap(arg_aMap); - return output; + try { + final Map? output = api.echoNullableMap(arg_aMap); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2778,8 +2933,15 @@ abstract class FlutterIntegrationCoreApi { final List args = (message as List?)!; final AnEnum? arg_anEnum = args[0] == null ? null : AnEnum.values[args[0]! as int]; - final AnEnum? output = api.echoNullableEnum(arg_anEnum); - return output?.index; + try { + final AnEnum? output = api.echoNullableEnum(arg_anEnum); + return wrapResponse(result: output?.index); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2792,9 +2954,15 @@ abstract class FlutterIntegrationCoreApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - // ignore message - await api.noopAsync(); - return; + try { + await api.noopAsync(); + return wrapResponse(empty: true); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2813,8 +2981,15 @@ abstract class FlutterIntegrationCoreApi { final String? arg_aString = (args[0] as String?); assert(arg_aString != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAsyncString was null, expected non-null String.'); - final String output = await api.echoAsyncString(arg_aString!); - return output; + try { + final String output = await api.echoAsyncString(arg_aString!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -2961,8 +3136,15 @@ abstract class FlutterSmallApi { final TestMessage? arg_msg = (args[0] as TestMessage?); assert(arg_msg != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoWrappedList was null, expected non-null TestMessage.'); - final TestMessage output = api.echoWrappedList(arg_msg!); - return output; + try { + final TestMessage output = api.echoWrappedList(arg_msg!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart index 31a24062074..2374bdb9bff 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/enum.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + /// This comment is to test enum documentation comments. enum EnumState { /// This comment is to test enum member (Pending) documentation comments. @@ -156,8 +167,15 @@ abstract class EnumApi2Flutter { final DataWithEnum? arg_data = (args[0] as DataWithEnum?); assert(arg_data != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.EnumApi2Flutter.echo was null, expected non-null DataWithEnum.'); - final DataWithEnum output = api.echo(arg_data!); - return output; + try { + final DataWithEnum output = api.echo(arg_data!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart index 5dfb8b7e037..4b8b89e555f 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/flutter_unittests.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + class FlutterSearchRequest { FlutterSearchRequest({ this.query, diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart index 482bbfd4f20..7ed95ca1878 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/message.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + /// This comment is to test enum documentation comments. /// /// This comment also tests multiple line comments. @@ -350,8 +361,15 @@ abstract class MessageFlutterSearchApi { (args[0] as MessageSearchRequest?); assert(arg_request != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.MessageFlutterSearchApi.search was null, expected non-null MessageSearchRequest.'); - final MessageSearchReply output = api.search(arg_request!); - return output; + try { + final MessageSearchReply output = api.search(arg_request!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart index a73735fde7a..a9f4c8343b7 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/multiple_arity.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + class MultipleArityHostApi { /// Constructor for [MultipleArityHostApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default @@ -76,8 +87,15 @@ abstract class MultipleArityFlutterApi { final int? arg_y = (args[1] as int?); assert(arg_y != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.MultipleArityFlutterApi.subtract was null, expected non-null int.'); - final int output = api.subtract(arg_x!, arg_y!); - return output; + try { + final int output = api.subtract(arg_x!, arg_y!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart index 4fc0d6a59c7..a00148ba2b6 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/non_null_fields.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + enum ReplyType { success, error, @@ -234,8 +245,15 @@ abstract class NonNullFieldFlutterApi { (args[0] as NonNullFieldSearchRequest?); assert(arg_request != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NonNullFieldFlutterApi.search was null, expected non-null NonNullFieldSearchRequest.'); - final NonNullFieldSearchReply output = api.search(arg_request!); - return output; + try { + final NonNullFieldSearchReply output = api.search(arg_request!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart index 145467832d9..5adf669e763 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/null_fields.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + enum NullFieldsSearchReplyType { success, failure, @@ -207,8 +218,15 @@ abstract class NullFieldsFlutterApi { (args[0] as NullFieldsSearchRequest?); assert(arg_request != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NullFieldsFlutterApi.search was null, expected non-null NullFieldsSearchRequest.'); - final NullFieldsSearchReply output = api.search(arg_request!); - return output; + try { + final NullFieldsSearchReply output = api.search(arg_request!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart index 286c5d5f14c..8b5c7011f1f 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/nullable_returns.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + class NullableReturnHostApi { /// Constructor for [NullableReturnHostApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default @@ -61,9 +72,15 @@ abstract class NullableReturnFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - // ignore message - final int? output = api.doit(); - return output; + try { + final int? output = api.doit(); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -112,7 +129,7 @@ class NullableArgHostApi { abstract class NullableArgFlutterApi { static const MessageCodec codec = StandardMessageCodec(); - int doit(int? x); + int? doit(int? x); static void setup(NullableArgFlutterApi? api, {BinaryMessenger? binaryMessenger}) { @@ -129,8 +146,15 @@ abstract class NullableArgFlutterApi { 'Argument for dev.flutter.pigeon.pigeon_integration_tests.NullableArgFlutterApi.doit was null.'); final List args = (message as List?)!; final int? arg_x = (args[0] as int?); - final int output = api.doit(arg_x); - return output; + try { + final int? output = api.doit(arg_x); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -186,9 +210,15 @@ abstract class NullableCollectionReturnFlutterApi { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - // ignore message - final List? output = api.doit(); - return output; + try { + final List? output = api.doit(); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -255,8 +285,15 @@ abstract class NullableCollectionArgFlutterApi { final List args = (message as List?)!; final List? arg_x = (args[0] as List?)?.cast(); - final List output = api.doit(arg_x); - return output; + try { + final List output = api.doit(arg_x); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart index ef12ee8243f..8dd4d79b2b5 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/lib/src/generated/primitive.gen.dart @@ -12,6 +12,17 @@ import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; import 'package:flutter/services.dart'; +List wrapResponse( + {Object? result, PlatformException? error, bool empty = false}) { + if (empty) { + return []; + } + if (error == null) { + return [result]; + } + return [error.code, error.message, error.details]; +} + class PrimitiveHostApi { /// Constructor for [PrimitiveHostApi]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default @@ -313,8 +324,15 @@ abstract class PrimitiveFlutterApi { final int? arg_value = (args[0] as int?); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.anInt was null, expected non-null int.'); - final int output = api.anInt(arg_value!); - return output; + try { + final int output = api.anInt(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -333,8 +351,15 @@ abstract class PrimitiveFlutterApi { final bool? arg_value = (args[0] as bool?); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBool was null, expected non-null bool.'); - final bool output = api.aBool(arg_value!); - return output; + try { + final bool output = api.aBool(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -353,8 +378,15 @@ abstract class PrimitiveFlutterApi { final String? arg_value = (args[0] as String?); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aString was null, expected non-null String.'); - final String output = api.aString(arg_value!); - return output; + try { + final String output = api.aString(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -373,8 +405,15 @@ abstract class PrimitiveFlutterApi { final double? arg_value = (args[0] as double?); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aDouble was null, expected non-null double.'); - final double output = api.aDouble(arg_value!); - return output; + try { + final double output = api.aDouble(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -394,8 +433,15 @@ abstract class PrimitiveFlutterApi { (args[0] as Map?); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aMap was null, expected non-null Map.'); - final Map output = api.aMap(arg_value!); - return output; + try { + final Map output = api.aMap(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -414,8 +460,15 @@ abstract class PrimitiveFlutterApi { final List? arg_value = (args[0] as List?); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aList was null, expected non-null List.'); - final List output = api.aList(arg_value!); - return output; + try { + final List output = api.aList(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -434,8 +487,15 @@ abstract class PrimitiveFlutterApi { final Int32List? arg_value = (args[0] as Int32List?); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.anInt32List was null, expected non-null Int32List.'); - final Int32List output = api.anInt32List(arg_value!); - return output; + try { + final Int32List output = api.anInt32List(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -455,8 +515,15 @@ abstract class PrimitiveFlutterApi { (args[0] as List?)?.cast(); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aBoolList was null, expected non-null List.'); - final List output = api.aBoolList(arg_value!); - return output; + try { + final List output = api.aBoolList(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } @@ -476,8 +543,15 @@ abstract class PrimitiveFlutterApi { (args[0] as Map?)?.cast(); assert(arg_value != null, 'Argument for dev.flutter.pigeon.pigeon_integration_tests.PrimitiveFlutterApi.aStringIntMap was null, expected non-null Map.'); - final Map output = api.aStringIntMap(arg_value!); - return output; + try { + final Map output = api.aStringIntMap(arg_value!); + return wrapResponse(result: output); + } on PlatformException catch (e) { + return wrapResponse(error: e); + } catch (e) { + return wrapResponse( + error: PlatformException(code: 'error', message: e.toString())); + } }); } } diff --git a/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.dart b/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.dart index ffa3063374b..28c341d6f0d 100644 --- a/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.dart +++ b/packages/pigeon/platform_tests/shared_test_plugin_code/test/null_safe_test.dart @@ -143,7 +143,8 @@ void main() { NullableArgFlutterApi.codec.encodeMessage([null]), (ByteData? data) { resultCompleter.complete( - NullableArgFlutterApi.codec.decodeMessage(data)! as int, + (NullableArgFlutterApi.codec.decodeMessage(data)! as List) + .first! as int, ); }, ); @@ -167,8 +168,9 @@ void main() { NullableCollectionArgFlutterApi.codec.encodeMessage([null]), (ByteData? data) { resultCompleter.complete( - (NullableCollectionArgFlutterApi.codec.decodeMessage(data)! - as List) + ((NullableCollectionArgFlutterApi.codec.decodeMessage(data)! + as List) + .first! as List) .cast(), ); }, 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 ab6e8622cd4..07de3995f0a 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 @@ -1921,41 +1921,83 @@ class FlutterIntegrationCoreApi(private val binaryMessenger: BinaryMessenger) { * A no-op function taking no arguments and returning no value, to sanity * test basic calling. */ - fun noop(callback: () -> Unit) { + fun noop(callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noop", codec) channel.send(null) { - callback() + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else { + callback(Result.success(Unit)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Responds with an error from an async function returning a value. */ - fun throwError(callback: (Any?) -> Unit) { + fun throwError(callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.throwError", codec) channel.send(null) { - val result = it - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Responds with an error from an async void function. */ - fun throwErrorFromVoid(callback: () -> Unit) { + fun throwErrorFromVoid(callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.throwErrorFromVoid", codec) channel.send(null) { - callback() + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else { + callback(Result.success(Unit)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed object, to test serialization and deserialization. */ - fun echoAllTypes(everythingArg: AllTypes, callback: (AllTypes) -> Unit) { + fun echoAllTypes(everythingArg: AllTypes, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAllTypes", codec) channel.send(listOf(everythingArg)) { - val result = it as AllTypes - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""))); + } else { + val output = it[0] as AllTypes + callback(Result.success(output)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed object, to test serialization and deserialization. */ - fun echoAllNullableTypes(everythingArg: AllNullableTypes?, callback: (AllNullableTypes?) -> Unit) { + fun echoAllNullableTypes(everythingArg: AllNullableTypes?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAllNullableTypes", codec) channel.send(listOf(everythingArg)) { - val result = it as AllNullableTypes? - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else { + val output = it[0] as AllNullableTypes? + callback(Result.success(output)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** @@ -1963,159 +2005,331 @@ class FlutterIntegrationCoreApi(private val binaryMessenger: BinaryMessenger) { * * Tests multiple-arity FlutterApi handling. */ - fun sendMultipleNullableTypes(aNullableBoolArg: Boolean?, aNullableIntArg: Long?, aNullableStringArg: String?, callback: (AllNullableTypes) -> Unit) { + fun sendMultipleNullableTypes(aNullableBoolArg: Boolean?, aNullableIntArg: Long?, aNullableStringArg: String?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.sendMultipleNullableTypes", codec) channel.send(listOf(aNullableBoolArg, aNullableIntArg, aNullableStringArg)) { - val result = it as AllNullableTypes - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""))); + } else { + val output = it[0] as AllNullableTypes + callback(Result.success(output)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed boolean, to test serialization and deserialization. */ - fun echoBool(aBoolArg: Boolean, callback: (Boolean) -> Unit) { + fun echoBool(aBoolArg: Boolean, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoBool", codec) channel.send(listOf(aBoolArg)) { - val result = it as Boolean - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed int, to test serialization and deserialization. */ - fun echoInt(anIntArg: Long, callback: (Long) -> Unit) { + fun echoInt(anIntArg: Long, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoInt", codec) channel.send(listOf(anIntArg)) { - val result = if (it is Int) it.toLong() else it as Long - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""))); + } else { + val output = it[0].let { if (it is Int) it.toLong() else it as Long } + callback(Result.success(output)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed double, to test serialization and deserialization. */ - fun echoDouble(aDoubleArg: Double, callback: (Double) -> Unit) { + fun echoDouble(aDoubleArg: Double, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoDouble", codec) channel.send(listOf(aDoubleArg)) { - val result = it as Double - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed string, to test serialization and deserialization. */ - fun echoString(aStringArg: String, callback: (String) -> Unit) { + fun echoString(aStringArg: String, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoString", codec) channel.send(listOf(aStringArg)) { - val result = it as String - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed byte list, to test serialization and deserialization. */ - fun echoUint8List(aListArg: ByteArray, callback: (ByteArray) -> Unit) { + fun echoUint8List(aListArg: ByteArray, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoUint8List", codec) channel.send(listOf(aListArg)) { - val result = it as ByteArray - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed list, to test serialization and deserialization. */ - fun echoList(aListArg: List, callback: (List) -> Unit) { + fun echoList(aListArg: List, callback: (Result>) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoList", codec) channel.send(listOf(aListArg)) { - val result = it as List - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed map, to test serialization and deserialization. */ - fun echoMap(aMapArg: Map, callback: (Map) -> Unit) { + fun echoMap(aMapArg: Map, callback: (Result>) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoMap", codec) channel.send(listOf(aMapArg)) { - val result = it as Map - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed enum to test serialization and deserialization. */ - fun echoEnum(anEnumArg: AnEnum, callback: (AnEnum) -> Unit) { + fun echoEnum(anEnumArg: AnEnum, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoEnum", codec) channel.send(listOf(anEnumArg.raw)) { - val result = AnEnum.ofRaw(it as Int)!! - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""))); + } else { + val output = AnEnum.ofRaw(it[0] as Int)!! + callback(Result.success(output)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed boolean, to test serialization and deserialization. */ - fun echoNullableBool(aBoolArg: Boolean?, callback: (Boolean?) -> Unit) { + fun echoNullableBool(aBoolArg: Boolean?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableBool", codec) channel.send(listOf(aBoolArg)) { - val result = it as Boolean? - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed int, to test serialization and deserialization. */ - fun echoNullableInt(anIntArg: Long?, callback: (Long?) -> Unit) { + fun echoNullableInt(anIntArg: Long?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableInt", codec) channel.send(listOf(anIntArg)) { - val result = if (it is Int) it.toLong() else it as Long? - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else { + val output = it[0].let { if (it is Int) it.toLong() else it as Long? } + callback(Result.success(output)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed double, to test serialization and deserialization. */ - fun echoNullableDouble(aDoubleArg: Double?, callback: (Double?) -> Unit) { + fun echoNullableDouble(aDoubleArg: Double?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableDouble", codec) channel.send(listOf(aDoubleArg)) { - val result = it as Double? - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed string, to test serialization and deserialization. */ - fun echoNullableString(aStringArg: String?, callback: (String?) -> Unit) { + fun echoNullableString(aStringArg: String?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableString", codec) channel.send(listOf(aStringArg)) { - val result = it as String? - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed byte list, to test serialization and deserialization. */ - fun echoNullableUint8List(aListArg: ByteArray?, callback: (ByteArray?) -> Unit) { + fun echoNullableUint8List(aListArg: ByteArray?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableUint8List", codec) channel.send(listOf(aListArg)) { - val result = it as ByteArray? - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed list, to test serialization and deserialization. */ - fun echoNullableList(aListArg: List?, callback: (List?) -> Unit) { + fun echoNullableList(aListArg: List?, callback: (Result?>) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableList", codec) channel.send(listOf(aListArg)) { - val result = it as List? - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed map, to test serialization and deserialization. */ - fun echoNullableMap(aMapArg: Map?, callback: (Map?) -> Unit) { + fun echoNullableMap(aMapArg: Map?, callback: (Result?>) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableMap", codec) channel.send(listOf(aMapArg)) { - val result = it as Map? - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed enum to test serialization and deserialization. */ - fun echoNullableEnum(anEnumArg: AnEnum?, callback: (AnEnum?) -> Unit) { + fun echoNullableEnum(anEnumArg: AnEnum?, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableEnum", codec) channel.send(listOf(anEnumArg?.raw)) { - val result = (it as Int?)?.let { - AnEnum.ofRaw(it) - } - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else { + val output = (it[0] as Int?)?.let { + AnEnum.ofRaw(it) + } + callback(Result.success(output)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** * A no-op function taking no arguments and returning no value, to sanity * test basic asynchronous calling. */ - fun noopAsync(callback: () -> Unit) { + fun noopAsync(callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noopAsync", codec) channel.send(null) { - callback() + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else { + callback(Result.success(Unit)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } /** Returns the passed in generic Object asynchronously. */ - fun echoAsyncString(aStringArg: String, callback: (String) -> Unit) { + fun echoAsyncString(aStringArg: String, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAsyncString", codec) channel.send(listOf(aStringArg)) { - val result = it as String - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("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(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } } @@ -2248,11 +2462,21 @@ class FlutterSmallApi(private val binaryMessenger: BinaryMessenger) { FlutterSmallApiCodec } } - fun echoWrappedList(msgArg: TestMessage, callback: (TestMessage) -> Unit) { + fun echoWrappedList(msgArg: TestMessage, callback: (Result) -> Unit) { val channel = BasicMessageChannel(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoWrappedList", codec) channel.send(listOf(msgArg)) { - val result = it as TestMessage - callback(result) + if (it is List<*>) { + if (it.size > 1) { + callback(Result.failure(FlutterError(it[0] as String, it[1] as String, it[2] as String?))); + } else if (it[0] == null) { + callback(Result.failure(FlutterError("null-error", "Flutter api returned null value for non-null return value.", ""))); + } else { + val output = it[0] as TestMessage + callback(Result.success(output)); + } + } else { + callback(Result.failure(FlutterError("channel-error", "Unable to establish connection on channel.", ""))); + } } } } 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 842c8ae72e0..28f85bb544d 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 @@ -240,16 +240,14 @@ class TestPlugin: FlutterPlugin, HostIntegrationCoreApi { } override fun callFlutterThrowError(callback: (Result) -> Unit) { - // TODO: (tarrinneal) Once flutter api error handling is added, complete these tests. - // See issue https://github.com/flutter/flutter/issues/118243 + flutterApi!!.throwError() { result -> callback(result) } } override fun callFlutterThrowErrorFromVoid(callback: (Result) -> Unit) { - // TODO: (tarrinneal) Once flutter api error handling is added, complete these tests. - // See issue https://github.com/flutter/flutter/issues/118243 + flutterApi!!.throwErrorFromVoid() { result -> callback(result) } } override fun callFlutterEchoAllTypes(everything: AllTypes, callback: (Result) -> Unit) { - flutterApi!!.echoAllTypes(everything) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoAllTypes(everything) { echo -> callback(echo) } } override fun callFlutterSendMultipleNullableTypes( @@ -259,76 +257,76 @@ class TestPlugin: FlutterPlugin, HostIntegrationCoreApi { callback: (Result) -> Unit ) { flutterApi!!.sendMultipleNullableTypes(aNullableBool, aNullableInt, aNullableString) { - echo -> callback(Result.success(echo)) + echo -> callback(echo) } } override fun callFlutterEchoBool(aBool: Boolean, callback: (Result) -> Unit) { - flutterApi!!.echoBool(aBool) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoBool(aBool) { echo -> callback(echo) } } override fun callFlutterEchoInt(anInt: Long, callback: (Result) -> Unit) { - flutterApi!!.echoInt(anInt) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoInt(anInt) { echo -> callback(echo) } } override fun callFlutterEchoDouble(aDouble: Double, callback: (Result) -> Unit) { - flutterApi!!.echoDouble(aDouble) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoDouble(aDouble) { echo -> callback(echo) } } override fun callFlutterEchoString(aString: String, callback: (Result) -> Unit) { - flutterApi!!.echoString(aString) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoString(aString) { echo -> callback(echo) } } override fun callFlutterEchoUint8List(aList: ByteArray, callback: (Result) -> Unit) { - flutterApi!!.echoUint8List(aList) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoUint8List(aList) { echo -> callback(echo) } } override fun callFlutterEchoList(aList: List, callback: (Result>) -> Unit){ - flutterApi!!.echoList(aList) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoList(aList) { echo -> callback(echo) } } override fun callFlutterEchoMap(aMap: Map, callback: (Result>) -> Unit) { - flutterApi!!.echoMap(aMap) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoMap(aMap) { echo -> callback(echo) } } override fun callFlutterEchoEnum(anEnum: AnEnum, callback: (Result) -> Unit) { - flutterApi!!.echoEnum(anEnum) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoEnum(anEnum) { echo -> callback(echo) } } override fun callFlutterEchoAllNullableTypes(everything: AllNullableTypes?, callback: (Result) -> Unit) { - flutterApi!!.echoAllNullableTypes(everything) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoAllNullableTypes(everything) { echo -> callback(echo) } } override fun callFlutterEchoNullableBool(aBool: Boolean?, callback: (Result) -> Unit) { - flutterApi!!.echoNullableBool(aBool) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoNullableBool(aBool) { echo -> callback(echo) } } override fun callFlutterEchoNullableInt(anInt: Long?, callback: (Result) -> Unit) { - flutterApi!!.echoNullableInt(anInt) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoNullableInt(anInt) { echo -> callback(echo) } } override fun callFlutterEchoNullableDouble(aDouble: Double?, callback: (Result) -> Unit) { - flutterApi!!.echoNullableDouble(aDouble) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoNullableDouble(aDouble) { echo -> callback(echo) } } override fun callFlutterEchoNullableString(aString: String?, callback: (Result) -> Unit) { - flutterApi!!.echoNullableString(aString) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoNullableString(aString) { echo -> callback(echo) } } override fun callFlutterEchoNullableUint8List(aList: ByteArray?, callback: (Result) -> Unit) { - flutterApi!!.echoNullableUint8List(aList) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoNullableUint8List(aList) { echo -> callback(echo) } } override fun callFlutterEchoNullableList(aList: List?, callback: (Result?>) -> Unit) { - flutterApi!!.echoNullableList(aList) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoNullableList(aList) { echo -> callback(echo) } } override fun callFlutterEchoNullableMap(aMap: Map?, callback: (Result?>) -> Unit) { - flutterApi!!.echoNullableMap(aMap) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoNullableMap(aMap) { echo -> callback(echo) } } override fun callFlutterEchoNullableEnum(anEnum: AnEnum?, callback: (Result) -> Unit) { - flutterApi!!.echoNullableEnum(anEnum) { echo -> callback(Result.success(echo)) } + flutterApi!!.echoNullableEnum(anEnum) { echo -> callback(echo) } } } diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AllDatatypesTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AllDatatypesTest.kt index af1ff21bb2e..01c35776194 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AllDatatypesTest.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AllDatatypesTest.kt @@ -65,7 +65,7 @@ internal class AllDatatypesTest: TestCase() { val reply = arg(2) message.position(0) val args = codec.decodeMessage(message) as ArrayList<*> - val replyData = codec.encodeMessage(args[0]) + val replyData = codec.encodeMessage(args) replyData?.position(0) reply.reply(replyData) } @@ -73,18 +73,21 @@ internal class AllDatatypesTest: TestCase() { var didCall = false api.echoAllNullableTypes(everything) { didCall = true - assertNotNull(it) - assertNull(it!!.aNullableBool) - assertNull(it.aNullableInt) - assertNull(it.aNullableDouble) - assertNull(it.aNullableString) - assertNull(it.aNullableByteArray) - assertNull(it.aNullable4ByteArray) - assertNull(it.aNullable8ByteArray) - assertNull(it.aNullableFloatArray) - assertNull(it.aNullableList) - assertNull(it.aNullableMap) - assertNull(it.nullableMapWithObject) + val output = (it.getOrNull())?.let { + assertNull(it.aNullableBool) + assertNull(it.aNullableInt) + assertNull(it.aNullableDouble) + assertNull(it.aNullableString) + assertNull(it.aNullableByteArray) + assertNull(it.aNullable4ByteArray) + assertNull(it.aNullable8ByteArray) + assertNull(it.aNullableFloatArray) + assertNull(it.aNullableList) + assertNull(it.aNullableMap) + assertNull(it.nullableMapWithObject) + } + assertNotNull(output) + } assertTrue(didCall) @@ -115,7 +118,7 @@ internal class AllDatatypesTest: TestCase() { val reply = arg(2) message.position(0) val args = codec.decodeMessage(message) as ArrayList<*> - val replyData = codec.encodeMessage(args[0]) + val replyData = codec.encodeMessage(args) replyData?.position(0) reply.reply(replyData) } @@ -123,7 +126,7 @@ internal class AllDatatypesTest: TestCase() { var didCall = false api.echoAllNullableTypes(everything) { didCall = true - compareAllNullableTypes(everything, it) + compareAllNullableTypes(everything, it.getOrNull()) } assertTrue(didCall) diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AsyncHandlersTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AsyncHandlersTest.kt index 6d18434aa0b..daaeba3fb3e 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AsyncHandlersTest.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/AsyncHandlersTest.kt @@ -27,7 +27,7 @@ internal class AsyncHandlersTest: TestCase() { val message = arg(1) val reply = arg(2) message.position(0) - val replyData = codec.encodeMessage(value) + val replyData = codec.encodeMessage(listOf(value)) replyData?.position(0) reply.reply(replyData) } @@ -35,7 +35,7 @@ internal class AsyncHandlersTest: TestCase() { var didCall = false api.echoAsyncString(value) { didCall = true - assertEquals(it, value) + assertEquals(it.getOrNull(), value) } assertTrue(didCall) diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/EchoBinaryMessenger.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/EchoBinaryMessenger.kt index e632ddf5787..7d0a7930911 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/EchoBinaryMessenger.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/EchoBinaryMessenger.kt @@ -23,7 +23,7 @@ internal class EchoBinaryMessenger(private val codec: MessageCodec): Binar ) { message?.rewind() val args = codec.decodeMessage(message) as ArrayList<*> - val replyData = codec.encodeMessage(args[0]) + val replyData = codec.encodeMessage(args) replyData?.position(0) callback?.reply(replyData) } diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/EnumTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/EnumTest.kt index c673303967e..97315caf647 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/EnumTest.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/EnumTest.kt @@ -61,7 +61,7 @@ internal class EnumTest: TestCase() { val reply = arg(2) message.position(0) val args = codec.decodeMessage(message) as ArrayList<*> - val replyData = codec.encodeMessage(args[0]) + val replyData = codec.encodeMessage(args) replyData?.position(0) reply.reply(replyData) } @@ -69,7 +69,7 @@ internal class EnumTest: TestCase() { var didCall = false api.echo(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/ListTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/ListTest.kt index 1a071f2dfc1..6f6f94576cc 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/ListTest.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/ListTest.kt @@ -27,7 +27,7 @@ class ListTest: TestCase() { val reply = arg(2) message.position(0) val args = codec.decodeMessage(message) as ArrayList<*> - val replyData = codec.encodeMessage(args[0]) + val replyData = codec.encodeMessage(args) replyData?.position(0) reply.reply(replyData) } @@ -35,7 +35,7 @@ class ListTest: TestCase() { var didCall = false api.echoWrappedList(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/MultipleArityTests.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/MultipleArityTests.kt index 76eeaae360d..0bdc9ebb149 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/MultipleArityTests.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/MultipleArityTests.kt @@ -60,7 +60,7 @@ class MultipleArityTests: TestCase() { val args = codec.decodeMessage(message) as ArrayList<*> val argX = args[0] as Long val argY = args[1] as Long - val replyData = codec.encodeMessage(argX - argY) + val replyData = codec.encodeMessage(listOf(argX - argY)) replyData?.position(0) reply.reply(replyData) } @@ -68,7 +68,7 @@ class MultipleArityTests: TestCase() { var didCall = false api.subtract(inputX, inputY) { didCall = true - assertEquals(inputX - inputY, it) + assertEquals(inputX - inputY, it.getOrNull()) } assertTrue(didCall) diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/NullableReturnsTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/NullableReturnsTest.kt index 5d83fa24d93..e2dcfade4ef 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/NullableReturnsTest.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/NullableReturnsTest.kt @@ -55,7 +55,7 @@ class NullableReturnsTest: TestCase() { every { binaryMessenger.send(any(), any(), any()) } answers { val codec = NullableReturnFlutterApi.codec val reply = arg(2) - val replyData = codec.encodeMessage(output) + val replyData = codec.encodeMessage(listOf(output)) replyData?.position(0) reply.reply(replyData) } @@ -63,7 +63,7 @@ class NullableReturnsTest: TestCase() { var didCall = false api.doit { didCall = true - assertEquals(output, it) + assertEquals(output, it.getOrNull()) } assertTrue(didCall) diff --git a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/PrimitiveTest.kt b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/PrimitiveTest.kt index 3ba267f7644..e25402c388e 100644 --- a/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/PrimitiveTest.kt +++ b/packages/pigeon/platform_tests/test_plugin/android/src/test/kotlin/com/example/test_plugin/PrimitiveTest.kt @@ -57,7 +57,7 @@ class PrimitiveTest: TestCase() { var didCall = false api.anInt(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) @@ -105,7 +105,7 @@ class PrimitiveTest: TestCase() { var didCall = false api.aBool(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) @@ -185,7 +185,7 @@ class PrimitiveTest: TestCase() { var didCall = false api.aDouble(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) @@ -233,7 +233,7 @@ class PrimitiveTest: TestCase() { var didCall = false api.aMap(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) @@ -281,7 +281,7 @@ class PrimitiveTest: TestCase() { var didCall = false api.aList(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) @@ -329,7 +329,7 @@ class PrimitiveTest: TestCase() { var didCall = false api.anInt32List(input) { didCall = true - assertTrue(input.contentEquals(it)) + assertTrue(input.contentEquals(it.getOrNull())) } assertTrue(didCall) @@ -377,7 +377,7 @@ class PrimitiveTest: TestCase() { var didCall = false api.aBoolList(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) @@ -425,7 +425,7 @@ class PrimitiveTest: TestCase() { var didCall = false api.aStringIntMap(input) { didCall = true - assertEquals(input, it) + assertEquals(input, it.getOrNull()) } assertTrue(didCall) diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AllDatatypesTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AllDatatypesTests.swift index 2373673adc3..ed6b5345946 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AllDatatypesTests.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AllDatatypesTests.swift @@ -16,21 +16,27 @@ class AllDatatypesTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") api.echoNullable(everything) { result in - XCTAssertNotNil(result) - XCTAssertNil(result!.aNullableBool) - XCTAssertNil(result!.aNullableInt) - XCTAssertNil(result!.aNullableDouble) - XCTAssertNil(result!.aNullableString) - XCTAssertNil(result!.aNullableByteArray) - XCTAssertNil(result!.aNullable4ByteArray) - XCTAssertNil(result!.aNullable8ByteArray) - XCTAssertNil(result!.aNullableFloatArray) - XCTAssertNil(result!.aNullableList) - XCTAssertNil(result!.aNullableMap) - XCTAssertNil(result!.nullableNestedList) - XCTAssertNil(result!.nullableMapWithAnnotations) - XCTAssertNil(result!.nullableMapWithObject) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertNotNil(res) + XCTAssertNil(res!.aNullableBool) + XCTAssertNil(res!.aNullableInt) + XCTAssertNil(res!.aNullableDouble) + XCTAssertNil(res!.aNullableString) + XCTAssertNil(res!.aNullableByteArray) + XCTAssertNil(res!.aNullable4ByteArray) + XCTAssertNil(res!.aNullable8ByteArray) + XCTAssertNil(res!.aNullableFloatArray) + XCTAssertNil(res!.aNullableList) + XCTAssertNil(res!.aNullableMap) + XCTAssertNil(res!.nullableNestedList) + XCTAssertNil(res!.nullableMapWithAnnotations) + XCTAssertNil(res!.nullableMapWithObject) + expectation.fulfill() + case .failure(_) : + return + + } } wait(for: [expectation], timeout: 1.0) @@ -59,24 +65,28 @@ class AllDatatypesTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") api.echoNullable(everything) { result in - XCTAssertNotNil(result) - XCTAssertEqual(result!.aNullableBool, everything.aNullableBool) - XCTAssertEqual(result!.aNullableInt, everything.aNullableInt) - XCTAssertEqual(result!.aNullableDouble, everything.aNullableDouble) - XCTAssertEqual(result!.aNullableString, everything.aNullableString) - XCTAssertEqual(result!.aNullableByteArray, everything.aNullableByteArray) - XCTAssertEqual(result!.aNullable4ByteArray, everything.aNullable4ByteArray) - XCTAssertEqual(result!.aNullable8ByteArray, everything.aNullable8ByteArray) - XCTAssertEqual(result!.aNullableFloatArray, everything.aNullableFloatArray) - XCTAssert(equalsList(result!.aNullableList, everything.aNullableList)) - XCTAssert(equalsDictionary(result!.aNullableMap, everything.aNullableMap)) - XCTAssertEqual(result!.nullableNestedList, everything.nullableNestedList) - XCTAssertEqual(result!.nullableMapWithAnnotations, everything.nullableMapWithAnnotations) - XCTAssert(equalsDictionary(result!.nullableMapWithObject, everything.nullableMapWithObject)) - - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertNotNil(res) + XCTAssertEqual(res!.aNullableBool, everything.aNullableBool) + XCTAssertEqual(res!.aNullableInt, everything.aNullableInt) + XCTAssertEqual(res!.aNullableDouble, everything.aNullableDouble) + XCTAssertEqual(res!.aNullableString, everything.aNullableString) + XCTAssertEqual(res!.aNullableByteArray, everything.aNullableByteArray) + XCTAssertEqual(res!.aNullable4ByteArray, everything.aNullable4ByteArray) + XCTAssertEqual(res!.aNullable8ByteArray, everything.aNullable8ByteArray) + XCTAssertEqual(res!.aNullableFloatArray, everything.aNullableFloatArray) + XCTAssert(equalsList(res!.aNullableList, everything.aNullableList)) + XCTAssert(equalsDictionary(res!.aNullableMap, everything.aNullableMap)) + XCTAssertEqual(res!.nullableNestedList, everything.nullableNestedList) + XCTAssertEqual(res!.nullableMapWithAnnotations, everything.nullableMapWithAnnotations) + XCTAssert(equalsDictionary(res!.nullableMapWithObject, everything.nullableMapWithObject)) + expectation.fulfill() + return + case .failure(_) : + return + } } - wait(for: [expectation], timeout: 1.0) } } diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AsyncHandlersTest.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AsyncHandlersTest.swift index 015c6ab6127..f5852c47a98 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AsyncHandlersTest.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/AsyncHandlersTest.swift @@ -26,9 +26,15 @@ class AsyncHandlersTest: XCTestCase { let flutterApi = FlutterIntegrationCoreApi(binaryMessenger: binaryMessenger) let expectation = XCTestExpectation(description: "callback") - flutterApi.echo(value) { output in - XCTAssertEqual(output, value) + flutterApi.echo(value) { result in + switch result { + case .success(let res) : + XCTAssertEqual(res, value) expectation.fulfill() + case .failure(_) : + return + } + } wait(for: [expectation], timeout: 1.0) } diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/EchoBinaryMessenger.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/EchoBinaryMessenger.swift index fef7e2d1b4c..a2f524c2bd9 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/EchoBinaryMessenger.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/EchoBinaryMessenger.swift @@ -31,11 +31,11 @@ class EchoBinaryMessenger: NSObject, FlutterBinaryMessenger { let firstArg = args.first, let castedFirstArg: Any? = nilOrValue(firstArg) else { - callback(self.defaultReturn.flatMap { self.codec.encode($0) }) + callback(self.defaultReturn.flatMap { self.codec.encode([$0]) }) return } - callback(self.codec.encode(castedFirstArg)) + callback(self.codec.encode([castedFirstArg])) } func setMessageHandlerOnChannel( diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/EnumTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/EnumTests.swift index 55ca025231c..2c8c0cc4119 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/EnumTests.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/EnumTests.swift @@ -48,8 +48,13 @@ class EnumTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") api.echo(data: data) { result in - XCTAssertEqual(data.state, result.state) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertEqual(res.state, res.state) + expectation.fulfill() + case .failure(_) : + return + } } wait(for: [expectation], timeout: 1.0) } diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/HandlerBinaryMessenger.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/HandlerBinaryMessenger.swift index 998a55d493e..fda20a40da5 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/HandlerBinaryMessenger.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/HandlerBinaryMessenger.swift @@ -35,7 +35,7 @@ class HandlerBinaryMessenger: NSObject, FlutterBinaryMessenger { } let result = self.handler(args) - callback(self.codec.encode(result)) + callback(self.codec.encode([result])) } func setMessageHandlerOnChannel( diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/ListTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/ListTests.swift index c48068e234d..b096ed2bc58 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/ListTests.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/ListTests.swift @@ -15,10 +15,15 @@ class ListTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") api.echo(top) { result in - XCTAssertEqual(1, result.testList?.count) - XCTAssertTrue(result.testList?[0] is TestMessage) - XCTAssert(equalsList(inside.testList, (result.testList?[0] as! TestMessage).testList)) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertEqual(1, res.testList?.count) + XCTAssertTrue(res.testList?[0] is TestMessage) + XCTAssert(equalsList(inside.testList, (res.testList?[0] as! TestMessage).testList)) + expectation.fulfill() + case .failure(_) : + return + } } wait(for: [expectation], timeout: 1.0) } diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/MockBinaryMessenger.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/MockBinaryMessenger.swift index debd800c5af..9f7f9483b1e 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/MockBinaryMessenger.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/MockBinaryMessenger.swift @@ -23,7 +23,7 @@ class MockBinaryMessenger: NSObject, FlutterBinaryMessenger { binaryReply callback: FlutterBinaryReply? = nil ) { if let result = result { - callback?(codec.encode(result)) + callback?(codec.encode([result])) } } diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/MultipleArityTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/MultipleArityTests.swift index eca07303031..52155f8927a 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/MultipleArityTests.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/MultipleArityTests.swift @@ -45,10 +45,14 @@ class MultipleArityTests: XCTestCase { let expectation = XCTestExpectation(description: "subtraction") api.subtract(x: 30, y: 10) { result in - XCTAssertEqual(20, result) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertEqual(20, res) + expectation.fulfill() + case .failure(_) : + return + } } wait(for: [expectation], timeout: 1.0) } - } diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/NullableReturnsTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/NullableReturnsTests.swift index 95f04ca8874..dca9d6e3d6e 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/NullableReturnsTests.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/NullableReturnsTests.swift @@ -26,8 +26,13 @@ class NullableReturnsTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") api.doit(x: nil) { result in - XCTAssertEqual(99, result) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertEqual(99, res) + expectation.fulfill() + case .failure(_) : + return + } } wait(for: [expectation], timeout: 1.0) } diff --git a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/PrimitiveTests.swift b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/PrimitiveTests.swift index 02d95421813..86b118e7f62 100644 --- a/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/PrimitiveTests.swift +++ b/packages/pigeon/platform_tests/test_plugin/example/ios/RunnerTests/PrimitiveTests.swift @@ -49,8 +49,14 @@ class PrimitiveTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") api.anInt(value: 1) { result in - XCTAssertEqual(1, result) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertEqual(1, res) + expectation.fulfill() + case .failure(_) : + return + + } } wait(for: [expectation], timeout: 1.0) } @@ -83,8 +89,13 @@ class PrimitiveTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") api.aBool(value: true) { result in - XCTAssertEqual(true, result) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertEqual(true, res) + expectation.fulfill() + case .failure(_) : + return + } } wait(for: [expectation], timeout: 1.0) } @@ -118,8 +129,13 @@ class PrimitiveTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") let arg: Double = 1.5 api.aDouble(value: arg) { result in - XCTAssertEqual(arg, result) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertEqual(arg, res) + expectation.fulfill() + case .failure(_) : + return + } } wait(for: [expectation], timeout: 1.0) } @@ -153,8 +169,13 @@ class PrimitiveTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") let arg: String = "hello" api.aString(value: arg) { result in - XCTAssertEqual(arg, result) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssertEqual(arg, res) + expectation.fulfill() + case .failure(_) : + return + } } wait(for: [expectation], timeout: 1.0) } @@ -188,8 +209,13 @@ class PrimitiveTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") let arg = ["hello"] api.aList(value: arg) { result in - XCTAssert(equalsList(arg, result)) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssert(equalsList(arg, res)) + expectation.fulfill() + case .failure(_) : + return + } } wait(for: [expectation], timeout: 1.0) } @@ -223,8 +249,14 @@ class PrimitiveTests: XCTestCase { let expectation = XCTestExpectation(description: "callback") let arg = ["hello": 1] api.aMap(value: arg) { result in - XCTAssert(equalsDictionary(arg, result)) - expectation.fulfill() + switch result { + case .success(let res) : + XCTAssert(equalsDictionary(arg, res)) + expectation.fulfill() + case .failure(_) : + return + } + } wait(for: [expectation], timeout: 1.0) } diff --git a/packages/pigeon/platform_tests/test_plugin/ios/Classes/CoreTests.gen.swift b/packages/pigeon/platform_tests/test_plugin/ios/Classes/CoreTests.gen.swift index 130d53b5c59..601136c458d 100644 --- a/packages/pigeon/platform_tests/test_plugin/ios/Classes/CoreTests.gen.swift +++ b/packages/pigeon/platform_tests/test_plugin/ios/Classes/CoreTests.gen.swift @@ -1750,195 +1750,448 @@ class FlutterIntegrationCoreApi { } /// A no-op function taking no arguments and returning no value, to sanity /// test basic calling. - func noop(completion: @escaping () -> Void) { + func noop(completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noop", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage(nil) { _ in - completion() + completion(.success(Void())) } } /// Responds with an error from an async function returning a value. - func throwError(completion: @escaping (Any?) -> Void) { + func throwError(completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.throwError", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage(nil) { response in - let result: Any? = response - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: Any? = listResponse[0] + completion(.success(result)) + } } } /// Responds with an error from an async void function. - func throwErrorFromVoid(completion: @escaping () -> Void) { + func throwErrorFromVoid(completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.throwErrorFromVoid", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage(nil) { _ in - completion() + completion(.success(Void())) } } /// Returns the passed object, to test serialization and deserialization. - func echo(_ everythingArg: AllTypes, completion: @escaping (AllTypes) -> Void) { + func echo(_ everythingArg: AllTypes, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAllTypes", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([everythingArg] as [Any?]) { response in - let result = response as! AllTypes - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! AllTypes + completion(.success(result)) + } } } /// Returns the passed object, to test serialization and deserialization. - func echoNullable(_ everythingArg: AllNullableTypes?, completion: @escaping (AllNullableTypes?) -> Void) { + func echoNullable(_ everythingArg: AllNullableTypes?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAllNullableTypes", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([everythingArg] as [Any?]) { response in - let result: AllNullableTypes? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: AllNullableTypes? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns passed in arguments of multiple types. /// /// Tests multiple-arity FlutterApi handling. - func sendMultipleNullableTypes(aBool aNullableBoolArg: Bool?, anInt aNullableIntArg: Int64?, aString aNullableStringArg: String?, completion: @escaping (AllNullableTypes) -> Void) { + func sendMultipleNullableTypes(aBool aNullableBoolArg: Bool?, anInt aNullableIntArg: Int64?, aString aNullableStringArg: String?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.sendMultipleNullableTypes", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aNullableBoolArg, aNullableIntArg, aNullableStringArg] as [Any?]) { response in - let result = response as! AllNullableTypes - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! AllNullableTypes + completion(.success(result)) + } } } /// Returns the passed boolean, to test serialization and deserialization. - func echo(_ aBoolArg: Bool, completion: @escaping (Bool) -> Void) { + func echo(_ aBoolArg: Bool, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoBool", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aBoolArg] as [Any?]) { response in - let result = response as! Bool - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! Bool + completion(.success(result)) + } } } /// Returns the passed int, to test serialization and deserialization. - func echo(_ anIntArg: Int64, completion: @escaping (Int64) -> Void) { + func echo(_ anIntArg: Int64, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoInt", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([anIntArg] as [Any?]) { response in - let result = response is Int64 ? response as! Int64 : Int64(response as! Int32) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] is Int64 ? listResponse[0] as! Int64 : Int64(listResponse[0] as! Int32) + completion(.success(result)) + } } } /// Returns the passed double, to test serialization and deserialization. - func echo(_ aDoubleArg: Double, completion: @escaping (Double) -> Void) { + func echo(_ aDoubleArg: Double, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoDouble", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aDoubleArg] as [Any?]) { response in - let result = response as! Double - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! Double + completion(.success(result)) + } } } /// Returns the passed string, to test serialization and deserialization. - func echo(_ aStringArg: String, completion: @escaping (String) -> Void) { + func echo(_ aStringArg: String, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoString", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aStringArg] as [Any?]) { response in - let result = response as! String - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! String + completion(.success(result)) + } } } /// Returns the passed byte list, to test serialization and deserialization. - func echo(_ aListArg: FlutterStandardTypedData, completion: @escaping (FlutterStandardTypedData) -> Void) { + func echo(_ aListArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoUint8List", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aListArg] as [Any?]) { response in - let result = response as! FlutterStandardTypedData - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! FlutterStandardTypedData + completion(.success(result)) + } } } /// Returns the passed list, to test serialization and deserialization. - func echo(_ aListArg: [Any?], completion: @escaping ([Any?]) -> Void) { + func echo(_ aListArg: [Any?], completion: @escaping (Result<[Any?], FlutterError>) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoList", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aListArg] as [Any?]) { response in - let result = response as! [Any?] - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! [Any?] + completion(.success(result)) + } } } /// Returns the passed map, to test serialization and deserialization. - func echo(_ aMapArg: [String?: Any?], completion: @escaping ([String?: Any?]) -> Void) { + func echo(_ aMapArg: [String?: Any?], completion: @escaping (Result<[String?: Any?], FlutterError>) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoMap", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aMapArg] as [Any?]) { response in - let result = response as! [String?: Any?] - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! [String?: Any?] + completion(.success(result)) + } } } /// Returns the passed enum to test serialization and deserialization. - func echo(_ anEnumArg: AnEnum, completion: @escaping (AnEnum) -> Void) { + func echo(_ anEnumArg: AnEnum, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoEnum", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([anEnumArg.rawValue] as [Any?]) { response in - let result = AnEnum(rawValue: response as! Int)! - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = AnEnum(rawValue: listResponse[0] as! Int)! + completion(.success(result)) + } } } /// Returns the passed boolean, to test serialization and deserialization. - func echoNullable(_ aBoolArg: Bool?, completion: @escaping (Bool?) -> Void) { + func echoNullable(_ aBoolArg: Bool?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableBool", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aBoolArg] as [Any?]) { response in - let result: Bool? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: Bool? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed int, to test serialization and deserialization. - func echoNullable(_ anIntArg: Int64?, completion: @escaping (Int64?) -> Void) { + func echoNullable(_ anIntArg: Int64?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableInt", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([anIntArg] as [Any?]) { response in - let result: Int64? = isNullish(response) ? nil : (response is Int64? ? response as! Int64? : Int64(response as! Int32)) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: Int64? = isNullish(listResponse[0]) ? nil : (listResponse[0] is Int64? ? listResponse[0] as! Int64? : Int64(listResponse[0] as! Int32)) + completion(.success(result)) + } } } /// Returns the passed double, to test serialization and deserialization. - func echoNullable(_ aDoubleArg: Double?, completion: @escaping (Double?) -> Void) { + func echoNullable(_ aDoubleArg: Double?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableDouble", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aDoubleArg] as [Any?]) { response in - let result: Double? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: Double? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed string, to test serialization and deserialization. - func echoNullable(_ aStringArg: String?, completion: @escaping (String?) -> Void) { + func echoNullable(_ aStringArg: String?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableString", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aStringArg] as [Any?]) { response in - let result: String? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: String? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed byte list, to test serialization and deserialization. - func echoNullable(_ aListArg: FlutterStandardTypedData?, completion: @escaping (FlutterStandardTypedData?) -> Void) { + func echoNullable(_ aListArg: FlutterStandardTypedData?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableUint8List", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aListArg] as [Any?]) { response in - let result: FlutterStandardTypedData? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: FlutterStandardTypedData? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed list, to test serialization and deserialization. - func echoNullable(_ aListArg: [Any?]?, completion: @escaping ([Any?]?) -> Void) { + func echoNullable(_ aListArg: [Any?]?, completion: @escaping (Result<[Any?]?, FlutterError>) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableList", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aListArg] as [Any?]) { response in - let result: [Any?]? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: [Any?]? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed map, to test serialization and deserialization. - func echoNullable(_ aMapArg: [String?: Any?]?, completion: @escaping ([String?: Any?]?) -> Void) { + func echoNullable(_ aMapArg: [String?: Any?]?, completion: @escaping (Result<[String?: Any?]?, FlutterError>) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableMap", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aMapArg] as [Any?]) { response in - let result: [String?: Any?]? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: [String?: Any?]? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed enum to test serialization and deserialization. - func echoNullable(_ anEnumArg: AnEnum?, completion: @escaping (AnEnum?) -> Void) { + func echoNullable(_ anEnumArg: AnEnum?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableEnum", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([anEnumArg?.rawValue] as [Any?]) { response in - let result: AnEnum? = isNullish(response) ? nil : AnEnum(rawValue: response as! Int)! - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: AnEnum? = isNullish(listResponse[0]) ? nil : AnEnum(rawValue: listResponse[0] as! Int)! + completion(.success(result)) + } } } /// A no-op function taking no arguments and returning no value, to sanity /// test basic asynchronous calling. - func noopAsync(completion: @escaping () -> Void) { + func noopAsync(completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noopAsync", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage(nil) { _ in - completion() + completion(.success(Void())) } } /// Returns the passed in generic Object asynchronously. - func echoAsync(_ aStringArg: String, completion: @escaping (String) -> Void) { + func echoAsync(_ aStringArg: String, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAsyncString", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aStringArg] as [Any?]) { response in - let result = response as! String - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! String + completion(.success(result)) + } } } } @@ -2063,11 +2316,24 @@ class FlutterSmallApi { var codec: FlutterStandardMessageCodec { return FlutterSmallApiCodec.shared } - func echo(_ msgArg: TestMessage, completion: @escaping (TestMessage) -> Void) { + func echo(_ msgArg: TestMessage, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoWrappedList", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([msgArg] as [Any?]) { response in - let result = response as! TestMessage - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! TestMessage + completion(.success(result)) + } } } } diff --git a/packages/pigeon/platform_tests/test_plugin/ios/Classes/TestPlugin.swift b/packages/pigeon/platform_tests/test_plugin/ios/Classes/TestPlugin.swift index 201b1136274..c29d1eef003 100644 --- a/packages/pigeon/platform_tests/test_plugin/ios/Classes/TestPlugin.swift +++ b/packages/pigeon/platform_tests/test_plugin/ios/Classes/TestPlugin.swift @@ -235,30 +235,57 @@ public class TestPlugin: NSObject, FlutterPlugin, HostIntegrationCoreApi { } func callFlutterNoop(completion: @escaping (Result) -> Void) { - flutterAPI.noop() { - completion(.success(Void())) + flutterAPI.noop() { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterThrowError(completion: @escaping (Result) -> Void) { - // TODO: (tarrinneal) Once flutter api error handling is added, enable these tests. - // See issue https://github.com/flutter/flutter/issues/118243 + flutterAPI.throwError() { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } + } } func callFlutterThrowErrorFromVoid(completion: @escaping (Result) -> Void) { - // TODO: (tarrinneal) Once flutter api error handling is added, enable these tests. - // See issue https://github.com/flutter/flutter/issues/118243 + flutterAPI.throwErrorFromVoid() { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } + } } func callFlutterEcho(_ everything: AllTypes, completion: @escaping (Result) -> Void) { - flutterAPI.echo(everything) { - completion(.success($0)) + flutterAPI.echo(everything) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ everything: AllNullableTypes?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(everything) { - completion(.success($0)) + flutterAPI.echoNullable(everything) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } @@ -272,104 +299,189 @@ public class TestPlugin: NSObject, FlutterPlugin, HostIntegrationCoreApi { aBool: aNullableBool, anInt: aNullableInt, aString: aNullableString - ) { - completion(.success($0)) + ) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aBool: Bool, completion: @escaping (Result) -> Void) { - flutterAPI.echo(aBool) { - completion(.success($0)) + flutterAPI.echo(aBool) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ anInt: Int64, completion: @escaping (Result) -> Void) { - flutterAPI.echo(anInt) { - completion(.success($0)) + flutterAPI.echo(anInt) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aDouble: Double, completion: @escaping (Result) -> Void) { - flutterAPI.echo(aDouble) { - completion(.success($0)) + flutterAPI.echo(aDouble) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aString: String, completion: @escaping (Result) -> Void) { - flutterAPI.echo(aString) { - completion(.success($0)) + flutterAPI.echo(aString) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aList: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { - flutterAPI.echo(aList) { - completion(.success($0)) + flutterAPI.echo(aList) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aList: [Any?], completion: @escaping (Result<[Any?], Error>) -> Void) { - flutterAPI.echo(aList) { - completion(.success($0)) + flutterAPI.echo(aList) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aMap: [String? : Any?], completion: @escaping (Result<[String? : Any?], Error>) -> Void) { - flutterAPI.echo(aMap) { - completion(.success($0)) + flutterAPI.echo(aMap) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ anEnum: AnEnum, completion: @escaping (Result) -> Void) { - flutterAPI.echo(anEnum) { - completion(.success($0)) + flutterAPI.echo(anEnum) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aBool: Bool?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(aBool) { - completion(.success($0)) + flutterAPI.echoNullable(aBool) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ anInt: Int64?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(anInt) { - completion(.success($0)) + flutterAPI.echoNullable(anInt) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aDouble: Double?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(aDouble) { - completion(.success($0)) + flutterAPI.echoNullable(aDouble) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aString: String?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(aString) { - completion(.success($0)) + flutterAPI.echoNullable(aString) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aList: FlutterStandardTypedData?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(aList) { - completion(.success($0)) + flutterAPI.echoNullable(aList) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aList: [Any?]?, completion: @escaping (Result<[Any?]?, Error>) -> Void) { - flutterAPI.echoNullable(aList) { - completion(.success($0)) + flutterAPI.echoNullable(aList) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aMap: [String? : Any?]?, completion: @escaping (Result<[String? : Any?]?, Error>) -> Void) { - flutterAPI.echoNullable(aMap) { - completion(.success($0)) + flutterAPI.echoNullable(aMap) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterNullableEcho(_ anEnum: AnEnum?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(anEnum) { - completion(.success($0)) + flutterAPI.echoNullable(anEnum) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } } diff --git a/packages/pigeon/platform_tests/test_plugin/macos/Classes/CoreTests.gen.swift b/packages/pigeon/platform_tests/test_plugin/macos/Classes/CoreTests.gen.swift index 130d53b5c59..601136c458d 100644 --- a/packages/pigeon/platform_tests/test_plugin/macos/Classes/CoreTests.gen.swift +++ b/packages/pigeon/platform_tests/test_plugin/macos/Classes/CoreTests.gen.swift @@ -1750,195 +1750,448 @@ class FlutterIntegrationCoreApi { } /// A no-op function taking no arguments and returning no value, to sanity /// test basic calling. - func noop(completion: @escaping () -> Void) { + func noop(completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noop", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage(nil) { _ in - completion() + completion(.success(Void())) } } /// Responds with an error from an async function returning a value. - func throwError(completion: @escaping (Any?) -> Void) { + func throwError(completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.throwError", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage(nil) { response in - let result: Any? = response - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: Any? = listResponse[0] + completion(.success(result)) + } } } /// Responds with an error from an async void function. - func throwErrorFromVoid(completion: @escaping () -> Void) { + func throwErrorFromVoid(completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.throwErrorFromVoid", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage(nil) { _ in - completion() + completion(.success(Void())) } } /// Returns the passed object, to test serialization and deserialization. - func echo(_ everythingArg: AllTypes, completion: @escaping (AllTypes) -> Void) { + func echo(_ everythingArg: AllTypes, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAllTypes", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([everythingArg] as [Any?]) { response in - let result = response as! AllTypes - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! AllTypes + completion(.success(result)) + } } } /// Returns the passed object, to test serialization and deserialization. - func echoNullable(_ everythingArg: AllNullableTypes?, completion: @escaping (AllNullableTypes?) -> Void) { + func echoNullable(_ everythingArg: AllNullableTypes?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAllNullableTypes", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([everythingArg] as [Any?]) { response in - let result: AllNullableTypes? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: AllNullableTypes? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns passed in arguments of multiple types. /// /// Tests multiple-arity FlutterApi handling. - func sendMultipleNullableTypes(aBool aNullableBoolArg: Bool?, anInt aNullableIntArg: Int64?, aString aNullableStringArg: String?, completion: @escaping (AllNullableTypes) -> Void) { + func sendMultipleNullableTypes(aBool aNullableBoolArg: Bool?, anInt aNullableIntArg: Int64?, aString aNullableStringArg: String?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.sendMultipleNullableTypes", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aNullableBoolArg, aNullableIntArg, aNullableStringArg] as [Any?]) { response in - let result = response as! AllNullableTypes - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! AllNullableTypes + completion(.success(result)) + } } } /// Returns the passed boolean, to test serialization and deserialization. - func echo(_ aBoolArg: Bool, completion: @escaping (Bool) -> Void) { + func echo(_ aBoolArg: Bool, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoBool", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aBoolArg] as [Any?]) { response in - let result = response as! Bool - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! Bool + completion(.success(result)) + } } } /// Returns the passed int, to test serialization and deserialization. - func echo(_ anIntArg: Int64, completion: @escaping (Int64) -> Void) { + func echo(_ anIntArg: Int64, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoInt", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([anIntArg] as [Any?]) { response in - let result = response is Int64 ? response as! Int64 : Int64(response as! Int32) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] is Int64 ? listResponse[0] as! Int64 : Int64(listResponse[0] as! Int32) + completion(.success(result)) + } } } /// Returns the passed double, to test serialization and deserialization. - func echo(_ aDoubleArg: Double, completion: @escaping (Double) -> Void) { + func echo(_ aDoubleArg: Double, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoDouble", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aDoubleArg] as [Any?]) { response in - let result = response as! Double - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! Double + completion(.success(result)) + } } } /// Returns the passed string, to test serialization and deserialization. - func echo(_ aStringArg: String, completion: @escaping (String) -> Void) { + func echo(_ aStringArg: String, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoString", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aStringArg] as [Any?]) { response in - let result = response as! String - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! String + completion(.success(result)) + } } } /// Returns the passed byte list, to test serialization and deserialization. - func echo(_ aListArg: FlutterStandardTypedData, completion: @escaping (FlutterStandardTypedData) -> Void) { + func echo(_ aListArg: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoUint8List", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aListArg] as [Any?]) { response in - let result = response as! FlutterStandardTypedData - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! FlutterStandardTypedData + completion(.success(result)) + } } } /// Returns the passed list, to test serialization and deserialization. - func echo(_ aListArg: [Any?], completion: @escaping ([Any?]) -> Void) { + func echo(_ aListArg: [Any?], completion: @escaping (Result<[Any?], FlutterError>) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoList", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aListArg] as [Any?]) { response in - let result = response as! [Any?] - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! [Any?] + completion(.success(result)) + } } } /// Returns the passed map, to test serialization and deserialization. - func echo(_ aMapArg: [String?: Any?], completion: @escaping ([String?: Any?]) -> Void) { + func echo(_ aMapArg: [String?: Any?], completion: @escaping (Result<[String?: Any?], FlutterError>) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoMap", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aMapArg] as [Any?]) { response in - let result = response as! [String?: Any?] - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! [String?: Any?] + completion(.success(result)) + } } } /// Returns the passed enum to test serialization and deserialization. - func echo(_ anEnumArg: AnEnum, completion: @escaping (AnEnum) -> Void) { + func echo(_ anEnumArg: AnEnum, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoEnum", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([anEnumArg.rawValue] as [Any?]) { response in - let result = AnEnum(rawValue: response as! Int)! - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = AnEnum(rawValue: listResponse[0] as! Int)! + completion(.success(result)) + } } } /// Returns the passed boolean, to test serialization and deserialization. - func echoNullable(_ aBoolArg: Bool?, completion: @escaping (Bool?) -> Void) { + func echoNullable(_ aBoolArg: Bool?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableBool", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aBoolArg] as [Any?]) { response in - let result: Bool? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: Bool? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed int, to test serialization and deserialization. - func echoNullable(_ anIntArg: Int64?, completion: @escaping (Int64?) -> Void) { + func echoNullable(_ anIntArg: Int64?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableInt", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([anIntArg] as [Any?]) { response in - let result: Int64? = isNullish(response) ? nil : (response is Int64? ? response as! Int64? : Int64(response as! Int32)) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: Int64? = isNullish(listResponse[0]) ? nil : (listResponse[0] is Int64? ? listResponse[0] as! Int64? : Int64(listResponse[0] as! Int32)) + completion(.success(result)) + } } } /// Returns the passed double, to test serialization and deserialization. - func echoNullable(_ aDoubleArg: Double?, completion: @escaping (Double?) -> Void) { + func echoNullable(_ aDoubleArg: Double?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableDouble", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aDoubleArg] as [Any?]) { response in - let result: Double? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: Double? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed string, to test serialization and deserialization. - func echoNullable(_ aStringArg: String?, completion: @escaping (String?) -> Void) { + func echoNullable(_ aStringArg: String?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableString", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aStringArg] as [Any?]) { response in - let result: String? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: String? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed byte list, to test serialization and deserialization. - func echoNullable(_ aListArg: FlutterStandardTypedData?, completion: @escaping (FlutterStandardTypedData?) -> Void) { + func echoNullable(_ aListArg: FlutterStandardTypedData?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableUint8List", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aListArg] as [Any?]) { response in - let result: FlutterStandardTypedData? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: FlutterStandardTypedData? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed list, to test serialization and deserialization. - func echoNullable(_ aListArg: [Any?]?, completion: @escaping ([Any?]?) -> Void) { + func echoNullable(_ aListArg: [Any?]?, completion: @escaping (Result<[Any?]?, FlutterError>) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableList", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aListArg] as [Any?]) { response in - let result: [Any?]? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: [Any?]? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed map, to test serialization and deserialization. - func echoNullable(_ aMapArg: [String?: Any?]?, completion: @escaping ([String?: Any?]?) -> Void) { + func echoNullable(_ aMapArg: [String?: Any?]?, completion: @escaping (Result<[String?: Any?]?, FlutterError>) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableMap", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aMapArg] as [Any?]) { response in - let result: [String?: Any?]? = nilOrValue(response) - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: [String?: Any?]? = nilOrValue(listResponse[0]) + completion(.success(result)) + } } } /// Returns the passed enum to test serialization and deserialization. - func echoNullable(_ anEnumArg: AnEnum?, completion: @escaping (AnEnum?) -> Void) { + func echoNullable(_ anEnumArg: AnEnum?, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoNullableEnum", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([anEnumArg?.rawValue] as [Any?]) { response in - let result: AnEnum? = isNullish(response) ? nil : AnEnum(rawValue: response as! Int)! - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else { + let result: AnEnum? = isNullish(listResponse[0]) ? nil : AnEnum(rawValue: listResponse[0] as! Int)! + completion(.success(result)) + } } } /// A no-op function taking no arguments and returning no value, to sanity /// test basic asynchronous calling. - func noopAsync(completion: @escaping () -> Void) { + func noopAsync(completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.noopAsync", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage(nil) { _ in - completion() + completion(.success(Void())) } } /// Returns the passed in generic Object asynchronously. - func echoAsync(_ aStringArg: String, completion: @escaping (String) -> Void) { + func echoAsync(_ aStringArg: String, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterIntegrationCoreApi.echoAsyncString", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([aStringArg] as [Any?]) { response in - let result = response as! String - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! String + completion(.success(result)) + } } } } @@ -2063,11 +2316,24 @@ class FlutterSmallApi { var codec: FlutterStandardMessageCodec { return FlutterSmallApiCodec.shared } - func echo(_ msgArg: TestMessage, completion: @escaping (TestMessage) -> Void) { + func echo(_ msgArg: TestMessage, completion: @escaping (Result) -> Void) { let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoWrappedList", binaryMessenger: binaryMessenger, codec: codec) channel.sendMessage([msgArg] as [Any?]) { response in - let result = response as! TestMessage - completion(result) + guard let listResponse = response as? [Any?] else { + completion(.failure(FlutterError(code: "channel-error", message: "Unable to establish connection on channel.", details: ""))) + return + } + if (listResponse.count > 1) { + let code: String = listResponse[0] as! String + let message: String? = nilOrValue(listResponse[1]) + let details: String? = nilOrValue(listResponse[2]) + completion(.failure(FlutterError(code: code, message: message, details: details))); + } else if (listResponse[0] == nil) { + completion(.failure(FlutterError(code: "null-error", message: "Flutter api returned null value for non-null return value.", details: ""))) + } else { + let result = listResponse[0] as! TestMessage + completion(.success(result)) + } } } } diff --git a/packages/pigeon/platform_tests/test_plugin/macos/Classes/TestPlugin.swift b/packages/pigeon/platform_tests/test_plugin/macos/Classes/TestPlugin.swift index a06f7a5fd10..3ed31b60d65 100644 --- a/packages/pigeon/platform_tests/test_plugin/macos/Classes/TestPlugin.swift +++ b/packages/pigeon/platform_tests/test_plugin/macos/Classes/TestPlugin.swift @@ -235,30 +235,57 @@ public class TestPlugin: NSObject, FlutterPlugin, HostIntegrationCoreApi { } func callFlutterNoop(completion: @escaping (Result) -> Void) { - flutterAPI.noop() { - completion(.success(Void())) + flutterAPI.noop() { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterThrowError(completion: @escaping (Result) -> Void) { - // TODO: (tarrinneal) Once flutter api error handling is added, enable these tests. - // See issue https://github.com/flutter/flutter/issues/118243 + flutterAPI.throwError() { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } + } } func callFlutterThrowErrorFromVoid(completion: @escaping (Result) -> Void) { - // TODO: (tarrinneal) Once flutter api error handling is added, enable these tests. - // See issue https://github.com/flutter/flutter/issues/118243 + flutterAPI.throwErrorFromVoid() { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } + } } func callFlutterEcho(_ everything: AllTypes, completion: @escaping (Result) -> Void) { - flutterAPI.echo(everything) { - completion(.success($0)) + flutterAPI.echo(everything) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ everything: AllNullableTypes?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(everything) { - completion(.success($0)) + flutterAPI.echoNullable(everything) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } @@ -272,104 +299,189 @@ public class TestPlugin: NSObject, FlutterPlugin, HostIntegrationCoreApi { aBool: aNullableBool, anInt: aNullableInt, aString: aNullableString - ) { - completion(.success($0)) + ) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aBool: Bool, completion: @escaping (Result) -> Void) { - flutterAPI.echo(aBool) { - completion(.success($0)) + flutterAPI.echo(aBool) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ anInt: Int64, completion: @escaping (Result) -> Void) { - flutterAPI.echo(anInt) { - completion(.success($0)) + flutterAPI.echo(anInt) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aDouble: Double, completion: @escaping (Result) -> Void) { - flutterAPI.echo(aDouble) { - completion(.success($0)) + flutterAPI.echo(aDouble) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aString: String, completion: @escaping (Result) -> Void) { - flutterAPI.echo(aString) { - completion(.success($0)) + flutterAPI.echo(aString) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aList: FlutterStandardTypedData, completion: @escaping (Result) -> Void) { - flutterAPI.echo(aList) { - completion(.success($0)) + flutterAPI.echo(aList) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aList: [Any?], completion: @escaping (Result<[Any?], Error>) -> Void) { - flutterAPI.echo(aList) { - completion(.success($0)) + flutterAPI.echo(aList) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ aMap: [String? : Any?], completion: @escaping (Result<[String? : Any?], Error>) -> Void) { - flutterAPI.echo(aMap) { - completion(.success($0)) + flutterAPI.echo(aMap) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEcho(_ anEnum: AnEnum, completion: @escaping (Result) -> Void) { - flutterAPI.echo(anEnum) { - completion(.success($0)) + flutterAPI.echo(anEnum) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aBool: Bool?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(aBool) { - completion(.success($0)) + flutterAPI.echoNullable(aBool) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ anInt: Int64?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(anInt) { - completion(.success($0)) + flutterAPI.echoNullable(anInt) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aDouble: Double?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(aDouble) { - completion(.success($0)) + flutterAPI.echoNullable(aDouble) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aString: String?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(aString) { - completion(.success($0)) + flutterAPI.echoNullable(aString) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aList: FlutterStandardTypedData?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(aList) { - completion(.success($0)) + flutterAPI.echoNullable(aList) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aList: [Any?]?, completion: @escaping (Result<[Any?]?, Error>) -> Void) { - flutterAPI.echoNullable(aList) { - completion(.success($0)) + flutterAPI.echoNullable(aList) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterEchoNullable(_ aMap: [String? : Any?]?, completion: @escaping (Result<[String? : Any?]?, Error>) -> Void) { - flutterAPI.echoNullable(aMap) { - completion(.success($0)) + flutterAPI.echoNullable(aMap) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } func callFlutterNullableEcho(_ anEnum: AnEnum?, completion: @escaping (Result) -> Void) { - flutterAPI.echoNullable(anEnum) { - completion(.success($0)) + flutterAPI.echoNullable(anEnum) { response in + switch response { + case .success(let res): + completion(.success(res)) + case .failure(let error): + completion(.failure(error)) + } } } } diff --git a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp index 3ef10d1f2d2..f4f557a664f 100644 --- a/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp +++ b/packages/pigeon/platform_tests/test_plugin/windows/pigeon/core_tests.gen.cpp @@ -3623,10 +3623,29 @@ void FlutterIntegrationCoreApi::Noop( "noop", &GetCodec()); EncodableValue encoded_api_arguments = EncodableValue(); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { on_success(); }); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + on_success(); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::ThrowError( @@ -3638,16 +3657,30 @@ void FlutterIntegrationCoreApi::ThrowError( "throwError", &GetCodec()); EncodableValue encoded_api_arguments = EncodableValue(); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* return_value = &encodable_return_value; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const auto* return_value = &list_return_value->at(0); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::ThrowErrorFromVoid( @@ -3659,10 +3692,29 @@ void FlutterIntegrationCoreApi::ThrowErrorFromVoid( "throwErrorFromVoid", &GetCodec()); EncodableValue encoded_api_arguments = EncodableValue(); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { on_success(); }); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + on_success(); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoAllTypes( @@ -3677,17 +3729,31 @@ void FlutterIntegrationCoreApi::EchoAllTypes( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ CustomEncodableValue(everything_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = std::any_cast( - std::get(encodable_return_value)); + std::get(list_return_value->at(0))); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoAllNullableTypes( @@ -3702,17 +3768,31 @@ void FlutterIntegrationCoreApi::EchoAllNullableTypes( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ everything_arg ? CustomEncodableValue(*everything_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto* return_value = &(std::any_cast( - std::get(encodable_return_value))); + std::get(list_return_value->at(0)))); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::SendMultipleNullableTypes( @@ -3733,17 +3813,31 @@ void FlutterIntegrationCoreApi::SendMultipleNullableTypes( a_nullable_string_arg ? EncodableValue(*a_nullable_string_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = std::any_cast( - std::get(encodable_return_value)); + std::get(list_return_value->at(0))); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoBool( @@ -3757,16 +3851,30 @@ void FlutterIntegrationCoreApi::EchoBool( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue(a_bool_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto& return_value = std::get(encodable_return_value); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const auto& return_value = std::get(list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoInt( @@ -3780,16 +3888,30 @@ void FlutterIntegrationCoreApi::EchoInt( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue(an_int_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const int64_t return_value = encodable_return_value.LongValue(); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const int64_t return_value = list_return_value->at(0).LongValue(); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoDouble( @@ -3803,16 +3925,30 @@ void FlutterIntegrationCoreApi::EchoDouble( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue(a_double_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto& return_value = std::get(encodable_return_value); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const auto& return_value = std::get(list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoString( @@ -3827,17 +3963,31 @@ void FlutterIntegrationCoreApi::EchoString( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue(a_string_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = - std::get(encodable_return_value); + std::get(list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoUint8List( @@ -3852,17 +4002,31 @@ void FlutterIntegrationCoreApi::EchoUint8List( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue(a_list_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = - std::get>(encodable_return_value); + std::get>(list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoList( @@ -3877,17 +4041,31 @@ void FlutterIntegrationCoreApi::EchoList( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue(a_list_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = - std::get(encodable_return_value); + std::get(list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoMap( @@ -3902,17 +4080,31 @@ void FlutterIntegrationCoreApi::EchoMap( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue(a_map_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = - std::get(encodable_return_value); + std::get(list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoEnum( @@ -3926,16 +4118,31 @@ void FlutterIntegrationCoreApi::EchoEnum( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue((int)an_enum_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const AnEnum& return_value = (AnEnum)encodable_return_value.LongValue(); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const AnEnum& return_value = + (AnEnum)list_return_value->at(0).LongValue(); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoNullableBool( @@ -3949,16 +4156,30 @@ void FlutterIntegrationCoreApi::EchoNullableBool( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ a_bool_arg ? EncodableValue(*a_bool_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* return_value = std::get_if(&encodable_return_value); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const auto* return_value = std::get_if(&list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoNullableInt( @@ -3972,21 +4193,35 @@ void FlutterIntegrationCoreApi::EchoNullableInt( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ an_int_arg ? EncodableValue(*an_int_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const int64_t return_value_value = - encodable_return_value.IsNull() + list_return_value->at(0).IsNull() ? 0 - : encodable_return_value.LongValue(); + : list_return_value->at(0).LongValue(); const auto* return_value = - encodable_return_value.IsNull() ? nullptr : &return_value_value; + list_return_value->at(0).IsNull() ? nullptr : &return_value_value; on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoNullableDouble( @@ -4000,16 +4235,31 @@ void FlutterIntegrationCoreApi::EchoNullableDouble( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ a_double_arg ? EncodableValue(*a_double_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; - const auto* return_value = std::get_if(&encodable_return_value); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const auto* return_value = + std::get_if(&list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoNullableString( @@ -4024,17 +4274,31 @@ void FlutterIntegrationCoreApi::EchoNullableString( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ a_string_arg ? EncodableValue(*a_string_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto* return_value = - std::get_if(&encodable_return_value); + std::get_if(&list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoNullableUint8List( @@ -4049,17 +4313,31 @@ void FlutterIntegrationCoreApi::EchoNullableUint8List( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ a_list_arg ? EncodableValue(*a_list_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto* return_value = - std::get_if>(&encodable_return_value); + std::get_if>(&list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoNullableList( @@ -4074,17 +4352,31 @@ void FlutterIntegrationCoreApi::EchoNullableList( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ a_list_arg ? EncodableValue(*a_list_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto* return_value = - std::get_if(&encodable_return_value); + std::get_if(&list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoNullableMap( @@ -4099,17 +4391,31 @@ void FlutterIntegrationCoreApi::EchoNullableMap( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ a_map_arg ? EncodableValue(*a_map_arg) : EncodableValue(), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto* return_value = - std::get_if(&encodable_return_value); + std::get_if(&list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoNullableEnum( @@ -4130,12 +4436,28 @@ void FlutterIntegrationCoreApi::EchoNullableEnum( std::unique_ptr response = GetCodec().DecodeMessage(reply, reply_size); const auto& encodable_return_value = *response; - const int64_t return_value_value = encodable_return_value.IsNull() - ? 0 - : encodable_return_value.LongValue(); - const auto* return_value = - encodable_return_value.IsNull() ? nullptr : &(AnEnum)return_value_value; - on_success(return_value); + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + const int64_t return_value_value = + list_return_value->at(0).IsNull() + ? 0 + : list_return_value->at(0).LongValue(); + const AnEnum enum_return_value = (AnEnum)return_value_value; + const auto* return_value = + list_return_value->at(0).IsNull() ? nullptr : &enum_return_value; + on_success(return_value); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } }); } @@ -4148,10 +4470,29 @@ void FlutterIntegrationCoreApi::NoopAsync( "noopAsync", &GetCodec()); EncodableValue encoded_api_arguments = EncodableValue(); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { on_success(); }); + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { + on_success(); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } void FlutterIntegrationCoreApi::EchoAsyncString( @@ -4166,17 +4507,31 @@ void FlutterIntegrationCoreApi::EchoAsyncString( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ EncodableValue(a_string_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = - std::get(encodable_return_value); + std::get(list_return_value->at(0)); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } /// The codec used by HostTrivialApi. @@ -4367,17 +4722,31 @@ void FlutterSmallApi::EchoWrappedList( EncodableValue encoded_api_arguments = EncodableValue(EncodableList{ CustomEncodableValue(msg_arg), }); - channel->Send( - encoded_api_arguments, - [on_success = std::move(on_success), on_error = std::move(on_error)]( - const uint8_t* reply, size_t reply_size) { - std::unique_ptr response = - GetCodec().DecodeMessage(reply, reply_size); - const auto& encodable_return_value = *response; + channel->Send(encoded_api_arguments, [on_success = std::move(on_success), + on_error = std::move(on_error)]( + const uint8_t* reply, + size_t reply_size) { + std::unique_ptr response = + GetCodec().DecodeMessage(reply, reply_size); + const auto& encodable_return_value = *response; + const auto* list_return_value = + std::get_if(&encodable_return_value); + if (list_return_value) { + if (list_return_value->size() > 1) { + on_error(FlutterError(std::get(list_return_value->at(0)), + std::get(list_return_value->at(1)), + list_return_value->at(2))); + } else { const auto& return_value = std::any_cast( - std::get(encodable_return_value)); + std::get(list_return_value->at(0))); on_success(return_value); - }); + } + } else { + on_error(FlutterError("channel-error", + "Unable to establish connection on channel.", + EncodableValue(""))); + } + }); } } // namespace core_tests_pigeontest diff --git a/packages/pigeon/pubspec.yaml b/packages/pigeon/pubspec.yaml index 1abcc471673..98b0fa577a5 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%3Apigeon -version: 11.0.1 # This must match the version in lib/generator_tools.dart +version: 12.0.0 # This must match the version in lib/generator_tools.dart environment: sdk: ">=2.19.0 <4.0.0" diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index d74bdc383d0..5ca7ef73e4b 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -694,7 +694,7 @@ void main() { expect(testCode, contains('abstract class ApiMock')); expect(testCode, isNot(contains('.ApiMock.doSomething'))); expect(testCode, contains('output')); - expect(testCode, contains('return [];')); + expect(testCode, contains('return [output];')); }); test('gen one async Flutter Api', () { diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index bc6c8f12ceb..4a36acec6db 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -371,8 +371,11 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('Reply')); - expect(code, contains('callback.reply(null)')); + expect( + code, + contains( + 'public void doSomething(@NonNull Input arg0Arg, @NonNull Result result)')); + expect(code, contains('result.success(null);')); }); test('gen host void argument api', () { @@ -439,7 +442,8 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('doSomething(@NonNull Reply')); + expect(code, + contains('public void doSomething(@NonNull Result result)')); expect(code, contains(RegExp(r'channel.send\(\s*null'))); }); @@ -955,8 +959,9 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('doit(@NonNull Reply> callback)')); - expect(code, contains('List output =')); + expect( + code, contains('public void doit(@NonNull Result> result)')); + expect(code, contains('List output = (List) listReply.get(0)')); }); test('flutter int return', () { @@ -984,11 +989,11 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('doit(@NonNull Reply callback)')); + expect(code, contains('public void doit(@NonNull Result result)')); expect( code, contains( - 'Long output = channelReply == null ? null : ((Number) channelReply).longValue();')); + 'Long output = listReply.get(0) == null ? null : ((Number) listReply.get(0)).longValue();')); }); test('host multiple args', () { @@ -1095,7 +1100,7 @@ void main() { expect( code, contains( - 'public void add(@NonNull Long xArg, @NonNull Long yArg, @NonNull Reply callback)')); + 'public void add(@NonNull Long xArg, @NonNull Long yArg, @NonNull Result result)')); expect( code, contains(RegExp( @@ -1259,7 +1264,7 @@ void main() { expect( code, contains( - 'public void doit(@Nullable Long fooArg, @NonNull Reply callback) {')); + 'public void doit(@Nullable Long fooArg, @NonNull Result result) {')); }); test('background platform channel', () { diff --git a/packages/pigeon/test/kotlin_generator_test.dart b/packages/pigeon/test/kotlin_generator_test.dart index b2e9d65f333..596b25b51fa 100644 --- a/packages/pigeon/test/kotlin_generator_test.dart +++ b/packages/pigeon/test/kotlin_generator_test.dart @@ -516,8 +516,8 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('callback: () -> Unit')); - expect(code, contains('callback()')); + expect(code, contains('callback: (Result) -> Unit')); + expect(code, contains('callback(Result.success(Unit))')); }); test('gen host void argument api', () { @@ -588,7 +588,8 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('fun doSomething(callback: (Output) -> Unit)')); + expect( + code, contains('fun doSomething(callback: (Result) -> Unit)')); expect(code, contains('channel.send(null)')); }); @@ -1064,9 +1065,9 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('fun doit(callback: (List) -> Unit')); - expect(code, contains('val result = it as List')); - expect(code, contains('callback(result)')); + expect(code, contains('fun doit(callback: (Result>) -> Unit)')); + expect(code, contains('val output = it[0] as List')); + expect(code, contains('callback(Result.success(output))')); }); test('host multiple args', () { @@ -1142,11 +1143,16 @@ void main() { ); final String code = sink.toString(); expect(code, contains('val channel = BasicMessageChannel')); - expect(code, - contains('val result = if (it is Int) it.toLong() else it as Long')); - expect(code, contains('callback(result)')); - expect(code, - contains('fun add(xArg: Long, yArg: Long, callback: (Long) -> Unit)')); + expect( + code, + contains( + 'val output = it[0].let { if (it is Int) it.toLong() else it as Long }'), + ); + expect(code, contains('callback(Result.success(output))')); + expect( + code, + contains( + 'fun add(xArg: Long, yArg: Long, callback: (Result) -> Unit)')); expect(code, contains('channel.send(listOf(xArg, yArg)) {')); }); @@ -1275,7 +1281,10 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('fun doit(fooArg: Long?, callback: () -> Unit')); + expect( + code, + contains('fun doit(fooArg: Long?, callback: (Result) -> Unit)'), + ); }); test('nonnull fields', () { diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index d6c1f5cfa48..aa506eb714f 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -168,7 +168,7 @@ void main() { expect( code, contains( - 'Enum1Box *enum1 = enum1AsNumber == nil ? nil : [[Enum1Box alloc] initWithValue: [enum1AsNumber integerValue]];')); + 'Enum1Box *enum1 = enum1AsNumber == nil ? nil : [[Enum1Box alloc] initWithValue:[enum1AsNumber integerValue]];')); }); test('primitive enum host', () { @@ -347,7 +347,7 @@ void main() { expect(code, contains('@protocol Api')); expect(code, contains('/// @return `nil` only when `error != nil`.')); expect(code, matches('nullable Output.*doSomething.*Input.*FlutterError')); - expect(code, matches('ApiSetup.*.*_Nullable')); + expect(code, matches('SetUpApi.*.*_Nullable')); expect(code, contains('ApiGetCodec(void)')); }); @@ -396,7 +396,7 @@ void main() { expect(code, contains('#import "foo.h"')); expect(code, contains('@implementation Input')); expect(code, contains('@implementation Output')); - expect(code, contains('ApiSetup(')); + expect(code, contains('SetUpApi(')); expect( code, contains( @@ -703,7 +703,7 @@ void main() { final String code = sink.toString(); expect(code, contains('ABCInput fromList')); expect(code, matches(r'ABCInput.*=.*args.*0.*\;')); - expect(code, contains('void ABCApiSetup(')); + expect(code, contains('void SetUpABCApi(')); }); test('gen flutter api header', () { diff --git a/packages/pigeon/test/swift_generator_test.dart b/packages/pigeon/test/swift_generator_test.dart index cd46023b5dc..9453b8577f9 100644 --- a/packages/pigeon/test/swift_generator_test.dart +++ b/packages/pigeon/test/swift_generator_test.dart @@ -353,8 +353,9 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, contains('completion: @escaping () -> Void')); - expect(code, contains('completion()')); + expect(code, + contains('completion: @escaping (Result) -> Void')); + expect(code, contains('completion(.success(Void()))')); }); test('gen host void argument api', () { @@ -422,8 +423,10 @@ void main() { dartPackageName: DEFAULT_PACKAGE_NAME, ); final String code = sink.toString(); - expect(code, - contains('func doSomething(completion: @escaping (Output) -> Void)')); + expect( + code, + contains( + 'func doSomething(completion: @escaping (Result) -> Void)')); expect(code, contains('channel.sendMessage(nil')); }); @@ -883,9 +886,11 @@ void main() { ); final String code = sink.toString(); expect( - code, contains('func doit(completion: @escaping ([Int64?]) -> Void')); - expect(code, contains('let result = response as! [Int64?]')); - expect(code, contains('completion(result)')); + code, + contains( + 'func doit(completion: @escaping (Result<[Int64?], FlutterError>) -> Void)')); + expect(code, contains('let result = listResponse[0] as! [Int64?]')); + expect(code, contains('completion(.success(result))')); }); test('host multiple args', () { @@ -964,12 +969,12 @@ void main() { expect( code, contains( - 'let result = response is Int64 ? response as! Int64 : Int64(response as! Int32)')); - expect(code, contains('completion(result)')); + 'let result = listResponse[0] is Int64 ? listResponse[0] as! Int64 : Int64(listResponse[0] as! Int32)')); + expect(code, contains('completion(.success(result))')); expect( code, contains( - 'func add(x xArg: Int64, y yArg: Int64, completion: @escaping (Int64) -> Void)')); + 'func add(x xArg: Int64, y yArg: Int64, completion: @escaping (Result) -> Void)')); expect(code, contains('channel.sendMessage([xArg, yArg] as [Any?]) { response in')); }); @@ -1105,7 +1110,7 @@ void main() { expect( code, contains( - 'func doit(foo fooArg: Int64?, completion: @escaping () -> Void')); + 'func doit(foo fooArg: Int64?, completion: @escaping (Result) -> Void)')); }); test('nonnull fields', () {