mirror of
https://github.com/flutter/packages.git
synced 2025-07-01 23:51:55 +08:00
[pigeon] add flutter api protocol (#5181)
Protocols to make testing with mocks easier. Fixes https://github.com/flutter/flutter/issues/136811
This commit is contained in:
@ -1,3 +1,7 @@
|
|||||||
|
## 12.0.1
|
||||||
|
|
||||||
|
* [swift] Adds protocol for Flutter APIs.
|
||||||
|
|
||||||
## 12.0.0
|
## 12.0.0
|
||||||
|
|
||||||
* Adds error handling on Flutter API methods.
|
* Adds error handling on Flutter API methods.
|
||||||
|
@ -173,8 +173,11 @@ class ExampleHostApiSetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Generated class from Pigeon that represents Flutter messages that can be called from Swift.
|
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||||
class MessageFlutterApi {
|
protocol MessageFlutterApiProtocol {
|
||||||
|
func flutterMethod(aString aStringArg: String?, completion: @escaping (Result<String, FlutterError>) -> Void)
|
||||||
|
}
|
||||||
|
class MessageFlutterApi: MessageFlutterApiProtocol {
|
||||||
private let binaryMessenger: FlutterBinaryMessenger
|
private let binaryMessenger: FlutterBinaryMessenger
|
||||||
init(binaryMessenger: FlutterBinaryMessenger){
|
init(binaryMessenger: FlutterBinaryMessenger){
|
||||||
self.binaryMessenger = binaryMessenger
|
self.binaryMessenger = binaryMessenger
|
||||||
|
@ -13,7 +13,7 @@ import 'ast.dart';
|
|||||||
/// The current version of pigeon.
|
/// The current version of pigeon.
|
||||||
///
|
///
|
||||||
/// This must match the version in pubspec.yaml.
|
/// This must match the version in pubspec.yaml.
|
||||||
const String pigeonVersion = '12.0.0';
|
const String pigeonVersion = '12.0.1';
|
||||||
|
|
||||||
/// Read all the content from [stdin] to a String.
|
/// Read all the content from [stdin] to a String.
|
||||||
String readStdin() {
|
String readStdin() {
|
||||||
|
@ -291,13 +291,22 @@ import FlutterMacOS
|
|||||||
if (isCustomCodec) {
|
if (isCustomCodec) {
|
||||||
_writeCodec(indent, api, root);
|
_writeCodec(indent, api, root);
|
||||||
}
|
}
|
||||||
|
|
||||||
const List<String> generatedComments = <String>[
|
const List<String> generatedComments = <String>[
|
||||||
' Generated class from Pigeon that represents Flutter messages that can be called from Swift.'
|
' Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.'
|
||||||
];
|
];
|
||||||
addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
|
addDocumentationComments(indent, api.documentationComments, _docCommentSpec,
|
||||||
generatorComments: generatedComments);
|
generatorComments: generatedComments);
|
||||||
|
|
||||||
indent.write('class ${api.name} ');
|
indent.addScoped('protocol ${api.name}Protocol {', '}', () {
|
||||||
|
for (final Method func in api.methods) {
|
||||||
|
addDocumentationComments(
|
||||||
|
indent, func.documentationComments, _docCommentSpec);
|
||||||
|
indent.writeln(_getMethodSignature(func));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
indent.write('class ${api.name}: ${api.name}Protocol ');
|
||||||
indent.addScoped('{', '}', () {
|
indent.addScoped('{', '}', () {
|
||||||
indent.writeln('private let binaryMessenger: FlutterBinaryMessenger');
|
indent.writeln('private let binaryMessenger: FlutterBinaryMessenger');
|
||||||
indent.write('init(binaryMessenger: FlutterBinaryMessenger)');
|
indent.write('init(binaryMessenger: FlutterBinaryMessenger)');
|
||||||
@ -314,47 +323,19 @@ import FlutterMacOS
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (final Method func in api.methods) {
|
for (final Method func in api.methods) {
|
||||||
final _SwiftFunctionComponents components =
|
|
||||||
_SwiftFunctionComponents.fromMethod(func);
|
|
||||||
|
|
||||||
final String channelName = makeChannelName(api, func, dartPackageName);
|
final String channelName = makeChannelName(api, func, dartPackageName);
|
||||||
final String returnType = func.returnType.isVoid
|
|
||||||
? 'Void'
|
|
||||||
: _nullsafeSwiftTypeForDartType(func.returnType);
|
|
||||||
String sendArgument;
|
|
||||||
addDocumentationComments(
|
addDocumentationComments(
|
||||||
indent, func.documentationComments, _docCommentSpec);
|
indent, func.documentationComments, _docCommentSpec);
|
||||||
|
indent.writeScoped('${_getMethodSignature(func)} {', '}', () {
|
||||||
if (func.arguments.isEmpty) {
|
|
||||||
indent.write(
|
|
||||||
'func ${func.name}(completion: @escaping (Result<$returnType, FlutterError>) -> Void) ');
|
|
||||||
sendArgument = 'nil';
|
|
||||||
} else {
|
|
||||||
final Iterable<String> argTypes = func.arguments
|
|
||||||
.map((NamedType e) => _nullsafeSwiftTypeForDartType(e.type));
|
|
||||||
final Iterable<String> argLabels = indexMap(components.arguments,
|
|
||||||
(int index, _SwiftFunctionArgument argument) {
|
|
||||||
return argument.label ??
|
|
||||||
_getArgumentName(index, argument.namedType);
|
|
||||||
});
|
|
||||||
final Iterable<String> argNames =
|
|
||||||
indexMap(func.arguments, _getSafeArgumentName);
|
|
||||||
final Iterable<String> enumSafeArgNames = func.arguments
|
final Iterable<String> enumSafeArgNames = func.arguments
|
||||||
.asMap()
|
.asMap()
|
||||||
.entries
|
.entries
|
||||||
.map((MapEntry<int, NamedType> e) =>
|
.map((MapEntry<int, NamedType> e) =>
|
||||||
getEnumSafeArgumentExpression(root, e.key, e.value));
|
getEnumSafeArgumentExpression(root, e.key, e.value));
|
||||||
sendArgument = '[${enumSafeArgNames.join(', ')}] as [Any?]';
|
final String sendArgument = func.arguments.isEmpty
|
||||||
final String argsSignature = map3(
|
? 'nil'
|
||||||
argTypes,
|
: '[${enumSafeArgNames.join(', ')}] as [Any?]';
|
||||||
argLabels,
|
|
||||||
argNames,
|
|
||||||
(String type, String label, String name) =>
|
|
||||||
'$label $name: $type').join(', ');
|
|
||||||
indent.write(
|
|
||||||
'func ${components.name}($argsSignature, completion: @escaping (Result<$returnType, FlutterError>) -> Void) ');
|
|
||||||
}
|
|
||||||
indent.addScoped('{', '}', () {
|
|
||||||
const String channel = 'channel';
|
const String channel = 'channel';
|
||||||
indent.writeln(
|
indent.writeln(
|
||||||
'let $channel = FlutterBasicMessageChannel(name: "$channelName", binaryMessenger: binaryMessenger$codecArgumentString)');
|
'let $channel = FlutterBasicMessageChannel(name: "$channelName", binaryMessenger: binaryMessenger$codecArgumentString)');
|
||||||
@ -893,6 +874,31 @@ String _nullsafeSwiftTypeForDartType(TypeDeclaration type) {
|
|||||||
return '${_swiftTypeForDartType(type)}$nullSafe';
|
return '${_swiftTypeForDartType(type)}$nullSafe';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _getMethodSignature(Method func) {
|
||||||
|
final _SwiftFunctionComponents components =
|
||||||
|
_SwiftFunctionComponents.fromMethod(func);
|
||||||
|
final String returnType = func.returnType.isVoid
|
||||||
|
? 'Void'
|
||||||
|
: _nullsafeSwiftTypeForDartType(func.returnType);
|
||||||
|
|
||||||
|
if (func.arguments.isEmpty) {
|
||||||
|
return 'func ${func.name}(completion: @escaping (Result<$returnType, FlutterError>) -> Void) ';
|
||||||
|
} else {
|
||||||
|
final Iterable<String> argTypes = func.arguments
|
||||||
|
.map((NamedType e) => _nullsafeSwiftTypeForDartType(e.type));
|
||||||
|
final Iterable<String> argLabels = indexMap(components.arguments,
|
||||||
|
(int index, _SwiftFunctionArgument argument) {
|
||||||
|
return argument.label ?? _getArgumentName(index, argument.namedType);
|
||||||
|
});
|
||||||
|
final Iterable<String> argNames =
|
||||||
|
indexMap(func.arguments, _getSafeArgumentName);
|
||||||
|
final String argsSignature = map3(argTypes, argLabels, argNames,
|
||||||
|
(String type, String label, String name) => '$label $name: $type')
|
||||||
|
.join(', ');
|
||||||
|
return 'func ${components.name}($argsSignature, completion: @escaping (Result<$returnType, FlutterError>) -> Void) ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A class that represents a Swift function argument.
|
/// A class that represents a Swift function argument.
|
||||||
///
|
///
|
||||||
/// The [name] is the name of the argument.
|
/// The [name] is the name of the argument.
|
||||||
|
@ -661,6 +661,10 @@ abstract class FlutterSmallApi {
|
|||||||
@ObjCSelector('echoWrappedList:')
|
@ObjCSelector('echoWrappedList:')
|
||||||
@SwiftFunction('echo(_:)')
|
@SwiftFunction('echo(_:)')
|
||||||
TestMessage echoWrappedList(TestMessage msg);
|
TestMessage echoWrappedList(TestMessage msg);
|
||||||
|
|
||||||
|
@ObjCSelector('echoString:')
|
||||||
|
@SwiftFunction('echo(_:)')
|
||||||
|
String echoString(String aString);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A data class containing a List, used in unit tests.
|
/// A data class containing a List, used in unit tests.
|
||||||
|
@ -4390,5 +4390,41 @@ public class CoreTests {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void echoString(@NonNull String aStringArg, @NonNull Result<String> result) {
|
||||||
|
BasicMessageChannel<Object> channel =
|
||||||
|
new BasicMessageChannel<>(
|
||||||
|
binaryMessenger,
|
||||||
|
"dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString",
|
||||||
|
getCodec());
|
||||||
|
channel.send(
|
||||||
|
new ArrayList<Object>(Collections.singletonList(aStringArg)),
|
||||||
|
channelReply -> {
|
||||||
|
if (channelReply instanceof List) {
|
||||||
|
List<Object> listReply = (List<Object>) 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.", ""));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -494,6 +494,8 @@ NSObject<FlutterMessageCodec> *FlutterSmallApiGetCodec(void);
|
|||||||
- (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger;
|
- (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger;
|
||||||
- (void)echoWrappedList:(TestMessage *)msg
|
- (void)echoWrappedList:(TestMessage *)msg
|
||||||
completion:(void (^)(TestMessage *_Nullable, FlutterError *_Nullable))completion;
|
completion:(void (^)(TestMessage *_Nullable, FlutterError *_Nullable))completion;
|
||||||
|
- (void)echoString:(NSString *)aString
|
||||||
|
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
@ -2971,4 +2971,30 @@ NSObject<FlutterMessageCodec> *FlutterSmallApiGetCodec(void) {
|
|||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
- (void)echoString:(NSString *)arg_aString
|
||||||
|
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion {
|
||||||
|
FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
|
||||||
|
messageChannelWithName:
|
||||||
|
@"dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString"
|
||||||
|
binaryMessenger:self.binaryMessenger
|
||||||
|
codec:FlutterSmallApiGetCodec()];
|
||||||
|
[channel sendMessage:@[ arg_aString ?: [NSNull null] ]
|
||||||
|
reply:^(NSArray<id> *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
|
@end
|
||||||
|
@ -494,6 +494,8 @@ NSObject<FlutterMessageCodec> *FlutterSmallApiGetCodec(void);
|
|||||||
- (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger;
|
- (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger;
|
||||||
- (void)echoWrappedList:(TestMessage *)msg
|
- (void)echoWrappedList:(TestMessage *)msg
|
||||||
completion:(void (^)(TestMessage *_Nullable, FlutterError *_Nullable))completion;
|
completion:(void (^)(TestMessage *_Nullable, FlutterError *_Nullable))completion;
|
||||||
|
- (void)echoString:(NSString *)aString
|
||||||
|
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
NS_ASSUME_NONNULL_END
|
||||||
|
@ -2971,4 +2971,30 @@ NSObject<FlutterMessageCodec> *FlutterSmallApiGetCodec(void) {
|
|||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
- (void)echoString:(NSString *)arg_aString
|
||||||
|
completion:(void (^)(NSString *_Nullable, FlutterError *_Nullable))completion {
|
||||||
|
FlutterBasicMessageChannel *channel = [FlutterBasicMessageChannel
|
||||||
|
messageChannelWithName:
|
||||||
|
@"dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString"
|
||||||
|
binaryMessenger:self.binaryMessenger
|
||||||
|
codec:FlutterSmallApiGetCodec()];
|
||||||
|
[channel sendMessage:@[ arg_aString ?: [NSNull null] ]
|
||||||
|
reply:^(NSArray<id> *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
|
@end
|
||||||
|
@ -3120,6 +3120,8 @@ abstract class FlutterSmallApi {
|
|||||||
|
|
||||||
TestMessage echoWrappedList(TestMessage msg);
|
TestMessage echoWrappedList(TestMessage msg);
|
||||||
|
|
||||||
|
String echoString(String aString);
|
||||||
|
|
||||||
static void setup(FlutterSmallApi? api, {BinaryMessenger? binaryMessenger}) {
|
static void setup(FlutterSmallApi? api, {BinaryMessenger? binaryMessenger}) {
|
||||||
{
|
{
|
||||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
@ -3148,5 +3150,32 @@ abstract class FlutterSmallApi {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||||
|
'dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString',
|
||||||
|
codec,
|
||||||
|
binaryMessenger: binaryMessenger);
|
||||||
|
if (api == null) {
|
||||||
|
channel.setMessageHandler(null);
|
||||||
|
} else {
|
||||||
|
channel.setMessageHandler((Object? message) async {
|
||||||
|
assert(message != null,
|
||||||
|
'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString was null.');
|
||||||
|
final List<Object?> args = (message as List<Object?>?)!;
|
||||||
|
final String? arg_aString = (args[0] as String?);
|
||||||
|
assert(arg_aString != null,
|
||||||
|
'Argument for dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString was null, expected non-null String.');
|
||||||
|
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()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2479,4 +2479,21 @@ class FlutterSmallApi(private val binaryMessenger: BinaryMessenger) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fun echoString(aStringArg: String, callback: (Result<String>) -> Unit) {
|
||||||
|
val channel = BasicMessageChannel<Any?>(binaryMessenger, "dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString", codec)
|
||||||
|
channel.send(listOf(aStringArg)) {
|
||||||
|
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.", "")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
import Flutter
|
||||||
|
import Foundation
|
||||||
import XCTest
|
import XCTest
|
||||||
|
|
||||||
@testable import test_plugin
|
@testable import test_plugin
|
||||||
|
|
||||||
class RunnerTests: XCTestCase {
|
class RunnerTests: XCTestCase {
|
||||||
@ -27,4 +30,32 @@ class RunnerTests: XCTestCase {
|
|||||||
let copy = MessageSearchReply.fromList(dict)
|
let copy = MessageSearchReply.fromList(dict)
|
||||||
XCTAssertEqual(reply.error, copy?.error)
|
XCTAssertEqual(reply.error, copy?.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This validates that pigeon clients can easily write tests that mock out Flutter API
|
||||||
|
/// calls using a pigeon-generated protocol.
|
||||||
|
func testEchoStringFromProtocol() throws {
|
||||||
|
let api: FlutterApiFromProtocol = FlutterApiFromProtocol()
|
||||||
|
let aString = "aString"
|
||||||
|
api.echo(aString) { response in
|
||||||
|
switch response {
|
||||||
|
case .success(let res):
|
||||||
|
XCTAssertEqual(aString, res)
|
||||||
|
case .failure(let error):
|
||||||
|
XCTFail(error.code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FlutterApiFromProtocol: FlutterSmallApiProtocol {
|
||||||
|
func echo(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void) {
|
||||||
|
completion(.success(aStringArg))
|
||||||
|
}
|
||||||
|
|
||||||
|
func echo(
|
||||||
|
_ msgArg: test_plugin.TestMessage,
|
||||||
|
completion: @escaping (Result<test_plugin.TestMessage, FlutterError>) -> Void
|
||||||
|
) {
|
||||||
|
completion(.success(msgArg))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1739,8 +1739,62 @@ class FlutterIntegrationCoreApiCodec: FlutterStandardMessageCodec {
|
|||||||
/// The core interface that the Dart platform_test code implements for host
|
/// The core interface that the Dart platform_test code implements for host
|
||||||
/// integration tests to call into.
|
/// integration tests to call into.
|
||||||
///
|
///
|
||||||
/// Generated class from Pigeon that represents Flutter messages that can be called from Swift.
|
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||||
class FlutterIntegrationCoreApi {
|
protocol FlutterIntegrationCoreApiProtocol {
|
||||||
|
/// A no-op function taking no arguments and returning no value, to sanity
|
||||||
|
/// test basic calling.
|
||||||
|
func noop(completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||||
|
/// Responds with an error from an async function returning a value.
|
||||||
|
func throwError(completion: @escaping (Result<Any?, FlutterError>) -> Void)
|
||||||
|
/// Responds with an error from an async void function.
|
||||||
|
func throwErrorFromVoid(completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed object, to test serialization and deserialization.
|
||||||
|
func echo(_ everythingArg: AllTypes, completion: @escaping (Result<AllTypes, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed object, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ everythingArg: AllNullableTypes?, completion: @escaping (Result<AllNullableTypes?, FlutterError>) -> Void)
|
||||||
|
/// 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 (Result<AllNullableTypes, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed boolean, to test serialization and deserialization.
|
||||||
|
func echo(_ aBoolArg: Bool, completion: @escaping (Result<Bool, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed int, to test serialization and deserialization.
|
||||||
|
func echo(_ anIntArg: Int64, completion: @escaping (Result<Int64, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed double, to test serialization and deserialization.
|
||||||
|
func echo(_ aDoubleArg: Double, completion: @escaping (Result<Double, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed string, to test serialization and deserialization.
|
||||||
|
func echo(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed byte list, to test serialization and deserialization.
|
||||||
|
func echo(_ aListArg: FlutterStandardTypedData, completion: @escaping (Result<FlutterStandardTypedData, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed list, to test serialization and deserialization.
|
||||||
|
func echo(_ aListArg: [Any?], completion: @escaping (Result<[Any?], FlutterError>) -> Void)
|
||||||
|
/// Returns the passed map, to test serialization and deserialization.
|
||||||
|
func echo(_ aMapArg: [String?: Any?], completion: @escaping (Result<[String?: Any?], FlutterError>) -> Void)
|
||||||
|
/// Returns the passed enum to test serialization and deserialization.
|
||||||
|
func echo(_ anEnumArg: AnEnum, completion: @escaping (Result<AnEnum, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed boolean, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aBoolArg: Bool?, completion: @escaping (Result<Bool?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed int, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ anIntArg: Int64?, completion: @escaping (Result<Int64?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed double, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aDoubleArg: Double?, completion: @escaping (Result<Double?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed string, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aStringArg: String?, completion: @escaping (Result<String?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed byte list, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aListArg: FlutterStandardTypedData?, completion: @escaping (Result<FlutterStandardTypedData?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed list, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aListArg: [Any?]?, completion: @escaping (Result<[Any?]?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed map, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aMapArg: [String?: Any?]?, completion: @escaping (Result<[String?: Any?]?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed enum to test serialization and deserialization.
|
||||||
|
func echoNullable(_ anEnumArg: AnEnum?, completion: @escaping (Result<AnEnum?, FlutterError>) -> Void)
|
||||||
|
/// A no-op function taking no arguments and returning no value, to sanity
|
||||||
|
/// test basic asynchronous calling.
|
||||||
|
func noopAsync(completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed in generic Object asynchronously.
|
||||||
|
func echoAsync(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void)
|
||||||
|
}
|
||||||
|
class FlutterIntegrationCoreApi: FlutterIntegrationCoreApiProtocol {
|
||||||
private let binaryMessenger: FlutterBinaryMessenger
|
private let binaryMessenger: FlutterBinaryMessenger
|
||||||
init(binaryMessenger: FlutterBinaryMessenger){
|
init(binaryMessenger: FlutterBinaryMessenger){
|
||||||
self.binaryMessenger = binaryMessenger
|
self.binaryMessenger = binaryMessenger
|
||||||
@ -2307,8 +2361,12 @@ class FlutterSmallApiCodec: FlutterStandardMessageCodec {
|
|||||||
|
|
||||||
/// A simple API called in some unit tests.
|
/// A simple API called in some unit tests.
|
||||||
///
|
///
|
||||||
/// Generated class from Pigeon that represents Flutter messages that can be called from Swift.
|
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||||
class FlutterSmallApi {
|
protocol FlutterSmallApiProtocol {
|
||||||
|
func echo(_ msgArg: TestMessage, completion: @escaping (Result<TestMessage, FlutterError>) -> Void)
|
||||||
|
func echo(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void)
|
||||||
|
}
|
||||||
|
class FlutterSmallApi: FlutterSmallApiProtocol {
|
||||||
private let binaryMessenger: FlutterBinaryMessenger
|
private let binaryMessenger: FlutterBinaryMessenger
|
||||||
init(binaryMessenger: FlutterBinaryMessenger){
|
init(binaryMessenger: FlutterBinaryMessenger){
|
||||||
self.binaryMessenger = binaryMessenger
|
self.binaryMessenger = binaryMessenger
|
||||||
@ -2336,4 +2394,24 @@ class FlutterSmallApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func echo(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void) {
|
||||||
|
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString", binaryMessenger: binaryMessenger, codec: codec)
|
||||||
|
channel.sendMessage([aStringArg] as [Any?]) { response in
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1739,8 +1739,62 @@ class FlutterIntegrationCoreApiCodec: FlutterStandardMessageCodec {
|
|||||||
/// The core interface that the Dart platform_test code implements for host
|
/// The core interface that the Dart platform_test code implements for host
|
||||||
/// integration tests to call into.
|
/// integration tests to call into.
|
||||||
///
|
///
|
||||||
/// Generated class from Pigeon that represents Flutter messages that can be called from Swift.
|
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||||
class FlutterIntegrationCoreApi {
|
protocol FlutterIntegrationCoreApiProtocol {
|
||||||
|
/// A no-op function taking no arguments and returning no value, to sanity
|
||||||
|
/// test basic calling.
|
||||||
|
func noop(completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||||
|
/// Responds with an error from an async function returning a value.
|
||||||
|
func throwError(completion: @escaping (Result<Any?, FlutterError>) -> Void)
|
||||||
|
/// Responds with an error from an async void function.
|
||||||
|
func throwErrorFromVoid(completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed object, to test serialization and deserialization.
|
||||||
|
func echo(_ everythingArg: AllTypes, completion: @escaping (Result<AllTypes, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed object, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ everythingArg: AllNullableTypes?, completion: @escaping (Result<AllNullableTypes?, FlutterError>) -> Void)
|
||||||
|
/// 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 (Result<AllNullableTypes, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed boolean, to test serialization and deserialization.
|
||||||
|
func echo(_ aBoolArg: Bool, completion: @escaping (Result<Bool, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed int, to test serialization and deserialization.
|
||||||
|
func echo(_ anIntArg: Int64, completion: @escaping (Result<Int64, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed double, to test serialization and deserialization.
|
||||||
|
func echo(_ aDoubleArg: Double, completion: @escaping (Result<Double, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed string, to test serialization and deserialization.
|
||||||
|
func echo(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed byte list, to test serialization and deserialization.
|
||||||
|
func echo(_ aListArg: FlutterStandardTypedData, completion: @escaping (Result<FlutterStandardTypedData, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed list, to test serialization and deserialization.
|
||||||
|
func echo(_ aListArg: [Any?], completion: @escaping (Result<[Any?], FlutterError>) -> Void)
|
||||||
|
/// Returns the passed map, to test serialization and deserialization.
|
||||||
|
func echo(_ aMapArg: [String?: Any?], completion: @escaping (Result<[String?: Any?], FlutterError>) -> Void)
|
||||||
|
/// Returns the passed enum to test serialization and deserialization.
|
||||||
|
func echo(_ anEnumArg: AnEnum, completion: @escaping (Result<AnEnum, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed boolean, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aBoolArg: Bool?, completion: @escaping (Result<Bool?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed int, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ anIntArg: Int64?, completion: @escaping (Result<Int64?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed double, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aDoubleArg: Double?, completion: @escaping (Result<Double?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed string, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aStringArg: String?, completion: @escaping (Result<String?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed byte list, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aListArg: FlutterStandardTypedData?, completion: @escaping (Result<FlutterStandardTypedData?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed list, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aListArg: [Any?]?, completion: @escaping (Result<[Any?]?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed map, to test serialization and deserialization.
|
||||||
|
func echoNullable(_ aMapArg: [String?: Any?]?, completion: @escaping (Result<[String?: Any?]?, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed enum to test serialization and deserialization.
|
||||||
|
func echoNullable(_ anEnumArg: AnEnum?, completion: @escaping (Result<AnEnum?, FlutterError>) -> Void)
|
||||||
|
/// A no-op function taking no arguments and returning no value, to sanity
|
||||||
|
/// test basic asynchronous calling.
|
||||||
|
func noopAsync(completion: @escaping (Result<Void, FlutterError>) -> Void)
|
||||||
|
/// Returns the passed in generic Object asynchronously.
|
||||||
|
func echoAsync(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void)
|
||||||
|
}
|
||||||
|
class FlutterIntegrationCoreApi: FlutterIntegrationCoreApiProtocol {
|
||||||
private let binaryMessenger: FlutterBinaryMessenger
|
private let binaryMessenger: FlutterBinaryMessenger
|
||||||
init(binaryMessenger: FlutterBinaryMessenger){
|
init(binaryMessenger: FlutterBinaryMessenger){
|
||||||
self.binaryMessenger = binaryMessenger
|
self.binaryMessenger = binaryMessenger
|
||||||
@ -2307,8 +2361,12 @@ class FlutterSmallApiCodec: FlutterStandardMessageCodec {
|
|||||||
|
|
||||||
/// A simple API called in some unit tests.
|
/// A simple API called in some unit tests.
|
||||||
///
|
///
|
||||||
/// Generated class from Pigeon that represents Flutter messages that can be called from Swift.
|
/// Generated protocol from Pigeon that represents Flutter messages that can be called from Swift.
|
||||||
class FlutterSmallApi {
|
protocol FlutterSmallApiProtocol {
|
||||||
|
func echo(_ msgArg: TestMessage, completion: @escaping (Result<TestMessage, FlutterError>) -> Void)
|
||||||
|
func echo(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void)
|
||||||
|
}
|
||||||
|
class FlutterSmallApi: FlutterSmallApiProtocol {
|
||||||
private let binaryMessenger: FlutterBinaryMessenger
|
private let binaryMessenger: FlutterBinaryMessenger
|
||||||
init(binaryMessenger: FlutterBinaryMessenger){
|
init(binaryMessenger: FlutterBinaryMessenger){
|
||||||
self.binaryMessenger = binaryMessenger
|
self.binaryMessenger = binaryMessenger
|
||||||
@ -2336,4 +2394,24 @@ class FlutterSmallApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func echo(_ aStringArg: String, completion: @escaping (Result<String, FlutterError>) -> Void) {
|
||||||
|
let channel = FlutterBasicMessageChannel(name: "dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString", binaryMessenger: binaryMessenger, codec: codec)
|
||||||
|
channel.sendMessage([aStringArg] as [Any?]) { response in
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4749,4 +4749,42 @@ void FlutterSmallApi::EchoWrappedList(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FlutterSmallApi::EchoString(
|
||||||
|
const std::string& a_string_arg,
|
||||||
|
std::function<void(const std::string&)>&& on_success,
|
||||||
|
std::function<void(const FlutterError&)>&& on_error) {
|
||||||
|
auto channel = std::make_unique<BasicMessageChannel<>>(
|
||||||
|
binary_messenger_,
|
||||||
|
"dev.flutter.pigeon.pigeon_integration_tests.FlutterSmallApi.echoString",
|
||||||
|
&GetCodec());
|
||||||
|
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<EncodableValue> response =
|
||||||
|
GetCodec().DecodeMessage(reply, reply_size);
|
||||||
|
const auto& encodable_return_value = *response;
|
||||||
|
const auto* list_return_value =
|
||||||
|
std::get_if<EncodableList>(&encodable_return_value);
|
||||||
|
if (list_return_value) {
|
||||||
|
if (list_return_value->size() > 1) {
|
||||||
|
on_error(FlutterError(std::get<std::string>(list_return_value->at(0)),
|
||||||
|
std::get<std::string>(list_return_value->at(1)),
|
||||||
|
list_return_value->at(2)));
|
||||||
|
} else {
|
||||||
|
const auto& return_value =
|
||||||
|
std::get<std::string>(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
|
} // namespace core_tests_pigeontest
|
||||||
|
@ -847,6 +847,9 @@ class FlutterSmallApi {
|
|||||||
void EchoWrappedList(const TestMessage& msg,
|
void EchoWrappedList(const TestMessage& msg,
|
||||||
std::function<void(const TestMessage&)>&& on_success,
|
std::function<void(const TestMessage&)>&& on_success,
|
||||||
std::function<void(const FlutterError&)>&& on_error);
|
std::function<void(const FlutterError&)>&& on_error);
|
||||||
|
void EchoString(const std::string& a_string,
|
||||||
|
std::function<void(const std::string&)>&& on_success,
|
||||||
|
std::function<void(const FlutterError&)>&& on_error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
flutter::BinaryMessenger* binary_messenger_;
|
flutter::BinaryMessenger* binary_messenger_;
|
||||||
|
@ -2,7 +2,7 @@ name: pigeon
|
|||||||
description: Code generator tool to make communication between Flutter and the host platform type-safe and easier.
|
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
|
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
|
issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3Apigeon
|
||||||
version: 12.0.0 # This must match the version in lib/generator_tools.dart
|
version: 12.0.1 # This must match the version in lib/generator_tools.dart
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.19.0 <4.0.0"
|
sdk: ">=2.19.0 <4.0.0"
|
||||||
|
Reference in New Issue
Block a user