mirror of
https://github.com/flutter/packages.git
synced 2025-07-04 01:33:59 +08:00
[pigeon] implemented primitive datatypes (#414)
This commit is contained in:
@ -4,6 +4,7 @@
|
||||
* [front-end] Added a more explicit error for static fields.
|
||||
* [front-end] Added more errors for incorrect usage of Pigeon (previously they were just ignored).
|
||||
* Moved Pigeon to using a custom codec which allows collection types to contain custom classes.
|
||||
* Started allowing primitive data types as arguments and return types.
|
||||
|
||||
## 0.3.0
|
||||
|
||||
|
@ -121,19 +121,14 @@ final BinaryMessenger$nullTag _binaryMessenger;
|
||||
}
|
||||
String argSignature = '';
|
||||
String sendArgument = 'null';
|
||||
String? encodedDeclaration;
|
||||
if (func.argType != 'void') {
|
||||
argSignature = '${func.argType} arg';
|
||||
sendArgument = 'encoded';
|
||||
encodedDeclaration = 'final Object encoded = arg.encode();';
|
||||
sendArgument = 'arg';
|
||||
}
|
||||
indent.write(
|
||||
'Future<${func.returnType}> ${func.name}($argSignature) async ',
|
||||
);
|
||||
indent.scoped('{', '}', () {
|
||||
if (encodedDeclaration != null) {
|
||||
indent.writeln(encodedDeclaration);
|
||||
}
|
||||
final String channelName = makeChannelName(api, func);
|
||||
indent.writeln(
|
||||
'final BasicMessageChannel<Object$nullTag> channel = BasicMessageChannel<Object$nullTag>(');
|
||||
@ -144,7 +139,7 @@ final BinaryMessenger$nullTag _binaryMessenger;
|
||||
});
|
||||
final String returnStatement = func.returnType == 'void'
|
||||
? '// noop'
|
||||
: 'return ${func.returnType}.decode(replyMap[\'${Keys.result}\']$unwrapOperator);';
|
||||
: 'return (replyMap[\'${Keys.result}\'] as ${func.returnType}$nullTag)$unwrapOperator;';
|
||||
indent.format('''
|
||||
final Map<Object$nullTag, Object$nullTag>$nullTag replyMap =\n\t\tawait channel.send($sendArgument) as Map<Object$nullTag, Object$nullTag>$nullTag;
|
||||
if (replyMap == null) {
|
||||
@ -237,7 +232,7 @@ void _writeFlutterApi(
|
||||
'assert(message != null, \'Argument for $channelName was null. Expected $argType.\');',
|
||||
);
|
||||
indent.writeln(
|
||||
'final $argType input = $argType.decode(message$unwrapOperator);',
|
||||
'final $argType input = (message as $argType$nullTag)$unwrapOperator;',
|
||||
);
|
||||
call = 'api.${func.name}(input)';
|
||||
}
|
||||
@ -254,7 +249,7 @@ void _writeFlutterApi(
|
||||
} else {
|
||||
indent.writeln('final $returnType output = $call;');
|
||||
}
|
||||
const String returnExpression = 'output.encode()';
|
||||
const String returnExpression = 'output';
|
||||
final String returnStatement = isMockHandler
|
||||
? 'return <Object$nullTag, Object$nullTag>{\'${Keys.result}\': $returnExpression};'
|
||||
: 'return $returnExpression;';
|
||||
|
@ -262,6 +262,20 @@ class EnumeratedClass {
|
||||
final int enumeration;
|
||||
}
|
||||
|
||||
/// Supported basic datatypes.
|
||||
const List<String> validTypes = <String>[
|
||||
'String',
|
||||
'bool',
|
||||
'int',
|
||||
'double',
|
||||
'Uint8List',
|
||||
'Int32List',
|
||||
'Int64List',
|
||||
'Float64List',
|
||||
'List',
|
||||
'Map',
|
||||
];
|
||||
|
||||
/// Custom codecs' custom types are enumerated from 255 down to this number to
|
||||
/// avoid collisions with the StandardMessageCodec.
|
||||
const int _minimumCodecFieldKey = 128;
|
||||
@ -274,8 +288,10 @@ Iterable<EnumeratedClass> getCodecClasses(Api api) sync* {
|
||||
names.add(method.returnType);
|
||||
names.add(method.argType);
|
||||
}
|
||||
final List<String> sortedNames =
|
||||
names.where((String element) => element != 'void').toList();
|
||||
final List<String> sortedNames = names
|
||||
.where((String element) =>
|
||||
element != 'void' && !validTypes.contains(element))
|
||||
.toList();
|
||||
sortedNames.sort();
|
||||
int enumeration = _minimumCodecFieldKey;
|
||||
const int maxCustomClassesPerApi = 255 - _minimumCodecFieldKey;
|
||||
|
@ -113,6 +113,22 @@ void _writeCodec(Indent indent, Api api) {
|
||||
});
|
||||
}
|
||||
|
||||
/// This performs Dart to Java type conversions. If performs a passthrough of
|
||||
/// the input if it can't be converted.
|
||||
// TODO(gaaclarke): Remove this method and unify it with `_javaTypeForDartType`.
|
||||
String _javaTypeForDartTypePassthrough(String type) {
|
||||
const Map<String, String> map = <String, String>{
|
||||
'int': 'Integer',
|
||||
'bool': 'Boolean',
|
||||
'double': 'Double',
|
||||
'Int32List': 'int[]',
|
||||
'Uint8List': 'byte[]',
|
||||
'Int64List': 'long[]',
|
||||
'Float64List': 'double[]',
|
||||
};
|
||||
return map[type] ?? type;
|
||||
}
|
||||
|
||||
void _writeHostApi(Indent indent, Api api) {
|
||||
assert(api.location == ApiLocation.host);
|
||||
|
||||
@ -121,11 +137,13 @@ void _writeHostApi(Indent indent, Api api) {
|
||||
indent.write('public interface ${api.name} ');
|
||||
indent.scoped('{', '}', () {
|
||||
for (final Method method in api.methods) {
|
||||
final String returnType =
|
||||
method.isAsynchronous ? 'void' : method.returnType;
|
||||
final String argType = _javaTypeForDartTypePassthrough(method.argType);
|
||||
final String returnType = method.isAsynchronous
|
||||
? 'void'
|
||||
: _javaTypeForDartTypePassthrough(method.returnType);
|
||||
final List<String> argSignature = <String>[];
|
||||
if (method.argType != 'void') {
|
||||
argSignature.add('${method.argType} arg');
|
||||
argSignature.add('$argType arg');
|
||||
}
|
||||
if (method.isAsynchronous) {
|
||||
final String returnType =
|
||||
@ -162,21 +180,27 @@ static MessageCodec<Object> getCodec() {
|
||||
indent.scoped('{', '} else {', () {
|
||||
indent.write('channel.setMessageHandler((message, reply) -> ');
|
||||
indent.scoped('{', '});', () {
|
||||
final String argType = method.argType;
|
||||
final String returnType = method.returnType;
|
||||
final String argType =
|
||||
_javaTypeForDartTypePassthrough(method.argType);
|
||||
final String returnType =
|
||||
_javaTypeForDartTypePassthrough(method.returnType);
|
||||
indent.writeln('Map<String, Object> wrapped = new HashMap<>();');
|
||||
indent.write('try ');
|
||||
indent.scoped('{', '}', () {
|
||||
final List<String> methodArgument = <String>[];
|
||||
if (argType != 'void') {
|
||||
indent.writeln('@SuppressWarnings("ConstantConditions")');
|
||||
indent.writeln(
|
||||
'$argType input = $argType.fromMap((Map<String, Object>)message);');
|
||||
indent.writeln('$argType input = ($argType)message;');
|
||||
indent.write('if (input == null) ');
|
||||
indent.scoped('{', '}', () {
|
||||
indent.writeln(
|
||||
'throw new NullPointerException("Message unexpectedly null.");');
|
||||
});
|
||||
methodArgument.add('input');
|
||||
}
|
||||
if (method.isAsynchronous) {
|
||||
final String resultValue =
|
||||
method.returnType == 'void' ? 'null' : 'result.toMap()';
|
||||
method.returnType == 'void' ? 'null' : 'result';
|
||||
methodArgument.add(
|
||||
'result -> { '
|
||||
'wrapped.put("${Keys.result}", $resultValue); '
|
||||
@ -193,8 +217,7 @@ static MessageCodec<Object> getCodec() {
|
||||
indent.writeln('wrapped.put("${Keys.result}", null);');
|
||||
} else {
|
||||
indent.writeln('$returnType output = $call;');
|
||||
indent.writeln(
|
||||
'wrapped.put("${Keys.result}", output.toMap());');
|
||||
indent.writeln('wrapped.put("${Keys.result}", output);');
|
||||
}
|
||||
});
|
||||
indent.write('catch (Error | RuntimeException exception) ');
|
||||
@ -242,16 +265,18 @@ static MessageCodec<Object> getCodec() {
|
||||
''');
|
||||
for (final Method func in api.methods) {
|
||||
final String channelName = makeChannelName(api, func);
|
||||
final String returnType =
|
||||
func.returnType == 'void' ? 'Void' : func.returnType;
|
||||
final String returnType = func.returnType == 'void'
|
||||
? 'Void'
|
||||
: _javaTypeForDartTypePassthrough(func.returnType);
|
||||
final String argType = _javaTypeForDartTypePassthrough(func.argType);
|
||||
String sendArgument;
|
||||
if (func.argType == 'void') {
|
||||
indent.write('public void ${func.name}(Reply<$returnType> callback) ');
|
||||
sendArgument = 'null';
|
||||
} else {
|
||||
indent.write(
|
||||
'public void ${func.name}(${func.argType} argInput, Reply<$returnType> callback) ');
|
||||
sendArgument = 'inputMap';
|
||||
'public void ${func.name}($argType argInput, Reply<$returnType> callback) ');
|
||||
sendArgument = 'argInput';
|
||||
}
|
||||
indent.scoped('{', '}', () {
|
||||
indent.writeln('BasicMessageChannel<Object> channel =');
|
||||
@ -261,18 +286,13 @@ static MessageCodec<Object> getCodec() {
|
||||
'new BasicMessageChannel<>(binaryMessenger, "$channelName", getCodec());');
|
||||
indent.dec();
|
||||
indent.dec();
|
||||
if (func.argType != 'void') {
|
||||
indent.writeln('Map<String, Object> inputMap = argInput.toMap();');
|
||||
}
|
||||
indent.write('channel.send($sendArgument, channelReply -> ');
|
||||
indent.scoped('{', '});', () {
|
||||
if (func.returnType == 'void') {
|
||||
indent.writeln('callback.reply(null);');
|
||||
} else {
|
||||
indent.writeln('Map outputMap = (Map)channelReply;');
|
||||
indent.writeln('@SuppressWarnings("ConstantConditions")');
|
||||
indent.writeln(
|
||||
'${func.returnType} output = ${func.returnType}.fromMap(outputMap);');
|
||||
indent.writeln('$returnType output = ($returnType)channelReply;');
|
||||
indent.writeln('callback.reply(output);');
|
||||
}
|
||||
});
|
||||
|
@ -67,16 +67,16 @@ String _callbackForType(String dartType, String objcType) {
|
||||
}
|
||||
|
||||
const Map<String, String> _objcTypeForDartTypeMap = <String, String>{
|
||||
'bool': 'NSNumber *',
|
||||
'int': 'NSNumber *',
|
||||
'String': 'NSString *',
|
||||
'double': 'NSNumber *',
|
||||
'Uint8List': 'FlutterStandardTypedData *',
|
||||
'Int32List': 'FlutterStandardTypedData *',
|
||||
'Int64List': 'FlutterStandardTypedData *',
|
||||
'Float64List': 'FlutterStandardTypedData *',
|
||||
'List': 'NSArray *',
|
||||
'Map': 'NSDictionary *',
|
||||
'bool': 'NSNumber',
|
||||
'int': 'NSNumber',
|
||||
'String': 'NSString',
|
||||
'double': 'NSNumber',
|
||||
'Uint8List': 'FlutterStandardTypedData',
|
||||
'Int32List': 'FlutterStandardTypedData',
|
||||
'Int64List': 'FlutterStandardTypedData',
|
||||
'Float64List': 'FlutterStandardTypedData',
|
||||
'List': 'NSArray',
|
||||
'Map': 'NSDictionary',
|
||||
};
|
||||
|
||||
const Map<String, String> _propertyTypeForDartTypeMap = <String, String>{
|
||||
@ -92,8 +92,18 @@ const Map<String, String> _propertyTypeForDartTypeMap = <String, String>{
|
||||
'Map': 'strong',
|
||||
};
|
||||
|
||||
String? _objcTypeForDartType(String type) {
|
||||
return _objcTypeForDartTypeMap[type];
|
||||
String? _objcTypePtrForPrimitiveDartType(String type) {
|
||||
return _objcTypeForDartTypeMap.containsKey(type)
|
||||
? '${_objcTypeForDartTypeMap[type]} *'
|
||||
: null;
|
||||
}
|
||||
|
||||
/// Returns the objc type for a dart [type], prepending the [classPrefix] for
|
||||
/// generated classes. For example:
|
||||
/// _objcTypeForDartType(null, 'int') => 'NSNumber'.
|
||||
String _objcTypeForDartType(String? classPrefix, String type) {
|
||||
final String? builtinObjcType = _objcTypeForDartTypeMap[type];
|
||||
return builtinObjcType ?? _className(classPrefix, type);
|
||||
}
|
||||
|
||||
String _propertyTypeForDartType(String type) {
|
||||
@ -112,7 +122,7 @@ void _writeClassDeclarations(
|
||||
indent.writeln('@interface ${_className(prefix, klass.name)} : NSObject');
|
||||
for (final Field field in klass.fields) {
|
||||
final HostDatatype hostDatatype = getHostDatatype(
|
||||
field, classes, enums, _objcTypeForDartType,
|
||||
field, classes, enums, _objcTypePtrForPrimitiveDartType,
|
||||
customResolver: enumNames.contains(field.dataType)
|
||||
? (String x) => _className(prefix, x)
|
||||
: (String x) => '${_className(prefix, x)} *');
|
||||
@ -217,14 +227,16 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) {
|
||||
final String apiName = _className(options.prefix, api.name);
|
||||
indent.writeln('@protocol $apiName');
|
||||
for (final Method func in api.methods) {
|
||||
final String returnTypeName = _className(options.prefix, func.returnType);
|
||||
final String returnTypeName =
|
||||
_objcTypeForDartType(options.prefix, func.returnType);
|
||||
if (func.isAsynchronous) {
|
||||
if (func.returnType == 'void') {
|
||||
if (func.argType == 'void') {
|
||||
indent.writeln(
|
||||
'-(void)${func.name}:(void(^)(FlutterError *_Nullable))completion;');
|
||||
} else {
|
||||
final String argType = _className(options.prefix, func.argType);
|
||||
final String argType =
|
||||
_objcTypeForDartType(options.prefix, func.argType);
|
||||
indent.writeln(
|
||||
'-(void)${func.name}:(nullable $argType *)input completion:(void(^)(FlutterError *_Nullable))completion;');
|
||||
}
|
||||
@ -233,7 +245,8 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) {
|
||||
indent.writeln(
|
||||
'-(void)${func.name}:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;');
|
||||
} else {
|
||||
final String argType = _className(options.prefix, func.argType);
|
||||
final String argType =
|
||||
_objcTypeForDartType(options.prefix, func.argType);
|
||||
indent.writeln(
|
||||
'-(void)${func.name}:(nullable $argType *)input completion:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;');
|
||||
}
|
||||
@ -245,7 +258,8 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) {
|
||||
indent.writeln(
|
||||
'-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;');
|
||||
} else {
|
||||
final String argType = _className(options.prefix, func.argType);
|
||||
final String argType =
|
||||
_objcTypeForDartType(options.prefix, func.argType);
|
||||
indent.writeln(
|
||||
'-($returnType)${func.name}:($argType*)input error:(FlutterError *_Nullable *_Nonnull)error;');
|
||||
}
|
||||
@ -264,12 +278,13 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) {
|
||||
indent.writeln(
|
||||
'- (instancetype)initWithBinaryMessenger:(id<FlutterBinaryMessenger>)binaryMessenger;');
|
||||
for (final Method func in api.methods) {
|
||||
final String returnType = _className(options.prefix, func.returnType);
|
||||
final String returnType =
|
||||
_objcTypeForDartType(options.prefix, func.returnType);
|
||||
final String callbackType = _callbackForType(func.returnType, returnType);
|
||||
if (func.argType == 'void') {
|
||||
indent.writeln('- (void)${func.name}:($callbackType)completion;');
|
||||
} else {
|
||||
final String argType = _className(options.prefix, func.argType);
|
||||
final String argType = _objcTypeForDartType(options.prefix, func.argType);
|
||||
indent.writeln(
|
||||
'- (void)${func.name}:($argType*)input completion:($callbackType)completion;');
|
||||
}
|
||||
@ -386,13 +401,14 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) {
|
||||
'[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) ');
|
||||
indent.scoped('{', '}];', () {
|
||||
final String returnType =
|
||||
_className(options.prefix, func.returnType);
|
||||
_objcTypeForDartType(options.prefix, func.returnType);
|
||||
String syncCall;
|
||||
if (func.argType == 'void') {
|
||||
syncCall = '[api ${func.name}:&error]';
|
||||
} else {
|
||||
final String argType = _className(options.prefix, func.argType);
|
||||
indent.writeln('$argType *input = [$argType fromMap:message];');
|
||||
final String argType =
|
||||
_objcTypeForDartType(options.prefix, func.argType);
|
||||
indent.writeln('$argType *input = message;');
|
||||
syncCall = '[api ${func.name}:input error:&error]';
|
||||
}
|
||||
if (func.isAsynchronous) {
|
||||
@ -412,8 +428,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) {
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const String callback =
|
||||
'callback(wrapResult([output toMap], error));';
|
||||
const String callback = 'callback(wrapResult(output, error));';
|
||||
if (func.argType == 'void') {
|
||||
indent.writeScoped(
|
||||
'[api ${func.name}:^($returnType *_Nullable output, FlutterError *_Nullable error) {',
|
||||
@ -435,7 +450,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) {
|
||||
indent.writeln('callback(wrapResult(nil, error));');
|
||||
} else {
|
||||
indent.writeln('$returnType *output = $syncCall;');
|
||||
indent.writeln('callback(wrapResult([output toMap], error));');
|
||||
indent.writeln('callback(wrapResult(output, error));');
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -470,7 +485,8 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) {
|
||||
});
|
||||
indent.addln('');
|
||||
for (final Method func in api.methods) {
|
||||
final String returnType = _className(options.prefix, func.returnType);
|
||||
final String returnType =
|
||||
_objcTypeForDartType(options.prefix, func.returnType);
|
||||
final String callbackType = _callbackForType(func.returnType, returnType);
|
||||
|
||||
String sendArgument;
|
||||
@ -478,10 +494,10 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) {
|
||||
indent.write('- (void)${func.name}:($callbackType)completion ');
|
||||
sendArgument = 'nil';
|
||||
} else {
|
||||
final String argType = _className(options.prefix, func.argType);
|
||||
final String argType = _objcTypeForDartType(options.prefix, func.argType);
|
||||
indent.write(
|
||||
'- (void)${func.name}:($argType*)input completion:($callbackType)completion ');
|
||||
sendArgument = 'inputMap';
|
||||
sendArgument = 'input';
|
||||
}
|
||||
indent.scoped('{', '}', () {
|
||||
indent.writeln('FlutterBasicMessageChannel *channel =');
|
||||
@ -494,17 +510,12 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) {
|
||||
'codec:${_getCodecGetterName(options.prefix, api.name)}()];');
|
||||
indent.dec();
|
||||
indent.dec();
|
||||
if (func.argType != 'void') {
|
||||
indent.writeln('NSDictionary* inputMap = [input toMap];');
|
||||
}
|
||||
indent.write('[channel sendMessage:$sendArgument reply:^(id reply) ');
|
||||
indent.scoped('{', '}];', () {
|
||||
if (func.returnType == 'void') {
|
||||
indent.writeln('completion(nil);');
|
||||
} else {
|
||||
indent.writeln('NSDictionary* outputMap = reply;');
|
||||
indent.writeln(
|
||||
'$returnType * output = [$returnType fromMap:outputMap];');
|
||||
indent.writeln('$returnType * output = reply;');
|
||||
indent.writeln('completion(output, nil);');
|
||||
}
|
||||
});
|
||||
@ -536,7 +547,7 @@ void generateObjcSource(ObjcOptions options, Root root, StringSink sink) {
|
||||
indent.addln('');
|
||||
|
||||
indent.format('''
|
||||
static NSDictionary<NSString*, id>* wrapResult(NSDictionary *result, FlutterError *error) {
|
||||
static NSDictionary<NSString*, id>* wrapResult(id result, FlutterError *error) {
|
||||
\tNSDictionary *errorDict = (NSDictionary *)[NSNull null];
|
||||
\tif (error) {
|
||||
\t\terrorDict = @{
|
||||
|
@ -25,19 +25,6 @@ import 'ast.dart';
|
||||
import 'dart_generator.dart';
|
||||
import 'objc_generator.dart';
|
||||
|
||||
const List<String> _validTypes = <String>[
|
||||
'String',
|
||||
'bool',
|
||||
'int',
|
||||
'double',
|
||||
'Uint8List',
|
||||
'Int32List',
|
||||
'Int64List',
|
||||
'Float64List',
|
||||
'List',
|
||||
'Map',
|
||||
];
|
||||
|
||||
class _Asynchronous {
|
||||
const _Asynchronous();
|
||||
}
|
||||
@ -397,7 +384,7 @@ List<Error> _validateAst(Root root, String source) {
|
||||
'Unsupported datatype:"${field.dataType}" in class "${klass.name}". Generic fields aren\'t yet supported (https://github.com/flutter/flutter/issues/63468).',
|
||||
lineNumber: _calculateLineNumberNullable(source, field.offset),
|
||||
));
|
||||
} else if (!(_validTypes.contains(field.dataType) ||
|
||||
} else if (!(validTypes.contains(field.dataType) ||
|
||||
customClasses.contains(field.dataType) ||
|
||||
customEnums.contains(field.dataType))) {
|
||||
result.add(Error(
|
||||
@ -413,28 +400,14 @@ List<Error> _validateAst(Root root, String source) {
|
||||
if (method.isReturnNullable) {
|
||||
result.add(Error(
|
||||
message:
|
||||
'Nullable return types types aren\'t supported for Pigeon methods: "${method.argType}" in API: "${api.name}" method: "${method.name}',
|
||||
'Nullable return types types aren\'t supported for Pigeon methods: "${method.argType}" in API: "${api.name}" method: "${method.name}"',
|
||||
lineNumber: _calculateLineNumberNullable(source, method.offset),
|
||||
));
|
||||
}
|
||||
if (method.isArgNullable) {
|
||||
result.add(Error(
|
||||
message:
|
||||
'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType}" in API: "${api.name}" method: "${method.name}',
|
||||
lineNumber: _calculateLineNumberNullable(source, method.offset),
|
||||
));
|
||||
}
|
||||
if (_validTypes.contains(method.argType)) {
|
||||
result.add(Error(
|
||||
message:
|
||||
'Primitive argument types aren\'t yet supported (https://github.com/flutter/flutter/issues/66467): "${method.argType}" in API: "${api.name}" method: "${method.name}',
|
||||
lineNumber: _calculateLineNumberNullable(source, method.offset),
|
||||
));
|
||||
}
|
||||
if (_validTypes.contains(method.returnType)) {
|
||||
result.add(Error(
|
||||
message:
|
||||
'Primitive return types aren\'t yet supported (https://github.com/flutter/flutter/issues/66467): "${method.returnType}" in API: "${api.name}" method: "${method.name}',
|
||||
'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType}" in API: "${api.name}" method: "${method.name}"',
|
||||
lineNumber: _calculateLineNumberNullable(source, method.offset),
|
||||
));
|
||||
}
|
||||
@ -502,7 +475,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor<Object?> {
|
||||
orElse: () => Class(name: '', fields: <Field>[]));
|
||||
for (final Field field in aClass.fields) {
|
||||
if (!referencedTypes.contains(field.dataType) &&
|
||||
!_validTypes.contains(field.dataType)) {
|
||||
!validTypes.contains(field.dataType)) {
|
||||
referencedTypes.add(field.dataType);
|
||||
classesToCheck.add(field.dataType);
|
||||
}
|
||||
|
@ -28,4 +28,5 @@ abstract class Api {
|
||||
SearchReply search(SearchRequest request);
|
||||
SearchReplies doSearches(SearchRequests request);
|
||||
SearchRequests echo(SearchRequests requests);
|
||||
int anInt(int value);
|
||||
}
|
||||
|
31
packages/pigeon/pigeons/primitive.dart
Normal file
31
packages/pigeon/pigeons/primitive.dart
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:pigeon/pigeon.dart';
|
||||
|
||||
@HostApi()
|
||||
abstract class PrimitiveHostApi {
|
||||
int anInt(int value);
|
||||
bool aBool(bool value);
|
||||
String aString(String value);
|
||||
double aDouble(double value);
|
||||
// ignore: always_specify_types
|
||||
Map aMap(Map value);
|
||||
// ignore: always_specify_types
|
||||
List aList(List value);
|
||||
Int32List anInt32List(Int32List value);
|
||||
}
|
||||
|
||||
@FlutterApi()
|
||||
abstract class PrimitiveFlutterApi {
|
||||
int anInt(int value);
|
||||
bool aBool(bool value);
|
||||
String aString(String value);
|
||||
double aDouble(double value);
|
||||
// ignore: always_specify_types
|
||||
Map aMap(Map value);
|
||||
// ignore: always_specify_types
|
||||
List aList(List value);
|
||||
Int32List anInt32List(Int32List value);
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>android_</name>
|
||||
<comment>Project android_ created by Buildship.</comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.buildship.core.gradleprojectbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.buildship.core.gradleprojectnature</nature>
|
||||
</natures>
|
||||
<filteredResources>
|
||||
<filter>
|
||||
<id>1624921942866</id>
|
||||
<name></name>
|
||||
<type>30</type>
|
||||
<matcher>
|
||||
<id>org.eclipse.core.resources.regexFilterMatcher</id>
|
||||
<arguments>node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
|
||||
</matcher>
|
||||
</filter>
|
||||
</filteredResources>
|
||||
</projectDescription>
|
@ -0,0 +1,13 @@
|
||||
arguments=
|
||||
auto.sync=false
|
||||
build.scans.enabled=false
|
||||
connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER)
|
||||
connection.project.dir=
|
||||
eclipse.preferences.version=1
|
||||
gradle.user.home=
|
||||
java.home=/Library/Java/JavaVirtualMachines/jdk-11-latest/Contents/Home
|
||||
jvm.arguments=
|
||||
offline.mode=false
|
||||
override.workspace.settings=true
|
||||
show.console.view=true
|
||||
show.executions.view=true
|
@ -9,15 +9,12 @@ import static org.mockito.Mockito.*;
|
||||
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import io.flutter.plugin.common.MessageCodec;
|
||||
import io.flutter.plugin.common.StandardMessageCodec;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Map;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
|
||||
public class PigeonTest {
|
||||
private MessageCodec<Object> codec = StandardMessageCodec.INSTANCE;
|
||||
|
||||
@Test
|
||||
public void toMapAndBack() {
|
||||
Pigeon.SetRequest request = new Pigeon.SetRequest();
|
||||
@ -62,6 +59,7 @@ public class PigeonTest {
|
||||
ArgumentCaptor<BinaryMessenger.BinaryMessageHandler> handler =
|
||||
ArgumentCaptor.forClass(BinaryMessenger.BinaryMessageHandler.class);
|
||||
verify(binaryMessenger).setMessageHandler(anyString(), handler.capture());
|
||||
MessageCodec<Object> codec = Pigeon.Api.getCodec();
|
||||
ByteBuffer message = codec.encodeMessage(null);
|
||||
handler
|
||||
.getValue()
|
||||
@ -86,7 +84,8 @@ public class PigeonTest {
|
||||
Pigeon.SetRequest request = new Pigeon.SetRequest();
|
||||
request.setValue(1234l);
|
||||
request.setState(Pigeon.LoadingState.complete);
|
||||
ByteBuffer message = codec.encodeMessage(request.toMap());
|
||||
MessageCodec<Object> codec = Pigeon.Api.getCodec();
|
||||
ByteBuffer message = codec.encodeMessage(request);
|
||||
message.rewind();
|
||||
handler
|
||||
.getValue()
|
||||
|
@ -0,0 +1,117 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
package com.example.android_unit_tests;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.example.android_unit_tests.Primitive.PrimitiveFlutterApi;
|
||||
import io.flutter.plugin.common.BinaryMessenger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.Test;
|
||||
|
||||
public class PrimitiveTest {
|
||||
private static BinaryMessenger makeMockBinaryMessenger() {
|
||||
BinaryMessenger binaryMessenger = mock(BinaryMessenger.class);
|
||||
doAnswer(
|
||||
invocation -> {
|
||||
ByteBuffer message = invocation.getArgument(1);
|
||||
BinaryMessenger.BinaryReply reply = invocation.getArgument(2);
|
||||
message.position(0);
|
||||
reply.reply(message);
|
||||
return null;
|
||||
})
|
||||
.when(binaryMessenger)
|
||||
.send(anyString(), any(), any());
|
||||
return binaryMessenger;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void primitiveInt() {
|
||||
BinaryMessenger binaryMessenger = makeMockBinaryMessenger();
|
||||
PrimitiveFlutterApi api = new PrimitiveFlutterApi(binaryMessenger);
|
||||
boolean[] didCall = {false};
|
||||
api.anInt(
|
||||
1,
|
||||
(Integer result) -> {
|
||||
didCall[0] = true;
|
||||
assertEquals(result, (Integer) 1);
|
||||
});
|
||||
assertTrue(didCall[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void primitiveBool() {
|
||||
BinaryMessenger binaryMessenger = makeMockBinaryMessenger();
|
||||
PrimitiveFlutterApi api = new PrimitiveFlutterApi(binaryMessenger);
|
||||
boolean[] didCall = {false};
|
||||
api.aBool(
|
||||
true,
|
||||
(Boolean result) -> {
|
||||
didCall[0] = true;
|
||||
assertEquals(result, (Boolean) true);
|
||||
});
|
||||
assertTrue(didCall[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void primitiveString() {
|
||||
BinaryMessenger binaryMessenger = makeMockBinaryMessenger();
|
||||
PrimitiveFlutterApi api = new PrimitiveFlutterApi(binaryMessenger);
|
||||
boolean[] didCall = {false};
|
||||
api.aString(
|
||||
"hello",
|
||||
(String result) -> {
|
||||
didCall[0] = true;
|
||||
assertEquals(result, "hello");
|
||||
});
|
||||
assertTrue(didCall[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void primitiveDouble() {
|
||||
BinaryMessenger binaryMessenger = makeMockBinaryMessenger();
|
||||
PrimitiveFlutterApi api = new PrimitiveFlutterApi(binaryMessenger);
|
||||
boolean[] didCall = {false};
|
||||
api.aDouble(
|
||||
1.5,
|
||||
(Double result) -> {
|
||||
didCall[0] = true;
|
||||
assertEquals(result, 1.5, 0.01);
|
||||
});
|
||||
assertTrue(didCall[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void primitiveMap() {
|
||||
BinaryMessenger binaryMessenger = makeMockBinaryMessenger();
|
||||
PrimitiveFlutterApi api = new PrimitiveFlutterApi(binaryMessenger);
|
||||
boolean[] didCall = {false};
|
||||
api.aMap(
|
||||
Collections.singletonMap("hello", 1),
|
||||
(Map result) -> {
|
||||
didCall[0] = true;
|
||||
assertEquals(result, Collections.singletonMap("hello", 1));
|
||||
});
|
||||
assertTrue(didCall[0]);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void primitiveList() {
|
||||
BinaryMessenger binaryMessenger = makeMockBinaryMessenger();
|
||||
PrimitiveFlutterApi api = new PrimitiveFlutterApi(binaryMessenger);
|
||||
boolean[] didCall = {false};
|
||||
api.aList(
|
||||
Collections.singletonList("hello"),
|
||||
(List result) -> {
|
||||
didCall[0] = true;
|
||||
assertEquals(result, Collections.singletonList("hello"));
|
||||
});
|
||||
assertTrue(didCall[0]);
|
||||
}
|
||||
}
|
@ -60,7 +60,7 @@ class _HostEverythingCodec extends StandardMessageCodec {
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is Everything) {
|
||||
buffer.putUint8(255);
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
@ -70,7 +70,7 @@ class _HostEverythingCodec extends StandardMessageCodec {
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 255:
|
||||
case 128:
|
||||
return Everything.decode(readValue(buffer)!);
|
||||
|
||||
default:
|
||||
@ -111,17 +111,16 @@ class HostEverything {
|
||||
details: error['details'],
|
||||
);
|
||||
} else {
|
||||
return Everything.decode(replyMap['result']!);
|
||||
return (replyMap['result'] as Everything?)!;
|
||||
}
|
||||
}
|
||||
|
||||
Future<Everything> echo(Everything arg) async {
|
||||
final Object encoded = arg.encode();
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.HostEverything.echo', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final Map<Object?, Object?>? replyMap =
|
||||
await channel.send(encoded) as Map<Object?, Object?>?;
|
||||
await channel.send(arg) as Map<Object?, Object?>?;
|
||||
if (replyMap == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -137,7 +136,7 @@ class HostEverything {
|
||||
details: error['details'],
|
||||
);
|
||||
} else {
|
||||
return Everything.decode(replyMap['result']!);
|
||||
return (replyMap['result'] as Everything?)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,7 +146,7 @@ class _FlutterEverythingCodec extends StandardMessageCodec {
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is Everything) {
|
||||
buffer.putUint8(255);
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
@ -157,7 +156,7 @@ class _FlutterEverythingCodec extends StandardMessageCodec {
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 255:
|
||||
case 128:
|
||||
return Everything.decode(readValue(buffer)!);
|
||||
|
||||
default:
|
||||
@ -181,7 +180,7 @@ abstract class FlutterEverything {
|
||||
channel.setMessageHandler((Object? message) async {
|
||||
// ignore message
|
||||
final Everything output = api.giveMeEverything();
|
||||
return output.encode();
|
||||
return output;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -194,9 +193,9 @@ abstract class FlutterEverything {
|
||||
channel.setMessageHandler((Object? message) async {
|
||||
assert(message != null,
|
||||
'Argument for dev.flutter.pigeon.FlutterEverything.echo was null. Expected Everything.');
|
||||
final Everything input = Everything.decode(message!);
|
||||
final Everything input = (message as Everything?)!;
|
||||
final Everything output = api.echo(input);
|
||||
return output.encode();
|
||||
return output;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -81,16 +81,16 @@ class _ApiCodec extends StandardMessageCodec {
|
||||
@override
|
||||
void writeValue(WriteBuffer buffer, Object? value) {
|
||||
if (value is SearchReplies) {
|
||||
buffer.putUint8(255);
|
||||
buffer.putUint8(128);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is SearchReply) {
|
||||
buffer.putUint8(254);
|
||||
buffer.putUint8(129);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is SearchRequest) {
|
||||
buffer.putUint8(253);
|
||||
buffer.putUint8(130);
|
||||
writeValue(buffer, value.encode());
|
||||
} else if (value is SearchRequests) {
|
||||
buffer.putUint8(252);
|
||||
buffer.putUint8(131);
|
||||
writeValue(buffer, value.encode());
|
||||
} else {
|
||||
super.writeValue(buffer, value);
|
||||
@ -100,16 +100,16 @@ class _ApiCodec extends StandardMessageCodec {
|
||||
@override
|
||||
Object? readValueOfType(int type, ReadBuffer buffer) {
|
||||
switch (type) {
|
||||
case 255:
|
||||
case 128:
|
||||
return SearchReplies.decode(readValue(buffer)!);
|
||||
|
||||
case 254:
|
||||
case 129:
|
||||
return SearchReply.decode(readValue(buffer)!);
|
||||
|
||||
case 253:
|
||||
case 130:
|
||||
return SearchRequest.decode(readValue(buffer)!);
|
||||
|
||||
case 252:
|
||||
case 131:
|
||||
return SearchRequests.decode(readValue(buffer)!);
|
||||
|
||||
default:
|
||||
@ -129,12 +129,11 @@ class Api {
|
||||
static const MessageCodec<Object?> codec = _ApiCodec();
|
||||
|
||||
Future<SearchReply> search(SearchRequest arg) async {
|
||||
final Object encoded = arg.encode();
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.Api.search', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final Map<Object?, Object?>? replyMap =
|
||||
await channel.send(encoded) as Map<Object?, Object?>?;
|
||||
await channel.send(arg) as Map<Object?, Object?>?;
|
||||
if (replyMap == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -150,17 +149,16 @@ class Api {
|
||||
details: error['details'],
|
||||
);
|
||||
} else {
|
||||
return SearchReply.decode(replyMap['result']!);
|
||||
return (replyMap['result'] as SearchReply?)!;
|
||||
}
|
||||
}
|
||||
|
||||
Future<SearchReplies> doSearches(SearchRequests arg) async {
|
||||
final Object encoded = arg.encode();
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.Api.doSearches', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final Map<Object?, Object?>? replyMap =
|
||||
await channel.send(encoded) as Map<Object?, Object?>?;
|
||||
await channel.send(arg) as Map<Object?, Object?>?;
|
||||
if (replyMap == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -176,17 +174,16 @@ class Api {
|
||||
details: error['details'],
|
||||
);
|
||||
} else {
|
||||
return SearchReplies.decode(replyMap['result']!);
|
||||
return (replyMap['result'] as SearchReplies?)!;
|
||||
}
|
||||
}
|
||||
|
||||
Future<SearchRequests> echo(SearchRequests arg) async {
|
||||
final Object encoded = arg.encode();
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.Api.echo', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final Map<Object?, Object?>? replyMap =
|
||||
await channel.send(encoded) as Map<Object?, Object?>?;
|
||||
await channel.send(arg) as Map<Object?, Object?>?;
|
||||
if (replyMap == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
@ -202,7 +199,32 @@ class Api {
|
||||
details: error['details'],
|
||||
);
|
||||
} else {
|
||||
return SearchRequests.decode(replyMap['result']!);
|
||||
return (replyMap['result'] as SearchRequests?)!;
|
||||
}
|
||||
}
|
||||
|
||||
Future<int> anInt(int arg) async {
|
||||
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
|
||||
'dev.flutter.pigeon.Api.anInt', codec,
|
||||
binaryMessenger: _binaryMessenger);
|
||||
final Map<Object?, Object?>? replyMap =
|
||||
await channel.send(arg) as Map<Object?, Object?>?;
|
||||
if (replyMap == null) {
|
||||
throw PlatformException(
|
||||
code: 'channel-error',
|
||||
message: 'Unable to establish connection on channel.',
|
||||
details: null,
|
||||
);
|
||||
} else if (replyMap['error'] != null) {
|
||||
final Map<Object?, Object?> error =
|
||||
(replyMap['error'] as Map<Object?, Object?>?)!;
|
||||
throw PlatformException(
|
||||
code: (error['code'] as String?)!,
|
||||
message: error['message'] as String?,
|
||||
details: error['details'],
|
||||
);
|
||||
} else {
|
||||
return (replyMap['result'] as int?)!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,9 +18,9 @@ void main() {
|
||||
final BinaryMessenger mockMessenger = MockBinaryMessenger();
|
||||
when(mockMessenger.send('dev.flutter.pigeon.HostEverything.echo', any))
|
||||
.thenAnswer((Invocation realInvocation) async {
|
||||
const StandardMessageCodec codec = StandardMessageCodec();
|
||||
const MessageCodec<Object?> codec = HostEverything.codec;
|
||||
final Object input =
|
||||
codec.decodeMessage(realInvocation.positionalArguments[1]);
|
||||
codec.decodeMessage(realInvocation.positionalArguments[1])!;
|
||||
return codec.encodeMessage(<String, Object>{'result': input});
|
||||
});
|
||||
final HostEverything api = HostEverything(binaryMessenger: mockMessenger);
|
||||
@ -53,7 +53,7 @@ void main() {
|
||||
final BinaryMessenger mockMessenger = MockBinaryMessenger();
|
||||
when(mockMessenger.send('dev.flutter.pigeon.HostEverything.echo', any))
|
||||
.thenAnswer((Invocation realInvocation) async {
|
||||
final MessageCodec<Object?> codec = HostEverything.codec;
|
||||
const MessageCodec<Object?> codec = HostEverything.codec;
|
||||
final Object? input =
|
||||
codec.decodeMessage(realInvocation.positionalArguments[1]);
|
||||
return codec.encodeMessage(<String, Object>{'result': input!});
|
||||
|
@ -38,8 +38,8 @@ void main() {
|
||||
final SearchReply reply = SearchReply()..result = 'ho';
|
||||
final BinaryMessenger mockMessenger = MockBinaryMessenger();
|
||||
final Completer<ByteData?> completer = Completer<ByteData?>();
|
||||
completer.complete(
|
||||
Api.codec.encodeMessage(<String, Object>{'result': reply.encode()}));
|
||||
completer
|
||||
.complete(Api.codec.encodeMessage(<String, Object>{'result': reply}));
|
||||
final Future<ByteData?> sendResult = completer.future;
|
||||
when(mockMessenger.send('dev.flutter.pigeon.Api.search', any))
|
||||
.thenAnswer((Invocation realInvocation) => sendResult);
|
||||
@ -66,4 +66,19 @@ void main() {
|
||||
expect(echo.requests!.length, 1);
|
||||
expect((echo.requests![0] as SearchRequest?)!.query, 'hey');
|
||||
});
|
||||
|
||||
test('primiative datatypes', () async {
|
||||
final BinaryMessenger mockMessenger = MockBinaryMessenger();
|
||||
when(mockMessenger.send('dev.flutter.pigeon.Api.anInt', any))
|
||||
.thenAnswer((Invocation realInvocation) async {
|
||||
final MessageCodec<Object?> codec = Api.codec;
|
||||
final Object? input =
|
||||
codec.decodeMessage(realInvocation.positionalArguments[1]);
|
||||
final int result = (input as int?)! + 1;
|
||||
return codec.encodeMessage(<String, Object>{'result': result});
|
||||
});
|
||||
final Api api = Api(binaryMessenger: mockMessenger);
|
||||
final int result = await api.anInt(1);
|
||||
expect(result, 2);
|
||||
});
|
||||
}
|
||||
|
@ -21,6 +21,6 @@
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>8.0</string>
|
||||
<string>9.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
0D50127523FF75B100CD5B95 /* RunnerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D50127423FF75B100CD5B95 /* RunnerTests.m */; };
|
||||
0D6FD3C526A76D400046D8BD /* primitive.gen.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FD3C426A76D400046D8BD /* primitive.gen.m */; };
|
||||
0D6FD3C726A777C00046D8BD /* PrimitiveTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D6FD3C626A777C00046D8BD /* PrimitiveTest.m */; };
|
||||
0D7A910A268D4A050056B5E1 /* ListTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A9109268D4A050056B5E1 /* ListTest.m */; };
|
||||
0D7A910D268E5D700056B5E1 /* all_void.gen.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D7A910C268E5D700056B5E1 /* all_void.gen.m */; };
|
||||
0D8C35EB25D45A7900B76435 /* AsyncHandlersTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0D8C35EA25D45A7900B76435 /* AsyncHandlersTest.m */; };
|
||||
@ -60,6 +62,9 @@
|
||||
0D50127223FF75B100CD5B95 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
0D50127423FF75B100CD5B95 /* RunnerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RunnerTests.m; sourceTree = "<group>"; };
|
||||
0D50127623FF75B100CD5B95 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
0D6FD3C326A76D400046D8BD /* primitive.gen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = primitive.gen.h; sourceTree = "<group>"; };
|
||||
0D6FD3C426A76D400046D8BD /* primitive.gen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = primitive.gen.m; sourceTree = "<group>"; };
|
||||
0D6FD3C626A777C00046D8BD /* PrimitiveTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrimitiveTest.m; sourceTree = "<group>"; };
|
||||
0D7A9109268D4A050056B5E1 /* ListTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ListTest.m; sourceTree = "<group>"; };
|
||||
0D7A910B268E5D700056B5E1 /* all_void.gen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = all_void.gen.h; sourceTree = "<group>"; };
|
||||
0D7A910C268E5D700056B5E1 /* all_void.gen.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = all_void.gen.m; sourceTree = "<group>"; };
|
||||
@ -133,6 +138,7 @@
|
||||
0DF4E5C7266ED80900AEA855 /* EchoMessenger.m */,
|
||||
0DF4E5CA266FDAE300AEA855 /* EnumTest.m */,
|
||||
0D7A9109268D4A050056B5E1 /* ListTest.m */,
|
||||
0D6FD3C626A777C00046D8BD /* PrimitiveTest.m */,
|
||||
);
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
@ -170,6 +176,8 @@
|
||||
97C146F01CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
0D6FD3C326A76D400046D8BD /* primitive.gen.h */,
|
||||
0D6FD3C426A76D400046D8BD /* primitive.gen.m */,
|
||||
0D7A910B268E5D700056B5E1 /* all_void.gen.h */,
|
||||
0D7A910C268E5D700056B5E1 /* all_void.gen.m */,
|
||||
0DD2E6AA2684031300A7D764 /* all_datatypes.gen.h */,
|
||||
@ -354,6 +362,7 @@
|
||||
0DF4E5C8266ED80900AEA855 /* EchoMessenger.m in Sources */,
|
||||
0DF4E5CB266FDAE300AEA855 /* EnumTest.m in Sources */,
|
||||
0D8C35EB25D45A7900B76435 /* AsyncHandlersTest.m in Sources */,
|
||||
0D6FD3C726A777C00046D8BD /* PrimitiveTest.m in Sources */,
|
||||
0D7A910A268D4A050056B5E1 /* ListTest.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -370,6 +379,7 @@
|
||||
0DD2E6C32684031300A7D764 /* void_arg_flutter.gen.m in Sources */,
|
||||
0DD2E6C22684031300A7D764 /* voidflutter.gen.m in Sources */,
|
||||
0DD2E6C02684031300A7D764 /* all_datatypes.gen.m in Sources */,
|
||||
0D6FD3C526A76D400046D8BD /* primitive.gen.m in Sources */,
|
||||
97C146F31CF9000F007C117D /* main.m in Sources */,
|
||||
0DD2E6BC2684031300A7D764 /* host2flutter.gen.m in Sources */,
|
||||
0DD2E6BE2684031300A7D764 /* message.gen.m in Sources */,
|
||||
@ -517,7 +527,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@ -596,7 +606,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@ -645,7 +655,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDEDidComputeMac32BitWarning</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
@ -8,24 +8,25 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@interface Value ()
|
||||
+ (Value*)fromMap:(NSDictionary*)dict;
|
||||
- (NSDictionary*)toMap;
|
||||
+ (Value *)fromMap:(NSDictionary *)dict;
|
||||
- (NSDictionary *)toMap;
|
||||
@end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@interface MockBinaryMessenger : NSObject<FlutterBinaryMessenger>
|
||||
@property(nonatomic, copy) NSNumber* result;
|
||||
@property(nonatomic, retain) FlutterStandardMessageCodec* codec;
|
||||
@property(nonatomic, retain) NSMutableDictionary<NSString*, FlutterBinaryMessageHandler>* handlers;
|
||||
@property(nonatomic, copy) NSNumber *result;
|
||||
@property(nonatomic, retain) NSObject<FlutterMessageCodec> *codec;
|
||||
@property(nonatomic, retain) NSMutableDictionary<NSString *, FlutterBinaryMessageHandler> *handlers;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
@end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@implementation MockBinaryMessenger
|
||||
|
||||
- (instancetype)init {
|
||||
- (instancetype)initWithCodec:(NSObject<FlutterMessageCodec> *)codec {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_codec = [FlutterStandardMessageCodec sharedInstance];
|
||||
_codec = codec;
|
||||
_handlers = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
@ -34,21 +35,20 @@
|
||||
- (void)cleanupConnection:(FlutterBinaryMessengerConnection)connection {
|
||||
}
|
||||
|
||||
- (void)sendOnChannel:(nonnull NSString*)channel message:(NSData* _Nullable)message {
|
||||
- (void)sendOnChannel:(nonnull NSString *)channel message:(NSData *_Nullable)message {
|
||||
}
|
||||
|
||||
- (void)sendOnChannel:(nonnull NSString*)channel
|
||||
message:(NSData* _Nullable)message
|
||||
- (void)sendOnChannel:(nonnull NSString *)channel
|
||||
message:(NSData *_Nullable)message
|
||||
binaryReply:(FlutterBinaryReply _Nullable)callback {
|
||||
if (self.result) {
|
||||
Value* output = [[Value alloc] init];
|
||||
Value *output = [[Value alloc] init];
|
||||
output.number = self.result;
|
||||
NSDictionary* outputDictionary = [output toMap];
|
||||
callback([_codec encode:outputDictionary]);
|
||||
callback([_codec encode:output]);
|
||||
}
|
||||
}
|
||||
|
||||
- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(nonnull NSString*)channel
|
||||
- (FlutterBinaryMessengerConnection)setMessageHandlerOnChannel:(nonnull NSString *)channel
|
||||
binaryMessageHandler:
|
||||
(FlutterBinaryMessageHandler _Nullable)handler {
|
||||
_handlers[channel] = [handler copy];
|
||||
@ -59,17 +59,17 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@interface MockApi2Host : NSObject<Api2Host>
|
||||
@property(nonatomic, copy) NSNumber* output;
|
||||
@property(nonatomic, retain) FlutterError* voidVoidError;
|
||||
@property(nonatomic, copy) NSNumber *output;
|
||||
@property(nonatomic, retain) FlutterError *voidVoidError;
|
||||
@end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@implementation MockApi2Host
|
||||
|
||||
- (void)calculate:(Value* _Nullable)input
|
||||
completion:(nonnull void (^)(Value* _Nullable, FlutterError* _Nullable))completion {
|
||||
- (void)calculate:(Value *_Nullable)input
|
||||
completion:(nonnull void (^)(Value *_Nullable, FlutterError *_Nullable))completion {
|
||||
if (self.output) {
|
||||
Value* output = [[Value alloc] init];
|
||||
Value *output = [[Value alloc] init];
|
||||
output.number = self.output;
|
||||
completion(output, nil);
|
||||
} else {
|
||||
@ -77,7 +77,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (void)voidVoid:(nonnull void (^)(FlutterError* _Nullable))completion {
|
||||
- (void)voidVoid:(nonnull void (^)(FlutterError *_Nullable))completion {
|
||||
completion(self.voidVoidError);
|
||||
}
|
||||
|
||||
@ -91,14 +91,15 @@
|
||||
@implementation AsyncHandlersTest
|
||||
|
||||
- (void)testAsyncHost2Flutter {
|
||||
MockBinaryMessenger* binaryMessenger = [[MockBinaryMessenger alloc] init];
|
||||
MockBinaryMessenger *binaryMessenger =
|
||||
[[MockBinaryMessenger alloc] initWithCodec:Api2FlutterGetCodec()];
|
||||
binaryMessenger.result = @(2);
|
||||
Api2Flutter* api2Flutter = [[Api2Flutter alloc] initWithBinaryMessenger:binaryMessenger];
|
||||
Value* input = [[Value alloc] init];
|
||||
Api2Flutter *api2Flutter = [[Api2Flutter alloc] initWithBinaryMessenger:binaryMessenger];
|
||||
Value *input = [[Value alloc] init];
|
||||
input.number = @(1);
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"calculate callback"];
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"calculate callback"];
|
||||
[api2Flutter calculate:input
|
||||
completion:^(Value* _Nonnull output, NSError* _Nullable error) {
|
||||
completion:^(Value *_Nonnull output, NSError *_Nullable error) {
|
||||
XCTAssertEqual(output.number.intValue, 2);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
@ -106,16 +107,17 @@
|
||||
}
|
||||
|
||||
- (void)testAsyncFlutter2HostVoidVoid {
|
||||
MockBinaryMessenger* binaryMessenger = [[MockBinaryMessenger alloc] init];
|
||||
MockApi2Host* mockApi2Host = [[MockApi2Host alloc] init];
|
||||
MockBinaryMessenger *binaryMessenger =
|
||||
[[MockBinaryMessenger alloc] initWithCodec:Api2HostGetCodec()];
|
||||
MockApi2Host *mockApi2Host = [[MockApi2Host alloc] init];
|
||||
mockApi2Host.output = @(2);
|
||||
Api2HostSetup(binaryMessenger, mockApi2Host);
|
||||
NSString* channelName = @"dev.flutter.pigeon.Api2Host.voidVoid";
|
||||
NSString *channelName = @"dev.flutter.pigeon.Api2Host.voidVoid";
|
||||
XCTAssertNotNil(binaryMessenger.handlers[channelName]);
|
||||
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"voidvoid callback"];
|
||||
binaryMessenger.handlers[channelName](nil, ^(NSData* data) {
|
||||
NSDictionary* outputMap = [binaryMessenger.codec decode:data];
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"voidvoid callback"];
|
||||
binaryMessenger.handlers[channelName](nil, ^(NSData *data) {
|
||||
NSDictionary *outputMap = [binaryMessenger.codec decode:data];
|
||||
XCTAssertEqualObjects(outputMap[@"result"], [NSNull null]);
|
||||
XCTAssertEqualObjects(outputMap[@"error"], [NSNull null]);
|
||||
[expectation fulfill];
|
||||
@ -124,16 +126,17 @@
|
||||
}
|
||||
|
||||
- (void)testAsyncFlutter2HostVoidVoidError {
|
||||
MockBinaryMessenger* binaryMessenger = [[MockBinaryMessenger alloc] init];
|
||||
MockApi2Host* mockApi2Host = [[MockApi2Host alloc] init];
|
||||
MockBinaryMessenger *binaryMessenger =
|
||||
[[MockBinaryMessenger alloc] initWithCodec:Api2HostGetCodec()];
|
||||
MockApi2Host *mockApi2Host = [[MockApi2Host alloc] init];
|
||||
mockApi2Host.voidVoidError = [FlutterError errorWithCode:@"code" message:@"message" details:nil];
|
||||
Api2HostSetup(binaryMessenger, mockApi2Host);
|
||||
NSString* channelName = @"dev.flutter.pigeon.Api2Host.voidVoid";
|
||||
NSString *channelName = @"dev.flutter.pigeon.Api2Host.voidVoid";
|
||||
XCTAssertNotNil(binaryMessenger.handlers[channelName]);
|
||||
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"voidvoid callback"];
|
||||
binaryMessenger.handlers[channelName](nil, ^(NSData* data) {
|
||||
NSDictionary* outputMap = [binaryMessenger.codec decode:data];
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"voidvoid callback"];
|
||||
binaryMessenger.handlers[channelName](nil, ^(NSData *data) {
|
||||
NSDictionary *outputMap = [binaryMessenger.codec decode:data];
|
||||
XCTAssertNotNil(outputMap[@"error"]);
|
||||
XCTAssertEqualObjects(outputMap[@"error"][@"code"], mockApi2Host.voidVoidError.code);
|
||||
[expectation fulfill];
|
||||
@ -142,20 +145,21 @@
|
||||
}
|
||||
|
||||
- (void)testAsyncFlutter2Host {
|
||||
MockBinaryMessenger* binaryMessenger = [[MockBinaryMessenger alloc] init];
|
||||
MockApi2Host* mockApi2Host = [[MockApi2Host alloc] init];
|
||||
MockBinaryMessenger *binaryMessenger =
|
||||
[[MockBinaryMessenger alloc] initWithCodec:Api2HostGetCodec()];
|
||||
MockApi2Host *mockApi2Host = [[MockApi2Host alloc] init];
|
||||
mockApi2Host.output = @(2);
|
||||
Api2HostSetup(binaryMessenger, mockApi2Host);
|
||||
NSString* channelName = @"dev.flutter.pigeon.Api2Host.calculate";
|
||||
NSString *channelName = @"dev.flutter.pigeon.Api2Host.calculate";
|
||||
XCTAssertNotNil(binaryMessenger.handlers[channelName]);
|
||||
|
||||
Value* input = [[Value alloc] init];
|
||||
Value *input = [[Value alloc] init];
|
||||
input.number = @(1);
|
||||
NSData* inputEncoded = [binaryMessenger.codec encode:[input toMap]];
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"calculate callback"];
|
||||
binaryMessenger.handlers[channelName](inputEncoded, ^(NSData* data) {
|
||||
NSDictionary* outputMap = [binaryMessenger.codec decode:data];
|
||||
Value* output = [Value fromMap:outputMap[@"result"]];
|
||||
NSData *inputEncoded = [binaryMessenger.codec encode:input];
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"calculate callback"];
|
||||
binaryMessenger.handlers[channelName](inputEncoded, ^(NSData *data) {
|
||||
NSDictionary *outputMap = [binaryMessenger.codec decode:data];
|
||||
Value *output = outputMap[@"result"];
|
||||
XCTAssertEqual(output.number.intValue, 2);
|
||||
[expectation fulfill];
|
||||
});
|
||||
@ -163,18 +167,19 @@
|
||||
}
|
||||
|
||||
- (void)testAsyncFlutter2HostError {
|
||||
MockBinaryMessenger* binaryMessenger = [[MockBinaryMessenger alloc] init];
|
||||
MockApi2Host* mockApi2Host = [[MockApi2Host alloc] init];
|
||||
MockBinaryMessenger *binaryMessenger =
|
||||
[[MockBinaryMessenger alloc] initWithCodec:Api2HostGetCodec()];
|
||||
MockApi2Host *mockApi2Host = [[MockApi2Host alloc] init];
|
||||
Api2HostSetup(binaryMessenger, mockApi2Host);
|
||||
NSString* channelName = @"dev.flutter.pigeon.Api2Host.calculate";
|
||||
NSString *channelName = @"dev.flutter.pigeon.Api2Host.calculate";
|
||||
XCTAssertNotNil(binaryMessenger.handlers[channelName]);
|
||||
|
||||
Value* input = [[Value alloc] init];
|
||||
Value *input = [[Value alloc] init];
|
||||
input.number = @(1);
|
||||
NSData* inputEncoded = [binaryMessenger.codec encode:[input toMap]];
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"calculate callback"];
|
||||
binaryMessenger.handlers[channelName](inputEncoded, ^(NSData* data) {
|
||||
NSDictionary* outputMap = [binaryMessenger.codec decode:data];
|
||||
NSData *inputEncoded = [binaryMessenger.codec encode:[input toMap]];
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@"calculate callback"];
|
||||
binaryMessenger.handlers[channelName](inputEncoded, ^(NSData *data) {
|
||||
NSDictionary *outputMap = [binaryMessenger.codec decode:data];
|
||||
XCTAssertNotNil(outputMap[@"error"]);
|
||||
[expectation fulfill];
|
||||
});
|
||||
|
@ -0,0 +1,94 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#import <Flutter/Flutter.h>
|
||||
#import <XCTest/XCTest.h>
|
||||
#import "EchoMessenger.h"
|
||||
#import "primitive.gen.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@interface PrimitiveTest : XCTestCase
|
||||
@end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@implementation PrimitiveTest
|
||||
|
||||
- (void)testIntPrimitive {
|
||||
EchoBinaryMessenger* binaryMessenger = [[EchoBinaryMessenger alloc] init];
|
||||
PrimitiveFlutterApi* api = [[PrimitiveFlutterApi alloc] initWithBinaryMessenger:binaryMessenger];
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"callback"];
|
||||
[api anInt:@1
|
||||
completion:^(NSNumber* _Nonnull result, NSError* _Nullable err) {
|
||||
XCTAssertEqualObjects(@1, result);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ expectation ] timeout:1.0];
|
||||
}
|
||||
|
||||
- (void)testBoolPrimitive {
|
||||
EchoBinaryMessenger* binaryMessenger = [[EchoBinaryMessenger alloc] init];
|
||||
PrimitiveFlutterApi* api = [[PrimitiveFlutterApi alloc] initWithBinaryMessenger:binaryMessenger];
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"callback"];
|
||||
NSNumber* arg = @YES;
|
||||
[api aBool:arg
|
||||
completion:^(NSNumber* _Nonnull result, NSError* _Nullable err) {
|
||||
XCTAssertEqualObjects(arg, result);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ expectation ] timeout:1.0];
|
||||
}
|
||||
|
||||
- (void)testDoublePrimitive {
|
||||
EchoBinaryMessenger* binaryMessenger = [[EchoBinaryMessenger alloc] init];
|
||||
PrimitiveFlutterApi* api = [[PrimitiveFlutterApi alloc] initWithBinaryMessenger:binaryMessenger];
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"callback"];
|
||||
NSNumber* arg = @(1.5);
|
||||
[api aBool:arg
|
||||
completion:^(NSNumber* _Nonnull result, NSError* _Nullable err) {
|
||||
XCTAssertEqualObjects(arg, result);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ expectation ] timeout:1.0];
|
||||
}
|
||||
|
||||
- (void)testStringPrimitive {
|
||||
EchoBinaryMessenger* binaryMessenger = [[EchoBinaryMessenger alloc] init];
|
||||
PrimitiveFlutterApi* api = [[PrimitiveFlutterApi alloc] initWithBinaryMessenger:binaryMessenger];
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"callback"];
|
||||
NSString* arg = @"hello";
|
||||
[api aString:arg
|
||||
completion:^(NSString* _Nonnull result, NSError* _Nullable err) {
|
||||
XCTAssertEqualObjects(arg, result);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ expectation ] timeout:1.0];
|
||||
}
|
||||
|
||||
- (void)testListPrimitive {
|
||||
EchoBinaryMessenger* binaryMessenger = [[EchoBinaryMessenger alloc] init];
|
||||
PrimitiveFlutterApi* api = [[PrimitiveFlutterApi alloc] initWithBinaryMessenger:binaryMessenger];
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"callback"];
|
||||
NSArray* arg = @[ @"hello" ];
|
||||
[api aList:arg
|
||||
completion:^(NSArray* _Nonnull result, NSError* _Nullable err) {
|
||||
XCTAssertEqualObjects(arg, result);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ expectation ] timeout:1.0];
|
||||
}
|
||||
|
||||
- (void)testMapPrimitive {
|
||||
EchoBinaryMessenger* binaryMessenger = [[EchoBinaryMessenger alloc] init];
|
||||
PrimitiveFlutterApi* api = [[PrimitiveFlutterApi alloc] initWithBinaryMessenger:binaryMessenger];
|
||||
XCTestExpectation* expectation = [self expectationWithDescription:@"callback"];
|
||||
NSDictionary* arg = @{ @"hello" : @1 };
|
||||
[api aMap:arg
|
||||
completion:^(NSDictionary* _Nonnull result, NSError* _Nullable err) {
|
||||
XCTAssertEqualObjects(arg, result);
|
||||
[expectation fulfill];
|
||||
}];
|
||||
[self waitForExpectations:@[ expectation ] timeout:1.0];
|
||||
}
|
||||
|
||||
@end
|
@ -249,6 +249,7 @@ run_ios_unittests() {
|
||||
gen_ios_unittests_code ./pigeons/host2flutter.dart ""
|
||||
gen_ios_unittests_code ./pigeons/list.dart "LST"
|
||||
gen_ios_unittests_code ./pigeons/message.dart ""
|
||||
gen_ios_unittests_code ./pigeons/primitive.dart ""
|
||||
gen_ios_unittests_code ./pigeons/void_arg_flutter.dart "VAF"
|
||||
gen_ios_unittests_code ./pigeons/void_arg_host.dart "VAH"
|
||||
gen_ios_unittests_code ./pigeons/voidflutter.dart "VF"
|
||||
@ -302,6 +303,7 @@ run_android_unittests() {
|
||||
gen_android_unittests_code ./pigeons/java_double_host_api.dart JavaDoubleHostApi
|
||||
gen_android_unittests_code ./pigeons/list.dart PigeonList
|
||||
gen_android_unittests_code ./pigeons/message.dart MessagePigeon
|
||||
gen_android_unittests_code ./pigeons/primitive.dart Primitive
|
||||
gen_android_unittests_code ./pigeons/void_arg_flutter.dart VoidArgFlutter
|
||||
gen_android_unittests_code ./pigeons/void_arg_host.dart VoidArgHost
|
||||
gen_android_unittests_code ./pigeons/voidflutter.dart VoidFlutter
|
||||
|
@ -392,7 +392,7 @@ void main() {
|
||||
expect(mainCode, contains('class Api {'));
|
||||
expect(mainCode, isNot(contains('abstract class ApiMock')));
|
||||
expect(mainCode, isNot(contains('.ApiMock.doSomething')));
|
||||
expect(mainCode, isNot(contains('\'${Keys.result}\': output.encode()')));
|
||||
expect(mainCode, isNot(contains('\'${Keys.result}\': output')));
|
||||
expect(mainCode, isNot(contains('return <Object, Object>{};')));
|
||||
generateTestDart(
|
||||
const DartOptions(isNullSafe: false), root, testCodeSink, "fo'o.dart");
|
||||
@ -401,7 +401,7 @@ void main() {
|
||||
expect(testCode, isNot(contains('class Api {')));
|
||||
expect(testCode, contains('abstract class ApiMock'));
|
||||
expect(testCode, isNot(contains('.ApiMock.doSomething')));
|
||||
expect(testCode, contains('\'${Keys.result}\': output.encode()'));
|
||||
expect(testCode, contains('\'${Keys.result}\': output'));
|
||||
expect(testCode, contains('return <Object, Object>{};'));
|
||||
});
|
||||
|
||||
|
@ -357,7 +357,7 @@ void main() {
|
||||
expect(
|
||||
code,
|
||||
contains(
|
||||
'api.doSomething(input, result -> { wrapped.put("result", result.toMap()); reply.reply(wrapped); });'));
|
||||
'api.doSomething(input, result -> { wrapped.put("result", result); reply.reply(wrapped); });'));
|
||||
expect(code, contains('channel.setMessageHandler(null)'));
|
||||
});
|
||||
|
||||
|
@ -409,7 +409,7 @@ void main() {
|
||||
generateObjcSource(const ObjcOptions(prefix: 'ABC'), root, sink);
|
||||
final String code = sink.toString();
|
||||
expect(code, contains('ABCInput fromMap'));
|
||||
expect(code, matches('ABCInput.*=.*ABCInput fromMap'));
|
||||
expect(code, matches('ABCInput.*=.*message'));
|
||||
expect(code, contains('void ABCApiSetup('));
|
||||
});
|
||||
|
||||
|
@ -307,28 +307,6 @@ abstract class NestorApi {
|
||||
expect(classNames.contains('OnlyVisibleFromNesting'), true);
|
||||
});
|
||||
|
||||
test('invalid datatype for argument', () {
|
||||
const String code = '''
|
||||
@HostApi()
|
||||
abstract class InvalidArgTypeApi {
|
||||
void doit(bool value);
|
||||
}
|
||||
''';
|
||||
final ParseResults results = _parseSource(code);
|
||||
expect(results.errors.length, 1);
|
||||
});
|
||||
|
||||
test('invalid datatype for argument', () {
|
||||
const String code = '''
|
||||
@HostApi()
|
||||
abstract class InvalidReturnTypeApi {
|
||||
bool doit();
|
||||
}
|
||||
''';
|
||||
final ParseResults results = _parseSource(code);
|
||||
expect(results.errors.length, 1);
|
||||
});
|
||||
|
||||
test('null safety flag', () {
|
||||
final PigeonOptions results =
|
||||
Pigeon.parseArgs(<String>['--dart_null_safety']);
|
||||
@ -546,32 +524,6 @@ abstract class Api {
|
||||
expect(results.errors[0].message, contains('Nullable'));
|
||||
});
|
||||
|
||||
test('primitive arguments', () {
|
||||
const String code = '''
|
||||
@HostApi()
|
||||
abstract class Api {
|
||||
void doit(int foo);
|
||||
}
|
||||
''';
|
||||
final ParseResults results = _parseSource(code);
|
||||
expect(results.errors.length, 1);
|
||||
expect(results.errors[0].lineNumber, 3);
|
||||
expect(results.errors[0].message, contains('Primitive'));
|
||||
});
|
||||
|
||||
test('primitive return', () {
|
||||
const String code = '''
|
||||
@HostApi()
|
||||
abstract class Api {
|
||||
int doit();
|
||||
}
|
||||
''';
|
||||
final ParseResults results = _parseSource(code);
|
||||
expect(results.errors.length, 1);
|
||||
expect(results.errors[0].lineNumber, 3);
|
||||
expect(results.errors[0].message, contains('Primitive'));
|
||||
});
|
||||
|
||||
test('test invalid import', () {
|
||||
const String code = 'import \'foo.dart\';\n';
|
||||
final ParseResults results = _parseSource(code);
|
||||
|
Reference in New Issue
Block a user