[pigeon] implemented primitive datatypes (#414)
diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md
index 5bca85d..6be42dc 100644
--- a/packages/pigeon/CHANGELOG.md
+++ b/packages/pigeon/CHANGELOG.md
@@ -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
diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart
index 8e6d59b..c231135 100644
--- a/packages/pigeon/lib/dart_generator.dart
+++ b/packages/pigeon/lib/dart_generator.dart
@@ -121,19 +121,14 @@
}
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 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 @@
'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 @@
} 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;';
diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart
index e5f07d9..560bcd1 100644
--- a/packages/pigeon/lib/generator_tools.dart
+++ b/packages/pigeon/lib/generator_tools.dart
@@ -262,6 +262,20 @@
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 @@
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;
diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart
index d53c829..eae2cea 100644
--- a/packages/pigeon/lib/java_generator.dart
+++ b/packages/pigeon/lib/java_generator.dart
@@ -113,6 +113,22 @@
});
}
+/// 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 @@
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 @@
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 @@
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 @@
''');
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 @@
'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);');
}
});
diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart
index c46708f..77612a4 100644
--- a/packages/pigeon/lib/objc_generator.dart
+++ b/packages/pigeon/lib/objc_generator.dart
@@ -67,16 +67,16 @@
}
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 @@
'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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
'[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 @@
});
}
} 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 @@
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 @@
});
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 @@
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 @@
'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 @@
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 = @{
diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart
index f04ae1d..a125222 100644
--- a/packages/pigeon/lib/pigeon_lib.dart
+++ b/packages/pigeon/lib/pigeon_lib.dart
@@ -25,19 +25,6 @@
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 @@
'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 @@
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 @@
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);
}
diff --git a/packages/pigeon/pigeons/flutter_unittests.dart b/packages/pigeon/pigeons/flutter_unittests.dart
index cb99095..de66fed 100644
--- a/packages/pigeon/pigeons/flutter_unittests.dart
+++ b/packages/pigeon/pigeons/flutter_unittests.dart
@@ -28,4 +28,5 @@
SearchReply search(SearchRequest request);
SearchReplies doSearches(SearchRequests request);
SearchRequests echo(SearchRequests requests);
+ int anInt(int value);
}
diff --git a/packages/pigeon/pigeons/primitive.dart b/packages/pigeon/pigeons/primitive.dart
new file mode 100644
index 0000000..2b45353
--- /dev/null
+++ b/packages/pigeon/pigeons/primitive.dart
@@ -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);
+}
diff --git a/packages/pigeon/platform_tests/android_unit_tests/android/.project b/packages/pigeon/platform_tests/android_unit_tests/android/.project
new file mode 100644
index 0000000..fe67538
--- /dev/null
+++ b/packages/pigeon/platform_tests/android_unit_tests/android/.project
@@ -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>
diff --git a/packages/pigeon/platform_tests/android_unit_tests/android/.settings/org.eclipse.buildship.core.prefs b/packages/pigeon/platform_tests/android_unit_tests/android/.settings/org.eclipse.buildship.core.prefs
new file mode 100644
index 0000000..51db0ab
--- /dev/null
+++ b/packages/pigeon/platform_tests/android_unit_tests/android/.settings/org.eclipse.buildship.core.prefs
@@ -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
diff --git a/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PigeonTest.java b/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PigeonTest.java
index 24b5724..196871d 100644
--- a/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PigeonTest.java
+++ b/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PigeonTest.java
@@ -9,15 +9,12 @@
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 @@
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 @@
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()
diff --git a/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PrimitiveTest.java b/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PrimitiveTest.java
new file mode 100644
index 0000000..36ce51c
--- /dev/null
+++ b/packages/pigeon/platform_tests/android_unit_tests/android/app/src/test/java/com/example/android_unit_tests/PrimitiveTest.java
@@ -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]);
+ }
+}
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/all_datatypes.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/all_datatypes.dart
index 5ad97e5..09db457 100644
--- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/all_datatypes.dart
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/all_datatypes.dart
@@ -60,7 +60,7 @@
@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 @@
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
- case 255:
+ case 128:
return Everything.decode(readValue(buffer)!);
default:
@@ -111,17 +111,16 @@
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 @@
details: error['details'],
);
} else {
- return Everything.decode(replyMap['result']!);
+ return (replyMap['result'] as Everything?)!;
}
}
}
@@ -147,7 +146,7 @@
@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 @@
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
- case 255:
+ case 128:
return Everything.decode(readValue(buffer)!);
default:
@@ -181,7 +180,7 @@
channel.setMessageHandler((Object? message) async {
// ignore message
final Everything output = api.giveMeEverything();
- return output.encode();
+ return output;
});
}
}
@@ -194,9 +193,9 @@
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;
});
}
}
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart
index 5445ab2..044bd03 100644
--- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart
@@ -81,16 +81,16 @@
@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 @@
@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 @@
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 @@
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 @@
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 @@
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?)!;
}
}
}
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/all_datatypes_test.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/all_datatypes_test.dart
index b886c77..7061fb8 100644
--- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/all_datatypes_test.dart
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/all_datatypes_test.dart
@@ -18,9 +18,9 @@
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 @@
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!});
diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart
index 769625c..08809d5 100644
--- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart
+++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/null_safe_test.dart
@@ -38,8 +38,8 @@
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 @@
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);
+ });
}
diff --git a/packages/pigeon/platform_tests/ios_unit_tests/ios/Flutter/AppFrameworkInfo.plist b/packages/pigeon/platform_tests/ios_unit_tests/ios/Flutter/AppFrameworkInfo.plist
index 6b4c0f7..f2872cf 100644
--- a/packages/pigeon/platform_tests/ios_unit_tests/ios/Flutter/AppFrameworkInfo.plist
+++ b/packages/pigeon/platform_tests/ios_unit_tests/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
- <string>8.0</string>
+ <string>9.0</string>
</dict>
</plist>
diff --git a/packages/pigeon/platform_tests/ios_unit_tests/ios/Runner.xcodeproj/project.pbxproj b/packages/pigeon/platform_tests/ios_unit_tests/ios/Runner.xcodeproj/project.pbxproj
index 1e35915..43466c9 100644
--- a/packages/pigeon/platform_tests/ios_unit_tests/ios/Runner.xcodeproj/project.pbxproj
+++ b/packages/pigeon/platform_tests/ios_unit_tests/ios/Runner.xcodeproj/project.pbxproj
@@ -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;
diff --git a/packages/pigeon/platform_tests/ios_unit_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/packages/pigeon/platform_tests/ios_unit_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
new file mode 100644
index 0000000..18d9810
--- /dev/null
+++ b/packages/pigeon/platform_tests/ios_unit_tests/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -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>
diff --git a/packages/pigeon/platform_tests/ios_unit_tests/ios/RunnerTests/AsyncHandlersTest.m b/packages/pigeon/platform_tests/ios_unit_tests/ios/RunnerTests/AsyncHandlersTest.m
index 88214ae..83ecd79 100644
--- a/packages/pigeon/platform_tests/ios_unit_tests/ios/RunnerTests/AsyncHandlersTest.m
+++ b/packages/pigeon/platform_tests/ios_unit_tests/ios/RunnerTests/AsyncHandlersTest.m
@@ -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];
});
diff --git a/packages/pigeon/platform_tests/ios_unit_tests/ios/RunnerTests/PrimitiveTest.m b/packages/pigeon/platform_tests/ios_unit_tests/ios/RunnerTests/PrimitiveTest.m
new file mode 100644
index 0000000..26fb77c
--- /dev/null
+++ b/packages/pigeon/platform_tests/ios_unit_tests/ios/RunnerTests/PrimitiveTest.m
@@ -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
diff --git a/packages/pigeon/run_tests.sh b/packages/pigeon/run_tests.sh
index af121e4..3419675 100755
--- a/packages/pigeon/run_tests.sh
+++ b/packages/pigeon/run_tests.sh
@@ -249,6 +249,7 @@
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 @@
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
diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart
index c26e85d..04b3488 100644
--- a/packages/pigeon/test/dart_generator_test.dart
+++ b/packages/pigeon/test/dart_generator_test.dart
@@ -392,7 +392,7 @@
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 @@
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>{};'));
});
diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart
index 84276b0..4ac1ab6 100644
--- a/packages/pigeon/test/java_generator_test.dart
+++ b/packages/pigeon/test/java_generator_test.dart
@@ -357,7 +357,7 @@
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)'));
});
diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart
index 383e84e..8acf439 100644
--- a/packages/pigeon/test/objc_generator_test.dart
+++ b/packages/pigeon/test/objc_generator_test.dart
@@ -409,7 +409,7 @@
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('));
});
diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart
index c716b8a..6aba0a0 100644
--- a/packages/pigeon/test/pigeon_lib_test.dart
+++ b/packages/pigeon/test/pigeon_lib_test.dart
@@ -307,28 +307,6 @@
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 @@
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);