From 43da42efb002cdb8b8e85e4a840b7d5f3f48dca9 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 21 Jul 2021 15:34:29 -0700 Subject: [PATCH 01/30] [pigeon] implemented generics --- packages/pigeon/lib/ast.dart | 28 +++++++- packages/pigeon/lib/dart_generator.dart | 22 +++++-- packages/pigeon/lib/pigeon_lib.dart | 49 ++++++++------ packages/pigeon/test/dart_generator_test.dart | 24 +++++++ packages/pigeon/test/pigeon_lib_test.dart | 66 +++++++++++++++---- 5 files changed, 147 insertions(+), 42 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index bfc438fe8de5..3c8f0d4d78b2 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -82,6 +82,30 @@ class Api extends Node { } } +/// A parameter to a generic entity. +class TypeArgument { + /// Constructor for [TypeArgument]. + TypeArgument({ + required this.dataType, + required this.isNullable, + this.typeArguments, + }); + + /// A string representation of the base datatype. + final String dataType; + + /// The type arguments to [TypeArgument]. + final List? typeArguments; + + /// True if the type is nullable. + final bool isNullable; + + @override + String toString() { + return '(TypeArgument dataType:$dataType isNullable:$isNullable typeArguments:$typeArguments)'; + } +} + /// Represents a field on a [Class]. class Field extends Node { /// Parametric constructor for [Field]. @@ -106,11 +130,11 @@ class Field extends Node { bool isNullable; /// Type parameters used for generics. - List? typeArguments; + List? typeArguments; @override String toString() { - return '(Field name:$name dataType:$dataType)'; + return '(Field name:$name dataType:$dataType typeArguments:$typeArguments)'; } } diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index c2311352b8a4..bce38946dd86 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -263,14 +263,24 @@ void _writeFlutterApi( }); } -String _addGenericTypes(String dataType, String nullTag) { - switch (dataType) { +String _flattenTypeArguments(List args, String nullTag) { + return args + .map((TypeArgument arg) => arg.typeArguments == null + ? '${arg.dataType}$nullTag' + : '${arg.dataType}<${_flattenTypeArguments(arg.typeArguments!, nullTag)}>$nullTag') + .reduce((String value, String element) => '$value, $element'); +} + +String _addGenericTypes(Field field, String nullTag) { + switch (field.dataType) { case 'List': - return 'List$nullTag'; + return (field.typeArguments == null) + ? 'List$nullTag' + : 'List<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; case 'Map': return 'Map$nullTag'; default: - return '$dataType$nullTag'; + return '${field.dataType}$nullTag'; } } @@ -315,7 +325,7 @@ void generateDart(DartOptions opt, Root root, StringSink sink) { indent.write('class ${klass.name} '); indent.scoped('{', '}', () { for (final Field field in klass.fields) { - final String datatype = _addGenericTypes(field.dataType, nullTag); + final String datatype = _addGenericTypes(field, nullTag); indent.writeln('$datatype ${field.name};'); } if (klass.fields.isNotEmpty) { @@ -367,7 +377,7 @@ pigeonMap['${field.name}'] != null \t\t: null''', leadingSpace: false, trailingNewline: false); } else { indent.add( - 'pigeonMap[\'${field.name}\'] as ${_addGenericTypes(field.dataType, nullTag)}', + 'pigeonMap[\'${field.name}\'] as ${_addGenericTypes(field, nullTag)}', ); } indent.addln(index == klass.fields.length - 1 ? ';' : ''); diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index a1252226f29b..a16fe87d91a1 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -379,12 +379,17 @@ List _validateAst(Root root, String source) { for (final Class klass in root.classes) { for (final Field field in klass.fields) { if (field.typeArguments != null) { - result.add(Error( - message: - '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) || + for (final TypeArgument typeArgument in field.typeArguments!) { + if (!typeArgument.isNullable) { + result.add(Error( + message: + 'Generic type arguments must be nullable in field "${field.name}" in class "${klass.name}".', + lineNumber: _calculateLineNumberNullable(source, field.offset), + )); + } + } + } + if (!(validTypes.contains(field.dataType) || customClasses.contains(field.dataType) || customEnums.contains(field.dataType))) { result.add(Error( @@ -660,6 +665,23 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { return null; } + List? typeAnnotationsToTypeArguments( + dart_ast.TypeArgumentList? typeArguments) { + List? result; + if (typeArguments != null) { + for (final Object x in typeArguments.childEntities) { + if (x is dart_ast.TypeName) { + result ??= []; + result.add(TypeArgument( + dataType: x.name.name, + isNullable: x.question != null, + typeArguments: typeAnnotationsToTypeArguments(x.typeArguments))); + } + } + } + return result; + } + @override Object? visitFieldDeclaration(dart_ast.FieldDeclaration node) { if (_currentClass != null) { @@ -683,20 +705,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { name: node.fields.variables[0].name.name, dataType: type.name.name, isNullable: type.question != null, - // TODO(aaclarke): This probably has to be recursive at some point. - // ignore: prefer_null_aware_operators - typeArguments: typeArguments == null - ? null - : typeArguments.arguments - .map((dart_ast.TypeAnnotation e) => Field( - name: '', - dataType: (e.childEntities.first - as dart_ast.SimpleIdentifier) - .name, - isNullable: e.question != null, - offset: e.offset, - )) - .toList(), + typeArguments: typeAnnotationsToTypeArguments(typeArguments), offset: node.offset, )); } diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 04b3488b303d..704b0ed1e772 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -574,4 +574,28 @@ void main() { final String code = sink.toString(); expect(code, startsWith('// hello world')); }); + + test('generics', () { + final Class klass = Class( + name: 'Foobar', + fields: [ + Field( + name: 'field1', + dataType: 'List', + isNullable: true, + typeArguments: [TypeArgument(dataType: 'int', isNullable: true)], + ), + ], + ); + final Root root = Root( + apis: [], + classes: [klass], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + generateDart(const DartOptions(isNullSafe: true), root, sink); + final String code = sink.toString(); + expect(code, contains('class Foobar')); + expect(code, contains(' List? field1;')); + }); } diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 6aba0a002f30..850584c861c0 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -537,38 +537,76 @@ abstract class Api { expect(parseResults.errors.length, 0); }); - test('error with generics', () { + test('error with static field', () { const String code = ''' -class WithTemplate { - List? list; +class WithStaticField { + static int? x; + int? y; } @HostApi() -abstract class WithTemplateApi { - void doit(WithTemplate withTemplate); +abstract class WithStaticFieldApi { + void doit(WithStaticField withTemplate); } '''; final ParseResults parseResult = _parseSource(code); expect(parseResult.errors.length, equals(1)); - expect(parseResult.errors[0].message, contains('Generic fields')); + expect(parseResult.errors[0].message, contains('static field')); expect(parseResult.errors[0].lineNumber, isNotNull); }); - test('error with static field', () { + test('parse generics', () { const String code = ''' -class WithStaticField { - static int? x; - int? y; +class Foo { + List? list; } @HostApi() -abstract class WithStaticFieldApi { - void doit(WithStaticField withTemplate); +abstract class Api { + void doit(Foo foo); +} +'''; + final ParseResults parseResult = _parseSource(code); + expect(parseResult.errors.length, equals(0)); + final Field field = parseResult.root.classes[0].fields[0]; + expect(field.typeArguments!.length, 1); + expect(field.typeArguments![0].dataType, 'int'); + }); + + test('parse recursive generics', () { + const String code = ''' +class Foo { + List?>? list; +} + +@HostApi() +abstract class Api { + void doit(Foo foo); +} +'''; + final ParseResults parseResult = _parseSource(code); + expect(parseResult.errors.length, equals(0)); + final Field field = parseResult.root.classes[0].fields[0]; + expect(field.typeArguments!.length, 1); + expect(field.typeArguments![0].dataType, 'List'); + expect(field.typeArguments![0].typeArguments![0].dataType, 'int'); + }); + + test('error nonnull type argument', () { + const String code = ''' +class Foo { + List list; +} + +@HostApi() +abstract class Api { + void doit(Foo foo); } '''; final ParseResults parseResult = _parseSource(code); expect(parseResult.errors.length, equals(1)); - expect(parseResult.errors[0].message, contains('static field')); - expect(parseResult.errors[0].lineNumber, isNotNull); + expect(parseResult.errors[0].message, contains('Generic type arguments must be nullable')); + expect(parseResult.errors[0].message, contains('"list"')); + expect(parseResult.errors[0].lineNumber, 2); }); } From 7d4f275d53fa3efe463cca7bb7b49aea71c7161e Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Wed, 21 Jul 2021 16:41:40 -0700 Subject: [PATCH 02/30] implemented generics for java --- packages/pigeon/lib/generator_tools.dart | 4 +- packages/pigeon/lib/java_generator.dart | 46 +++++++++++++------ packages/pigeon/lib/objc_generator.dart | 6 +-- packages/pigeon/test/java_generator_test.dart | 25 ++++++++++ 4 files changed, 61 insertions(+), 20 deletions(-) diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index 560bcd184fbd..e52be610e6b3 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -159,9 +159,9 @@ class HostDatatype { /// `builtinResolver` will return the host datatype for the Dart datatype for /// builtin types. `customResolver` can modify the datatype of custom types. HostDatatype getHostDatatype(Field field, List classes, List enums, - String? Function(String) builtinResolver, + String? Function(Field) builtinResolver, {String Function(String)? customResolver}) { - final String? datatype = builtinResolver(field.dataType); + final String? datatype = builtinResolver(field); if (datatype == null) { if (classes.map((Class x) => x.name).contains(field.dataType)) { final String customName = customResolver != null diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index eae2cea23567..dc65af896234 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -5,19 +5,6 @@ import 'ast.dart'; import 'generator_tools.dart'; -const Map _javaTypeForDartTypeMap = { - 'bool': 'Boolean', - 'int': 'Long', - 'String': 'String', - 'double': 'Double', - 'Uint8List': 'byte[]', - 'Int32List': 'int[]', - 'Int64List': 'long[]', - 'Float64List': 'double[]', - 'List': 'List', - 'Map': 'Map', -}; - /// Options that control how Java code will be generated. class JavaOptions { /// Creates a [JavaOptions] object @@ -313,8 +300,37 @@ String _makeSetter(Field field) { return 'set$uppercased'; } -String? _javaTypeForDartType(String datatype) { - return _javaTypeForDartTypeMap[datatype]; +String _flattenTypeArguments(List args) { + return args + .map((TypeArgument e) => e.typeArguments == null + ? _boxedType(e.dataType) + : '${_boxedType(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') + .reduce((String value, String element) => '$value, $element'); +} + +String? _javaTypeForDartType(Field field) { + const Map javaTypeForDartTypeMap = { + 'bool': 'Boolean', + 'int': 'Long', + 'String': 'String', + 'double': 'Double', + 'Uint8List': 'byte[]', + 'Int32List': 'int[]', + 'Int64List': 'long[]', + 'Float64List': 'double[]', + 'Map': 'Map', + }; + if (javaTypeForDartTypeMap.containsKey(field.dataType)) { + return javaTypeForDartTypeMap[field.dataType]; + } else if (field.dataType == 'List') { + if (field.typeArguments == null) { + return 'List'; + } else { + return 'List<${_flattenTypeArguments(field.typeArguments!)}>'; + } + } else { + return null; + } } String _castObject( diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index 77612a49854f..e84446ee5438 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -92,9 +92,9 @@ const Map _propertyTypeForDartTypeMap = { 'Map': 'strong', }; -String? _objcTypePtrForPrimitiveDartType(String type) { - return _objcTypeForDartTypeMap.containsKey(type) - ? '${_objcTypeForDartTypeMap[type]} *' +String? _objcTypePtrForPrimitiveDartType(Field field) { + return _objcTypeForDartTypeMap.containsKey(field.dataType) + ? '${_objcTypeForDartTypeMap[field.dataType]} *' : null; } diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 4ac1ab63071b..d77d91747d01 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -441,4 +441,29 @@ void main() { final String code = sink.toString(); expect(code, startsWith('// hello world')); }); + + test('generics', () { + final Class klass = Class( + name: 'Foobar', + fields: [ + Field( + name: 'field1', + dataType: 'List', + isNullable: true, + typeArguments: [TypeArgument(dataType: 'int', isNullable: true)], + ), + ], + ); + final Root root = Root( + apis: [], + classes: [klass], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const JavaOptions javaOptions = JavaOptions(className: 'Messages'); + generateJava(javaOptions, root, sink); + final String code = sink.toString(); + expect(code, contains('class Foobar')); + expect(code, contains('List field1;')); + }); } From bd04fa88c0531e9e0be4eeb9b058e4e286649d1a Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 22 Jul 2021 13:55:01 -0700 Subject: [PATCH 03/30] implemented generics for objc --- packages/pigeon/lib/objc_generator.dart | 18 ++++++++++--- packages/pigeon/test/objc_generator_test.dart | 26 +++++++++++++++++++ 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index e84446ee5438..a64b87aeb6d3 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -92,9 +92,19 @@ const Map _propertyTypeForDartTypeMap = { 'Map': 'strong', }; -String? _objcTypePtrForPrimitiveDartType(Field field) { +String _flattenTypeArguments(String? classPrefix, List args) { + return args + .map((TypeArgument e) => e.typeArguments == null + ? '${_objcTypeForDartType(classPrefix, e.dataType)} *' + : '${_objcTypeForDartType(classPrefix, e.dataType)}<${_flattenTypeArguments(classPrefix, e.typeArguments!)}> *') + .reduce((String value, String element) => '$value, $element'); +} + +String? _objcTypePtrForPrimitiveDartType(String? classPrefix, Field field) { return _objcTypeForDartTypeMap.containsKey(field.dataType) - ? '${_objcTypeForDartTypeMap[field.dataType]} *' + ? field.typeArguments == null + ? '${_objcTypeForDartTypeMap[field.dataType]} *' + : '${_objcTypeForDartTypeMap[field.dataType]}<${_flattenTypeArguments(classPrefix, field.typeArguments!)}> *' : null; } @@ -121,8 +131,8 @@ void _writeClassDeclarations( for (final Class klass in classes) { indent.writeln('@interface ${_className(prefix, klass.name)} : NSObject'); for (final Field field in klass.fields) { - final HostDatatype hostDatatype = getHostDatatype( - field, classes, enums, _objcTypePtrForPrimitiveDartType, + final HostDatatype hostDatatype = getHostDatatype(field, classes, enums, + (Field x) => _objcTypePtrForPrimitiveDartType(prefix, x), customResolver: enumNames.contains(field.dataType) ? (String x) => _className(prefix, x) : (String x) => '${_className(prefix, x)} *'); diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 8acf43920cc9..49022bd21ce7 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -1000,4 +1000,30 @@ void main() { final String code = sink.toString(); expect(code, startsWith('// hello world')); }); + + test('generics', () { + final Class klass = Class( + name: 'Foobar', + fields: [ + Field( + name: 'field1', + dataType: 'List', + isNullable: true, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ], + ), + ], + ); + final Root root = Root( + apis: [], + classes: [klass], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + generateObjcHeader( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('NSArray * field1')); + }); } From 3e75a355407fb57ff4e9b4bdc56499b6bf39ecd7 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 22 Jul 2021 14:33:14 -0700 Subject: [PATCH 04/30] started parsing return value generics --- packages/pigeon/lib/ast.dart | 6 +-- packages/pigeon/lib/dart_generator.dart | 12 ++--- packages/pigeon/lib/generator_tools.dart | 2 +- packages/pigeon/lib/java_generator.dart | 19 ++++---- packages/pigeon/lib/objc_generator.dart | 22 +++++----- packages/pigeon/lib/pigeon_lib.dart | 10 +++-- packages/pigeon/test/dart_generator_test.dart | 29 ++++++------ packages/pigeon/test/java_generator_test.dart | 16 +++---- packages/pigeon/test/objc_generator_test.dart | 44 +++++++++---------- packages/pigeon/test/pigeon_lib_test.dart | 17 +++++-- 10 files changed, 94 insertions(+), 83 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index 3c8f0d4d78b2..f10c914e5955 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -23,7 +23,6 @@ class Method extends Node { required this.argType, this.isArgNullable = false, this.isAsynchronous = false, - this.isReturnNullable = false, this.offset, }); @@ -31,10 +30,7 @@ class Method extends Node { String name; /// The data-type of the return value. - String returnType; - - /// True if the method can return a null value. - bool isReturnNullable; + Field returnType; /// The data-type of the argument. String argType; diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index bce38946dd86..c26d87649574 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -126,7 +126,7 @@ final BinaryMessenger$nullTag _binaryMessenger; sendArgument = 'arg'; } indent.write( - 'Future<${func.returnType}> ${func.name}($argSignature) async ', + 'Future<${func.returnType.dataType}> ${func.name}($argSignature) async ', ); indent.scoped('{', '}', () { final String channelName = makeChannelName(api, func); @@ -137,9 +137,9 @@ final BinaryMessenger$nullTag _binaryMessenger; '\'$channelName\', codec, binaryMessenger: _binaryMessenger);', ); }); - final String returnStatement = func.returnType == 'void' + final String returnStatement = func.returnType.dataType == 'void' ? '// noop' - : 'return (replyMap[\'${Keys.result}\'] as ${func.returnType}$nullTag)$unwrapOperator;'; + : 'return (replyMap[\'${Keys.result}\'] as ${func.returnType.dataType}$nullTag)$unwrapOperator;'; indent.format(''' final Map$nullTag replyMap =\n\t\tawait channel.send($sendArgument) as Map$nullTag; if (replyMap == null) { @@ -182,7 +182,7 @@ void _writeFlutterApi( for (final Method func in api.methods) { final bool isAsync = func.isAsynchronous; final String returnType = - isAsync ? 'Future<${func.returnType}>' : func.returnType; + isAsync ? 'Future<${func.returnType.dataType}>' : func.returnType.dataType; final String argSignature = func.argType == 'void' ? '' : '${func.argType} arg'; indent.writeln('$returnType ${func.name}($argSignature);'); @@ -216,11 +216,11 @@ void _writeFlutterApi( ); indent.scoped('{', '});', () { final String argType = func.argType; - final String returnType = func.returnType; + final String returnType = func.returnType.dataType; final bool isAsync = func.isAsynchronous; final String emptyReturnStatement = isMockHandler ? 'return {};' - : func.returnType == 'void' + : func.returnType.dataType == 'void' ? 'return;' : 'return null;'; String call; diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index e52be610e6b3..99c097fc2701 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -285,7 +285,7 @@ const int _minimumCodecFieldKey = 128; Iterable getCodecClasses(Api api) sync* { final Set names = {}; for (final Method method in api.methods) { - names.add(method.returnType); + names.add(method.returnType.dataType); names.add(method.argType); } final List sortedNames = names diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index dc65af896234..9b889e30d0d6 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -127,14 +127,15 @@ void _writeHostApi(Indent indent, Api api) { final String argType = _javaTypeForDartTypePassthrough(method.argType); final String returnType = method.isAsynchronous ? 'void' - : _javaTypeForDartTypePassthrough(method.returnType); + : _javaTypeForDartTypePassthrough(method.returnType.dataType); final List argSignature = []; if (method.argType != 'void') { argSignature.add('$argType arg'); } if (method.isAsynchronous) { - final String returnType = - method.returnType == 'void' ? 'Void' : method.returnType; + final String returnType = method.returnType.dataType == 'void' + ? 'Void' + : method.returnType.dataType; argSignature.add('Result<$returnType> result'); } indent.writeln('$returnType ${method.name}(${argSignature.join(', ')});'); @@ -170,7 +171,7 @@ static MessageCodec getCodec() { final String argType = _javaTypeForDartTypePassthrough(method.argType); final String returnType = - _javaTypeForDartTypePassthrough(method.returnType); + _javaTypeForDartTypePassthrough(method.returnType.dataType); indent.writeln('Map wrapped = new HashMap<>();'); indent.write('try '); indent.scoped('{', '}', () { @@ -187,7 +188,7 @@ static MessageCodec getCodec() { } if (method.isAsynchronous) { final String resultValue = - method.returnType == 'void' ? 'null' : 'result'; + method.returnType.dataType == 'void' ? 'null' : 'result'; methodArgument.add( 'result -> { ' 'wrapped.put("${Keys.result}", $resultValue); ' @@ -199,7 +200,7 @@ static MessageCodec getCodec() { 'api.${method.name}(${methodArgument.join(', ')})'; if (method.isAsynchronous) { indent.writeln('$call;'); - } else if (method.returnType == 'void') { + } else if (method.returnType.dataType == 'void') { indent.writeln('$call;'); indent.writeln('wrapped.put("${Keys.result}", null);'); } else { @@ -252,9 +253,9 @@ static MessageCodec getCodec() { '''); for (final Method func in api.methods) { final String channelName = makeChannelName(api, func); - final String returnType = func.returnType == 'void' + final String returnType = func.returnType.dataType == 'void' ? 'Void' - : _javaTypeForDartTypePassthrough(func.returnType); + : _javaTypeForDartTypePassthrough(func.returnType.dataType); final String argType = _javaTypeForDartTypePassthrough(func.argType); String sendArgument; if (func.argType == 'void') { @@ -275,7 +276,7 @@ static MessageCodec getCodec() { indent.dec(); indent.write('channel.send($sendArgument, channelReply -> '); indent.scoped('{', '});', () { - if (func.returnType == 'void') { + if (func.returnType.dataType == 'void') { indent.writeln('callback.reply(null);'); } else { indent.writeln('@SuppressWarnings("ConstantConditions")'); diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index a64b87aeb6d3..a5383718004e 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -238,9 +238,9 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { indent.writeln('@protocol $apiName'); for (final Method func in api.methods) { final String returnTypeName = - _objcTypeForDartType(options.prefix, func.returnType); + _objcTypeForDartType(options.prefix, func.returnType.dataType); if (func.isAsynchronous) { - if (func.returnType == 'void') { + if (func.returnType.dataType == 'void') { if (func.argType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)(FlutterError *_Nullable))completion;'); @@ -263,7 +263,7 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { } } else { final String returnType = - func.returnType == 'void' ? 'void' : 'nullable $returnTypeName *'; + func.returnType.dataType == 'void' ? 'void' : 'nullable $returnTypeName *'; if (func.argType == 'void') { indent.writeln( '-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;'); @@ -289,8 +289,8 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) { '- (instancetype)initWithBinaryMessenger:(id)binaryMessenger;'); for (final Method func in api.methods) { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType); - final String callbackType = _callbackForType(func.returnType, returnType); + _objcTypeForDartType(options.prefix, func.returnType.dataType); + final String callbackType = _callbackForType(func.returnType.dataType, returnType); if (func.argType == 'void') { indent.writeln('- (void)${func.name}:($callbackType)completion;'); } else { @@ -411,7 +411,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { '[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) '); indent.scoped('{', '}];', () { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType); + _objcTypeForDartType(options.prefix, func.returnType.dataType); String syncCall; if (func.argType == 'void') { syncCall = '[api ${func.name}:&error]'; @@ -422,7 +422,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { syncCall = '[api ${func.name}:input error:&error]'; } if (func.isAsynchronous) { - if (func.returnType == 'void') { + if (func.returnType.dataType == 'void') { const String callback = 'callback(wrapResult(nil, error));'; if (func.argType == 'void') { indent.writeScoped( @@ -455,7 +455,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { } } else { indent.writeln('FlutterError *error;'); - if (func.returnType == 'void') { + if (func.returnType.dataType == 'void') { indent.writeln('$syncCall;'); indent.writeln('callback(wrapResult(nil, error));'); } else { @@ -496,8 +496,8 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { indent.addln(''); for (final Method func in api.methods) { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType); - final String callbackType = _callbackForType(func.returnType, returnType); + _objcTypeForDartType(options.prefix, func.returnType.dataType); + final String callbackType = _callbackForType(func.returnType.dataType, returnType); String sendArgument; if (func.argType == 'void') { @@ -522,7 +522,7 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { indent.dec(); indent.write('[channel sendMessage:$sendArgument reply:^(id reply) '); indent.scoped('{', '}];', () { - if (func.returnType == 'void') { + if (func.returnType.dataType == 'void') { indent.writeln('completion(nil);'); } else { indent.writeln('$returnType * output = reply;'); diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index a16fe87d91a1..dc22d7819008 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -402,7 +402,7 @@ List _validateAst(Root root, String source) { } for (final Api api in root.apis) { for (final Method method in api.methods) { - if (method.isReturnNullable) { + if (method.returnType.isNullable) { result.add(Error( message: 'Nullable return types types aren\'t supported for Pigeon methods: "${method.argType}" in API: "${api.name}" method: "${method.name}"', @@ -468,7 +468,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { for (final Api api in _apis) { for (final Method method in api.methods) { referencedTypes.add(method.argType); - referencedTypes.add(method.returnType); + referencedTypes.add(method.returnType.dataType); } } @@ -638,9 +638,11 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { if (_currentApi != null) { _currentApi!.methods.add(Method( name: node.name.name, - returnType: node.returnType.toString(), + returnType: Field( + name: '', + dataType: node.returnType.toString(), + isNullable: node.returnType!.question != null), argType: argType, - isReturnNullable: node.returnType!.question != null, isArgNullable: isNullable, isAsynchronous: isAsynchronous, offset: node.offset)); diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 704b0ed1e772..229b041da527 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -59,7 +59,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) @@ -133,7 +133,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) @@ -167,7 +167,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) @@ -194,7 +194,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) @@ -224,7 +224,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) @@ -251,7 +251,7 @@ void main() { name: 'doSomething', argType: 'EnumClass', isArgNullable: false, - returnType: 'EnumClass', + returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), isAsynchronous: false, ) ]) @@ -288,7 +288,7 @@ void main() { name: 'doSomething', argType: 'EnumClass', isArgNullable: false, - returnType: 'EnumClass', + returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), isAsynchronous: false, ) ]) @@ -327,7 +327,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) @@ -357,14 +357,15 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: + Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ), Method( name: 'voidReturner', argType: 'Input', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) @@ -434,7 +435,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) @@ -470,7 +471,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true, ) ]) @@ -505,7 +506,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) @@ -539,7 +540,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index d77d91747d01..897b4d8ba1d3 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -89,7 +89,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: true, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) @@ -145,7 +145,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) @@ -172,7 +172,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) @@ -196,7 +196,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) @@ -220,7 +220,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) @@ -244,7 +244,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) @@ -334,7 +334,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) @@ -368,7 +368,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 49022bd21ce7..f70aadd1cd82 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -122,7 +122,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output') + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -157,7 +157,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output') + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -354,7 +354,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Nested') + returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -387,7 +387,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Nested') + returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -420,7 +420,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output') + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -456,7 +456,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output') + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -488,7 +488,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void') + returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -513,7 +513,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void') + returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -540,7 +540,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void') + returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -565,7 +565,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void') + returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ @@ -591,7 +591,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output') + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Output', fields: [ @@ -616,7 +616,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output') + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Output', fields: [ @@ -641,7 +641,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output') + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Output', fields: [ @@ -669,7 +669,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output') + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Output', fields: [ @@ -732,7 +732,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) ], classes: [ @@ -768,7 +768,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) ], classes: [ @@ -804,7 +804,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) ], classes: [ @@ -833,7 +833,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) ], classes: [], enums: []); @@ -854,7 +854,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) ], classes: [ @@ -890,7 +890,7 @@ void main() { name: 'doSomething', argType: 'Input', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) ], classes: [ @@ -926,7 +926,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'void', + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) ], classes: [], enums: []); @@ -945,7 +945,7 @@ void main() { name: 'doSomething', argType: 'void', isArgNullable: false, - returnType: 'Output', + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) ], classes: [ diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 850584c861c0..ca5cca938078 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -94,7 +94,7 @@ abstract class Api1 { expect(root.apis[0].methods.length, equals(1)); expect(root.apis[0].methods[0].name, equals('doit')); expect(root.apis[0].methods[0].argType, equals('Input1')); - expect(root.apis[0].methods[0].returnType, equals('Output1')); + expect(root.apis[0].methods[0].returnType.dataType, equals('Output1')); Class? input; Class? output; @@ -241,7 +241,7 @@ abstract class VoidApi { expect(results.root.apis.length, equals(1)); expect(results.root.apis[0].methods.length, equals(1)); expect(results.root.apis[0].name, equals('VoidApi')); - expect(results.root.apis[0].methods[0].returnType, equals('void')); + expect(results.root.apis[0].methods[0].returnType.dataType, equals('void')); }); test('void arg host api', () { @@ -260,7 +260,7 @@ abstract class VoidArgApi { expect(results.root.apis.length, equals(1)); expect(results.root.apis[0].methods.length, equals(1)); expect(results.root.apis[0].name, equals('VoidArgApi')); - expect(results.root.apis[0].methods[0].returnType, equals('Output1')); + expect(results.root.apis[0].methods[0].returnType.dataType, equals('Output1')); expect(results.root.apis[0].methods[0].argType, equals('void')); }); @@ -609,4 +609,15 @@ abstract class Api { expect(parseResult.errors[0].message, contains('"list"')); expect(parseResult.errors[0].lineNumber, 2); }); + +// test('return type generics', () { +// const String code = ''' +// @HostApi() +// abstract class Api { +// List doit(); +// } +// '''; +// final ParseResults parseResult = _parseSource(code); +// // expect(parseResult.root.apis[0].methods[0].returnType +// }); } From 5cebd6855eae85778de3c49fe05ed4a3ed1c3b44 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 22 Jul 2021 14:52:51 -0700 Subject: [PATCH 05/30] started parsing return value generics --- packages/pigeon/lib/pigeon_lib.dart | 2 ++ packages/pigeon/test/pigeon_lib_test.dart | 29 +++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index dc22d7819008..d7d455f16418 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -641,6 +641,8 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { returnType: Field( name: '', dataType: node.returnType.toString(), + typeArguments: typeAnnotationsToTypeArguments( + (node.returnType as dart_ast.NamedType?)!.typeArguments), isNullable: node.returnType!.question != null), argType: argType, isArgNullable: isNullable, diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index ca5cca938078..0236634addfd 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -260,7 +260,8 @@ abstract class VoidArgApi { expect(results.root.apis.length, equals(1)); expect(results.root.apis[0].methods.length, equals(1)); expect(results.root.apis[0].name, equals('VoidArgApi')); - expect(results.root.apis[0].methods[0].returnType.dataType, equals('Output1')); + expect( + results.root.apis[0].methods[0].returnType.dataType, equals('Output1')); expect(results.root.apis[0].methods[0].argType, equals('void')); }); @@ -605,19 +606,23 @@ abstract class Api { '''; final ParseResults parseResult = _parseSource(code); expect(parseResult.errors.length, equals(1)); - expect(parseResult.errors[0].message, contains('Generic type arguments must be nullable')); + expect(parseResult.errors[0].message, + contains('Generic type arguments must be nullable')); expect(parseResult.errors[0].message, contains('"list"')); expect(parseResult.errors[0].lineNumber, 2); }); -// test('return type generics', () { -// const String code = ''' -// @HostApi() -// abstract class Api { -// List doit(); -// } -// '''; -// final ParseResults parseResult = _parseSource(code); -// // expect(parseResult.root.apis[0].methods[0].returnType -// }); + test('return type generics', () { + const String code = ''' +@HostApi() +abstract class Api { + List doit(); +} +'''; + final ParseResults parseResult = _parseSource(code); + expect( + parseResult + .root.apis[0].methods[0].returnType.typeArguments![0].dataType, + 'double'); + }); } From 8e9de1dd961e69538975bdb25a7c2746be1dcacf Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 22 Jul 2021 15:45:17 -0700 Subject: [PATCH 06/30] started parsing argument generics --- packages/pigeon/lib/ast.dart | 6 +- packages/pigeon/lib/dart_generator.dart | 8 +-- packages/pigeon/lib/generator_tools.dart | 2 +- packages/pigeon/lib/java_generator.dart | 18 ++++- packages/pigeon/lib/objc_generator.dart | 28 ++++---- packages/pigeon/lib/pigeon_lib.dart | 17 +++-- packages/pigeon/test/dart_generator_test.dart | 42 ++++-------- packages/pigeon/test/java_generator_test.dart | 24 +++---- packages/pigeon/test/objc_generator_test.dart | 66 +++++++------------ packages/pigeon/test/pigeon_lib_test.dart | 27 +++++++- 10 files changed, 115 insertions(+), 123 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index f10c914e5955..f7caaea380c6 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -21,7 +21,6 @@ class Method extends Node { required this.name, required this.returnType, required this.argType, - this.isArgNullable = false, this.isAsynchronous = false, this.offset, }); @@ -33,10 +32,7 @@ class Method extends Node { Field returnType; /// The data-type of the argument. - String argType; - - /// True if the argument has a null tag `?`. - bool isArgNullable; + Field argType; /// Whether the receiver of this method is expected to return synchronously or not. bool isAsynchronous; diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index c26d87649574..aeb7ac59209b 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -121,8 +121,8 @@ final BinaryMessenger$nullTag _binaryMessenger; } String argSignature = ''; String sendArgument = 'null'; - if (func.argType != 'void') { - argSignature = '${func.argType} arg'; + if (func.argType.dataType != 'void') { + argSignature = '${func.argType.dataType} arg'; sendArgument = 'arg'; } indent.write( @@ -184,7 +184,7 @@ void _writeFlutterApi( final String returnType = isAsync ? 'Future<${func.returnType.dataType}>' : func.returnType.dataType; final String argSignature = - func.argType == 'void' ? '' : '${func.argType} arg'; + func.argType.dataType == 'void' ? '' : '${func.argType.dataType} arg'; indent.writeln('$returnType ${func.name}($argSignature);'); } indent.write('static void setup(${api.name}$nullTag api) '); @@ -215,7 +215,7 @@ void _writeFlutterApi( 'channel.$messageHandlerSetter((Object$nullTag message) async ', ); indent.scoped('{', '});', () { - final String argType = func.argType; + final String argType = func.argType.dataType; final String returnType = func.returnType.dataType; final bool isAsync = func.isAsynchronous; final String emptyReturnStatement = isMockHandler diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index 99c097fc2701..a41a75800674 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -286,7 +286,7 @@ Iterable getCodecClasses(Api api) sync* { final Set names = {}; for (final Method method in api.methods) { names.add(method.returnType.dataType); - names.add(method.argType); + names.add(method.argType.dataType); } final List sortedNames = names .where((String element) => diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 9b889e30d0d6..074605709a93 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -124,12 +124,16 @@ void _writeHostApi(Indent indent, Api api) { indent.write('public interface ${api.name} '); indent.scoped('{', '}', () { for (final Method method in api.methods) { +<<<<<<< HEAD final String argType = _javaTypeForDartTypePassthrough(method.argType); +======= + final String argType = _boxedType(method.argType.dataType); +>>>>>>> 3af9039 (started parsing argument generics) final String returnType = method.isAsynchronous ? 'void' : _javaTypeForDartTypePassthrough(method.returnType.dataType); final List argSignature = []; - if (method.argType != 'void') { + if (method.argType.dataType != 'void') { argSignature.add('$argType arg'); } if (method.isAsynchronous) { @@ -168,10 +172,15 @@ static MessageCodec getCodec() { indent.scoped('{', '} else {', () { indent.write('channel.setMessageHandler((message, reply) -> '); indent.scoped('{', '});', () { +<<<<<<< HEAD final String argType = _javaTypeForDartTypePassthrough(method.argType); final String returnType = _javaTypeForDartTypePassthrough(method.returnType.dataType); +======= + final String argType = _boxedType(method.argType.dataType); + final String returnType = _boxedType(method.returnType.dataType); +>>>>>>> 3af9039 (started parsing argument generics) indent.writeln('Map wrapped = new HashMap<>();'); indent.write('try '); indent.scoped('{', '}', () { @@ -255,10 +264,15 @@ static MessageCodec getCodec() { final String channelName = makeChannelName(api, func); final String returnType = func.returnType.dataType == 'void' ? 'Void' +<<<<<<< HEAD : _javaTypeForDartTypePassthrough(func.returnType.dataType); final String argType = _javaTypeForDartTypePassthrough(func.argType); +======= + : _boxedType(func.returnType.dataType); + final String argType = _boxedType(func.argType.dataType); +>>>>>>> 3af9039 (started parsing argument generics) String sendArgument; - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { indent.write('public void ${func.name}(Reply<$returnType> callback) '); sendArgument = 'null'; } else { diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index a5383718004e..b7e9867973b4 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -241,22 +241,22 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { _objcTypeForDartType(options.prefix, func.returnType.dataType); if (func.isAsynchronous) { if (func.returnType.dataType == 'void') { - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)(FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)(FlutterError *_Nullable))completion;'); } } else { - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } @@ -264,12 +264,12 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { } else { final String returnType = func.returnType.dataType == 'void' ? 'void' : 'nullable $returnTypeName *'; - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { indent.writeln( '-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '-($returnType)${func.name}:($argType*)input error:(FlutterError *_Nullable *_Nonnull)error;'); } @@ -291,10 +291,10 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) { final String returnType = _objcTypeForDartType(options.prefix, func.returnType.dataType); final String callbackType = _callbackForType(func.returnType.dataType, returnType); - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { indent.writeln('- (void)${func.name}:($callbackType)completion;'); } else { - final String argType = _objcTypeForDartType(options.prefix, func.argType); + final String argType = _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '- (void)${func.name}:($argType*)input completion:($callbackType)completion;'); } @@ -413,18 +413,18 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { final String returnType = _objcTypeForDartType(options.prefix, func.returnType.dataType); String syncCall; - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { syncCall = '[api ${func.name}:&error]'; } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln('$argType *input = message;'); syncCall = '[api ${func.name}:input error:&error]'; } if (func.isAsynchronous) { if (func.returnType.dataType == 'void') { const String callback = 'callback(wrapResult(nil, error));'; - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { indent.writeScoped( '[api ${func.name}:^(FlutterError *_Nullable error) {', '}];', () { @@ -439,7 +439,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { } } else { const String callback = 'callback(wrapResult(output, error));'; - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { indent.writeScoped( '[api ${func.name}:^($returnType *_Nullable output, FlutterError *_Nullable error) {', '}];', () { @@ -500,11 +500,11 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { final String callbackType = _callbackForType(func.returnType.dataType, returnType); String sendArgument; - if (func.argType == 'void') { + if (func.argType.dataType == 'void') { indent.write('- (void)${func.name}:($callbackType)completion '); sendArgument = 'nil'; } else { - final String argType = _objcTypeForDartType(options.prefix, func.argType); + final String argType = _objcTypeForDartType(options.prefix, func.argType.dataType); indent.write( '- (void)${func.name}:($argType*)input completion:($callbackType)completion '); sendArgument = 'input'; diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index d7d455f16418..27e3c447d181 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -405,14 +405,14 @@ List _validateAst(Root root, String source) { if (method.returnType.isNullable) { 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.dataType}" in API: "${api.name}" method: "${method.name}"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.isArgNullable) { + if (method.argType.isNullable) { result.add(Error( message: - 'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType}" in API: "${api.name}" method: "${method.name}"', + 'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name}"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } @@ -467,7 +467,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final Set referencedTypes = {}; for (final Api api in _apis) { for (final Method method in api.methods) { - referencedTypes.add(method.argType); + referencedTypes.add(method.argType.dataType); referencedTypes.add(method.returnType.dataType); } } @@ -623,6 +623,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final dart_ast.FormalParameterList parameters = node.parameters!; late String argType; bool isNullable = false; + List? argTypeArguments; if (parameters.parameters.isEmpty) { argType = 'void'; } else { @@ -633,6 +634,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { .firstWhere((e) => e is dart_ast.TypeName) as dart_ast.TypeName; argType = typeName.name.name; isNullable = typeName.question != null; + argTypeArguments = typeAnnotationsToTypeArguments(typeName.typeArguments); } final bool isAsynchronous = _hasMetadata(node.metadata, 'async'); if (_currentApi != null) { @@ -644,8 +646,11 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { typeArguments: typeAnnotationsToTypeArguments( (node.returnType as dart_ast.NamedType?)!.typeArguments), isNullable: node.returnType!.question != null), - argType: argType, - isArgNullable: isNullable, + argType: Field( + dataType: argType, + isNullable: isNullable, + name: '', + typeArguments: argTypeArguments), isAsynchronous: isAsynchronous, offset: node.offset)); } else if (_currentClass != null) { diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 229b041da527..960907f5e8f6 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -57,8 +57,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -131,8 +130,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -165,8 +163,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -192,8 +189,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -222,8 +218,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'void'), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -249,8 +244,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'EnumClass', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'EnumClass'), returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), isAsynchronous: false, ) @@ -286,8 +280,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'EnumClass', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'EnumClass'), returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), isAsynchronous: false, ) @@ -325,8 +318,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'void'), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -355,16 +347,14 @@ void main() { methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ), Method( name: 'voidReturner', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -433,8 +423,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) @@ -469,8 +458,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true, ) @@ -504,8 +492,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'Input'), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) @@ -538,8 +525,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', isNullable: false, dataType: 'void'), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 897b4d8ba1d3..89be8c245b93 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -87,8 +87,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: true, + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -143,8 +142,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -170,8 +168,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -194,8 +191,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -218,8 +214,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -242,8 +237,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -332,8 +326,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) @@ -366,8 +359,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index f70aadd1cd82..b35e25576611 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -120,8 +120,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -155,8 +154,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -352,8 +350,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ @@ -385,8 +382,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ @@ -418,8 +414,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -454,8 +449,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -486,8 +480,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -511,8 +504,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -538,8 +530,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -563,8 +554,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -589,8 +579,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType:'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -614,8 +603,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType:'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -639,8 +627,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType:'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -667,8 +654,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType:'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -730,8 +716,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -766,8 +751,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -802,8 +786,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType:'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -831,8 +814,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType:'void', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -852,8 +834,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -888,8 +869,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'Input', - isArgNullable: false, + argType: Field(name: '', dataType:'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -924,8 +904,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType:'void', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -943,8 +922,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: 'void', - isArgNullable: false, + argType: Field(name: '', dataType:'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 0236634addfd..a4b632a96034 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -93,7 +93,7 @@ abstract class Api1 { expect(root.apis[0].name, equals('Api1')); expect(root.apis[0].methods.length, equals(1)); expect(root.apis[0].methods[0].name, equals('doit')); - expect(root.apis[0].methods[0].argType, equals('Input1')); + expect(root.apis[0].methods[0].argType.dataType, equals('Input1')); expect(root.apis[0].methods[0].returnType.dataType, equals('Output1')); Class? input; @@ -262,7 +262,7 @@ abstract class VoidArgApi { expect(results.root.apis[0].name, equals('VoidArgApi')); expect( results.root.apis[0].methods[0].returnType.dataType, equals('Output1')); - expect(results.root.apis[0].methods[0].argType, equals('void')); + expect(results.root.apis[0].methods[0].argType.dataType, equals('void')); }); test('mockDartClass', () { @@ -616,7 +616,7 @@ abstract class Api { const String code = ''' @HostApi() abstract class Api { - List doit(); + List doit(); } '''; final ParseResults parseResult = _parseSource(code); @@ -624,5 +624,26 @@ abstract class Api { parseResult .root.apis[0].methods[0].returnType.typeArguments![0].dataType, 'double'); + expect( + parseResult + .root.apis[0].methods[0].returnType.typeArguments![0].isNullable, + isTrue); + }); + + test('argument generics', () { + const String code = ''' +@HostApi() +abstract class Api { + void doit(List value); +} +'''; + final ParseResults parseResult = _parseSource(code); + expect( + parseResult.root.apis[0].methods[0].argType.typeArguments![0].dataType, + 'double'); + expect( + parseResult + .root.apis[0].methods[0].argType.typeArguments![0].isNullable, + isTrue); }); } From ceafca5432c3c184e0a21aa4d4dbe098eae936b9 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 22 Jul 2021 16:20:27 -0700 Subject: [PATCH 07/30] fixed maps on dart --- packages/pigeon/lib/dart_generator.dart | 13 +++- packages/pigeon/pigeons/all_datatypes.dart | 2 + .../lib/all_datatypes.dart | 51 +++++++-------- .../lib/null_safe_pigeon.dart | 64 +++++++++---------- .../test/all_datatypes_test.dart | 6 ++ packages/pigeon/test/dart_generator_test.dart | 31 ++++++++- packages/pigeon/test/pigeon_lib_test.dart | 18 ++++++ 7 files changed, 124 insertions(+), 61 deletions(-) diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index aeb7ac59209b..baa888f02aeb 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -181,8 +181,9 @@ void _writeFlutterApi( indent.addln(''); for (final Method func in api.methods) { final bool isAsync = func.isAsynchronous; - final String returnType = - isAsync ? 'Future<${func.returnType.dataType}>' : func.returnType.dataType; + final String returnType = isAsync + ? 'Future<${func.returnType.dataType}>' + : func.returnType.dataType; final String argSignature = func.argType.dataType == 'void' ? '' : '${func.argType.dataType} arg'; indent.writeln('$returnType ${func.name}($argSignature);'); @@ -278,7 +279,9 @@ String _addGenericTypes(Field field, String nullTag) { ? 'List$nullTag' : 'List<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; case 'Map': - return 'Map$nullTag'; + return (field.typeArguments == null) + ? 'Map$nullTag' + : 'Map<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; default: return '${field.dataType}$nullTag'; } @@ -375,6 +378,10 @@ pigeonMap['${field.name}'] != null pigeonMap['${field.name}'] != null \t\t? ${field.dataType}.values[pigeonMap['${field.name}']$unwrapOperator as int] \t\t: null''', leadingSpace: false, trailingNewline: false); + } else if (field.dataType == 'Map' && field.typeArguments != null) { + indent.add( + '(pigeonMap[\'${field.name}\'] as Map$nullTag)$nullTag.cast<${_flattenTypeArguments(field.typeArguments!, nullTag)}>()', + ); } else { indent.add( 'pigeonMap[\'${field.name}\'] as ${_addGenericTypes(field, nullTag)}', diff --git a/packages/pigeon/pigeons/all_datatypes.dart b/packages/pigeon/pigeons/all_datatypes.dart index 0a8c2c27626f..138b4caf62c3 100644 --- a/packages/pigeon/pigeons/all_datatypes.dart +++ b/packages/pigeon/pigeons/all_datatypes.dart @@ -17,6 +17,8 @@ class Everything { List? aList; // ignore: always_specify_types Map? aMap; + List?>? nestedList; + Map? mapWithAnnotations; } @HostApi() 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 09db4570911d..a31f120ebd19 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 @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// +// // Autogenerated from Pigeon (v0.3.0), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name @@ -23,6 +23,8 @@ class Everything { Float64List? aFloatArray; List? aList; Map? aMap; + List?>? nestedList; + Map? mapWithAnnotations; Object encode() { final Map pigeonMap = {}; @@ -36,6 +38,8 @@ class Everything { pigeonMap['aFloatArray'] = aFloatArray; pigeonMap['aList'] = aList; pigeonMap['aMap'] = aMap; + pigeonMap['nestedList'] = nestedList; + pigeonMap['mapWithAnnotations'] = mapWithAnnotations; return pigeonMap; } @@ -51,7 +55,9 @@ class Everything { ..a8ByteArray = pigeonMap['a8ByteArray'] as Int64List? ..aFloatArray = pigeonMap['aFloatArray'] as Float64List? ..aList = pigeonMap['aList'] as List? - ..aMap = pigeonMap['aMap'] as Map?; + ..aMap = pigeonMap['aMap'] as Map? + ..nestedList = pigeonMap['nestedList'] as List?>? + ..mapWithAnnotations = (pigeonMap['mapWithAnnotations'] as Map?)?.cast(); } } @@ -62,19 +68,20 @@ class _HostEverythingCodec extends StandardMessageCodec { if (value is Everything) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else { + } else +{ super.writeValue(buffer, value); } } - @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return Everything.decode(readValue(buffer)!); - - default: + + default: return super.readValueOfType(type, buffer); + } } } @@ -83,8 +90,7 @@ class HostEverything { /// Constructor for [HostEverything]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - HostEverything({BinaryMessenger? binaryMessenger}) - : _binaryMessenger = binaryMessenger; + HostEverything({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; @@ -92,8 +98,7 @@ class HostEverything { Future giveMeEverything() async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.HostEverything.giveMeEverything', codec, - binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.HostEverything.giveMeEverything', codec, binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(null) as Map?; if (replyMap == null) { @@ -103,8 +108,7 @@ class HostEverything { details: null, ); } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + final Map error = (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -117,8 +121,7 @@ class HostEverything { Future echo(Everything arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.HostEverything.echo', codec, - binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.HostEverything.echo', codec, binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; if (replyMap == null) { @@ -128,8 +131,7 @@ class HostEverything { details: null, ); } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + final Map error = (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -148,23 +150,23 @@ class _FlutterEverythingCodec extends StandardMessageCodec { if (value is Everything) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else { + } else +{ super.writeValue(buffer, value); } } - @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return Everything.decode(readValue(buffer)!); - - default: + + default: return super.readValueOfType(type, buffer); + } } } - abstract class FlutterEverything { static const MessageCodec codec = _FlutterEverythingCodec(); @@ -191,8 +193,7 @@ abstract class FlutterEverything { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, - 'Argument for dev.flutter.pigeon.FlutterEverything.echo was null. Expected Everything.'); + assert(message != null, 'Argument for dev.flutter.pigeon.FlutterEverything.echo was null. Expected Everything.'); final Everything input = (message as Everything?)!; final Everything output = api.echo(input); 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 044bd03e80ee..97d3a82c504a 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 @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// +// // Autogenerated from Pigeon (v0.3.0), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name @@ -23,7 +23,8 @@ class SearchRequest { static SearchRequest decode(Object message) { final Map pigeonMap = message as Map; - return SearchRequest()..query = pigeonMap['query'] as String?; + return SearchRequest() + ..query = pigeonMap['query'] as String?; } } @@ -57,7 +58,8 @@ class SearchRequests { static SearchRequests decode(Object message) { final Map pigeonMap = message as Map; - return SearchRequests()..requests = pigeonMap['requests'] as List?; + return SearchRequests() + ..requests = pigeonMap['requests'] as List?; } } @@ -72,7 +74,8 @@ class SearchReplies { static SearchReplies decode(Object message) { final Map pigeonMap = message as Map; - return SearchReplies()..replies = pigeonMap['replies'] as List?; + return SearchReplies() + ..replies = pigeonMap['replies'] as List?; } } @@ -83,37 +86,41 @@ class _ApiCodec extends StandardMessageCodec { if (value is SearchReplies) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else if (value is SearchReply) { + } else + if (value is SearchReply) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else if (value is SearchRequest) { + } else + if (value is SearchRequest) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else if (value is SearchRequests) { + } else + if (value is SearchRequests) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else { + } else +{ super.writeValue(buffer, value); } } - @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return SearchReplies.decode(readValue(buffer)!); - - case 129: + + case 129: return SearchReply.decode(readValue(buffer)!); - - case 130: + + case 130: return SearchRequest.decode(readValue(buffer)!); - - case 131: + + case 131: return SearchRequests.decode(readValue(buffer)!); - - default: + + default: return super.readValueOfType(type, buffer); + } } } @@ -130,8 +137,7 @@ class Api { Future search(SearchRequest arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.Api.search', codec, - binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.Api.search', codec, binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; if (replyMap == null) { @@ -141,8 +147,7 @@ class Api { details: null, ); } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + final Map error = (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -155,8 +160,7 @@ class Api { Future doSearches(SearchRequests arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.Api.doSearches', codec, - binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.Api.doSearches', codec, binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; if (replyMap == null) { @@ -166,8 +170,7 @@ class Api { details: null, ); } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + final Map error = (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -180,8 +183,7 @@ class Api { Future echo(SearchRequests arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.Api.echo', codec, - binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.Api.echo', codec, binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; if (replyMap == null) { @@ -191,8 +193,7 @@ class Api { details: null, ); } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + final Map error = (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -216,8 +217,7 @@ class Api { details: null, ); } else if (replyMap['error'] != null) { - final Map error = - (replyMap['error'] as Map?)!; + final Map error = (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, 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 7061fb8fa47a..4a253606cfb4 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 @@ -35,6 +35,8 @@ void main() { expect(result.aFloatArray, isNull); expect(result.aList, isNull); expect(result.aMap, isNull); + expect(result.nestedList, isNull); + expect(result.mapWithAnnotations, isNull); }); test('with values', () async { @@ -50,6 +52,8 @@ void main() { Float64List.fromList([1.0, 2.5, 3.0, 4.25]); everything.aList = [1, 2, 3, 4]; everything.aMap = {'hello': 1234}; + everything.aList = >[[true]]; + everything.mapWithAnnotations = {'hello': 'world'}; final BinaryMessenger mockMessenger = MockBinaryMessenger(); when(mockMessenger.send('dev.flutter.pigeon.HostEverything.echo', any)) .thenAnswer((Invocation realInvocation) async { @@ -70,5 +74,7 @@ void main() { expect(result.aFloatArray, everything.aFloatArray); expect(result.aList, everything.aList); expect(result.aMap, everything.aMap); + expect(result.aList, everything.aList); + expect(result.mapWithAnnotations, everything.mapWithAnnotations); }); } diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 960907f5e8f6..f31338c0f571 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -570,7 +570,9 @@ void main() { name: 'field1', dataType: 'List', isNullable: true, - typeArguments: [TypeArgument(dataType: 'int', isNullable: true)], + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ], ), ], ); @@ -585,4 +587,31 @@ void main() { expect(code, contains('class Foobar')); expect(code, contains(' List? field1;')); }); + + test('map generics', () { + final Class klass = Class( + name: 'Foobar', + fields: [ + Field( + name: 'field1', + dataType: 'Map', + isNullable: true, + typeArguments: [ + TypeArgument(dataType: 'String', isNullable: true), + TypeArgument(dataType: 'int', isNullable: true), + ], + ), + ], + ); + final Root root = Root( + apis: [], + classes: [klass], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + generateDart(const DartOptions(isNullSafe: true), root, sink); + final String code = sink.toString(); + expect(code, contains('class Foobar')); + expect(code, contains(' Map? field1;')); + }); } diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index a4b632a96034..0affcc1d542c 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -646,4 +646,22 @@ abstract class Api { .root.apis[0].methods[0].argType.typeArguments![0].isNullable, isTrue); }); + + test('map generics', (){ + const String code = ''' +class Foo { + Map map; +} + +@HostApi() +abstract class Api { + void doit(Foo foo); +} +'''; + final ParseResults parseResult = _parseSource(code); + final Field field = parseResult.root.classes[0].fields[0]; + expect(field.typeArguments!.length, 2); + expect(field.typeArguments![0].dataType, 'String'); + expect(field.typeArguments![1].dataType, 'int'); + }); } From d4e133a55e88f7e4e4d04e61887be1c1821c1cc7 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Fri, 23 Jul 2021 14:00:03 -0700 Subject: [PATCH 08/30] formatter and started throwing an error for primitive generics --- packages/pigeon/CHANGELOG.md | 1 + packages/pigeon/lib/objc_generator.dart | 17 +++-- packages/pigeon/lib/pigeon_lib.dart | 14 ++++ .../lib/all_datatypes.dart | 47 ++++++++------ .../lib/null_safe_pigeon.dart | 64 +++++++++---------- .../test/all_datatypes_test.dart | 4 +- packages/pigeon/test/java_generator_test.dart | 4 +- packages/pigeon/test/objc_generator_test.dart | 44 ++++++------- packages/pigeon/test/pigeon_lib_test.dart | 36 ++++++----- 9 files changed, 133 insertions(+), 98 deletions(-) diff --git a/packages/pigeon/CHANGELOG.md b/packages/pigeon/CHANGELOG.md index 6be42dca77c6..c63fd4685f5c 100644 --- a/packages/pigeon/CHANGELOG.md +++ b/packages/pigeon/CHANGELOG.md @@ -5,6 +5,7 @@ * [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. +* Started supporting generics' type arguments for fields in classes. ## 0.3.0 diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index b7e9867973b4..30be78af9f22 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -262,8 +262,9 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { } } } else { - final String returnType = - func.returnType.dataType == 'void' ? 'void' : 'nullable $returnTypeName *'; + final String returnType = func.returnType.dataType == 'void' + ? 'void' + : 'nullable $returnTypeName *'; if (func.argType.dataType == 'void') { indent.writeln( '-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;'); @@ -290,11 +291,13 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) { for (final Method func in api.methods) { final String returnType = _objcTypeForDartType(options.prefix, func.returnType.dataType); - final String callbackType = _callbackForType(func.returnType.dataType, returnType); + final String callbackType = + _callbackForType(func.returnType.dataType, returnType); if (func.argType.dataType == 'void') { indent.writeln('- (void)${func.name}:($callbackType)completion;'); } else { - final String argType = _objcTypeForDartType(options.prefix, func.argType.dataType); + final String argType = + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '- (void)${func.name}:($argType*)input completion:($callbackType)completion;'); } @@ -497,14 +500,16 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { for (final Method func in api.methods) { final String returnType = _objcTypeForDartType(options.prefix, func.returnType.dataType); - final String callbackType = _callbackForType(func.returnType.dataType, returnType); + final String callbackType = + _callbackForType(func.returnType.dataType, returnType); String sendArgument; if (func.argType.dataType == 'void') { indent.write('- (void)${func.name}:($callbackType)completion '); sendArgument = 'nil'; } else { - final String argType = _objcTypeForDartType(options.prefix, func.argType.dataType); + final String argType = + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.write( '- (void)${func.name}:($argType*)input completion:($callbackType)completion '); sendArgument = 'input'; diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 27e3c447d181..8576318cd44f 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -409,6 +409,13 @@ List _validateAst(Root root, String source) { lineNumber: _calculateLineNumberNullable(source, method.offset), )); } + if (method.returnType.typeArguments != null) { + result.add(Error( + message: + 'Generic type arguments for primitive return values isn\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + lineNumber: _calculateLineNumberNullable(source, method.offset), + )); + } if (method.argType.isNullable) { result.add(Error( message: @@ -416,6 +423,13 @@ List _validateAst(Root root, String source) { lineNumber: _calculateLineNumberNullable(source, method.offset), )); } + if (method.argType.typeArguments != null) { + result.add(Error( + message: + 'Generic type arguments for primitive arguments isn\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + lineNumber: _calculateLineNumberNullable(source, method.offset), + )); + } } } 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 a31f120ebd19..dd60777ef72f 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 @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// +// // Autogenerated from Pigeon (v0.3.0), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name @@ -57,7 +57,9 @@ class Everything { ..aList = pigeonMap['aList'] as List? ..aMap = pigeonMap['aMap'] as Map? ..nestedList = pigeonMap['nestedList'] as List?>? - ..mapWithAnnotations = (pigeonMap['mapWithAnnotations'] as Map?)?.cast(); + ..mapWithAnnotations = + (pigeonMap['mapWithAnnotations'] as Map?) + ?.cast(); } } @@ -68,20 +70,19 @@ class _HostEverythingCodec extends StandardMessageCodec { if (value is Everything) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else -{ + } else { super.writeValue(buffer, value); } } + @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return Everything.decode(readValue(buffer)!); - - default: + + default: return super.readValueOfType(type, buffer); - } } } @@ -90,7 +91,8 @@ class HostEverything { /// Constructor for [HostEverything]. The [binaryMessenger] named argument is /// available for dependency injection. If it is left null, the default /// BinaryMessenger will be used which routes to the host platform. - HostEverything({BinaryMessenger? binaryMessenger}) : _binaryMessenger = binaryMessenger; + HostEverything({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; final BinaryMessenger? _binaryMessenger; @@ -98,7 +100,8 @@ class HostEverything { Future giveMeEverything() async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.HostEverything.giveMeEverything', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.HostEverything.giveMeEverything', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(null) as Map?; if (replyMap == null) { @@ -108,7 +111,8 @@ class HostEverything { details: null, ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -121,7 +125,8 @@ class HostEverything { Future echo(Everything arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.HostEverything.echo', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.HostEverything.echo', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; if (replyMap == null) { @@ -131,7 +136,8 @@ class HostEverything { details: null, ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -150,23 +156,23 @@ class _FlutterEverythingCodec extends StandardMessageCodec { if (value is Everything) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else -{ + } else { super.writeValue(buffer, value); } } + @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return Everything.decode(readValue(buffer)!); - - default: + + default: return super.readValueOfType(type, buffer); - } } } + abstract class FlutterEverything { static const MessageCodec codec = _FlutterEverythingCodec(); @@ -193,7 +199,8 @@ abstract class FlutterEverything { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { - assert(message != null, 'Argument for dev.flutter.pigeon.FlutterEverything.echo was null. Expected Everything.'); + assert(message != null, + 'Argument for dev.flutter.pigeon.FlutterEverything.echo was null. Expected Everything.'); final Everything input = (message as Everything?)!; final Everything output = api.echo(input); 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 97d3a82c504a..044bd03e80ee 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 @@ -1,7 +1,7 @@ // Copyright 2013 The Flutter Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// +// // Autogenerated from Pigeon (v0.3.0), do not edit directly. // See also: https://pub.dev/packages/pigeon // ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name @@ -23,8 +23,7 @@ class SearchRequest { static SearchRequest decode(Object message) { final Map pigeonMap = message as Map; - return SearchRequest() - ..query = pigeonMap['query'] as String?; + return SearchRequest()..query = pigeonMap['query'] as String?; } } @@ -58,8 +57,7 @@ class SearchRequests { static SearchRequests decode(Object message) { final Map pigeonMap = message as Map; - return SearchRequests() - ..requests = pigeonMap['requests'] as List?; + return SearchRequests()..requests = pigeonMap['requests'] as List?; } } @@ -74,8 +72,7 @@ class SearchReplies { static SearchReplies decode(Object message) { final Map pigeonMap = message as Map; - return SearchReplies() - ..replies = pigeonMap['replies'] as List?; + return SearchReplies()..replies = pigeonMap['replies'] as List?; } } @@ -86,41 +83,37 @@ class _ApiCodec extends StandardMessageCodec { if (value is SearchReplies) { buffer.putUint8(128); writeValue(buffer, value.encode()); - } else - if (value is SearchReply) { + } else if (value is SearchReply) { buffer.putUint8(129); writeValue(buffer, value.encode()); - } else - if (value is SearchRequest) { + } else if (value is SearchRequest) { buffer.putUint8(130); writeValue(buffer, value.encode()); - } else - if (value is SearchRequests) { + } else if (value is SearchRequests) { buffer.putUint8(131); writeValue(buffer, value.encode()); - } else -{ + } else { super.writeValue(buffer, value); } } + @override Object? readValueOfType(int type, ReadBuffer buffer) { switch (type) { - case 128: + case 128: return SearchReplies.decode(readValue(buffer)!); - - case 129: + + case 129: return SearchReply.decode(readValue(buffer)!); - - case 130: + + case 130: return SearchRequest.decode(readValue(buffer)!); - - case 131: + + case 131: return SearchRequests.decode(readValue(buffer)!); - - default: + + default: return super.readValueOfType(type, buffer); - } } } @@ -137,7 +130,8 @@ class Api { Future search(SearchRequest arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.Api.search', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.Api.search', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; if (replyMap == null) { @@ -147,7 +141,8 @@ class Api { details: null, ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -160,7 +155,8 @@ class Api { Future doSearches(SearchRequests arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.Api.doSearches', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.Api.doSearches', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; if (replyMap == null) { @@ -170,7 +166,8 @@ class Api { details: null, ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -183,7 +180,8 @@ class Api { Future echo(SearchRequests arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.Api.echo', codec, binaryMessenger: _binaryMessenger); + 'dev.flutter.pigeon.Api.echo', codec, + binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; if (replyMap == null) { @@ -193,7 +191,8 @@ class Api { details: null, ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, @@ -217,7 +216,8 @@ class Api { details: null, ); } else if (replyMap['error'] != null) { - final Map error = (replyMap['error'] as Map?)!; + final Map error = + (replyMap['error'] as Map?)!; throw PlatformException( code: (error['code'] as String?)!, message: error['message'] as String?, 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 4a253606cfb4..4cad76d88853 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 @@ -52,7 +52,9 @@ void main() { Float64List.fromList([1.0, 2.5, 3.0, 4.25]); everything.aList = [1, 2, 3, 4]; everything.aMap = {'hello': 1234}; - everything.aList = >[[true]]; + everything.aList = >[ + [true] + ]; everything.mapWithAnnotations = {'hello': 'world'}; final BinaryMessenger mockMessenger = MockBinaryMessenger(); when(mockMessenger.send('dev.flutter.pigeon.HostEverything.echo', any)) diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 89be8c245b93..510d6d922260 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -442,7 +442,9 @@ void main() { name: 'field1', dataType: 'List', isNullable: true, - typeArguments: [TypeArgument(dataType: 'int', isNullable: true)], + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ], ), ], ); diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index b35e25576611..759b16e3f296 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -120,7 +120,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -154,7 +154,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -350,7 +350,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ @@ -382,7 +382,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ @@ -414,7 +414,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -449,7 +449,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -480,7 +480,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -504,7 +504,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -530,7 +530,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -554,7 +554,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -579,7 +579,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'void', isNullable: false), + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -603,7 +603,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'void', isNullable: false), + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -627,7 +627,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'void', isNullable: false), + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -654,7 +654,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'void', isNullable: false), + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -716,7 +716,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -751,7 +751,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -786,7 +786,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'void', isNullable: false), + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -814,7 +814,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'void', isNullable: false), + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -834,7 +834,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -869,7 +869,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'Input', isNullable: false), + argType: Field(name: '', dataType: 'Input', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -904,7 +904,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'void', isNullable: false), + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -922,7 +922,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType:'void', isNullable: false), + argType: Field(name: '', dataType: 'void', isNullable: false), returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 0affcc1d542c..371bbc671e20 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -620,14 +620,16 @@ abstract class Api { } '''; final ParseResults parseResult = _parseSource(code); - expect( - parseResult - .root.apis[0].methods[0].returnType.typeArguments![0].dataType, - 'double'); - expect( - parseResult - .root.apis[0].methods[0].returnType.typeArguments![0].isNullable, - isTrue); + expect(parseResult.errors.length, equals(1)); + // TODO(gaaclarke): Make this not an error, https://github.com/flutter/flutter/issues/86963. + // expect( + // parseResult + // .root.apis[0].methods[0].returnType.typeArguments![0].dataType, + // 'double'); + // expect( + // parseResult + // .root.apis[0].methods[0].returnType.typeArguments![0].isNullable, + // isTrue); }); test('argument generics', () { @@ -638,16 +640,18 @@ abstract class Api { } '''; final ParseResults parseResult = _parseSource(code); - expect( - parseResult.root.apis[0].methods[0].argType.typeArguments![0].dataType, - 'double'); - expect( - parseResult - .root.apis[0].methods[0].argType.typeArguments![0].isNullable, - isTrue); + expect(parseResult.errors.length, equals(1)); + // TODO(gaaclarke): Make this not an error, https://github.com/flutter/flutter/issues/86963. + // expect( + // parseResult.root.apis[0].methods[0].argType.typeArguments![0].dataType, + // 'double'); + // expect( + // parseResult + // .root.apis[0].methods[0].argType.typeArguments![0].isNullable, + // isTrue); }); - test('map generics', (){ + test('map generics', () { const String code = ''' class Foo { Map map; From f4ab00dda265aa5d42ce1fd6c7de9dc30f0a5b68 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 27 Jul 2021 17:28:59 -0700 Subject: [PATCH 09/30] fixed faulty rebase --- packages/pigeon/lib/java_generator.dart | 26 +++++++------------------ 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 074605709a93..7dc905a850ed 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -124,11 +124,8 @@ void _writeHostApi(Indent indent, Api api) { indent.write('public interface ${api.name} '); indent.scoped('{', '}', () { for (final Method method in api.methods) { -<<<<<<< HEAD - final String argType = _javaTypeForDartTypePassthrough(method.argType); -======= - final String argType = _boxedType(method.argType.dataType); ->>>>>>> 3af9039 (started parsing argument generics) + final String argType = + _javaTypeForDartTypePassthrough(method.argType.dataType); final String returnType = method.isAsynchronous ? 'void' : _javaTypeForDartTypePassthrough(method.returnType.dataType); @@ -172,15 +169,10 @@ static MessageCodec getCodec() { indent.scoped('{', '} else {', () { indent.write('channel.setMessageHandler((message, reply) -> '); indent.scoped('{', '});', () { -<<<<<<< HEAD final String argType = - _javaTypeForDartTypePassthrough(method.argType); + _javaTypeForDartTypePassthrough(method.argType.dataType); final String returnType = _javaTypeForDartTypePassthrough(method.returnType.dataType); -======= - final String argType = _boxedType(method.argType.dataType); - final String returnType = _boxedType(method.returnType.dataType); ->>>>>>> 3af9039 (started parsing argument generics) indent.writeln('Map wrapped = new HashMap<>();'); indent.write('try '); indent.scoped('{', '}', () { @@ -264,13 +256,9 @@ static MessageCodec getCodec() { final String channelName = makeChannelName(api, func); final String returnType = func.returnType.dataType == 'void' ? 'Void' -<<<<<<< HEAD : _javaTypeForDartTypePassthrough(func.returnType.dataType); - final String argType = _javaTypeForDartTypePassthrough(func.argType); -======= - : _boxedType(func.returnType.dataType); - final String argType = _boxedType(func.argType.dataType); ->>>>>>> 3af9039 (started parsing argument generics) + final String argType = + _javaTypeForDartTypePassthrough(func.argType.dataType); String sendArgument; if (func.argType.dataType == 'void') { indent.write('public void ${func.name}(Reply<$returnType> callback) '); @@ -318,8 +306,8 @@ String _makeSetter(Field field) { String _flattenTypeArguments(List args) { return args .map((TypeArgument e) => e.typeArguments == null - ? _boxedType(e.dataType) - : '${_boxedType(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') + ? _javaTypeForDartTypePassthrough(e.dataType) + : '${_javaTypeForDartTypePassthrough(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') .reduce((String value, String element) => '$value, $element'); } From e0819cfc116be6eddcc39361ef0d88d203a7a5ef Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 29 Jul 2021 11:08:08 -0700 Subject: [PATCH 10/30] stuarts feedback --- packages/pigeon/lib/ast.dart | 4 ++-- packages/pigeon/lib/dart_generator.dart | 4 ++++ packages/pigeon/lib/java_generator.dart | 2 ++ packages/pigeon/lib/objc_generator.dart | 2 ++ packages/pigeon/lib/pigeon_lib.dart | 4 ++-- 5 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index f7caaea380c6..2ef8a94f5f51 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -74,7 +74,7 @@ class Api extends Node { } } -/// A parameter to a generic entity. +/// A parameter to a generic entity. For example, "String" to "List". class TypeArgument { /// Constructor for [TypeArgument]. TypeArgument({ @@ -86,7 +86,7 @@ class TypeArgument { /// A string representation of the base datatype. final String dataType; - /// The type arguments to [TypeArgument]. + /// The type arguments to this [TypeArgument]. final List? typeArguments; /// True if the type is nullable. diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index baa888f02aeb..1fb7128c7c24 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -264,6 +264,8 @@ void _writeFlutterApi( }); } +/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be +/// used in Dart code. String _flattenTypeArguments(List args, String nullTag) { return args .map((TypeArgument arg) => arg.typeArguments == null @@ -272,6 +274,8 @@ String _flattenTypeArguments(List args, String nullTag) { .reduce((String value, String element) => '$value, $element'); } +/// Creates the type declaration for use in Dart code from a [Field] making sure +/// that type arguments are used for primitive generic types. String _addGenericTypes(Field field, String nullTag) { switch (field.dataType) { case 'List': diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 7dc905a850ed..175e3722c67a 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -303,6 +303,8 @@ String _makeSetter(Field field) { return 'set$uppercased'; } +/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be +/// used in Java code. String _flattenTypeArguments(List args) { return args .map((TypeArgument e) => e.typeArguments == null diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index 30be78af9f22..9f71f8d88cec 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -92,6 +92,8 @@ const Map _propertyTypeForDartTypeMap = { 'Map': 'strong', }; +/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be +/// used in objc code. String _flattenTypeArguments(String? classPrefix, List args) { return args .map((TypeArgument e) => e.typeArguments == null diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 8576318cd44f..5cb83cdd0b80 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -412,7 +412,7 @@ List _validateAst(Root root, String source) { if (method.returnType.typeArguments != null) { result.add(Error( message: - 'Generic type arguments for primitive return values isn\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + 'Generic type arguments for primitive return values aren\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } @@ -426,7 +426,7 @@ List _validateAst(Root root, String source) { if (method.argType.typeArguments != null) { result.add(Error( message: - 'Generic type arguments for primitive arguments isn\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } From 6ea9b5b48de8a2507674a202c0d3169fc39fe276 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Fri, 30 Jul 2021 14:39:33 -0700 Subject: [PATCH 11/30] stuarts feedback for typedeclaration --- packages/pigeon/lib/ast.dart | 34 +- packages/pigeon/lib/dart_generator.dart | 62 +- packages/pigeon/lib/generator_tools.dart | 18 +- packages/pigeon/lib/java_generator.dart | 60 +- packages/pigeon/lib/objc_generator.dart | 84 +- packages/pigeon/lib/pigeon_lib.dart | 83 +- packages/pigeon/test/dart_generator_test.dart | 540 +++++++--- packages/pigeon/test/java_generator_test.dart | 413 ++++++-- packages/pigeon/test/objc_generator_test.dart | 973 +++++++++++++----- packages/pigeon/test/pigeon_lib_test.dart | 46 +- 10 files changed, 1664 insertions(+), 649 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index 2ef8a94f5f51..5971ce3cea04 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -74,10 +74,10 @@ class Api extends Node { } } -/// A parameter to a generic entity. For example, "String" to "List". -class TypeArgument { - /// Constructor for [TypeArgument]. - TypeArgument({ +/// Represents a type declaration. +class TypeDeclaration { + /// Constructor for [TypeDeclaration]. + TypeDeclaration({ required this.dataType, required this.isNullable, this.typeArguments, @@ -86,47 +86,35 @@ class TypeArgument { /// A string representation of the base datatype. final String dataType; - /// The type arguments to this [TypeArgument]. - final List? typeArguments; + /// The type arguments to this [TypeDeclaration]. + final List? typeArguments; /// True if the type is nullable. final bool isNullable; @override String toString() { - return '(TypeArgument dataType:$dataType isNullable:$isNullable typeArguments:$typeArguments)'; + return '(TypeDeclaration dataType:$dataType isNullable:$isNullable typeArguments:$typeArguments)'; } } /// Represents a field on a [Class]. class Field extends Node { /// Parametric constructor for [Field]. - Field({ - required this.name, - required this.dataType, - required this.isNullable, - this.typeArguments, - this.offset, - }); + Field({required this.name, required this.type, this.offset}); /// The name of the field. String name; - /// The data-type of the field (ex 'String' or 'int'). - String dataType; - /// The offset in the source file where the field appears. int? offset; - /// True if the datatype is nullable (ex `int?`). - bool isNullable; - - /// Type parameters used for generics. - List? typeArguments; + /// The type of the [Field]. + TypeDeclaration type; @override String toString() { - return '(Field name:$name dataType:$dataType typeArguments:$typeArguments)'; + return '(Field name:$name type:$type)'; } } diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 1fb7128c7c24..976ed2bf40ee 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -121,12 +121,12 @@ final BinaryMessenger$nullTag _binaryMessenger; } String argSignature = ''; String sendArgument = 'null'; - if (func.argType.dataType != 'void') { - argSignature = '${func.argType.dataType} arg'; + if (func.argType.type.dataType != 'void') { + argSignature = '${func.argType.type.dataType} arg'; sendArgument = 'arg'; } indent.write( - 'Future<${func.returnType.dataType}> ${func.name}($argSignature) async ', + 'Future<${func.returnType.type.dataType}> ${func.name}($argSignature) async ', ); indent.scoped('{', '}', () { final String channelName = makeChannelName(api, func); @@ -137,9 +137,9 @@ final BinaryMessenger$nullTag _binaryMessenger; '\'$channelName\', codec, binaryMessenger: _binaryMessenger);', ); }); - final String returnStatement = func.returnType.dataType == 'void' + final String returnStatement = func.returnType.type.dataType == 'void' ? '// noop' - : 'return (replyMap[\'${Keys.result}\'] as ${func.returnType.dataType}$nullTag)$unwrapOperator;'; + : 'return (replyMap[\'${Keys.result}\'] as ${func.returnType.type.dataType}$nullTag)$unwrapOperator;'; indent.format(''' final Map$nullTag replyMap =\n\t\tawait channel.send($sendArgument) as Map$nullTag; if (replyMap == null) { @@ -182,10 +182,11 @@ void _writeFlutterApi( for (final Method func in api.methods) { final bool isAsync = func.isAsynchronous; final String returnType = isAsync - ? 'Future<${func.returnType.dataType}>' - : func.returnType.dataType; - final String argSignature = - func.argType.dataType == 'void' ? '' : '${func.argType.dataType} arg'; + ? 'Future<${func.returnType.type.dataType}>' + : func.returnType.type.dataType; + final String argSignature = func.argType.type.dataType == 'void' + ? '' + : '${func.argType.type.dataType} arg'; indent.writeln('$returnType ${func.name}($argSignature);'); } indent.write('static void setup(${api.name}$nullTag api) '); @@ -216,12 +217,12 @@ void _writeFlutterApi( 'channel.$messageHandlerSetter((Object$nullTag message) async ', ); indent.scoped('{', '});', () { - final String argType = func.argType.dataType; - final String returnType = func.returnType.dataType; + final String argType = func.argType.type.dataType; + final String returnType = func.returnType.type.dataType; final bool isAsync = func.isAsynchronous; final String emptyReturnStatement = isMockHandler ? 'return {};' - : func.returnType.dataType == 'void' + : func.returnType.type.dataType == 'void' ? 'return;' : 'return null;'; String call; @@ -264,30 +265,30 @@ void _writeFlutterApi( }); } -/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be +/// Converts a [List] of [TypeDeclaration]s to a comma separated [String] to be /// used in Dart code. -String _flattenTypeArguments(List args, String nullTag) { +String _flattenTypeDeclarations(List args, String nullTag) { return args - .map((TypeArgument arg) => arg.typeArguments == null + .map((TypeDeclaration arg) => arg.typeArguments == null ? '${arg.dataType}$nullTag' - : '${arg.dataType}<${_flattenTypeArguments(arg.typeArguments!, nullTag)}>$nullTag') + : '${arg.dataType}<${_flattenTypeDeclarations(arg.typeArguments!, nullTag)}>$nullTag') .reduce((String value, String element) => '$value, $element'); } /// Creates the type declaration for use in Dart code from a [Field] making sure /// that type arguments are used for primitive generic types. String _addGenericTypes(Field field, String nullTag) { - switch (field.dataType) { + switch (field.type.dataType) { case 'List': - return (field.typeArguments == null) + return (field.type.typeArguments == null) ? 'List$nullTag' - : 'List<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; + : 'List<${_flattenTypeDeclarations(field.type.typeArguments!, nullTag)}>$nullTag'; case 'Map': - return (field.typeArguments == null) + return (field.type.typeArguments == null) ? 'Map$nullTag' - : 'Map<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; + : 'Map<${_flattenTypeDeclarations(field.type.typeArguments!, nullTag)}>$nullTag'; default: - return '${field.dataType}$nullTag'; + return '${field.type.dataType}$nullTag'; } } @@ -345,11 +346,11 @@ void generateDart(DartOptions opt, Root root, StringSink sink) { ); for (final Field field in klass.fields) { indent.write('pigeonMap[\'${field.name}\'] = '); - if (customClassNames.contains(field.dataType)) { + if (customClassNames.contains(field.type.dataType)) { indent.addln( '${field.name} == null ? null : ${field.name}$unwrapOperator.encode();', ); - } else if (customEnumNames.contains(field.dataType)) { + } else if (customEnumNames.contains(field.type.dataType)) { indent.addln( '${field.name} == null ? null : ${field.name}$unwrapOperator.index;', ); @@ -372,19 +373,20 @@ void generateDart(DartOptions opt, Root root, StringSink sink) { for (int index = 0; index < klass.fields.length; index += 1) { final Field field = klass.fields[index]; indent.write('..${field.name} = '); - if (customClassNames.contains(field.dataType)) { + if (customClassNames.contains(field.type.dataType)) { indent.format(''' pigeonMap['${field.name}'] != null -\t\t? ${field.dataType}.decode(pigeonMap['${field.name}']$unwrapOperator) +\t\t? ${field.type.dataType}.decode(pigeonMap['${field.name}']$unwrapOperator) \t\t: null''', leadingSpace: false, trailingNewline: false); - } else if (customEnumNames.contains(field.dataType)) { + } else if (customEnumNames.contains(field.type.dataType)) { indent.format(''' pigeonMap['${field.name}'] != null -\t\t? ${field.dataType}.values[pigeonMap['${field.name}']$unwrapOperator as int] +\t\t? ${field.type.dataType}.values[pigeonMap['${field.name}']$unwrapOperator as int] \t\t: null''', leadingSpace: false, trailingNewline: false); - } else if (field.dataType == 'Map' && field.typeArguments != null) { + } else if (field.type.dataType == 'Map' && + field.type.typeArguments != null) { indent.add( - '(pigeonMap[\'${field.name}\'] as Map$nullTag)$nullTag.cast<${_flattenTypeArguments(field.typeArguments!, nullTag)}>()', + '(pigeonMap[\'${field.name}\'] as Map$nullTag)$nullTag.cast<${_flattenTypeDeclarations(field.type.typeArguments!, nullTag)}>()', ); } else { indent.add( diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index a41a75800674..e1a25463420f 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -163,19 +163,19 @@ HostDatatype getHostDatatype(Field field, List classes, List enums, {String Function(String)? customResolver}) { final String? datatype = builtinResolver(field); if (datatype == null) { - if (classes.map((Class x) => x.name).contains(field.dataType)) { + if (classes.map((Class x) => x.name).contains(field.type.dataType)) { final String customName = customResolver != null - ? customResolver(field.dataType) - : field.dataType; + ? customResolver(field.type.dataType) + : field.type.dataType; return HostDatatype(datatype: customName, isBuiltin: false); - } else if (enums.map((Enum x) => x.name).contains(field.dataType)) { + } else if (enums.map((Enum x) => x.name).contains(field.type.dataType)) { final String customName = customResolver != null - ? customResolver(field.dataType) - : field.dataType; + ? customResolver(field.type.dataType) + : field.type.dataType; return HostDatatype(datatype: customName, isBuiltin: false); } else { throw Exception( - 'unrecognized datatype for field:"${field.name}" of type:"${field.dataType}"'); + 'unrecognized datatype for field:"${field.name}" of type:"${field.type.dataType}"'); } } else { return HostDatatype(datatype: datatype, isBuiltin: true); @@ -285,8 +285,8 @@ const int _minimumCodecFieldKey = 128; Iterable getCodecClasses(Api api) sync* { final Set names = {}; for (final Method method in api.methods) { - names.add(method.returnType.dataType); - names.add(method.argType.dataType); + names.add(method.returnType.type.dataType); + names.add(method.argType.type.dataType); } final List sortedNames = names .where((String element) => diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 175e3722c67a..83e616182a4f 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -125,18 +125,18 @@ void _writeHostApi(Indent indent, Api api) { indent.scoped('{', '}', () { for (final Method method in api.methods) { final String argType = - _javaTypeForDartTypePassthrough(method.argType.dataType); + _javaTypeForDartTypePassthrough(method.argType.type.dataType); final String returnType = method.isAsynchronous ? 'void' - : _javaTypeForDartTypePassthrough(method.returnType.dataType); + : _javaTypeForDartTypePassthrough(method.returnType.type.dataType); final List argSignature = []; - if (method.argType.dataType != 'void') { + if (method.argType.type.dataType != 'void') { argSignature.add('$argType arg'); } if (method.isAsynchronous) { - final String returnType = method.returnType.dataType == 'void' + final String returnType = method.returnType.type.dataType == 'void' ? 'Void' - : method.returnType.dataType; + : method.returnType.type.dataType; argSignature.add('Result<$returnType> result'); } indent.writeln('$returnType ${method.name}(${argSignature.join(', ')});'); @@ -170,9 +170,9 @@ static MessageCodec getCodec() { indent.write('channel.setMessageHandler((message, reply) -> '); indent.scoped('{', '});', () { final String argType = - _javaTypeForDartTypePassthrough(method.argType.dataType); - final String returnType = - _javaTypeForDartTypePassthrough(method.returnType.dataType); + _javaTypeForDartTypePassthrough(method.argType.type.dataType); + final String returnType = _javaTypeForDartTypePassthrough( + method.returnType.type.dataType); indent.writeln('Map wrapped = new HashMap<>();'); indent.write('try '); indent.scoped('{', '}', () { @@ -189,7 +189,9 @@ static MessageCodec getCodec() { } if (method.isAsynchronous) { final String resultValue = - method.returnType.dataType == 'void' ? 'null' : 'result'; + method.returnType.type.dataType == 'void' + ? 'null' + : 'result'; methodArgument.add( 'result -> { ' 'wrapped.put("${Keys.result}", $resultValue); ' @@ -201,7 +203,7 @@ static MessageCodec getCodec() { 'api.${method.name}(${methodArgument.join(', ')})'; if (method.isAsynchronous) { indent.writeln('$call;'); - } else if (method.returnType.dataType == 'void') { + } else if (method.returnType.type.dataType == 'void') { indent.writeln('$call;'); indent.writeln('wrapped.put("${Keys.result}", null);'); } else { @@ -254,13 +256,13 @@ static MessageCodec getCodec() { '''); for (final Method func in api.methods) { final String channelName = makeChannelName(api, func); - final String returnType = func.returnType.dataType == 'void' + final String returnType = func.returnType.type.dataType == 'void' ? 'Void' - : _javaTypeForDartTypePassthrough(func.returnType.dataType); + : _javaTypeForDartTypePassthrough(func.returnType.type.dataType); final String argType = - _javaTypeForDartTypePassthrough(func.argType.dataType); + _javaTypeForDartTypePassthrough(func.argType.type.dataType); String sendArgument; - if (func.argType.dataType == 'void') { + if (func.argType.type.dataType == 'void') { indent.write('public void ${func.name}(Reply<$returnType> callback) '); sendArgument = 'null'; } else { @@ -278,7 +280,7 @@ static MessageCodec getCodec() { indent.dec(); indent.write('channel.send($sendArgument, channelReply -> '); indent.scoped('{', '});', () { - if (func.returnType.dataType == 'void') { + if (func.returnType.type.dataType == 'void') { indent.writeln('callback.reply(null);'); } else { indent.writeln('@SuppressWarnings("ConstantConditions")'); @@ -303,11 +305,11 @@ String _makeSetter(Field field) { return 'set$uppercased'; } -/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be +/// Converts a [List] of [TypeDeclaration]s to a comma separated [String] to be /// used in Java code. -String _flattenTypeArguments(List args) { +String _flattenTypeArguments(List args) { return args - .map((TypeArgument e) => e.typeArguments == null + .map((TypeDeclaration e) => e.typeArguments == null ? _javaTypeForDartTypePassthrough(e.dataType) : '${_javaTypeForDartTypePassthrough(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') .reduce((String value, String element) => '$value, $element'); @@ -325,13 +327,13 @@ String? _javaTypeForDartType(Field field) { 'Float64List': 'double[]', 'Map': 'Map', }; - if (javaTypeForDartTypeMap.containsKey(field.dataType)) { - return javaTypeForDartTypeMap[field.dataType]; - } else if (field.dataType == 'List') { - if (field.typeArguments == null) { + if (javaTypeForDartTypeMap.containsKey(field.type.dataType)) { + return javaTypeForDartTypeMap[field.type.dataType]; + } else if (field.type.dataType == 'List') { + if (field.type.typeArguments == null) { return 'List'; } else { - return 'List<${_flattenTypeArguments(field.typeArguments!)}>'; + return 'List<${_flattenTypeArguments(field.type.typeArguments!)}>'; } } else { return null; @@ -342,10 +344,10 @@ String _castObject( Field field, List classes, List enums, String varName) { final HostDatatype hostDatatype = getHostDatatype(field, classes, enums, _javaTypeForDartType); - if (field.dataType == 'int') { + if (field.type.dataType == 'int') { return '($varName == null) ? null : (($varName instanceof Integer) ? (Integer)$varName : (${hostDatatype.datatype})$varName)'; } else if (!hostDatatype.isBuiltin && - classes.map((Class x) => x.name).contains(field.dataType)) { + classes.map((Class x) => x.name).contains(field.type.dataType)) { return '${hostDatatype.datatype}.fromMap((Map)$varName)'; } else { return '(${hostDatatype.datatype})$varName'; @@ -433,10 +435,10 @@ void generateJava(JavaOptions options, Root root, StringSink sink) { field, root.classes, root.enums, _javaTypeForDartType); String toWriteValue = ''; if (!hostDatatype.isBuiltin && - rootClassNameSet.contains(field.dataType)) { + rootClassNameSet.contains(field.type.dataType)) { toWriteValue = '${field.name}.toMap()'; } else if (!hostDatatype.isBuiltin && - rootEnumNameSet.contains(field.dataType)) { + rootEnumNameSet.contains(field.type.dataType)) { toWriteValue = '${field.name}.index'; } else { toWriteValue = field.name; @@ -450,9 +452,9 @@ void generateJava(JavaOptions options, Root root, StringSink sink) { indent.writeln('${klass.name} fromMapResult = new ${klass.name}();'); for (final Field field in klass.fields) { indent.writeln('Object ${field.name} = map.get("${field.name}");'); - if (rootEnumNameSet.contains(field.dataType)) { + if (rootEnumNameSet.contains(field.type.dataType)) { indent.writeln( - 'fromMapResult.${field.name} = ${field.dataType}.values()[(int)${field.name}];'); + 'fromMapResult.${field.name} = ${field.type.dataType}.values()[(int)${field.name}];'); } else { indent.writeln( 'fromMapResult.${field.name} = ${_castObject(field, root.classes, root.enums, field.name)};'); diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index 9f71f8d88cec..f038d0d82fe6 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -92,21 +92,21 @@ const Map _propertyTypeForDartTypeMap = { 'Map': 'strong', }; -/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be +/// Converts a [List] of [TypeDeclaration]s to a comma separated [String] to be /// used in objc code. -String _flattenTypeArguments(String? classPrefix, List args) { +String _flattenTypeArguments(String? classPrefix, List args) { return args - .map((TypeArgument e) => e.typeArguments == null + .map((TypeDeclaration e) => e.typeArguments == null ? '${_objcTypeForDartType(classPrefix, e.dataType)} *' : '${_objcTypeForDartType(classPrefix, e.dataType)}<${_flattenTypeArguments(classPrefix, e.typeArguments!)}> *') .reduce((String value, String element) => '$value, $element'); } String? _objcTypePtrForPrimitiveDartType(String? classPrefix, Field field) { - return _objcTypeForDartTypeMap.containsKey(field.dataType) - ? field.typeArguments == null - ? '${_objcTypeForDartTypeMap[field.dataType]} *' - : '${_objcTypeForDartTypeMap[field.dataType]}<${_flattenTypeArguments(classPrefix, field.typeArguments!)}> *' + return _objcTypeForDartTypeMap.containsKey(field.type.dataType) + ? field.type.typeArguments == null + ? '${_objcTypeForDartTypeMap[field.type.dataType]} *' + : '${_objcTypeForDartTypeMap[field.type.dataType]}<${_flattenTypeArguments(classPrefix, field.type.typeArguments!)}> *' : null; } @@ -135,13 +135,13 @@ void _writeClassDeclarations( for (final Field field in klass.fields) { final HostDatatype hostDatatype = getHostDatatype(field, classes, enums, (Field x) => _objcTypePtrForPrimitiveDartType(prefix, x), - customResolver: enumNames.contains(field.dataType) + customResolver: enumNames.contains(field.type.dataType) ? (String x) => _className(prefix, x) : (String x) => '${_className(prefix, x)} *'); late final String propertyType; if (hostDatatype.isBuiltin) { - propertyType = _propertyTypeForDartType(field.dataType); - } else if (enumNames.contains(field.dataType)) { + propertyType = _propertyTypeForDartType(field.type.dataType); + } else if (enumNames.contains(field.type.dataType)) { propertyType = 'assign'; } else { propertyType = 'strong'; @@ -240,39 +240,39 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { indent.writeln('@protocol $apiName'); for (final Method func in api.methods) { final String returnTypeName = - _objcTypeForDartType(options.prefix, func.returnType.dataType); + _objcTypeForDartType(options.prefix, func.returnType.type.dataType); if (func.isAsynchronous) { - if (func.returnType.dataType == 'void') { - if (func.argType.dataType == 'void') { + if (func.returnType.type.dataType == 'void') { + if (func.argType.type.dataType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)(FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.argType.type.dataType); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)(FlutterError *_Nullable))completion;'); } } else { - if (func.argType.dataType == 'void') { + if (func.argType.type.dataType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.argType.type.dataType); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } } } else { - final String returnType = func.returnType.dataType == 'void' + final String returnType = func.returnType.type.dataType == 'void' ? 'void' : 'nullable $returnTypeName *'; - if (func.argType.dataType == 'void') { + if (func.argType.type.dataType == 'void') { indent.writeln( '-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.argType.type.dataType); indent.writeln( '-($returnType)${func.name}:($argType*)input error:(FlutterError *_Nullable *_Nonnull)error;'); } @@ -292,14 +292,14 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) { '- (instancetype)initWithBinaryMessenger:(id)binaryMessenger;'); for (final Method func in api.methods) { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType.dataType); + _objcTypeForDartType(options.prefix, func.returnType.type.dataType); final String callbackType = - _callbackForType(func.returnType.dataType, returnType); - if (func.argType.dataType == 'void') { + _callbackForType(func.returnType.type.dataType, returnType); + if (func.argType.type.dataType == 'void') { indent.writeln('- (void)${func.name}:($callbackType)completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.argType.type.dataType); indent.writeln( '- (void)${func.name}:($argType*)input completion:($callbackType)completion;'); } @@ -367,8 +367,8 @@ void generateObjcHeader(ObjcOptions options, Root root, StringSink sink) { String _dictGetter( List classNames, String dict, Field field, String? prefix) { - if (classNames.contains(field.dataType)) { - String className = field.dataType; + if (classNames.contains(field.type.dataType)) { + String className = field.type.dataType; if (prefix != null) { className = '$prefix$className'; } @@ -380,9 +380,9 @@ String _dictGetter( String _dictValue( List classNames, List enumNames, Field field) { - if (classNames.contains(field.dataType)) { + if (classNames.contains(field.type.dataType)) { return '(self.${field.name} ? [self.${field.name} toMap] : [NSNull null])'; - } else if (enumNames.contains(field.dataType)) { + } else if (enumNames.contains(field.type.dataType)) { return '@(self.${field.name})'; } else { return '(self.${field.name} ? self.${field.name} : [NSNull null])'; @@ -415,21 +415,21 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { indent.write( '[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) '); indent.scoped('{', '}];', () { - final String returnType = - _objcTypeForDartType(options.prefix, func.returnType.dataType); + final String returnType = _objcTypeForDartType( + options.prefix, func.returnType.type.dataType); String syncCall; - if (func.argType.dataType == 'void') { + if (func.argType.type.dataType == 'void') { syncCall = '[api ${func.name}:&error]'; } else { - final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + final String argType = _objcTypeForDartType( + options.prefix, func.argType.type.dataType); indent.writeln('$argType *input = message;'); syncCall = '[api ${func.name}:input error:&error]'; } if (func.isAsynchronous) { - if (func.returnType.dataType == 'void') { + if (func.returnType.type.dataType == 'void') { const String callback = 'callback(wrapResult(nil, error));'; - if (func.argType.dataType == 'void') { + if (func.argType.type.dataType == 'void') { indent.writeScoped( '[api ${func.name}:^(FlutterError *_Nullable error) {', '}];', () { @@ -444,7 +444,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { } } else { const String callback = 'callback(wrapResult(output, error));'; - if (func.argType.dataType == 'void') { + if (func.argType.type.dataType == 'void') { indent.writeScoped( '[api ${func.name}:^($returnType *_Nullable output, FlutterError *_Nullable error) {', '}];', () { @@ -460,7 +460,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { } } else { indent.writeln('FlutterError *error;'); - if (func.returnType.dataType == 'void') { + if (func.returnType.type.dataType == 'void') { indent.writeln('$syncCall;'); indent.writeln('callback(wrapResult(nil, error));'); } else { @@ -501,17 +501,17 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { indent.addln(''); for (final Method func in api.methods) { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType.dataType); + _objcTypeForDartType(options.prefix, func.returnType.type.dataType); final String callbackType = - _callbackForType(func.returnType.dataType, returnType); + _callbackForType(func.returnType.type.dataType, returnType); String sendArgument; - if (func.argType.dataType == 'void') { + if (func.argType.type.dataType == 'void') { indent.write('- (void)${func.name}:($callbackType)completion '); sendArgument = 'nil'; } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.argType.type.dataType); indent.write( '- (void)${func.name}:($argType*)input completion:($callbackType)completion '); sendArgument = 'input'; @@ -529,7 +529,7 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { indent.dec(); indent.write('[channel sendMessage:$sendArgument reply:^(id reply) '); indent.scoped('{', '}];', () { - if (func.returnType.dataType == 'void') { + if (func.returnType.type.dataType == 'void') { indent.writeln('completion(nil);'); } else { indent.writeln('$returnType * output = reply;'); @@ -598,7 +598,7 @@ static NSDictionary* wrapResult(id result, FlutterError *error) { const String resultName = 'result'; indent.writeln('$className* $resultName = [[$className alloc] init];'); for (final Field field in klass.fields) { - if (enumNames.contains(field.dataType)) { + if (enumNames.contains(field.type.dataType)) { indent.writeln( '$resultName.${field.name} = [${_dictGetter(classNames, 'dict', field, options.prefix)} integerValue];'); } else { diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 5cb83cdd0b80..7ff54b2d20c2 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -378,8 +378,8 @@ List _validateAst(Root root, String source) { final List customEnums = root.enums.map((Enum x) => x.name).toList(); for (final Class klass in root.classes) { for (final Field field in klass.fields) { - if (field.typeArguments != null) { - for (final TypeArgument typeArgument in field.typeArguments!) { + if (field.type.typeArguments != null) { + for (final TypeDeclaration typeArgument in field.type.typeArguments!) { if (!typeArgument.isNullable) { result.add(Error( message: @@ -389,12 +389,12 @@ List _validateAst(Root root, String source) { } } } - if (!(validTypes.contains(field.dataType) || - customClasses.contains(field.dataType) || - customEnums.contains(field.dataType))) { + if (!(validTypes.contains(field.type.dataType) || + customClasses.contains(field.type.dataType) || + customEnums.contains(field.type.dataType))) { result.add(Error( message: - 'Unsupported datatype:"${field.dataType}" in class "${klass.name}".', + 'Unsupported datatype:"${field.type.dataType}" in class "${klass.name}".', lineNumber: _calculateLineNumberNullable(source, field.offset), )); } @@ -402,31 +402,31 @@ List _validateAst(Root root, String source) { } for (final Api api in root.apis) { for (final Method method in api.methods) { - if (method.returnType.isNullable) { + if (method.returnType.type.isNullable) { result.add(Error( message: - 'Nullable return types types aren\'t supported for Pigeon methods: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name}"', + 'Nullable return types types aren\'t supported for Pigeon methods: "${method.argType.type.dataType}" in API: "${api.name}" method: "${method.name}"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.returnType.typeArguments != null) { + if (method.returnType.type.typeArguments != null) { result.add(Error( message: - 'Generic type arguments for primitive return values aren\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + 'Generic type arguments for primitive return values aren\'t yet supported: "${method.argType.type.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.argType.isNullable) { + if (method.argType.type.isNullable) { result.add(Error( message: - 'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name}"', + 'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType.type.dataType}" in API: "${api.name}" method: "${method.name}"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.argType.typeArguments != null) { + if (method.argType.type.typeArguments != null) { result.add(Error( message: - 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.argType.type.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } @@ -481,8 +481,8 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final Set referencedTypes = {}; for (final Api api in _apis) { for (final Method method in api.methods) { - referencedTypes.add(method.argType.dataType); - referencedTypes.add(method.returnType.dataType); + referencedTypes.add(method.argType.type.dataType); + referencedTypes.add(method.returnType.type.dataType); } } @@ -493,10 +493,10 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final Class aClass = _classes.firstWhere((Class x) => x.name == next, orElse: () => Class(name: '', fields: [])); for (final Field field in aClass.fields) { - if (!referencedTypes.contains(field.dataType) && - !validTypes.contains(field.dataType)) { - referencedTypes.add(field.dataType); - classesToCheck.add(field.dataType); + if (!referencedTypes.contains(field.type.dataType) && + !validTypes.contains(field.type.dataType)) { + referencedTypes.add(field.type.dataType); + classesToCheck.add(field.type.dataType); } } } @@ -637,7 +637,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final dart_ast.FormalParameterList parameters = node.parameters!; late String argType; bool isNullable = false; - List? argTypeArguments; + List? argTypeArguments; if (parameters.parameters.isEmpty) { argType = 'void'; } else { @@ -656,15 +656,21 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { name: node.name.name, returnType: Field( name: '', - dataType: node.returnType.toString(), - typeArguments: typeAnnotationsToTypeArguments( - (node.returnType as dart_ast.NamedType?)!.typeArguments), - isNullable: node.returnType!.question != null), + offset: null, + type: TypeDeclaration( + dataType: node.returnType.toString(), + isNullable: node.returnType!.question != null, + typeArguments: typeAnnotationsToTypeArguments( + (node.returnType as dart_ast.NamedType?)!.typeArguments), + )), argType: Field( - dataType: argType, - isNullable: isNullable, name: '', - typeArguments: argTypeArguments), + offset: null, + type: TypeDeclaration( + dataType: argType, + isNullable: isNullable, + typeArguments: argTypeArguments, + )), isAsynchronous: isAsynchronous, offset: node.offset)); } else if (_currentClass != null) { @@ -688,14 +694,14 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { return null; } - List? typeAnnotationsToTypeArguments( + List? typeAnnotationsToTypeArguments( dart_ast.TypeArgumentList? typeArguments) { - List? result; + List? result; if (typeArguments != null) { for (final Object x in typeArguments.childEntities) { if (x is dart_ast.TypeName) { - result ??= []; - result.add(TypeArgument( + result ??= []; + result.add(TypeDeclaration( dataType: x.name.name, isNullable: x.question != null, typeArguments: typeAnnotationsToTypeArguments(x.typeArguments))); @@ -725,12 +731,13 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { } else { final dart_ast.TypeArgumentList? typeArguments = type.typeArguments; _currentClass!.fields.add(Field( - name: node.fields.variables[0].name.name, - dataType: type.name.name, - isNullable: type.question != null, - typeArguments: typeAnnotationsToTypeArguments(typeArguments), - offset: node.offset, - )); + name: node.fields.variables[0].name.name, + offset: node.offset, + type: TypeDeclaration( + dataType: type.name.name, + isNullable: type.question != null, + typeArguments: typeAnnotationsToTypeArguments(typeArguments), + ))); } } else { _errors.add(Error( diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index f31338c0f571..ac1c30ffc301 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -13,10 +13,13 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'dataType1', - isNullable: true, - ), + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'dataType1', + isNullable: true, + typeArguments: null, + )), ], ); final Root root = Root( @@ -57,25 +60,45 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -91,20 +114,26 @@ void main() { name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ], ), Class( name: 'Nested', fields: [ Field( - name: 'nested', - dataType: 'Input', - isNullable: true, - ) + name: 'nested', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: true, + typeArguments: null, + )) ], ) ], enums: []); @@ -130,25 +159,45 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -163,18 +212,35 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -189,18 +255,35 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -218,18 +301,35 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'void'), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -244,18 +344,35 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'EnumClass'), - returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'EnumClass', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'EnumClass', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'EnumClass', fields: [ Field( - name: 'enum1', - dataType: 'Enum', - isNullable: true, - ) + name: 'enum1', + offset: null, + type: TypeDeclaration( + dataType: 'Enum', + isNullable: true, + typeArguments: null, + )) ]), ], enums: [ Enum( @@ -280,18 +397,35 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'EnumClass'), - returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'EnumClass', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'EnumClass', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'EnumClass', fields: [ Field( - name: 'enum1', - dataType: 'Enum', - isNullable: true, - ) + name: 'enum1', + offset: null, + type: TypeDeclaration( + dataType: 'Enum', + isNullable: true, + typeArguments: null, + )) ]), ], enums: [ Enum( @@ -318,18 +452,35 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'void'), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -347,32 +498,65 @@ void main() { methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: - Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ), Method( name: 'voidReturner', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer mainCodeSink = StringBuffer(); @@ -401,10 +585,13 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'dataType1', - isNullable: true, - ), + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'dataType1', + isNullable: true, + typeArguments: null, + )), ], ); final Root root = Root( @@ -423,25 +610,45 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -458,25 +665,45 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -492,25 +719,45 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -525,18 +772,35 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'void'), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -567,13 +831,15 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'List', - isNullable: true, - typeArguments: [ - TypeArgument(dataType: 'int', isNullable: true) - ], - ), + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'List', + isNullable: true, + typeArguments: [ + TypeDeclaration(dataType: 'int', isNullable: true) + ], + )), ], ); final Root root = Root( @@ -593,14 +859,16 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'Map', - isNullable: true, - typeArguments: [ - TypeArgument(dataType: 'String', isNullable: true), - TypeArgument(dataType: 'int', isNullable: true), - ], - ), + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'Map', + isNullable: true, + typeArguments: [ + TypeDeclaration(dataType: 'String', isNullable: true), + TypeDeclaration(dataType: 'int', isNullable: true), + ], + )), ], ); final Root root = Root( diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 510d6d922260..1e69951b194f 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -12,10 +12,13 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'int', - isNullable: true, - ), + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'int', + isNullable: true, + typeArguments: null, + )), ], ); final Root root = Root( @@ -62,10 +65,13 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'int', - isNullable: true, - ) + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'int', + isNullable: true, + typeArguments: null, + )) ], ); final Root root = Root( @@ -87,17 +93,45 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field(name: 'input', dataType: 'String', isNullable: true) + Field( + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ - Field(name: 'output', dataType: 'String', isNullable: true) + Field( + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -112,14 +146,70 @@ void main() { test('all the simple datatypes header', () { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ - Field(name: 'aBool', dataType: 'bool', isNullable: true), - Field(name: 'aInt', dataType: 'int', isNullable: true), - Field(name: 'aDouble', dataType: 'double', isNullable: true), - Field(name: 'aString', dataType: 'String', isNullable: true), - Field(name: 'aUint8List', dataType: 'Uint8List', isNullable: true), - Field(name: 'aInt32List', dataType: 'Int32List', isNullable: true), - Field(name: 'aInt64List', dataType: 'Int64List', isNullable: true), - Field(name: 'aFloat64List', dataType: 'Float64List', isNullable: true), + Field( + name: 'aBool', + offset: null, + type: TypeDeclaration( + dataType: 'bool', + isNullable: true, + typeArguments: null, + )), + Field( + name: 'aInt', + offset: null, + type: TypeDeclaration( + dataType: 'int', + isNullable: true, + typeArguments: null, + )), + Field( + name: 'aDouble', + offset: null, + type: TypeDeclaration( + dataType: 'double', + isNullable: true, + typeArguments: null, + )), + Field( + name: 'aString', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )), + Field( + name: 'aUint8List', + offset: null, + type: TypeDeclaration( + dataType: 'Uint8List', + isNullable: true, + typeArguments: null, + )), + Field( + name: 'aInt32List', + offset: null, + type: TypeDeclaration( + dataType: 'Int32List', + isNullable: true, + typeArguments: null, + )), + Field( + name: 'aInt64List', + offset: null, + type: TypeDeclaration( + dataType: 'Int64List', + isNullable: true, + typeArguments: null, + )), + Field( + name: 'aFloat64List', + offset: null, + type: TypeDeclaration( + dataType: 'Float64List', + isNullable: true, + typeArguments: null, + )), ]), ], enums: []); @@ -142,17 +232,45 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field(name: 'input', dataType: 'String', isNullable: true) + Field( + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ - Field(name: 'output', dataType: 'String', isNullable: true) + Field( + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -168,14 +286,35 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field(name: 'input', dataType: 'String', isNullable: true) + Field( + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -191,14 +330,35 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field(name: 'input', dataType: 'String', isNullable: true) + Field( + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -214,14 +374,35 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Output', fields: [ - Field(name: 'output', dataType: 'String', isNullable: true) + Field( + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -237,14 +418,35 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Output', fields: [ - Field(name: 'output', dataType: 'String', isNullable: true) + Field( + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -258,7 +460,14 @@ void main() { test('gen list', () { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ - Field(name: 'field1', dataType: 'List', isNullable: true) + Field( + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'List', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -272,7 +481,14 @@ void main() { test('gen map', () { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ - Field(name: 'field1', dataType: 'Map', isNullable: true) + Field( + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'Map', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -288,20 +504,26 @@ void main() { name: 'Outer', fields: [ Field( - name: 'nested', - dataType: 'Nested', - isNullable: true, - ) + name: 'nested', + offset: null, + type: TypeDeclaration( + dataType: 'Nested', + isNullable: true, + typeArguments: null, + )) ], ); final Class nestedClass = Class( name: 'Nested', fields: [ Field( - name: 'data', - dataType: 'int', - isNullable: true, - ) + name: 'data', + offset: null, + type: TypeDeclaration( + dataType: 'int', + isNullable: true, + typeArguments: null, + )) ], ); final Root root = Root( @@ -326,17 +548,45 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field(name: 'input', dataType: 'String', isNullable: true) + Field( + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ - Field(name: 'output', dataType: 'String', isNullable: true) + Field( + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -359,17 +609,45 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field(name: 'input', dataType: 'String', isNullable: true) + Field( + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ - Field(name: 'output', dataType: 'String', isNullable: true) + Field( + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -392,10 +670,13 @@ void main() { name: 'EnumClass', fields: [ Field( - name: 'enum1', - dataType: 'Enum1', - isNullable: true, - ), + name: 'enum1', + offset: null, + type: TypeDeclaration( + dataType: 'Enum1', + isNullable: true, + typeArguments: null, + )), ], ); final Root root = Root( @@ -439,13 +720,15 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'List', - isNullable: true, - typeArguments: [ - TypeArgument(dataType: 'int', isNullable: true) - ], - ), + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'List', + isNullable: true, + typeArguments: [ + TypeDeclaration(dataType: 'int', isNullable: true) + ], + )), ], ); final Root root = Root( diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 759b16e3f296..97ac90eb140d 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -11,10 +11,13 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'String', - isNullable: true, - ) + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -28,10 +31,13 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'String', - isNullable: true, - ) + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -85,15 +91,21 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'String', - isNullable: true, - ), + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )), Field( - name: 'enum1', - dataType: 'Enum1', - isNullable: true, - ), + name: 'enum1', + offset: null, + type: TypeDeclaration( + dataType: 'Enum1', + isNullable: true, + typeArguments: null, + )), ], ), ], @@ -120,23 +132,43 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -154,23 +186,43 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -186,45 +238,69 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'aBool', - dataType: 'bool', - isNullable: true, - ), + name: 'aBool', + offset: null, + type: TypeDeclaration( + dataType: 'bool', + isNullable: true, + typeArguments: null, + )), Field( - name: 'aInt', - dataType: 'int', - isNullable: true, - ), + name: 'aInt', + offset: null, + type: TypeDeclaration( + dataType: 'int', + isNullable: true, + typeArguments: null, + )), Field( - name: 'aDouble', - dataType: 'double', - isNullable: true, - ), + name: 'aDouble', + offset: null, + type: TypeDeclaration( + dataType: 'double', + isNullable: true, + typeArguments: null, + )), Field( - name: 'aString', - dataType: 'String', - isNullable: true, - ), + name: 'aString', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )), Field( - name: 'aUint8List', - dataType: 'Uint8List', - isNullable: true, - ), + name: 'aUint8List', + offset: null, + type: TypeDeclaration( + dataType: 'Uint8List', + isNullable: true, + typeArguments: null, + )), Field( - name: 'aInt32List', - dataType: 'Int32List', - isNullable: true, - ), + name: 'aInt32List', + offset: null, + type: TypeDeclaration( + dataType: 'Int32List', + isNullable: true, + typeArguments: null, + )), Field( - name: 'aInt64List', - dataType: 'Int64List', - isNullable: true, - ), + name: 'aInt64List', + offset: null, + type: TypeDeclaration( + dataType: 'Int64List', + isNullable: true, + typeArguments: null, + )), Field( - name: 'aFloat64List', - dataType: 'Float64List', - isNullable: true, - ), + name: 'aFloat64List', + offset: null, + type: TypeDeclaration( + dataType: 'Float64List', + isNullable: true, + typeArguments: null, + )), ]), ], enums: []); @@ -251,10 +327,13 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'aBool', - dataType: 'bool', - isNullable: true, - ), + name: 'aBool', + offset: null, + type: TypeDeclaration( + dataType: 'bool', + isNullable: true, + typeArguments: null, + )), ]), ], enums: []); @@ -269,17 +348,23 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Nested', fields: [ Field( - name: 'nested', - dataType: 'Input', - isNullable: true, - ) + name: 'nested', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -293,17 +378,23 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Nested', fields: [ Field( - name: 'nested', - dataType: 'Input', - isNullable: true, - ) + name: 'nested', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -317,10 +408,13 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'String', - isNullable: true, - ) + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -333,10 +427,13 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'String', - isNullable: true, - ) + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -350,23 +447,43 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Nested', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Nested', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Nested', fields: [ Field( - name: 'nested', - dataType: 'Input', - isNullable: true, - ) + name: 'nested', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -382,23 +499,43 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Nested', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Nested', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Nested', fields: [ Field( - name: 'nested', - dataType: 'Input', - isNullable: true, - ) + name: 'nested', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -414,23 +551,43 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -449,23 +606,43 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -480,16 +657,33 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -504,16 +698,33 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -530,16 +741,33 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -554,16 +782,33 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -579,16 +824,33 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -603,16 +865,33 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -627,16 +906,33 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -654,16 +950,33 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false)) + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + ))) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -681,10 +994,13 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'List', - isNullable: true, - ) + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'List', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -698,10 +1014,13 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'Map', - isNullable: true, - ) + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'Map', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -716,24 +1035,44 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -751,24 +1090,44 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -786,17 +1145,34 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -814,8 +1190,22 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true) ]) ], classes: [], enums: []); @@ -834,24 +1224,44 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -869,24 +1279,44 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Input', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - dataType: 'String', - isNullable: true, - ) + name: 'input', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -904,8 +1334,22 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'void', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true) ]) ], classes: [], enums: []); @@ -922,17 +1366,34 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), - returnType: Field(name: '', dataType: 'Output', isNullable: false), + argType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'void', + isNullable: false, + typeArguments: null, + )), + returnType: Field( + name: '', + offset: null, + type: TypeDeclaration( + dataType: 'Output', + isNullable: false, + typeArguments: null, + )), isAsynchronous: true) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - dataType: 'String', - isNullable: true, - ) + name: 'output', + offset: null, + type: TypeDeclaration( + dataType: 'String', + isNullable: true, + typeArguments: null, + )) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -984,13 +1445,15 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - dataType: 'List', - isNullable: true, - typeArguments: [ - TypeArgument(dataType: 'int', isNullable: true) - ], - ), + name: 'field1', + offset: null, + type: TypeDeclaration( + dataType: 'List', + isNullable: true, + typeArguments: [ + TypeDeclaration(dataType: 'int', isNullable: true) + ], + )), ], ); final Root root = Root( diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 371bbc671e20..7e4d1ad109a0 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -93,8 +93,8 @@ abstract class Api1 { expect(root.apis[0].name, equals('Api1')); expect(root.apis[0].methods.length, equals(1)); expect(root.apis[0].methods[0].name, equals('doit')); - expect(root.apis[0].methods[0].argType.dataType, equals('Input1')); - expect(root.apis[0].methods[0].returnType.dataType, equals('Output1')); + expect(root.apis[0].methods[0].argType.type.dataType, equals('Input1')); + expect(root.apis[0].methods[0].returnType.type.dataType, equals('Output1')); Class? input; Class? output; @@ -110,13 +110,13 @@ abstract class Api1 { expect(input?.fields.length, equals(1)); expect(input?.fields[0].name, equals('input')); - expect(input?.fields[0].dataType, equals('String')); - expect(input?.fields[0].isNullable, isTrue); + expect(input?.fields[0].type.dataType, equals('String')); + expect(input?.fields[0].type.isNullable, isTrue); expect(output?.fields.length, equals(1)); expect(output?.fields[0].name, equals('output')); - expect(output?.fields[0].dataType, equals('String')); - expect(output?.fields[0].isNullable, isTrue); + expect(output?.fields[0].type.dataType, equals('String')); + expect(output?.fields[0].type.isNullable, isTrue); }); test('invalid datatype', () { @@ -157,8 +157,8 @@ abstract class Api { expect(results.root.classes.length, equals(1)); expect(results.root.classes[0].name, equals('ClassWithEnum')); expect(results.root.classes[0].fields.length, equals(1)); - expect(results.root.classes[0].fields[0].dataType, equals('Enum1')); - expect(results.root.classes[0].fields[0].isNullable, isTrue); + expect(results.root.classes[0].fields[0].type.dataType, equals('Enum1')); + expect(results.root.classes[0].fields[0].type.isNullable, isTrue); expect(results.root.classes[0].fields[0].name, equals('enum1')); }); @@ -203,8 +203,8 @@ abstract class Api { final Class nested = results.root.classes.firstWhere((Class x) => x.name == 'Nested'); expect(nested.fields.length, equals(1)); - expect(nested.fields[0].dataType, equals('Input1')); - expect(nested.fields[0].isNullable, isTrue); + expect(nested.fields[0].type.dataType, equals('Input1')); + expect(nested.fields[0].type.isNullable, isTrue); }); test('flutter api', () { @@ -241,7 +241,8 @@ abstract class VoidApi { expect(results.root.apis.length, equals(1)); expect(results.root.apis[0].methods.length, equals(1)); expect(results.root.apis[0].name, equals('VoidApi')); - expect(results.root.apis[0].methods[0].returnType.dataType, equals('void')); + expect(results.root.apis[0].methods[0].returnType.type.dataType, + equals('void')); }); test('void arg host api', () { @@ -260,9 +261,10 @@ abstract class VoidArgApi { expect(results.root.apis.length, equals(1)); expect(results.root.apis[0].methods.length, equals(1)); expect(results.root.apis[0].name, equals('VoidArgApi')); + expect(results.root.apis[0].methods[0].returnType.type.dataType, + equals('Output1')); expect( - results.root.apis[0].methods[0].returnType.dataType, equals('Output1')); - expect(results.root.apis[0].methods[0].argType.dataType, equals('void')); + results.root.apis[0].methods[0].argType.type.dataType, equals('void')); }); test('mockDartClass', () { @@ -410,7 +412,7 @@ abstract class NotificationsHostApi { final Class foo = results.root.classes.firstWhere((Class aClass) => aClass.name == 'Foo'); expect(foo.fields.length, 1); - expect(foo.fields[0].dataType, 'Bar'); + expect(foo.fields[0].type.dataType, 'Bar'); }); test('test compilation error', () { @@ -570,8 +572,8 @@ abstract class Api { final ParseResults parseResult = _parseSource(code); expect(parseResult.errors.length, equals(0)); final Field field = parseResult.root.classes[0].fields[0]; - expect(field.typeArguments!.length, 1); - expect(field.typeArguments![0].dataType, 'int'); + expect(field.type.typeArguments!.length, 1); + expect(field.type.typeArguments![0].dataType, 'int'); }); test('parse recursive generics', () { @@ -588,9 +590,9 @@ abstract class Api { final ParseResults parseResult = _parseSource(code); expect(parseResult.errors.length, equals(0)); final Field field = parseResult.root.classes[0].fields[0]; - expect(field.typeArguments!.length, 1); - expect(field.typeArguments![0].dataType, 'List'); - expect(field.typeArguments![0].typeArguments![0].dataType, 'int'); + expect(field.type.typeArguments!.length, 1); + expect(field.type.typeArguments![0].dataType, 'List'); + expect(field.type.typeArguments![0].typeArguments![0].dataType, 'int'); }); test('error nonnull type argument', () { @@ -664,8 +666,8 @@ abstract class Api { '''; final ParseResults parseResult = _parseSource(code); final Field field = parseResult.root.classes[0].fields[0]; - expect(field.typeArguments!.length, 2); - expect(field.typeArguments![0].dataType, 'String'); - expect(field.typeArguments![1].dataType, 'int'); + expect(field.type.typeArguments!.length, 2); + expect(field.type.typeArguments![0].dataType, 'String'); + expect(field.type.typeArguments![1].dataType, 'int'); }); } From 69744ac7f430f15e8ec036a991f31d2236c484fc Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Aug 2021 09:59:11 -0700 Subject: [PATCH 12/30] Revert "stuarts feedback for typedeclaration" This reverts commit 6ea9b5b48de8a2507674a202c0d3169fc39fe276. --- packages/pigeon/lib/ast.dart | 34 +- packages/pigeon/lib/dart_generator.dart | 62 +- packages/pigeon/lib/generator_tools.dart | 18 +- packages/pigeon/lib/java_generator.dart | 60 +- packages/pigeon/lib/objc_generator.dart | 84 +- packages/pigeon/lib/pigeon_lib.dart | 83 +- packages/pigeon/test/dart_generator_test.dart | 540 +++------- packages/pigeon/test/java_generator_test.dart | 413 ++------ packages/pigeon/test/objc_generator_test.dart | 973 +++++------------- packages/pigeon/test/pigeon_lib_test.dart | 46 +- 10 files changed, 649 insertions(+), 1664 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index 5971ce3cea04..2ef8a94f5f51 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -74,10 +74,10 @@ class Api extends Node { } } -/// Represents a type declaration. -class TypeDeclaration { - /// Constructor for [TypeDeclaration]. - TypeDeclaration({ +/// A parameter to a generic entity. For example, "String" to "List". +class TypeArgument { + /// Constructor for [TypeArgument]. + TypeArgument({ required this.dataType, required this.isNullable, this.typeArguments, @@ -86,35 +86,47 @@ class TypeDeclaration { /// A string representation of the base datatype. final String dataType; - /// The type arguments to this [TypeDeclaration]. - final List? typeArguments; + /// The type arguments to this [TypeArgument]. + final List? typeArguments; /// True if the type is nullable. final bool isNullable; @override String toString() { - return '(TypeDeclaration dataType:$dataType isNullable:$isNullable typeArguments:$typeArguments)'; + return '(TypeArgument dataType:$dataType isNullable:$isNullable typeArguments:$typeArguments)'; } } /// Represents a field on a [Class]. class Field extends Node { /// Parametric constructor for [Field]. - Field({required this.name, required this.type, this.offset}); + Field({ + required this.name, + required this.dataType, + required this.isNullable, + this.typeArguments, + this.offset, + }); /// The name of the field. String name; + /// The data-type of the field (ex 'String' or 'int'). + String dataType; + /// The offset in the source file where the field appears. int? offset; - /// The type of the [Field]. - TypeDeclaration type; + /// True if the datatype is nullable (ex `int?`). + bool isNullable; + + /// Type parameters used for generics. + List? typeArguments; @override String toString() { - return '(Field name:$name type:$type)'; + return '(Field name:$name dataType:$dataType typeArguments:$typeArguments)'; } } diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 976ed2bf40ee..1fb7128c7c24 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -121,12 +121,12 @@ final BinaryMessenger$nullTag _binaryMessenger; } String argSignature = ''; String sendArgument = 'null'; - if (func.argType.type.dataType != 'void') { - argSignature = '${func.argType.type.dataType} arg'; + if (func.argType.dataType != 'void') { + argSignature = '${func.argType.dataType} arg'; sendArgument = 'arg'; } indent.write( - 'Future<${func.returnType.type.dataType}> ${func.name}($argSignature) async ', + 'Future<${func.returnType.dataType}> ${func.name}($argSignature) async ', ); indent.scoped('{', '}', () { final String channelName = makeChannelName(api, func); @@ -137,9 +137,9 @@ final BinaryMessenger$nullTag _binaryMessenger; '\'$channelName\', codec, binaryMessenger: _binaryMessenger);', ); }); - final String returnStatement = func.returnType.type.dataType == 'void' + final String returnStatement = func.returnType.dataType == 'void' ? '// noop' - : 'return (replyMap[\'${Keys.result}\'] as ${func.returnType.type.dataType}$nullTag)$unwrapOperator;'; + : 'return (replyMap[\'${Keys.result}\'] as ${func.returnType.dataType}$nullTag)$unwrapOperator;'; indent.format(''' final Map$nullTag replyMap =\n\t\tawait channel.send($sendArgument) as Map$nullTag; if (replyMap == null) { @@ -182,11 +182,10 @@ void _writeFlutterApi( for (final Method func in api.methods) { final bool isAsync = func.isAsynchronous; final String returnType = isAsync - ? 'Future<${func.returnType.type.dataType}>' - : func.returnType.type.dataType; - final String argSignature = func.argType.type.dataType == 'void' - ? '' - : '${func.argType.type.dataType} arg'; + ? 'Future<${func.returnType.dataType}>' + : func.returnType.dataType; + final String argSignature = + func.argType.dataType == 'void' ? '' : '${func.argType.dataType} arg'; indent.writeln('$returnType ${func.name}($argSignature);'); } indent.write('static void setup(${api.name}$nullTag api) '); @@ -217,12 +216,12 @@ void _writeFlutterApi( 'channel.$messageHandlerSetter((Object$nullTag message) async ', ); indent.scoped('{', '});', () { - final String argType = func.argType.type.dataType; - final String returnType = func.returnType.type.dataType; + final String argType = func.argType.dataType; + final String returnType = func.returnType.dataType; final bool isAsync = func.isAsynchronous; final String emptyReturnStatement = isMockHandler ? 'return {};' - : func.returnType.type.dataType == 'void' + : func.returnType.dataType == 'void' ? 'return;' : 'return null;'; String call; @@ -265,30 +264,30 @@ void _writeFlutterApi( }); } -/// Converts a [List] of [TypeDeclaration]s to a comma separated [String] to be +/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in Dart code. -String _flattenTypeDeclarations(List args, String nullTag) { +String _flattenTypeArguments(List args, String nullTag) { return args - .map((TypeDeclaration arg) => arg.typeArguments == null + .map((TypeArgument arg) => arg.typeArguments == null ? '${arg.dataType}$nullTag' - : '${arg.dataType}<${_flattenTypeDeclarations(arg.typeArguments!, nullTag)}>$nullTag') + : '${arg.dataType}<${_flattenTypeArguments(arg.typeArguments!, nullTag)}>$nullTag') .reduce((String value, String element) => '$value, $element'); } /// Creates the type declaration for use in Dart code from a [Field] making sure /// that type arguments are used for primitive generic types. String _addGenericTypes(Field field, String nullTag) { - switch (field.type.dataType) { + switch (field.dataType) { case 'List': - return (field.type.typeArguments == null) + return (field.typeArguments == null) ? 'List$nullTag' - : 'List<${_flattenTypeDeclarations(field.type.typeArguments!, nullTag)}>$nullTag'; + : 'List<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; case 'Map': - return (field.type.typeArguments == null) + return (field.typeArguments == null) ? 'Map$nullTag' - : 'Map<${_flattenTypeDeclarations(field.type.typeArguments!, nullTag)}>$nullTag'; + : 'Map<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; default: - return '${field.type.dataType}$nullTag'; + return '${field.dataType}$nullTag'; } } @@ -346,11 +345,11 @@ void generateDart(DartOptions opt, Root root, StringSink sink) { ); for (final Field field in klass.fields) { indent.write('pigeonMap[\'${field.name}\'] = '); - if (customClassNames.contains(field.type.dataType)) { + if (customClassNames.contains(field.dataType)) { indent.addln( '${field.name} == null ? null : ${field.name}$unwrapOperator.encode();', ); - } else if (customEnumNames.contains(field.type.dataType)) { + } else if (customEnumNames.contains(field.dataType)) { indent.addln( '${field.name} == null ? null : ${field.name}$unwrapOperator.index;', ); @@ -373,20 +372,19 @@ void generateDart(DartOptions opt, Root root, StringSink sink) { for (int index = 0; index < klass.fields.length; index += 1) { final Field field = klass.fields[index]; indent.write('..${field.name} = '); - if (customClassNames.contains(field.type.dataType)) { + if (customClassNames.contains(field.dataType)) { indent.format(''' pigeonMap['${field.name}'] != null -\t\t? ${field.type.dataType}.decode(pigeonMap['${field.name}']$unwrapOperator) +\t\t? ${field.dataType}.decode(pigeonMap['${field.name}']$unwrapOperator) \t\t: null''', leadingSpace: false, trailingNewline: false); - } else if (customEnumNames.contains(field.type.dataType)) { + } else if (customEnumNames.contains(field.dataType)) { indent.format(''' pigeonMap['${field.name}'] != null -\t\t? ${field.type.dataType}.values[pigeonMap['${field.name}']$unwrapOperator as int] +\t\t? ${field.dataType}.values[pigeonMap['${field.name}']$unwrapOperator as int] \t\t: null''', leadingSpace: false, trailingNewline: false); - } else if (field.type.dataType == 'Map' && - field.type.typeArguments != null) { + } else if (field.dataType == 'Map' && field.typeArguments != null) { indent.add( - '(pigeonMap[\'${field.name}\'] as Map$nullTag)$nullTag.cast<${_flattenTypeDeclarations(field.type.typeArguments!, nullTag)}>()', + '(pigeonMap[\'${field.name}\'] as Map$nullTag)$nullTag.cast<${_flattenTypeArguments(field.typeArguments!, nullTag)}>()', ); } else { indent.add( diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index e1a25463420f..a41a75800674 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -163,19 +163,19 @@ HostDatatype getHostDatatype(Field field, List classes, List enums, {String Function(String)? customResolver}) { final String? datatype = builtinResolver(field); if (datatype == null) { - if (classes.map((Class x) => x.name).contains(field.type.dataType)) { + if (classes.map((Class x) => x.name).contains(field.dataType)) { final String customName = customResolver != null - ? customResolver(field.type.dataType) - : field.type.dataType; + ? customResolver(field.dataType) + : field.dataType; return HostDatatype(datatype: customName, isBuiltin: false); - } else if (enums.map((Enum x) => x.name).contains(field.type.dataType)) { + } else if (enums.map((Enum x) => x.name).contains(field.dataType)) { final String customName = customResolver != null - ? customResolver(field.type.dataType) - : field.type.dataType; + ? customResolver(field.dataType) + : field.dataType; return HostDatatype(datatype: customName, isBuiltin: false); } else { throw Exception( - 'unrecognized datatype for field:"${field.name}" of type:"${field.type.dataType}"'); + 'unrecognized datatype for field:"${field.name}" of type:"${field.dataType}"'); } } else { return HostDatatype(datatype: datatype, isBuiltin: true); @@ -285,8 +285,8 @@ const int _minimumCodecFieldKey = 128; Iterable getCodecClasses(Api api) sync* { final Set names = {}; for (final Method method in api.methods) { - names.add(method.returnType.type.dataType); - names.add(method.argType.type.dataType); + names.add(method.returnType.dataType); + names.add(method.argType.dataType); } final List sortedNames = names .where((String element) => diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 83e616182a4f..175e3722c67a 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -125,18 +125,18 @@ void _writeHostApi(Indent indent, Api api) { indent.scoped('{', '}', () { for (final Method method in api.methods) { final String argType = - _javaTypeForDartTypePassthrough(method.argType.type.dataType); + _javaTypeForDartTypePassthrough(method.argType.dataType); final String returnType = method.isAsynchronous ? 'void' - : _javaTypeForDartTypePassthrough(method.returnType.type.dataType); + : _javaTypeForDartTypePassthrough(method.returnType.dataType); final List argSignature = []; - if (method.argType.type.dataType != 'void') { + if (method.argType.dataType != 'void') { argSignature.add('$argType arg'); } if (method.isAsynchronous) { - final String returnType = method.returnType.type.dataType == 'void' + final String returnType = method.returnType.dataType == 'void' ? 'Void' - : method.returnType.type.dataType; + : method.returnType.dataType; argSignature.add('Result<$returnType> result'); } indent.writeln('$returnType ${method.name}(${argSignature.join(', ')});'); @@ -170,9 +170,9 @@ static MessageCodec getCodec() { indent.write('channel.setMessageHandler((message, reply) -> '); indent.scoped('{', '});', () { final String argType = - _javaTypeForDartTypePassthrough(method.argType.type.dataType); - final String returnType = _javaTypeForDartTypePassthrough( - method.returnType.type.dataType); + _javaTypeForDartTypePassthrough(method.argType.dataType); + final String returnType = + _javaTypeForDartTypePassthrough(method.returnType.dataType); indent.writeln('Map wrapped = new HashMap<>();'); indent.write('try '); indent.scoped('{', '}', () { @@ -189,9 +189,7 @@ static MessageCodec getCodec() { } if (method.isAsynchronous) { final String resultValue = - method.returnType.type.dataType == 'void' - ? 'null' - : 'result'; + method.returnType.dataType == 'void' ? 'null' : 'result'; methodArgument.add( 'result -> { ' 'wrapped.put("${Keys.result}", $resultValue); ' @@ -203,7 +201,7 @@ static MessageCodec getCodec() { 'api.${method.name}(${methodArgument.join(', ')})'; if (method.isAsynchronous) { indent.writeln('$call;'); - } else if (method.returnType.type.dataType == 'void') { + } else if (method.returnType.dataType == 'void') { indent.writeln('$call;'); indent.writeln('wrapped.put("${Keys.result}", null);'); } else { @@ -256,13 +254,13 @@ static MessageCodec getCodec() { '''); for (final Method func in api.methods) { final String channelName = makeChannelName(api, func); - final String returnType = func.returnType.type.dataType == 'void' + final String returnType = func.returnType.dataType == 'void' ? 'Void' - : _javaTypeForDartTypePassthrough(func.returnType.type.dataType); + : _javaTypeForDartTypePassthrough(func.returnType.dataType); final String argType = - _javaTypeForDartTypePassthrough(func.argType.type.dataType); + _javaTypeForDartTypePassthrough(func.argType.dataType); String sendArgument; - if (func.argType.type.dataType == 'void') { + if (func.argType.dataType == 'void') { indent.write('public void ${func.name}(Reply<$returnType> callback) '); sendArgument = 'null'; } else { @@ -280,7 +278,7 @@ static MessageCodec getCodec() { indent.dec(); indent.write('channel.send($sendArgument, channelReply -> '); indent.scoped('{', '});', () { - if (func.returnType.type.dataType == 'void') { + if (func.returnType.dataType == 'void') { indent.writeln('callback.reply(null);'); } else { indent.writeln('@SuppressWarnings("ConstantConditions")'); @@ -305,11 +303,11 @@ String _makeSetter(Field field) { return 'set$uppercased'; } -/// Converts a [List] of [TypeDeclaration]s to a comma separated [String] to be +/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in Java code. -String _flattenTypeArguments(List args) { +String _flattenTypeArguments(List args) { return args - .map((TypeDeclaration e) => e.typeArguments == null + .map((TypeArgument e) => e.typeArguments == null ? _javaTypeForDartTypePassthrough(e.dataType) : '${_javaTypeForDartTypePassthrough(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') .reduce((String value, String element) => '$value, $element'); @@ -327,13 +325,13 @@ String? _javaTypeForDartType(Field field) { 'Float64List': 'double[]', 'Map': 'Map', }; - if (javaTypeForDartTypeMap.containsKey(field.type.dataType)) { - return javaTypeForDartTypeMap[field.type.dataType]; - } else if (field.type.dataType == 'List') { - if (field.type.typeArguments == null) { + if (javaTypeForDartTypeMap.containsKey(field.dataType)) { + return javaTypeForDartTypeMap[field.dataType]; + } else if (field.dataType == 'List') { + if (field.typeArguments == null) { return 'List'; } else { - return 'List<${_flattenTypeArguments(field.type.typeArguments!)}>'; + return 'List<${_flattenTypeArguments(field.typeArguments!)}>'; } } else { return null; @@ -344,10 +342,10 @@ String _castObject( Field field, List classes, List enums, String varName) { final HostDatatype hostDatatype = getHostDatatype(field, classes, enums, _javaTypeForDartType); - if (field.type.dataType == 'int') { + if (field.dataType == 'int') { return '($varName == null) ? null : (($varName instanceof Integer) ? (Integer)$varName : (${hostDatatype.datatype})$varName)'; } else if (!hostDatatype.isBuiltin && - classes.map((Class x) => x.name).contains(field.type.dataType)) { + classes.map((Class x) => x.name).contains(field.dataType)) { return '${hostDatatype.datatype}.fromMap((Map)$varName)'; } else { return '(${hostDatatype.datatype})$varName'; @@ -435,10 +433,10 @@ void generateJava(JavaOptions options, Root root, StringSink sink) { field, root.classes, root.enums, _javaTypeForDartType); String toWriteValue = ''; if (!hostDatatype.isBuiltin && - rootClassNameSet.contains(field.type.dataType)) { + rootClassNameSet.contains(field.dataType)) { toWriteValue = '${field.name}.toMap()'; } else if (!hostDatatype.isBuiltin && - rootEnumNameSet.contains(field.type.dataType)) { + rootEnumNameSet.contains(field.dataType)) { toWriteValue = '${field.name}.index'; } else { toWriteValue = field.name; @@ -452,9 +450,9 @@ void generateJava(JavaOptions options, Root root, StringSink sink) { indent.writeln('${klass.name} fromMapResult = new ${klass.name}();'); for (final Field field in klass.fields) { indent.writeln('Object ${field.name} = map.get("${field.name}");'); - if (rootEnumNameSet.contains(field.type.dataType)) { + if (rootEnumNameSet.contains(field.dataType)) { indent.writeln( - 'fromMapResult.${field.name} = ${field.type.dataType}.values()[(int)${field.name}];'); + 'fromMapResult.${field.name} = ${field.dataType}.values()[(int)${field.name}];'); } else { indent.writeln( 'fromMapResult.${field.name} = ${_castObject(field, root.classes, root.enums, field.name)};'); diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index f038d0d82fe6..9f71f8d88cec 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -92,21 +92,21 @@ const Map _propertyTypeForDartTypeMap = { 'Map': 'strong', }; -/// Converts a [List] of [TypeDeclaration]s to a comma separated [String] to be +/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in objc code. -String _flattenTypeArguments(String? classPrefix, List args) { +String _flattenTypeArguments(String? classPrefix, List args) { return args - .map((TypeDeclaration e) => e.typeArguments == null + .map((TypeArgument e) => e.typeArguments == null ? '${_objcTypeForDartType(classPrefix, e.dataType)} *' : '${_objcTypeForDartType(classPrefix, e.dataType)}<${_flattenTypeArguments(classPrefix, e.typeArguments!)}> *') .reduce((String value, String element) => '$value, $element'); } String? _objcTypePtrForPrimitiveDartType(String? classPrefix, Field field) { - return _objcTypeForDartTypeMap.containsKey(field.type.dataType) - ? field.type.typeArguments == null - ? '${_objcTypeForDartTypeMap[field.type.dataType]} *' - : '${_objcTypeForDartTypeMap[field.type.dataType]}<${_flattenTypeArguments(classPrefix, field.type.typeArguments!)}> *' + return _objcTypeForDartTypeMap.containsKey(field.dataType) + ? field.typeArguments == null + ? '${_objcTypeForDartTypeMap[field.dataType]} *' + : '${_objcTypeForDartTypeMap[field.dataType]}<${_flattenTypeArguments(classPrefix, field.typeArguments!)}> *' : null; } @@ -135,13 +135,13 @@ void _writeClassDeclarations( for (final Field field in klass.fields) { final HostDatatype hostDatatype = getHostDatatype(field, classes, enums, (Field x) => _objcTypePtrForPrimitiveDartType(prefix, x), - customResolver: enumNames.contains(field.type.dataType) + customResolver: enumNames.contains(field.dataType) ? (String x) => _className(prefix, x) : (String x) => '${_className(prefix, x)} *'); late final String propertyType; if (hostDatatype.isBuiltin) { - propertyType = _propertyTypeForDartType(field.type.dataType); - } else if (enumNames.contains(field.type.dataType)) { + propertyType = _propertyTypeForDartType(field.dataType); + } else if (enumNames.contains(field.dataType)) { propertyType = 'assign'; } else { propertyType = 'strong'; @@ -240,39 +240,39 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { indent.writeln('@protocol $apiName'); for (final Method func in api.methods) { final String returnTypeName = - _objcTypeForDartType(options.prefix, func.returnType.type.dataType); + _objcTypeForDartType(options.prefix, func.returnType.dataType); if (func.isAsynchronous) { - if (func.returnType.type.dataType == 'void') { - if (func.argType.type.dataType == 'void') { + if (func.returnType.dataType == 'void') { + if (func.argType.dataType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)(FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.type.dataType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)(FlutterError *_Nullable))completion;'); } } else { - if (func.argType.type.dataType == 'void') { + if (func.argType.dataType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.type.dataType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } } } else { - final String returnType = func.returnType.type.dataType == 'void' + final String returnType = func.returnType.dataType == 'void' ? 'void' : 'nullable $returnTypeName *'; - if (func.argType.type.dataType == 'void') { + if (func.argType.dataType == 'void') { indent.writeln( '-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.type.dataType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '-($returnType)${func.name}:($argType*)input error:(FlutterError *_Nullable *_Nonnull)error;'); } @@ -292,14 +292,14 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) { '- (instancetype)initWithBinaryMessenger:(id)binaryMessenger;'); for (final Method func in api.methods) { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType.type.dataType); + _objcTypeForDartType(options.prefix, func.returnType.dataType); final String callbackType = - _callbackForType(func.returnType.type.dataType, returnType); - if (func.argType.type.dataType == 'void') { + _callbackForType(func.returnType.dataType, returnType); + if (func.argType.dataType == 'void') { indent.writeln('- (void)${func.name}:($callbackType)completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.type.dataType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln( '- (void)${func.name}:($argType*)input completion:($callbackType)completion;'); } @@ -367,8 +367,8 @@ void generateObjcHeader(ObjcOptions options, Root root, StringSink sink) { String _dictGetter( List classNames, String dict, Field field, String? prefix) { - if (classNames.contains(field.type.dataType)) { - String className = field.type.dataType; + if (classNames.contains(field.dataType)) { + String className = field.dataType; if (prefix != null) { className = '$prefix$className'; } @@ -380,9 +380,9 @@ String _dictGetter( String _dictValue( List classNames, List enumNames, Field field) { - if (classNames.contains(field.type.dataType)) { + if (classNames.contains(field.dataType)) { return '(self.${field.name} ? [self.${field.name} toMap] : [NSNull null])'; - } else if (enumNames.contains(field.type.dataType)) { + } else if (enumNames.contains(field.dataType)) { return '@(self.${field.name})'; } else { return '(self.${field.name} ? self.${field.name} : [NSNull null])'; @@ -415,21 +415,21 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { indent.write( '[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) '); indent.scoped('{', '}];', () { - final String returnType = _objcTypeForDartType( - options.prefix, func.returnType.type.dataType); + final String returnType = + _objcTypeForDartType(options.prefix, func.returnType.dataType); String syncCall; - if (func.argType.type.dataType == 'void') { + if (func.argType.dataType == 'void') { syncCall = '[api ${func.name}:&error]'; } else { - final String argType = _objcTypeForDartType( - options.prefix, func.argType.type.dataType); + final String argType = + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.writeln('$argType *input = message;'); syncCall = '[api ${func.name}:input error:&error]'; } if (func.isAsynchronous) { - if (func.returnType.type.dataType == 'void') { + if (func.returnType.dataType == 'void') { const String callback = 'callback(wrapResult(nil, error));'; - if (func.argType.type.dataType == 'void') { + if (func.argType.dataType == 'void') { indent.writeScoped( '[api ${func.name}:^(FlutterError *_Nullable error) {', '}];', () { @@ -444,7 +444,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { } } else { const String callback = 'callback(wrapResult(output, error));'; - if (func.argType.type.dataType == 'void') { + if (func.argType.dataType == 'void') { indent.writeScoped( '[api ${func.name}:^($returnType *_Nullable output, FlutterError *_Nullable error) {', '}];', () { @@ -460,7 +460,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { } } else { indent.writeln('FlutterError *error;'); - if (func.returnType.type.dataType == 'void') { + if (func.returnType.dataType == 'void') { indent.writeln('$syncCall;'); indent.writeln('callback(wrapResult(nil, error));'); } else { @@ -501,17 +501,17 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { indent.addln(''); for (final Method func in api.methods) { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType.type.dataType); + _objcTypeForDartType(options.prefix, func.returnType.dataType); final String callbackType = - _callbackForType(func.returnType.type.dataType, returnType); + _callbackForType(func.returnType.dataType, returnType); String sendArgument; - if (func.argType.type.dataType == 'void') { + if (func.argType.dataType == 'void') { indent.write('- (void)${func.name}:($callbackType)completion '); sendArgument = 'nil'; } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.type.dataType); + _objcTypeForDartType(options.prefix, func.argType.dataType); indent.write( '- (void)${func.name}:($argType*)input completion:($callbackType)completion '); sendArgument = 'input'; @@ -529,7 +529,7 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { indent.dec(); indent.write('[channel sendMessage:$sendArgument reply:^(id reply) '); indent.scoped('{', '}];', () { - if (func.returnType.type.dataType == 'void') { + if (func.returnType.dataType == 'void') { indent.writeln('completion(nil);'); } else { indent.writeln('$returnType * output = reply;'); @@ -598,7 +598,7 @@ static NSDictionary* wrapResult(id result, FlutterError *error) { const String resultName = 'result'; indent.writeln('$className* $resultName = [[$className alloc] init];'); for (final Field field in klass.fields) { - if (enumNames.contains(field.type.dataType)) { + if (enumNames.contains(field.dataType)) { indent.writeln( '$resultName.${field.name} = [${_dictGetter(classNames, 'dict', field, options.prefix)} integerValue];'); } else { diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 7ff54b2d20c2..5cb83cdd0b80 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -378,8 +378,8 @@ List _validateAst(Root root, String source) { final List customEnums = root.enums.map((Enum x) => x.name).toList(); for (final Class klass in root.classes) { for (final Field field in klass.fields) { - if (field.type.typeArguments != null) { - for (final TypeDeclaration typeArgument in field.type.typeArguments!) { + if (field.typeArguments != null) { + for (final TypeArgument typeArgument in field.typeArguments!) { if (!typeArgument.isNullable) { result.add(Error( message: @@ -389,12 +389,12 @@ List _validateAst(Root root, String source) { } } } - if (!(validTypes.contains(field.type.dataType) || - customClasses.contains(field.type.dataType) || - customEnums.contains(field.type.dataType))) { + if (!(validTypes.contains(field.dataType) || + customClasses.contains(field.dataType) || + customEnums.contains(field.dataType))) { result.add(Error( message: - 'Unsupported datatype:"${field.type.dataType}" in class "${klass.name}".', + 'Unsupported datatype:"${field.dataType}" in class "${klass.name}".', lineNumber: _calculateLineNumberNullable(source, field.offset), )); } @@ -402,31 +402,31 @@ List _validateAst(Root root, String source) { } for (final Api api in root.apis) { for (final Method method in api.methods) { - if (method.returnType.type.isNullable) { + if (method.returnType.isNullable) { result.add(Error( message: - 'Nullable return types types aren\'t supported for Pigeon methods: "${method.argType.type.dataType}" in API: "${api.name}" method: "${method.name}"', + 'Nullable return types types aren\'t supported for Pigeon methods: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name}"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.returnType.type.typeArguments != null) { + if (method.returnType.typeArguments != null) { result.add(Error( message: - 'Generic type arguments for primitive return values aren\'t yet supported: "${method.argType.type.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + 'Generic type arguments for primitive return values aren\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.argType.type.isNullable) { + if (method.argType.isNullable) { result.add(Error( message: - 'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType.type.dataType}" in API: "${api.name}" method: "${method.name}"', + 'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name}"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.argType.type.typeArguments != null) { + if (method.argType.typeArguments != null) { result.add(Error( message: - 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.argType.type.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } @@ -481,8 +481,8 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final Set referencedTypes = {}; for (final Api api in _apis) { for (final Method method in api.methods) { - referencedTypes.add(method.argType.type.dataType); - referencedTypes.add(method.returnType.type.dataType); + referencedTypes.add(method.argType.dataType); + referencedTypes.add(method.returnType.dataType); } } @@ -493,10 +493,10 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final Class aClass = _classes.firstWhere((Class x) => x.name == next, orElse: () => Class(name: '', fields: [])); for (final Field field in aClass.fields) { - if (!referencedTypes.contains(field.type.dataType) && - !validTypes.contains(field.type.dataType)) { - referencedTypes.add(field.type.dataType); - classesToCheck.add(field.type.dataType); + if (!referencedTypes.contains(field.dataType) && + !validTypes.contains(field.dataType)) { + referencedTypes.add(field.dataType); + classesToCheck.add(field.dataType); } } } @@ -637,7 +637,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final dart_ast.FormalParameterList parameters = node.parameters!; late String argType; bool isNullable = false; - List? argTypeArguments; + List? argTypeArguments; if (parameters.parameters.isEmpty) { argType = 'void'; } else { @@ -656,21 +656,15 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { name: node.name.name, returnType: Field( name: '', - offset: null, - type: TypeDeclaration( - dataType: node.returnType.toString(), - isNullable: node.returnType!.question != null, - typeArguments: typeAnnotationsToTypeArguments( - (node.returnType as dart_ast.NamedType?)!.typeArguments), - )), + dataType: node.returnType.toString(), + typeArguments: typeAnnotationsToTypeArguments( + (node.returnType as dart_ast.NamedType?)!.typeArguments), + isNullable: node.returnType!.question != null), argType: Field( + dataType: argType, + isNullable: isNullable, name: '', - offset: null, - type: TypeDeclaration( - dataType: argType, - isNullable: isNullable, - typeArguments: argTypeArguments, - )), + typeArguments: argTypeArguments), isAsynchronous: isAsynchronous, offset: node.offset)); } else if (_currentClass != null) { @@ -694,14 +688,14 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { return null; } - List? typeAnnotationsToTypeArguments( + List? typeAnnotationsToTypeArguments( dart_ast.TypeArgumentList? typeArguments) { - List? result; + List? result; if (typeArguments != null) { for (final Object x in typeArguments.childEntities) { if (x is dart_ast.TypeName) { - result ??= []; - result.add(TypeDeclaration( + result ??= []; + result.add(TypeArgument( dataType: x.name.name, isNullable: x.question != null, typeArguments: typeAnnotationsToTypeArguments(x.typeArguments))); @@ -731,13 +725,12 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { } else { final dart_ast.TypeArgumentList? typeArguments = type.typeArguments; _currentClass!.fields.add(Field( - name: node.fields.variables[0].name.name, - offset: node.offset, - type: TypeDeclaration( - dataType: type.name.name, - isNullable: type.question != null, - typeArguments: typeAnnotationsToTypeArguments(typeArguments), - ))); + name: node.fields.variables[0].name.name, + dataType: type.name.name, + isNullable: type.question != null, + typeArguments: typeAnnotationsToTypeArguments(typeArguments), + offset: node.offset, + )); } } else { _errors.add(Error( diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index ac1c30ffc301..f31338c0f571 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -13,13 +13,10 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'dataType1', - isNullable: true, - typeArguments: null, - )), + name: 'field1', + dataType: 'dataType1', + isNullable: true, + ), ], ); final Root root = Root( @@ -60,45 +57,25 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -114,26 +91,20 @@ void main() { name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ], ), Class( name: 'Nested', fields: [ Field( - name: 'nested', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: true, - typeArguments: null, - )) + name: 'nested', + dataType: 'Input', + isNullable: true, + ) ], ) ], enums: []); @@ -159,45 +130,25 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -212,35 +163,18 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -255,35 +189,18 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -301,35 +218,18 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'void'), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -344,35 +244,18 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'EnumClass', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'EnumClass', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'EnumClass'), + returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'EnumClass', fields: [ Field( - name: 'enum1', - offset: null, - type: TypeDeclaration( - dataType: 'Enum', - isNullable: true, - typeArguments: null, - )) + name: 'enum1', + dataType: 'Enum', + isNullable: true, + ) ]), ], enums: [ Enum( @@ -397,35 +280,18 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'EnumClass', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'EnumClass', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'EnumClass'), + returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'EnumClass', fields: [ Field( - name: 'enum1', - offset: null, - type: TypeDeclaration( - dataType: 'Enum', - isNullable: true, - typeArguments: null, - )) + name: 'enum1', + dataType: 'Enum', + isNullable: true, + ) ]), ], enums: [ Enum( @@ -452,35 +318,18 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'void'), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -498,65 +347,32 @@ void main() { methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: + Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ), Method( name: 'voidReturner', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer mainCodeSink = StringBuffer(); @@ -585,13 +401,10 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'dataType1', - isNullable: true, - typeArguments: null, - )), + name: 'field1', + dataType: 'dataType1', + isNullable: true, + ), ], ); final Root root = Root( @@ -610,45 +423,25 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -665,45 +458,25 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -719,45 +492,25 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'Input'), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -772,35 +525,18 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', isNullable: false, dataType: 'void'), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -831,15 +567,13 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'List', - isNullable: true, - typeArguments: [ - TypeDeclaration(dataType: 'int', isNullable: true) - ], - )), + name: 'field1', + dataType: 'List', + isNullable: true, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ], + ), ], ); final Root root = Root( @@ -859,16 +593,14 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'Map', - isNullable: true, - typeArguments: [ - TypeDeclaration(dataType: 'String', isNullable: true), - TypeDeclaration(dataType: 'int', isNullable: true), - ], - )), + name: 'field1', + dataType: 'Map', + isNullable: true, + typeArguments: [ + TypeArgument(dataType: 'String', isNullable: true), + TypeArgument(dataType: 'int', isNullable: true), + ], + ), ], ); final Root root = Root( diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 1e69951b194f..510d6d922260 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -12,13 +12,10 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'int', - isNullable: true, - typeArguments: null, - )), + name: 'field1', + dataType: 'int', + isNullable: true, + ), ], ); final Root root = Root( @@ -65,13 +62,10 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'int', - isNullable: true, - typeArguments: null, - )) + name: 'field1', + dataType: 'int', + isNullable: true, + ) ], ); final Root root = Root( @@ -93,45 +87,17 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'input', dataType: 'String', isNullable: true) ]), Class(name: 'Output', fields: [ - Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'output', dataType: 'String', isNullable: true) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -146,70 +112,14 @@ void main() { test('all the simple datatypes header', () { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ - Field( - name: 'aBool', - offset: null, - type: TypeDeclaration( - dataType: 'bool', - isNullable: true, - typeArguments: null, - )), - Field( - name: 'aInt', - offset: null, - type: TypeDeclaration( - dataType: 'int', - isNullable: true, - typeArguments: null, - )), - Field( - name: 'aDouble', - offset: null, - type: TypeDeclaration( - dataType: 'double', - isNullable: true, - typeArguments: null, - )), - Field( - name: 'aString', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )), - Field( - name: 'aUint8List', - offset: null, - type: TypeDeclaration( - dataType: 'Uint8List', - isNullable: true, - typeArguments: null, - )), - Field( - name: 'aInt32List', - offset: null, - type: TypeDeclaration( - dataType: 'Int32List', - isNullable: true, - typeArguments: null, - )), - Field( - name: 'aInt64List', - offset: null, - type: TypeDeclaration( - dataType: 'Int64List', - isNullable: true, - typeArguments: null, - )), - Field( - name: 'aFloat64List', - offset: null, - type: TypeDeclaration( - dataType: 'Float64List', - isNullable: true, - typeArguments: null, - )), + Field(name: 'aBool', dataType: 'bool', isNullable: true), + Field(name: 'aInt', dataType: 'int', isNullable: true), + Field(name: 'aDouble', dataType: 'double', isNullable: true), + Field(name: 'aString', dataType: 'String', isNullable: true), + Field(name: 'aUint8List', dataType: 'Uint8List', isNullable: true), + Field(name: 'aInt32List', dataType: 'Int32List', isNullable: true), + Field(name: 'aInt64List', dataType: 'Int64List', isNullable: true), + Field(name: 'aFloat64List', dataType: 'Float64List', isNullable: true), ]), ], enums: []); @@ -232,45 +142,17 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'input', dataType: 'String', isNullable: true) ]), Class(name: 'Output', fields: [ - Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'output', dataType: 'String', isNullable: true) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -286,35 +168,14 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'input', dataType: 'String', isNullable: true) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -330,35 +191,14 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'input', dataType: 'String', isNullable: true) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -374,35 +214,14 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Output', fields: [ - Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'output', dataType: 'String', isNullable: true) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -418,35 +237,14 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) ]) ], classes: [ Class(name: 'Output', fields: [ - Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'output', dataType: 'String', isNullable: true) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -460,14 +258,7 @@ void main() { test('gen list', () { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ - Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'List', - isNullable: true, - typeArguments: null, - )) + Field(name: 'field1', dataType: 'List', isNullable: true) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -481,14 +272,7 @@ void main() { test('gen map', () { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ - Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'Map', - isNullable: true, - typeArguments: null, - )) + Field(name: 'field1', dataType: 'Map', isNullable: true) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -504,26 +288,20 @@ void main() { name: 'Outer', fields: [ Field( - name: 'nested', - offset: null, - type: TypeDeclaration( - dataType: 'Nested', - isNullable: true, - typeArguments: null, - )) + name: 'nested', + dataType: 'Nested', + isNullable: true, + ) ], ); final Class nestedClass = Class( name: 'Nested', fields: [ Field( - name: 'data', - offset: null, - type: TypeDeclaration( - dataType: 'int', - isNullable: true, - typeArguments: null, - )) + name: 'data', + dataType: 'int', + isNullable: true, + ) ], ); final Root root = Root( @@ -548,45 +326,17 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'input', dataType: 'String', isNullable: true) ]), Class(name: 'Output', fields: [ - Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'output', dataType: 'String', isNullable: true) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -609,45 +359,17 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) ]) ], classes: [ Class(name: 'Input', fields: [ - Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'input', dataType: 'String', isNullable: true) ]), Class(name: 'Output', fields: [ - Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + Field(name: 'output', dataType: 'String', isNullable: true) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -670,13 +392,10 @@ void main() { name: 'EnumClass', fields: [ Field( - name: 'enum1', - offset: null, - type: TypeDeclaration( - dataType: 'Enum1', - isNullable: true, - typeArguments: null, - )), + name: 'enum1', + dataType: 'Enum1', + isNullable: true, + ), ], ); final Root root = Root( @@ -720,15 +439,13 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'List', - isNullable: true, - typeArguments: [ - TypeDeclaration(dataType: 'int', isNullable: true) - ], - )), + name: 'field1', + dataType: 'List', + isNullable: true, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ], + ), ], ); final Root root = Root( diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 97ac90eb140d..759b16e3f296 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -11,13 +11,10 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'field1', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -31,13 +28,10 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'field1', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -91,21 +85,15 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )), + name: 'field1', + dataType: 'String', + isNullable: true, + ), Field( - name: 'enum1', - offset: null, - type: TypeDeclaration( - dataType: 'Enum1', - isNullable: true, - typeArguments: null, - )), + name: 'enum1', + dataType: 'Enum1', + isNullable: true, + ), ], ), ], @@ -132,43 +120,23 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -186,43 +154,23 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -238,69 +186,45 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'aBool', - offset: null, - type: TypeDeclaration( - dataType: 'bool', - isNullable: true, - typeArguments: null, - )), + name: 'aBool', + dataType: 'bool', + isNullable: true, + ), Field( - name: 'aInt', - offset: null, - type: TypeDeclaration( - dataType: 'int', - isNullable: true, - typeArguments: null, - )), + name: 'aInt', + dataType: 'int', + isNullable: true, + ), Field( - name: 'aDouble', - offset: null, - type: TypeDeclaration( - dataType: 'double', - isNullable: true, - typeArguments: null, - )), + name: 'aDouble', + dataType: 'double', + isNullable: true, + ), Field( - name: 'aString', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )), + name: 'aString', + dataType: 'String', + isNullable: true, + ), Field( - name: 'aUint8List', - offset: null, - type: TypeDeclaration( - dataType: 'Uint8List', - isNullable: true, - typeArguments: null, - )), + name: 'aUint8List', + dataType: 'Uint8List', + isNullable: true, + ), Field( - name: 'aInt32List', - offset: null, - type: TypeDeclaration( - dataType: 'Int32List', - isNullable: true, - typeArguments: null, - )), + name: 'aInt32List', + dataType: 'Int32List', + isNullable: true, + ), Field( - name: 'aInt64List', - offset: null, - type: TypeDeclaration( - dataType: 'Int64List', - isNullable: true, - typeArguments: null, - )), + name: 'aInt64List', + dataType: 'Int64List', + isNullable: true, + ), Field( - name: 'aFloat64List', - offset: null, - type: TypeDeclaration( - dataType: 'Float64List', - isNullable: true, - typeArguments: null, - )), + name: 'aFloat64List', + dataType: 'Float64List', + isNullable: true, + ), ]), ], enums: []); @@ -327,13 +251,10 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'aBool', - offset: null, - type: TypeDeclaration( - dataType: 'bool', - isNullable: true, - typeArguments: null, - )), + name: 'aBool', + dataType: 'bool', + isNullable: true, + ), ]), ], enums: []); @@ -348,23 +269,17 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Nested', fields: [ Field( - name: 'nested', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: true, - typeArguments: null, - )) + name: 'nested', + dataType: 'Input', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -378,23 +293,17 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Nested', fields: [ Field( - name: 'nested', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: true, - typeArguments: null, - )) + name: 'nested', + dataType: 'Input', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -408,13 +317,10 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'field1', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -427,13 +333,10 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'field1', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -447,43 +350,23 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Nested', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Nested', fields: [ Field( - name: 'nested', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: true, - typeArguments: null, - )) + name: 'nested', + dataType: 'Input', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -499,43 +382,23 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Nested', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Nested', fields: [ Field( - name: 'nested', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: true, - typeArguments: null, - )) + name: 'nested', + dataType: 'Input', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -551,43 +414,23 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -606,43 +449,23 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]) ], enums: []); final StringBuffer sink = StringBuffer(); @@ -657,33 +480,16 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -698,33 +504,16 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -741,33 +530,16 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -782,33 +554,16 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -824,33 +579,16 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -865,33 +603,16 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -906,33 +627,16 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -950,33 +654,16 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - ))) + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -994,13 +681,10 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'List', - isNullable: true, - typeArguments: null, - )) + name: 'field1', + dataType: 'List', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -1014,13 +698,10 @@ void main() { final Root root = Root(apis: [], classes: [ Class(name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'Map', - isNullable: true, - typeArguments: null, - )) + name: 'field1', + dataType: 'Map', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -1035,44 +716,24 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -1090,44 +751,24 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -1145,34 +786,17 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -1190,22 +814,8 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) ], classes: [], enums: []); @@ -1224,44 +834,24 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -1279,44 +869,24 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Input', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'Input', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) ], classes: [ Class(name: 'Input', fields: [ Field( - name: 'input', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'input', + dataType: 'String', + isNullable: true, + ) ]), Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -1334,22 +904,8 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) ], classes: [], enums: []); @@ -1366,34 +922,17 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'void', - isNullable: false, - typeArguments: null, - )), - returnType: Field( - name: '', - offset: null, - type: TypeDeclaration( - dataType: 'Output', - isNullable: false, - typeArguments: null, - )), + argType: Field(name: '', dataType: 'void', isNullable: false), + returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) ], classes: [ Class(name: 'Output', fields: [ Field( - name: 'output', - offset: null, - type: TypeDeclaration( - dataType: 'String', - isNullable: true, - typeArguments: null, - )) + name: 'output', + dataType: 'String', + isNullable: true, + ) ]), ], enums: []); final StringBuffer sink = StringBuffer(); @@ -1445,15 +984,13 @@ void main() { name: 'Foobar', fields: [ Field( - name: 'field1', - offset: null, - type: TypeDeclaration( - dataType: 'List', - isNullable: true, - typeArguments: [ - TypeDeclaration(dataType: 'int', isNullable: true) - ], - )), + name: 'field1', + dataType: 'List', + isNullable: true, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ], + ), ], ); final Root root = Root( diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 7e4d1ad109a0..371bbc671e20 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -93,8 +93,8 @@ abstract class Api1 { expect(root.apis[0].name, equals('Api1')); expect(root.apis[0].methods.length, equals(1)); expect(root.apis[0].methods[0].name, equals('doit')); - expect(root.apis[0].methods[0].argType.type.dataType, equals('Input1')); - expect(root.apis[0].methods[0].returnType.type.dataType, equals('Output1')); + expect(root.apis[0].methods[0].argType.dataType, equals('Input1')); + expect(root.apis[0].methods[0].returnType.dataType, equals('Output1')); Class? input; Class? output; @@ -110,13 +110,13 @@ abstract class Api1 { expect(input?.fields.length, equals(1)); expect(input?.fields[0].name, equals('input')); - expect(input?.fields[0].type.dataType, equals('String')); - expect(input?.fields[0].type.isNullable, isTrue); + expect(input?.fields[0].dataType, equals('String')); + expect(input?.fields[0].isNullable, isTrue); expect(output?.fields.length, equals(1)); expect(output?.fields[0].name, equals('output')); - expect(output?.fields[0].type.dataType, equals('String')); - expect(output?.fields[0].type.isNullable, isTrue); + expect(output?.fields[0].dataType, equals('String')); + expect(output?.fields[0].isNullable, isTrue); }); test('invalid datatype', () { @@ -157,8 +157,8 @@ abstract class Api { expect(results.root.classes.length, equals(1)); expect(results.root.classes[0].name, equals('ClassWithEnum')); expect(results.root.classes[0].fields.length, equals(1)); - expect(results.root.classes[0].fields[0].type.dataType, equals('Enum1')); - expect(results.root.classes[0].fields[0].type.isNullable, isTrue); + expect(results.root.classes[0].fields[0].dataType, equals('Enum1')); + expect(results.root.classes[0].fields[0].isNullable, isTrue); expect(results.root.classes[0].fields[0].name, equals('enum1')); }); @@ -203,8 +203,8 @@ abstract class Api { final Class nested = results.root.classes.firstWhere((Class x) => x.name == 'Nested'); expect(nested.fields.length, equals(1)); - expect(nested.fields[0].type.dataType, equals('Input1')); - expect(nested.fields[0].type.isNullable, isTrue); + expect(nested.fields[0].dataType, equals('Input1')); + expect(nested.fields[0].isNullable, isTrue); }); test('flutter api', () { @@ -241,8 +241,7 @@ abstract class VoidApi { expect(results.root.apis.length, equals(1)); expect(results.root.apis[0].methods.length, equals(1)); expect(results.root.apis[0].name, equals('VoidApi')); - expect(results.root.apis[0].methods[0].returnType.type.dataType, - equals('void')); + expect(results.root.apis[0].methods[0].returnType.dataType, equals('void')); }); test('void arg host api', () { @@ -261,10 +260,9 @@ abstract class VoidArgApi { expect(results.root.apis.length, equals(1)); expect(results.root.apis[0].methods.length, equals(1)); expect(results.root.apis[0].name, equals('VoidArgApi')); - expect(results.root.apis[0].methods[0].returnType.type.dataType, - equals('Output1')); expect( - results.root.apis[0].methods[0].argType.type.dataType, equals('void')); + results.root.apis[0].methods[0].returnType.dataType, equals('Output1')); + expect(results.root.apis[0].methods[0].argType.dataType, equals('void')); }); test('mockDartClass', () { @@ -412,7 +410,7 @@ abstract class NotificationsHostApi { final Class foo = results.root.classes.firstWhere((Class aClass) => aClass.name == 'Foo'); expect(foo.fields.length, 1); - expect(foo.fields[0].type.dataType, 'Bar'); + expect(foo.fields[0].dataType, 'Bar'); }); test('test compilation error', () { @@ -572,8 +570,8 @@ abstract class Api { final ParseResults parseResult = _parseSource(code); expect(parseResult.errors.length, equals(0)); final Field field = parseResult.root.classes[0].fields[0]; - expect(field.type.typeArguments!.length, 1); - expect(field.type.typeArguments![0].dataType, 'int'); + expect(field.typeArguments!.length, 1); + expect(field.typeArguments![0].dataType, 'int'); }); test('parse recursive generics', () { @@ -590,9 +588,9 @@ abstract class Api { final ParseResults parseResult = _parseSource(code); expect(parseResult.errors.length, equals(0)); final Field field = parseResult.root.classes[0].fields[0]; - expect(field.type.typeArguments!.length, 1); - expect(field.type.typeArguments![0].dataType, 'List'); - expect(field.type.typeArguments![0].typeArguments![0].dataType, 'int'); + expect(field.typeArguments!.length, 1); + expect(field.typeArguments![0].dataType, 'List'); + expect(field.typeArguments![0].typeArguments![0].dataType, 'int'); }); test('error nonnull type argument', () { @@ -666,8 +664,8 @@ abstract class Api { '''; final ParseResults parseResult = _parseSource(code); final Field field = parseResult.root.classes[0].fields[0]; - expect(field.type.typeArguments!.length, 2); - expect(field.type.typeArguments![0].dataType, 'String'); - expect(field.type.typeArguments![1].dataType, 'int'); + expect(field.typeArguments!.length, 2); + expect(field.typeArguments![0].dataType, 'String'); + expect(field.typeArguments![1].dataType, 'int'); }); } From 98601261870fc69f6e0a14804937110a711b759e Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Aug 2021 10:16:22 -0700 Subject: [PATCH 13/30] introduced the TypedEntity and TypeDeclaration --- packages/pigeon/lib/ast.dart | 66 +++++++++++++++---- packages/pigeon/lib/dart_generator.dart | 4 +- packages/pigeon/lib/java_generator.dart | 4 +- packages/pigeon/lib/objc_generator.dart | 4 +- packages/pigeon/lib/pigeon_lib.dart | 12 ++-- packages/pigeon/test/dart_generator_test.dart | 10 +-- packages/pigeon/test/java_generator_test.dart | 4 +- packages/pigeon/test/objc_generator_test.dart | 4 +- 8 files changed, 75 insertions(+), 33 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index 2ef8a94f5f51..b1124e994d84 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -98,31 +98,73 @@ class TypeArgument { } } +/// An entity that represents a typed concept, like a [TypeArgument] or [Field]. +abstract class TypedEntity { + /// The data-type of the entity (ex 'String' or 'int'). + String get dataType; + + /// The type arguments to the entity. + List? get typeArguments; + + /// True if the type is nullable. + bool get isNullable; +} + +/// Represents a type declaration. +class TypeDeclaration implements TypedEntity { + /// Constructor for [TypeDeclaration]. + TypeDeclaration({ + required this.dataType, + required this.isNullable, + this.typeArguments, + }); + + @override + final String dataType; + + @override + final List? typeArguments; + + @override + final bool isNullable; + + @override + String toString() { + return '(TypeDeclaration dataType:$dataType isNullable:$isNullable typeArguments:$typeArguments)'; + } +} + /// Represents a field on a [Class]. -class Field extends Node { +class Field extends Node implements TypedEntity { /// Parametric constructor for [Field]. Field({ required this.name, - required this.dataType, - required this.isNullable, - this.typeArguments, + required String dataType, + required bool isNullable, + List? typeArguments, this.offset, - }); + }) : type = TypeDeclaration( + dataType: dataType, + isNullable: isNullable, + typeArguments: typeArguments); /// The name of the field. String name; - /// The data-type of the field (ex 'String' or 'int'). - String dataType; - /// The offset in the source file where the field appears. int? offset; - /// True if the datatype is nullable (ex `int?`). - bool isNullable; + /// The type of the [Field]. + TypeDeclaration type; + + @override + String get dataType => type.dataType; + + @override + bool get isNullable => type.isNullable; - /// Type parameters used for generics. - List? typeArguments; + @override + List? get typeArguments => type.typeArguments; @override String toString() { diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 1fb7128c7c24..76cb74e3b01d 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -266,9 +266,9 @@ void _writeFlutterApi( /// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in Dart code. -String _flattenTypeArguments(List args, String nullTag) { +String _flattenTypeArguments(List args, String nullTag) { return args - .map((TypeArgument arg) => arg.typeArguments == null + .map((TypedEntity arg) => arg.typeArguments == null ? '${arg.dataType}$nullTag' : '${arg.dataType}<${_flattenTypeArguments(arg.typeArguments!, nullTag)}>$nullTag') .reduce((String value, String element) => '$value, $element'); diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 175e3722c67a..007c7e96507b 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -305,9 +305,9 @@ String _makeSetter(Field field) { /// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in Java code. -String _flattenTypeArguments(List args) { +String _flattenTypeArguments(List args) { return args - .map((TypeArgument e) => e.typeArguments == null + .map((TypedEntity e) => e.typeArguments == null ? _javaTypeForDartTypePassthrough(e.dataType) : '${_javaTypeForDartTypePassthrough(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') .reduce((String value, String element) => '$value, $element'); diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index 9f71f8d88cec..f234c7281e1f 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -94,9 +94,9 @@ const Map _propertyTypeForDartTypeMap = { /// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in objc code. -String _flattenTypeArguments(String? classPrefix, List args) { +String _flattenTypeArguments(String? classPrefix, List args) { return args - .map((TypeArgument e) => e.typeArguments == null + .map((TypedEntity e) => e.typeArguments == null ? '${_objcTypeForDartType(classPrefix, e.dataType)} *' : '${_objcTypeForDartType(classPrefix, e.dataType)}<${_flattenTypeArguments(classPrefix, e.typeArguments!)}> *') .reduce((String value, String element) => '$value, $element'); diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 5cb83cdd0b80..8cbfc08a1dac 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -379,7 +379,7 @@ List _validateAst(Root root, String source) { for (final Class klass in root.classes) { for (final Field field in klass.fields) { if (field.typeArguments != null) { - for (final TypeArgument typeArgument in field.typeArguments!) { + for (final TypedEntity typeArgument in field.typeArguments!) { if (!typeArgument.isNullable) { result.add(Error( message: @@ -637,7 +637,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final dart_ast.FormalParameterList parameters = node.parameters!; late String argType; bool isNullable = false; - List? argTypeArguments; + List? argTypeArguments; if (parameters.parameters.isEmpty) { argType = 'void'; } else { @@ -688,14 +688,14 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { return null; } - List? typeAnnotationsToTypeArguments( + List? typeAnnotationsToTypeArguments( dart_ast.TypeArgumentList? typeArguments) { - List? result; + List? result; if (typeArguments != null) { for (final Object x in typeArguments.childEntities) { if (x is dart_ast.TypeName) { - result ??= []; - result.add(TypeArgument( + result ??= []; + result.add(TypeDeclaration( dataType: x.name.name, isNullable: x.question != null, typeArguments: typeAnnotationsToTypeArguments(x.typeArguments))); diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index f31338c0f571..817ecfee8591 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -570,8 +570,8 @@ void main() { name: 'field1', dataType: 'List', isNullable: true, - typeArguments: [ - TypeArgument(dataType: 'int', isNullable: true) + typeArguments: [ + TypeDeclaration(dataType: 'int', isNullable: true) ], ), ], @@ -596,9 +596,9 @@ void main() { name: 'field1', dataType: 'Map', isNullable: true, - typeArguments: [ - TypeArgument(dataType: 'String', isNullable: true), - TypeArgument(dataType: 'int', isNullable: true), + typeArguments: [ + TypeDeclaration(dataType: 'String', isNullable: true), + TypeDeclaration(dataType: 'int', isNullable: true), ], ), ], diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 510d6d922260..e050daec9ba4 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -442,8 +442,8 @@ void main() { name: 'field1', dataType: 'List', isNullable: true, - typeArguments: [ - TypeArgument(dataType: 'int', isNullable: true) + typeArguments: [ + TypeDeclaration(dataType: 'int', isNullable: true) ], ), ], diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 759b16e3f296..36bcce2b7581 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -987,8 +987,8 @@ void main() { name: 'field1', dataType: 'List', isNullable: true, - typeArguments: [ - TypeArgument(dataType: 'int', isNullable: true) + typeArguments: [ + TypeDeclaration(dataType: 'int', isNullable: true) ], ), ], From 845897d304d4cfe553c8ddad71bcb654a6219b8d Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Aug 2021 12:02:11 -0700 Subject: [PATCH 14/30] Revert "introduced the TypedEntity and TypeDeclaration" This reverts commit 98601261870fc69f6e0a14804937110a711b759e. --- packages/pigeon/lib/ast.dart | 66 ++++--------------- packages/pigeon/lib/dart_generator.dart | 4 +- packages/pigeon/lib/java_generator.dart | 4 +- packages/pigeon/lib/objc_generator.dart | 4 +- packages/pigeon/lib/pigeon_lib.dart | 12 ++-- packages/pigeon/test/dart_generator_test.dart | 10 +-- packages/pigeon/test/java_generator_test.dart | 4 +- packages/pigeon/test/objc_generator_test.dart | 4 +- 8 files changed, 33 insertions(+), 75 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index b1124e994d84..2ef8a94f5f51 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -98,73 +98,31 @@ class TypeArgument { } } -/// An entity that represents a typed concept, like a [TypeArgument] or [Field]. -abstract class TypedEntity { - /// The data-type of the entity (ex 'String' or 'int'). - String get dataType; - - /// The type arguments to the entity. - List? get typeArguments; - - /// True if the type is nullable. - bool get isNullable; -} - -/// Represents a type declaration. -class TypeDeclaration implements TypedEntity { - /// Constructor for [TypeDeclaration]. - TypeDeclaration({ - required this.dataType, - required this.isNullable, - this.typeArguments, - }); - - @override - final String dataType; - - @override - final List? typeArguments; - - @override - final bool isNullable; - - @override - String toString() { - return '(TypeDeclaration dataType:$dataType isNullable:$isNullable typeArguments:$typeArguments)'; - } -} - /// Represents a field on a [Class]. -class Field extends Node implements TypedEntity { +class Field extends Node { /// Parametric constructor for [Field]. Field({ required this.name, - required String dataType, - required bool isNullable, - List? typeArguments, + required this.dataType, + required this.isNullable, + this.typeArguments, this.offset, - }) : type = TypeDeclaration( - dataType: dataType, - isNullable: isNullable, - typeArguments: typeArguments); + }); /// The name of the field. String name; + /// The data-type of the field (ex 'String' or 'int'). + String dataType; + /// The offset in the source file where the field appears. int? offset; - /// The type of the [Field]. - TypeDeclaration type; - - @override - String get dataType => type.dataType; - - @override - bool get isNullable => type.isNullable; + /// True if the datatype is nullable (ex `int?`). + bool isNullable; - @override - List? get typeArguments => type.typeArguments; + /// Type parameters used for generics. + List? typeArguments; @override String toString() { diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 76cb74e3b01d..1fb7128c7c24 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -266,9 +266,9 @@ void _writeFlutterApi( /// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in Dart code. -String _flattenTypeArguments(List args, String nullTag) { +String _flattenTypeArguments(List args, String nullTag) { return args - .map((TypedEntity arg) => arg.typeArguments == null + .map((TypeArgument arg) => arg.typeArguments == null ? '${arg.dataType}$nullTag' : '${arg.dataType}<${_flattenTypeArguments(arg.typeArguments!, nullTag)}>$nullTag') .reduce((String value, String element) => '$value, $element'); diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 007c7e96507b..175e3722c67a 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -305,9 +305,9 @@ String _makeSetter(Field field) { /// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in Java code. -String _flattenTypeArguments(List args) { +String _flattenTypeArguments(List args) { return args - .map((TypedEntity e) => e.typeArguments == null + .map((TypeArgument e) => e.typeArguments == null ? _javaTypeForDartTypePassthrough(e.dataType) : '${_javaTypeForDartTypePassthrough(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') .reduce((String value, String element) => '$value, $element'); diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index f234c7281e1f..9f71f8d88cec 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -94,9 +94,9 @@ const Map _propertyTypeForDartTypeMap = { /// Converts a [List] of [TypeArgument]s to a comma separated [String] to be /// used in objc code. -String _flattenTypeArguments(String? classPrefix, List args) { +String _flattenTypeArguments(String? classPrefix, List args) { return args - .map((TypedEntity e) => e.typeArguments == null + .map((TypeArgument e) => e.typeArguments == null ? '${_objcTypeForDartType(classPrefix, e.dataType)} *' : '${_objcTypeForDartType(classPrefix, e.dataType)}<${_flattenTypeArguments(classPrefix, e.typeArguments!)}> *') .reduce((String value, String element) => '$value, $element'); diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 8cbfc08a1dac..5cb83cdd0b80 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -379,7 +379,7 @@ List _validateAst(Root root, String source) { for (final Class klass in root.classes) { for (final Field field in klass.fields) { if (field.typeArguments != null) { - for (final TypedEntity typeArgument in field.typeArguments!) { + for (final TypeArgument typeArgument in field.typeArguments!) { if (!typeArgument.isNullable) { result.add(Error( message: @@ -637,7 +637,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final dart_ast.FormalParameterList parameters = node.parameters!; late String argType; bool isNullable = false; - List? argTypeArguments; + List? argTypeArguments; if (parameters.parameters.isEmpty) { argType = 'void'; } else { @@ -688,14 +688,14 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { return null; } - List? typeAnnotationsToTypeArguments( + List? typeAnnotationsToTypeArguments( dart_ast.TypeArgumentList? typeArguments) { - List? result; + List? result; if (typeArguments != null) { for (final Object x in typeArguments.childEntities) { if (x is dart_ast.TypeName) { - result ??= []; - result.add(TypeDeclaration( + result ??= []; + result.add(TypeArgument( dataType: x.name.name, isNullable: x.question != null, typeArguments: typeAnnotationsToTypeArguments(x.typeArguments))); diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 817ecfee8591..f31338c0f571 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -570,8 +570,8 @@ void main() { name: 'field1', dataType: 'List', isNullable: true, - typeArguments: [ - TypeDeclaration(dataType: 'int', isNullable: true) + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) ], ), ], @@ -596,9 +596,9 @@ void main() { name: 'field1', dataType: 'Map', isNullable: true, - typeArguments: [ - TypeDeclaration(dataType: 'String', isNullable: true), - TypeDeclaration(dataType: 'int', isNullable: true), + typeArguments: [ + TypeArgument(dataType: 'String', isNullable: true), + TypeArgument(dataType: 'int', isNullable: true), ], ), ], diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index e050daec9ba4..510d6d922260 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -442,8 +442,8 @@ void main() { name: 'field1', dataType: 'List', isNullable: true, - typeArguments: [ - TypeDeclaration(dataType: 'int', isNullable: true) + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) ], ), ], diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 36bcce2b7581..759b16e3f296 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -987,8 +987,8 @@ void main() { name: 'field1', dataType: 'List', isNullable: true, - typeArguments: [ - TypeDeclaration(dataType: 'int', isNullable: true) + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) ], ), ], From eea78a276b8a750ce248b685400be968a78261e4 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Fri, 23 Jul 2021 16:24:50 -0700 Subject: [PATCH 15/30] [pigeon] implemented multiple arity Started parsing the arguments --- packages/pigeon/lib/ast.dart | 6 +- packages/pigeon/lib/dart_generator.dart | 11 +-- packages/pigeon/lib/generator_tools.dart | 2 +- packages/pigeon/lib/java_generator.dart | 10 +-- packages/pigeon/lib/objc_generator.dart | 30 +++---- packages/pigeon/lib/pigeon_lib.dart | 65 +++++++++----- packages/pigeon/test/dart_generator_test.dart | 56 +++++++++--- packages/pigeon/test/java_generator_test.dart | 32 +++++-- packages/pigeon/test/objc_generator_test.dart | 88 ++++++++++++++----- packages/pigeon/test/pigeon_lib_test.dart | 27 +++++- 10 files changed, 228 insertions(+), 99 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index 2ef8a94f5f51..dd74c00c456d 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -20,7 +20,7 @@ class Method extends Node { Method({ required this.name, required this.returnType, - required this.argType, + required this.arguments, this.isAsynchronous = false, this.offset, }); @@ -32,7 +32,7 @@ class Method extends Node { Field returnType; /// The data-type of the argument. - Field argType; + List arguments; /// Whether the receiver of this method is expected to return synchronously or not. bool isAsynchronous; @@ -42,7 +42,7 @@ class Method extends Node { @override String toString() { - return '(Api name:$name returnType:$returnType argType:$argType isAsynchronous:$isAsynchronous)'; + return '(Api name:$name returnType:$returnType argType:$arguments isAsynchronous:$isAsynchronous)'; } } diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 1fb7128c7c24..4feb580ac937 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -121,8 +121,8 @@ final BinaryMessenger$nullTag _binaryMessenger; } String argSignature = ''; String sendArgument = 'null'; - if (func.argType.dataType != 'void') { - argSignature = '${func.argType.dataType} arg'; + if (func.arguments[0].dataType != 'void') { + argSignature = '${func.arguments[0].dataType} arg'; sendArgument = 'arg'; } indent.write( @@ -184,8 +184,9 @@ void _writeFlutterApi( final String returnType = isAsync ? 'Future<${func.returnType.dataType}>' : func.returnType.dataType; - final String argSignature = - func.argType.dataType == 'void' ? '' : '${func.argType.dataType} arg'; + final String argSignature = func.arguments[0].dataType == 'void' + ? '' + : '${func.arguments[0].dataType} arg'; indent.writeln('$returnType ${func.name}($argSignature);'); } indent.write('static void setup(${api.name}$nullTag api) '); @@ -216,7 +217,7 @@ void _writeFlutterApi( 'channel.$messageHandlerSetter((Object$nullTag message) async ', ); indent.scoped('{', '});', () { - final String argType = func.argType.dataType; + final String argType = func.arguments[0].dataType; final String returnType = func.returnType.dataType; final bool isAsync = func.isAsynchronous; final String emptyReturnStatement = isMockHandler diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index a41a75800674..a1f07cf38630 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -286,7 +286,7 @@ Iterable getCodecClasses(Api api) sync* { final Set names = {}; for (final Method method in api.methods) { names.add(method.returnType.dataType); - names.add(method.argType.dataType); + names.add(method.arguments[0].dataType); } final List sortedNames = names .where((String element) => diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 175e3722c67a..1a73a2bff4b6 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -125,12 +125,12 @@ void _writeHostApi(Indent indent, Api api) { indent.scoped('{', '}', () { for (final Method method in api.methods) { final String argType = - _javaTypeForDartTypePassthrough(method.argType.dataType); + _javaTypeForDartTypePassthrough(method.arguments[0].dataType); final String returnType = method.isAsynchronous ? 'void' : _javaTypeForDartTypePassthrough(method.returnType.dataType); final List argSignature = []; - if (method.argType.dataType != 'void') { + if (method.arguments[0].dataType != 'void') { argSignature.add('$argType arg'); } if (method.isAsynchronous) { @@ -170,7 +170,7 @@ static MessageCodec getCodec() { indent.write('channel.setMessageHandler((message, reply) -> '); indent.scoped('{', '});', () { final String argType = - _javaTypeForDartTypePassthrough(method.argType.dataType); + _javaTypeForDartTypePassthrough(method.arguments[0].dataType); final String returnType = _javaTypeForDartTypePassthrough(method.returnType.dataType); indent.writeln('Map wrapped = new HashMap<>();'); @@ -258,9 +258,9 @@ static MessageCodec getCodec() { ? 'Void' : _javaTypeForDartTypePassthrough(func.returnType.dataType); final String argType = - _javaTypeForDartTypePassthrough(func.argType.dataType); + _javaTypeForDartTypePassthrough(func.arguments[0].dataType); String sendArgument; - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { indent.write('public void ${func.name}(Reply<$returnType> callback) '); sendArgument = 'null'; } else { diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index 9f71f8d88cec..f49a067d7142 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -243,22 +243,22 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { _objcTypeForDartType(options.prefix, func.returnType.dataType); if (func.isAsynchronous) { if (func.returnType.dataType == 'void') { - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)(FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.arguments[0].dataType); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)(FlutterError *_Nullable))completion;'); } } else { - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { indent.writeln( '-(void)${func.name}:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.arguments[0].dataType); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } @@ -267,12 +267,12 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { final String returnType = func.returnType.dataType == 'void' ? 'void' : 'nullable $returnTypeName *'; - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { indent.writeln( '-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.arguments[0].dataType); indent.writeln( '-($returnType)${func.name}:($argType*)input error:(FlutterError *_Nullable *_Nonnull)error;'); } @@ -295,11 +295,11 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) { _objcTypeForDartType(options.prefix, func.returnType.dataType); final String callbackType = _callbackForType(func.returnType.dataType, returnType); - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { indent.writeln('- (void)${func.name}:($callbackType)completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.arguments[0].dataType); indent.writeln( '- (void)${func.name}:($argType*)input completion:($callbackType)completion;'); } @@ -418,18 +418,18 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { final String returnType = _objcTypeForDartType(options.prefix, func.returnType.dataType); String syncCall; - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { syncCall = '[api ${func.name}:&error]'; } else { - final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + final String argType = _objcTypeForDartType( + options.prefix, func.arguments[0].dataType); indent.writeln('$argType *input = message;'); syncCall = '[api ${func.name}:input error:&error]'; } if (func.isAsynchronous) { if (func.returnType.dataType == 'void') { const String callback = 'callback(wrapResult(nil, error));'; - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { indent.writeScoped( '[api ${func.name}:^(FlutterError *_Nullable error) {', '}];', () { @@ -444,7 +444,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { } } else { const String callback = 'callback(wrapResult(output, error));'; - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { indent.writeScoped( '[api ${func.name}:^($returnType *_Nullable output, FlutterError *_Nullable error) {', '}];', () { @@ -506,12 +506,12 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { _callbackForType(func.returnType.dataType, returnType); String sendArgument; - if (func.argType.dataType == 'void') { + if (func.arguments[0].dataType == 'void') { indent.write('- (void)${func.name}:($callbackType)completion '); sendArgument = 'nil'; } else { final String argType = - _objcTypeForDartType(options.prefix, func.argType.dataType); + _objcTypeForDartType(options.prefix, func.arguments[0].dataType); indent.write( '- (void)${func.name}:($argType*)input completion:($callbackType)completion '); sendArgument = 'input'; diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 5cb83cdd0b80..c078dfd002e0 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -405,28 +405,35 @@ List _validateAst(Root root, String source) { if (method.returnType.isNullable) { result.add(Error( message: - 'Nullable return types types aren\'t supported for Pigeon methods: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name}"', + 'Nullable return types types aren\'t supported for Pigeon methods: "${method.arguments[0].dataType}" in API: "${api.name}" method: "${method.name}"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } if (method.returnType.typeArguments != null) { result.add(Error( message: - 'Generic type arguments for primitive return values aren\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + 'Generic type arguments for primitive return values aren\'t yet supported: "${method.returnType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.argType.isNullable) { + if (method.arguments.length > 1) { result.add(Error( message: - 'Nullable argument types aren\'t supported for Pigeon methods: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name}"', + 'Multiple arguments aren\'t yet supported, in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86971)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.argType.typeArguments != null) { + if (method.arguments[0].isNullable) { result.add(Error( message: - 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.argType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', + 'Nullable argument types aren\'t supported for Pigeon methods: "${method.arguments[0].dataType}" in API: "${api.name}" method: "${method.name}"', + lineNumber: _calculateLineNumberNullable(source, method.offset), + )); + } + if (method.arguments[0].typeArguments != null) { + result.add(Error( + message: + 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.arguments[0].dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } @@ -481,7 +488,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final Set referencedTypes = {}; for (final Api api in _apis) { for (final Method method in api.methods) { - referencedTypes.add(method.argType.dataType); + referencedTypes.add(method.arguments[0].dataType); referencedTypes.add(method.returnType.dataType); } } @@ -632,23 +639,37 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { return null; } + Field formalParameterToField(dart_ast.FormalParameter parameter) { + final dart_ast.TypeName typeName = parameter.childEntities + // ignore: always_specify_types + .firstWhere((e) => e is dart_ast.TypeName) as dart_ast.TypeName; + final String argType = typeName.name.name; + final bool isNullable = typeName.question != null; + final List? argTypeArguments = + typeAnnotationsToTypeArguments(typeName.typeArguments); + return Field( + dataType: argType, + isNullable: isNullable, + name: '', + typeArguments: argTypeArguments, + ); + } + @override Object? visitMethodDeclaration(dart_ast.MethodDeclaration node) { final dart_ast.FormalParameterList parameters = node.parameters!; - late String argType; - bool isNullable = false; - List? argTypeArguments; + late List arguments; if (parameters.parameters.isEmpty) { - argType = 'void'; + arguments = [ + Field( + dataType: 'void', + isNullable: false, + name: '', + typeArguments: null, + ) + ]; } else { - final dart_ast.FormalParameter firstParameter = - parameters.parameters.first; - final dart_ast.TypeName typeName = firstParameter.childEntities - // ignore: always_specify_types - .firstWhere((e) => e is dart_ast.TypeName) as dart_ast.TypeName; - argType = typeName.name.name; - isNullable = typeName.question != null; - argTypeArguments = typeAnnotationsToTypeArguments(typeName.typeArguments); + arguments = parameters.parameters.map(formalParameterToField).toList(); } final bool isAsynchronous = _hasMetadata(node.metadata, 'async'); if (_currentApi != null) { @@ -660,11 +681,7 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { typeArguments: typeAnnotationsToTypeArguments( (node.returnType as dart_ast.NamedType?)!.typeArguments), isNullable: node.returnType!.question != null), - argType: Field( - dataType: argType, - isNullable: isNullable, - name: '', - typeArguments: argTypeArguments), + arguments: arguments, isAsynchronous: isAsynchronous, offset: node.offset)); } else if (_currentClass != null) { diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index f31338c0f571..5e5b3d5f3adf 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -57,7 +57,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -130,7 +132,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -163,7 +167,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -189,7 +195,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -218,7 +226,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'void'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'void') + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -244,7 +254,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'EnumClass'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'EnumClass') + ], returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), isAsynchronous: false, ) @@ -280,7 +292,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'EnumClass'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'EnumClass') + ], returnType: Field(name: '', dataType: 'EnumClass', isNullable: false), isAsynchronous: false, ) @@ -318,7 +332,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'void'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'void') + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -347,14 +363,18 @@ void main() { methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ), Method( name: 'voidReturner', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -423,7 +443,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) @@ -458,7 +480,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true, ) @@ -492,7 +516,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'Input'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'Input') + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) @@ -525,7 +551,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', isNullable: false, dataType: 'void'), + arguments: [ + Field(name: '', isNullable: false, dataType: 'void') + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 510d6d922260..c41943d05696 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -87,7 +87,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -142,7 +144,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -168,7 +172,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -191,7 +197,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: false, ) @@ -214,7 +222,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -237,7 +247,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -326,7 +338,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) @@ -359,7 +373,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 759b16e3f296..8b129ad3a6dd 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -120,7 +120,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -154,7 +156,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -350,7 +354,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ @@ -382,7 +388,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Nested', isNullable: false)) ]) ], classes: [ @@ -414,7 +422,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -449,7 +459,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -480,7 +492,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -504,7 +518,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -530,7 +546,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -554,7 +572,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false)) ]) ], classes: [ @@ -579,7 +599,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -603,7 +625,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -627,7 +651,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -654,7 +680,9 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -716,7 +744,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -751,7 +781,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -786,7 +818,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -814,7 +848,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -834,7 +870,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -869,7 +907,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'Input', isNullable: false), + arguments: [ + Field(name: '', dataType: 'Input', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -904,7 +944,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -922,7 +964,9 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - argType: Field(name: '', dataType: 'void', isNullable: false), + arguments: [ + Field(name: '', dataType: 'void', isNullable: false) + ], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 371bbc671e20..d88e9fc92d09 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -93,7 +93,7 @@ abstract class Api1 { expect(root.apis[0].name, equals('Api1')); expect(root.apis[0].methods.length, equals(1)); expect(root.apis[0].methods[0].name, equals('doit')); - expect(root.apis[0].methods[0].argType.dataType, equals('Input1')); + expect(root.apis[0].methods[0].arguments[0].dataType, equals('Input1')); expect(root.apis[0].methods[0].returnType.dataType, equals('Output1')); Class? input; @@ -262,7 +262,8 @@ abstract class VoidArgApi { expect(results.root.apis[0].name, equals('VoidArgApi')); expect( results.root.apis[0].methods[0].returnType.dataType, equals('Output1')); - expect(results.root.apis[0].methods[0].argType.dataType, equals('void')); + expect( + results.root.apis[0].methods[0].arguments[0].dataType, equals('void')); }); test('mockDartClass', () { @@ -668,4 +669,26 @@ abstract class Api { expect(field.typeArguments![0].dataType, 'String'); expect(field.typeArguments![1].dataType, 'int'); }); + + test('two arguments', () { + const String code = ''' +class Input { + String? input; +} + +@HostApi() +abstract class Api { + void method(Input input1, Input input2); +} +'''; + final ParseResults results = _parseSource(code); + expect(results.errors.length, 1); + expect(results.errors[0].lineNumber, 7); + expect(results.errors[0].message, contains('Multiple arguments')); + // TODO(gaaclarke): Make this not an error, https://github.com/flutter/flutter/issues/86971. + // expect(results.root.apis.length, 1); + // expect(results.root.apis[0].methods.length, equals(1)); + // expect(results.root.apis[0].methods[0].name, equals('method')); + // expect(results.root.apis[0].methods[0].arguments.length, 2); + }); } From 9bdd2efbe1908a6b954bbe860fb1ffe45401c588 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Fri, 23 Jul 2021 17:26:01 -0700 Subject: [PATCH 16/30] removed 'void' references, took an empty list to mean void --- packages/pigeon/lib/dart_generator.dart | 11 +++---- packages/pigeon/lib/generator_tools.dart | 4 ++- packages/pigeon/lib/java_generator.dart | 18 +++++------ packages/pigeon/lib/objc_generator.dart | 16 +++++----- packages/pigeon/lib/pigeon_lib.dart | 24 +++++--------- packages/pigeon/test/dart_generator_test.dart | 12 ++----- packages/pigeon/test/java_generator_test.dart | 8 ++--- packages/pigeon/test/objc_generator_test.dart | 32 +++++-------------- packages/pigeon/test/pigeon_lib_test.dart | 3 +- 9 files changed, 47 insertions(+), 81 deletions(-) diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 4feb580ac937..f20f7c6b59f5 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -121,7 +121,7 @@ final BinaryMessenger$nullTag _binaryMessenger; } String argSignature = ''; String sendArgument = 'null'; - if (func.arguments[0].dataType != 'void') { + if (func.arguments.isNotEmpty) { argSignature = '${func.arguments[0].dataType} arg'; sendArgument = 'arg'; } @@ -184,9 +184,8 @@ void _writeFlutterApi( final String returnType = isAsync ? 'Future<${func.returnType.dataType}>' : func.returnType.dataType; - final String argSignature = func.arguments[0].dataType == 'void' - ? '' - : '${func.arguments[0].dataType} arg'; + final String argSignature = + func.arguments.isEmpty ? '' : '${func.arguments[0].dataType} arg'; indent.writeln('$returnType ${func.name}($argSignature);'); } indent.write('static void setup(${api.name}$nullTag api) '); @@ -217,7 +216,6 @@ void _writeFlutterApi( 'channel.$messageHandlerSetter((Object$nullTag message) async ', ); indent.scoped('{', '});', () { - final String argType = func.arguments[0].dataType; final String returnType = func.returnType.dataType; final bool isAsync = func.isAsynchronous; final String emptyReturnStatement = isMockHandler @@ -226,10 +224,11 @@ void _writeFlutterApi( ? 'return;' : 'return null;'; String call; - if (argType == 'void') { + if (func.arguments.isEmpty) { indent.writeln('// ignore message'); call = 'api.${func.name}()'; } else { + final String argType = func.arguments[0].dataType; indent.writeln( 'assert(message != null, \'Argument for $channelName was null. Expected $argType.\');', ); diff --git a/packages/pigeon/lib/generator_tools.dart b/packages/pigeon/lib/generator_tools.dart index a1f07cf38630..e2b391757439 100644 --- a/packages/pigeon/lib/generator_tools.dart +++ b/packages/pigeon/lib/generator_tools.dart @@ -286,7 +286,9 @@ Iterable getCodecClasses(Api api) sync* { final Set names = {}; for (final Method method in api.methods) { names.add(method.returnType.dataType); - names.add(method.arguments[0].dataType); + if (method.arguments.isNotEmpty) { + names.add(method.arguments[0].dataType); + } } final List sortedNames = names .where((String element) => diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 1a73a2bff4b6..3f9ff0eb3896 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -124,13 +124,13 @@ void _writeHostApi(Indent indent, Api api) { indent.write('public interface ${api.name} '); indent.scoped('{', '}', () { for (final Method method in api.methods) { - final String argType = - _javaTypeForDartTypePassthrough(method.arguments[0].dataType); final String returnType = method.isAsynchronous ? 'void' : _javaTypeForDartTypePassthrough(method.returnType.dataType); final List argSignature = []; - if (method.arguments[0].dataType != 'void') { + if (method.arguments.isNotEmpty) { + final String argType = + _javaTypeForDartTypePassthrough(method.arguments[0].dataType); argSignature.add('$argType arg'); } if (method.isAsynchronous) { @@ -169,15 +169,15 @@ static MessageCodec getCodec() { indent.scoped('{', '} else {', () { indent.write('channel.setMessageHandler((message, reply) -> '); indent.scoped('{', '});', () { - final String argType = - _javaTypeForDartTypePassthrough(method.arguments[0].dataType); final String returnType = _javaTypeForDartTypePassthrough(method.returnType.dataType); indent.writeln('Map wrapped = new HashMap<>();'); indent.write('try '); indent.scoped('{', '}', () { final List methodArgument = []; - if (argType != 'void') { + if (method.arguments.isNotEmpty) { + final String argType = _javaTypeForDartTypePassthrough( + method.arguments[0].dataType); indent.writeln('@SuppressWarnings("ConstantConditions")'); indent.writeln('$argType input = ($argType)message;'); indent.write('if (input == null) '); @@ -257,13 +257,13 @@ static MessageCodec getCodec() { final String returnType = func.returnType.dataType == 'void' ? 'Void' : _javaTypeForDartTypePassthrough(func.returnType.dataType); - final String argType = - _javaTypeForDartTypePassthrough(func.arguments[0].dataType); String sendArgument; - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { indent.write('public void ${func.name}(Reply<$returnType> callback) '); sendArgument = 'null'; } else { + final String argType = + _javaTypeForDartTypePassthrough(func.arguments[0].dataType); indent.write( 'public void ${func.name}($argType argInput, Reply<$returnType> callback) '); sendArgument = 'argInput'; diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index f49a067d7142..87e0994e3b66 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -243,7 +243,7 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { _objcTypeForDartType(options.prefix, func.returnType.dataType); if (func.isAsynchronous) { if (func.returnType.dataType == 'void') { - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { indent.writeln( '-(void)${func.name}:(void(^)(FlutterError *_Nullable))completion;'); } else { @@ -253,7 +253,7 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { '-(void)${func.name}:(nullable $argType *)input completion:(void(^)(FlutterError *_Nullable))completion;'); } } else { - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { indent.writeln( '-(void)${func.name}:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } else { @@ -267,7 +267,7 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { final String returnType = func.returnType.dataType == 'void' ? 'void' : 'nullable $returnTypeName *'; - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { indent.writeln( '-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;'); } else { @@ -295,7 +295,7 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) { _objcTypeForDartType(options.prefix, func.returnType.dataType); final String callbackType = _callbackForType(func.returnType.dataType, returnType); - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { indent.writeln('- (void)${func.name}:($callbackType)completion;'); } else { final String argType = @@ -418,7 +418,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { final String returnType = _objcTypeForDartType(options.prefix, func.returnType.dataType); String syncCall; - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { syncCall = '[api ${func.name}:&error]'; } else { final String argType = _objcTypeForDartType( @@ -429,7 +429,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { if (func.isAsynchronous) { if (func.returnType.dataType == 'void') { const String callback = 'callback(wrapResult(nil, error));'; - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { indent.writeScoped( '[api ${func.name}:^(FlutterError *_Nullable error) {', '}];', () { @@ -444,7 +444,7 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { } } else { const String callback = 'callback(wrapResult(output, error));'; - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { indent.writeScoped( '[api ${func.name}:^($returnType *_Nullable output, FlutterError *_Nullable error) {', '}];', () { @@ -506,7 +506,7 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { _callbackForType(func.returnType.dataType, returnType); String sendArgument; - if (func.arguments[0].dataType == 'void') { + if (func.arguments.isEmpty) { indent.write('- (void)${func.name}:($callbackType)completion '); sendArgument = 'nil'; } else { diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index c078dfd002e0..342a5659cc0a 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -423,14 +423,15 @@ List _validateAst(Root root, String source) { lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.arguments[0].isNullable) { + if (method.arguments.isNotEmpty && method.arguments[0].isNullable) { result.add(Error( message: 'Nullable argument types aren\'t supported for Pigeon methods: "${method.arguments[0].dataType}" in API: "${api.name}" method: "${method.name}"', lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.arguments[0].typeArguments != null) { + if (method.arguments.isNotEmpty && + method.arguments[0].typeArguments != null) { result.add(Error( message: 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.arguments[0].dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', @@ -488,7 +489,9 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { final Set referencedTypes = {}; for (final Api api in _apis) { for (final Method method in api.methods) { - referencedTypes.add(method.arguments[0].dataType); + if (method.arguments.isNotEmpty) { + referencedTypes.add(method.arguments[0].dataType); + } referencedTypes.add(method.returnType.dataType); } } @@ -658,19 +661,8 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { @override Object? visitMethodDeclaration(dart_ast.MethodDeclaration node) { final dart_ast.FormalParameterList parameters = node.parameters!; - late List arguments; - if (parameters.parameters.isEmpty) { - arguments = [ - Field( - dataType: 'void', - isNullable: false, - name: '', - typeArguments: null, - ) - ]; - } else { - arguments = parameters.parameters.map(formalParameterToField).toList(); - } + final List arguments = + parameters.parameters.map(formalParameterToField).toList(); final bool isAsynchronous = _hasMetadata(node.metadata, 'async'); if (_currentApi != null) { _currentApi!.methods.add(Method( diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 5e5b3d5f3adf..805d6c719e16 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -226,9 +226,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', isNullable: false, dataType: 'void') - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -332,9 +330,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', isNullable: false, dataType: 'void') - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -551,9 +547,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', isNullable: false, dataType: 'void') - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true, ) diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index c41943d05696..9b9803285636 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -222,9 +222,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) @@ -247,9 +245,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: false, ) diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 8b129ad3a6dd..9ef5f9e9b4e5 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -599,9 +599,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -625,9 +623,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -651,9 +647,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -680,9 +674,7 @@ void main() { Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false)) ]) ], classes: [ @@ -818,9 +810,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) @@ -848,9 +838,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -944,9 +932,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'void', isNullable: false), isAsynchronous: true) ]) @@ -964,9 +950,7 @@ void main() { Api(name: 'Api', location: ApiLocation.host, methods: [ Method( name: 'doSomething', - arguments: [ - Field(name: '', dataType: 'void', isNullable: false) - ], + arguments: [], returnType: Field(name: '', dataType: 'Output', isNullable: false), isAsynchronous: true) ]) diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index d88e9fc92d09..f783f79fd692 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -262,8 +262,7 @@ abstract class VoidArgApi { expect(results.root.apis[0].name, equals('VoidArgApi')); expect( results.root.apis[0].methods[0].returnType.dataType, equals('Output1')); - expect( - results.root.apis[0].methods[0].arguments[0].dataType, equals('void')); + expect(results.root.apis[0].methods[0].arguments.isEmpty, isTrue); }); test('mockDartClass', () { From f6dd824ef37983e72762fd0cf670a72378aa4aa4 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 3 Aug 2021 09:38:30 -0700 Subject: [PATCH 17/30] added syntactic entity import --- packages/pigeon/lib/pigeon_lib.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 342a5659cc0a..25413423a983 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -13,7 +13,8 @@ import 'package:analyzer/dart/analysis/analysis_context_collection.dart' import 'package:analyzer/dart/analysis/results.dart' show ParsedUnitResult; import 'package:analyzer/dart/analysis/session.dart' show AnalysisSession; import 'package:analyzer/dart/ast/ast.dart' as dart_ast; -import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit; +import 'package:analyzer/dart/ast/syntactic_entity.dart' + as dart_ast_syntactic_entity; import 'package:analyzer/dart/ast/visitor.dart' as dart_ast_visitor; import 'package:analyzer/error/error.dart' show AnalysisError; import 'package:args/args.dart'; @@ -643,9 +644,9 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { } Field formalParameterToField(dart_ast.FormalParameter parameter) { - final dart_ast.TypeName typeName = parameter.childEntities - // ignore: always_specify_types - .firstWhere((e) => e is dart_ast.TypeName) as dart_ast.TypeName; + final dart_ast.TypeName typeName = parameter.childEntities.firstWhere( + (dart_ast_syntactic_entity.SyntacticEntity e) => + e is dart_ast.TypeName) as dart_ast.TypeName; final String argType = typeName.name.name; final bool isNullable = typeName.question != null; final List? argTypeArguments = @@ -805,7 +806,7 @@ class Pigeon { final ParsedUnitResult result = session.getParsedUnit2(path) as ParsedUnitResult; if (result.errors.isEmpty) { - final CompilationUnit unit = result.unit; + final dart_ast.CompilationUnit unit = result.unit; unit.accept(rootBuilder); } else { for (final AnalysisError error in result.errors) { From ad972ac4c0f01f4dd36bfe3755258a1d3c820b0f Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Mon, 26 Jul 2021 10:28:29 -0700 Subject: [PATCH 18/30] [pigeon] implemented generics support in primitives (dart support) --- packages/pigeon/lib/dart_generator.dart | 25 +++++---- packages/pigeon/lib/pigeon_lib.dart | 8 --- packages/pigeon/test/dart_generator_test.dart | 54 +++++++++++++++++++ packages/pigeon/test/java_generator_test.dart | 28 ++++++++++ packages/pigeon/test/pigeon_lib_test.dart | 16 +++--- 5 files changed, 104 insertions(+), 27 deletions(-) diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index f20f7c6b59f5..da9503bce770 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -122,7 +122,7 @@ final BinaryMessenger$nullTag _binaryMessenger; String argSignature = ''; String sendArgument = 'null'; if (func.arguments.isNotEmpty) { - argSignature = '${func.arguments[0].dataType} arg'; + argSignature = '${_addGenericTypes(func.arguments[0], nullTag)} arg'; sendArgument = 'arg'; } indent.write( @@ -184,8 +184,9 @@ void _writeFlutterApi( final String returnType = isAsync ? 'Future<${func.returnType.dataType}>' : func.returnType.dataType; - final String argSignature = - func.arguments.isEmpty ? '' : '${func.arguments[0].dataType} arg'; + final String argSignature = func.arguments.isEmpty + ? '' + : '${_addGenericTypes(func.arguments[0], nullTag)} arg'; indent.writeln('$returnType ${func.name}($argSignature);'); } indent.write('static void setup(${api.name}$nullTag api) '); @@ -280,17 +281,21 @@ String _addGenericTypes(Field field, String nullTag) { switch (field.dataType) { case 'List': return (field.typeArguments == null) - ? 'List$nullTag' - : 'List<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; + ? 'List' + : 'List<${_flattenTypeArguments(field.typeArguments!, nullTag)}>'; case 'Map': return (field.typeArguments == null) - ? 'Map$nullTag' - : 'Map<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; + ? 'Map' + : 'Map<${_flattenTypeArguments(field.typeArguments!, nullTag)}>'; default: - return '${field.dataType}$nullTag'; + return field.dataType; } } +String _addGenericTypesNullable(Field field, String nullTag) { + return '${_addGenericTypes(field, nullTag)}$nullTag'; +} + /// Generates Dart source code for the given AST represented by [root], /// outputting the code to [sink]. void generateDart(DartOptions opt, Root root, StringSink sink) { @@ -332,7 +337,7 @@ void generateDart(DartOptions opt, Root root, StringSink sink) { indent.write('class ${klass.name} '); indent.scoped('{', '}', () { for (final Field field in klass.fields) { - final String datatype = _addGenericTypes(field, nullTag); + final String datatype = _addGenericTypesNullable(field, nullTag); indent.writeln('$datatype ${field.name};'); } if (klass.fields.isNotEmpty) { @@ -388,7 +393,7 @@ pigeonMap['${field.name}'] != null ); } else { indent.add( - 'pigeonMap[\'${field.name}\'] as ${_addGenericTypes(field, nullTag)}', + 'pigeonMap[\'${field.name}\'] as ${_addGenericTypesNullable(field, nullTag)}', ); } indent.addln(index == klass.fields.length - 1 ? ';' : ''); diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 25413423a983..b1f3c1229323 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -431,14 +431,6 @@ List _validateAst(Root root, String source) { lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.arguments.isNotEmpty && - method.arguments[0].typeArguments != null) { - result.add(Error( - message: - 'Generic type arguments for primitive arguments aren\'t yet supported: "${method.arguments[0].dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', - lineNumber: _calculateLineNumberNullable(source, method.offset), - )); - } } } diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 805d6c719e16..590e1ae48b16 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -636,4 +636,58 @@ void main() { expect(code, contains('class Foobar')); expect(code, contains(' Map? field1;')); }); + + test('host generics argument', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.host, methods: [ + Method( + name: 'doit', + returnType: Field(dataType: 'void', isNullable: false, name: ''), + arguments: [ + Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]) + ]) + ]) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + generateDart(const DartOptions(isNullSafe: true), root, sink); + final String code = sink.toString(); + expect(code, contains('doit(List arg')); + }); + + test('flutter generics argument', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.flutter, methods: [ + Method( + name: 'doit', + returnType: Field(dataType: 'void', isNullable: false, name: ''), + arguments: [ + Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]) + ]) + ]) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + generateDart(const DartOptions(isNullSafe: true), root, sink); + final String code = sink.toString(); + expect(code, contains('doit(List arg')); + }); } diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index 9b9803285636..da1e5c77597a 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -472,4 +472,32 @@ void main() { expect(code, contains('class Foobar')); expect(code, contains('List field1;')); }); + + // test('generics argument', () { + // final Root root = Root( + // apis: [ + // Api(name: 'Api', location: ApiLocation.host, methods: [ + // Method( + // name: 'doit', + // returnType: Field(dataType: 'void', isNullable: false, name: ''), + // arguments: [ + // Field( + // name: 'arg', + // dataType: 'List', + // isNullable: false, + // typeArguments: [ + // TypeArgument(dataType: 'int', isNullable: true) + // ]) + // ]) + // ]) + // ], + // classes: [], + // enums: [], + // ); + // final StringBuffer sink = StringBuffer(); + // const JavaOptions javaOptions = JavaOptions(className: 'Messages'); + // generateJava(javaOptions, root, sink); + // final String code = sink.toString(); + // expect(code, contains('doit(List arg')); + // }); } diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index f783f79fd692..fe8043d59e34 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -640,15 +640,13 @@ abstract class Api { } '''; final ParseResults parseResult = _parseSource(code); - expect(parseResult.errors.length, equals(1)); - // TODO(gaaclarke): Make this not an error, https://github.com/flutter/flutter/issues/86963. - // expect( - // parseResult.root.apis[0].methods[0].argType.typeArguments![0].dataType, - // 'double'); - // expect( - // parseResult - // .root.apis[0].methods[0].argType.typeArguments![0].isNullable, - // isTrue); + expect( + parseResult.root.apis[0].methods[0].arguments[0].typeArguments![0].dataType, + 'double'); + expect( + parseResult + .root.apis[0].methods[0].arguments[0].typeArguments![0].isNullable, + isTrue); }); test('map generics', () { From 27e1518a8d5b68f6a9db763db1b9ce0ea73b2897 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Mon, 26 Jul 2021 10:52:15 -0700 Subject: [PATCH 19/30] java support --- packages/pigeon/lib/java_generator.dart | 35 ++++---- packages/pigeon/pigeons/primitive.dart | 2 + .../android_unit_tests/PrimitiveTest.java | 8 +- packages/pigeon/test/dart_generator_test.dart | 4 +- packages/pigeon/test/java_generator_test.dart | 84 ++++++++++++------- 5 files changed, 79 insertions(+), 54 deletions(-) diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index 3f9ff0eb3896..e222401f210d 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -100,22 +100,6 @@ 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 map = { - '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); @@ -129,8 +113,7 @@ void _writeHostApi(Indent indent, Api api) { : _javaTypeForDartTypePassthrough(method.returnType.dataType); final List argSignature = []; if (method.arguments.isNotEmpty) { - final String argType = - _javaTypeForDartTypePassthrough(method.arguments[0].dataType); + final String argType = _javaTypeForDartType(method.arguments[0]) ?? method.arguments[0].dataType; argSignature.add('$argType arg'); } if (method.isAsynchronous) { @@ -262,8 +245,7 @@ static MessageCodec getCodec() { indent.write('public void ${func.name}(Reply<$returnType> callback) '); sendArgument = 'null'; } else { - final String argType = - _javaTypeForDartTypePassthrough(func.arguments[0].dataType); + final String argType = _javaTypeForDartType(func.arguments[0]) ?? func.arguments[0].dataType; indent.write( 'public void ${func.name}($argType argInput, Reply<$returnType> callback) '); sendArgument = 'argInput'; @@ -313,6 +295,19 @@ String _flattenTypeArguments(List args) { .reduce((String value, String element) => '$value, $element'); } +String _javaTypeForDartTypePassthrough(String type) { + const Map map = { + 'int': 'Long', + 'bool': 'Boolean', + 'double': 'Double', + 'Int32List': 'int[]', + 'Uint8List': 'byte[]', + 'Int64List': 'long[]', + 'Float64List': 'double[]', + }; + return map[type] ?? type; +} + String? _javaTypeForDartType(Field field) { const Map javaTypeForDartTypeMap = { 'bool': 'Boolean', diff --git a/packages/pigeon/pigeons/primitive.dart b/packages/pigeon/pigeons/primitive.dart index 2b453532b084..0a3dfcd9f942 100644 --- a/packages/pigeon/pigeons/primitive.dart +++ b/packages/pigeon/pigeons/primitive.dart @@ -15,6 +15,7 @@ abstract class PrimitiveHostApi { // ignore: always_specify_types List aList(List value); Int32List anInt32List(Int32List value); + void aBoolList(List value); } @FlutterApi() @@ -28,4 +29,5 @@ abstract class PrimitiveFlutterApi { // ignore: always_specify_types List aList(List value); Int32List anInt32List(Int32List value); + void aBoolList(List value); } 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 index 36ce51cd35a0..f64db1f14006 100644 --- 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 @@ -36,11 +36,11 @@ public void primitiveInt() { BinaryMessenger binaryMessenger = makeMockBinaryMessenger(); PrimitiveFlutterApi api = new PrimitiveFlutterApi(binaryMessenger); boolean[] didCall = {false}; - api.anInt( - 1, - (Integer result) -> { + api.inc( + 1L, + (Long result) -> { didCall[0] = true; - assertEquals(result, (Integer) 1); + assertEquals(result, (Long) 1L); }); assertTrue(didCall[0]); } diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 590e1ae48b16..fc3458bbee99 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -663,7 +663,7 @@ void main() { final String code = sink.toString(); expect(code, contains('doit(List arg')); }); - + test('flutter generics argument', () { final Root root = Root( apis: [ @@ -689,5 +689,5 @@ void main() { generateDart(const DartOptions(isNullSafe: true), root, sink); final String code = sink.toString(); expect(code, contains('doit(List arg')); - }); + }); } diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index da1e5c77597a..b2e3ab3af7d0 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -470,34 +470,62 @@ void main() { generateJava(javaOptions, root, sink); final String code = sink.toString(); expect(code, contains('class Foobar')); - expect(code, contains('List field1;')); + expect(code, contains('List field1;')); }); - // test('generics argument', () { - // final Root root = Root( - // apis: [ - // Api(name: 'Api', location: ApiLocation.host, methods: [ - // Method( - // name: 'doit', - // returnType: Field(dataType: 'void', isNullable: false, name: ''), - // arguments: [ - // Field( - // name: 'arg', - // dataType: 'List', - // isNullable: false, - // typeArguments: [ - // TypeArgument(dataType: 'int', isNullable: true) - // ]) - // ]) - // ]) - // ], - // classes: [], - // enums: [], - // ); - // final StringBuffer sink = StringBuffer(); - // const JavaOptions javaOptions = JavaOptions(className: 'Messages'); - // generateJava(javaOptions, root, sink); - // final String code = sink.toString(); - // expect(code, contains('doit(List arg')); - // }); + test('host generics argument', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.host, methods: [ + Method( + name: 'doit', + returnType: Field(dataType: 'void', isNullable: false, name: ''), + arguments: [ + Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]) + ]) + ]) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const JavaOptions javaOptions = JavaOptions(className: 'Messages'); + generateJava(javaOptions, root, sink); + final String code = sink.toString(); + expect(code, contains('doit(List arg')); + }); + + test('flutter generics argument', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.flutter, methods: [ + Method( + name: 'doit', + returnType: Field(dataType: 'void', isNullable: false, name: ''), + arguments: [ + Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]) + ]) + ]) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const JavaOptions javaOptions = JavaOptions(className: 'Messages'); + generateJava(javaOptions, root, sink); + final String code = sink.toString(); + expect(code, contains('doit(List arg')); + }); } From 96a9ec2c0c7b1b6a942906fb6bb33041a56940e2 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Mon, 26 Jul 2021 11:43:29 -0700 Subject: [PATCH 20/30] implemented objc --- packages/pigeon/lib/ast.dart | 20 ++- packages/pigeon/lib/objc_generator.dart | 86 +++++----- packages/pigeon/test/objc_generator_test.dart | 147 +++++++++++++++++- 3 files changed, 204 insertions(+), 49 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index dd74c00c456d..c590febbf04f 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -74,8 +74,18 @@ class Api extends Node { } } +/// An entity that represents a typed concept, like a [TypeArgument] or [Field]. +abstract class TypedEntity { + /// The data-type of the entity (ex 'String' or 'int'). + String get dataType; + /// The type arguments to the entity. + List? get typeArguments; + /// True if the type is nullable. + bool get isNullable; +} + /// A parameter to a generic entity. For example, "String" to "List". -class TypeArgument { +class TypeArgument implements TypedEntity { /// Constructor for [TypeArgument]. TypeArgument({ required this.dataType, @@ -84,12 +94,15 @@ class TypeArgument { }); /// A string representation of the base datatype. + @override final String dataType; /// The type arguments to this [TypeArgument]. + @override final List? typeArguments; /// True if the type is nullable. + @override final bool isNullable; @override @@ -99,7 +112,7 @@ class TypeArgument { } /// Represents a field on a [Class]. -class Field extends Node { +class Field extends Node implements TypedEntity { /// Parametric constructor for [Field]. Field({ required this.name, @@ -113,15 +126,18 @@ class Field extends Node { String name; /// The data-type of the field (ex 'String' or 'int'). + @override String dataType; /// The offset in the source file where the field appears. int? offset; /// True if the datatype is nullable (ex `int?`). + @override bool isNullable; /// Type parameters used for generics. + @override List? typeArguments; @override diff --git a/packages/pigeon/lib/objc_generator.dart b/packages/pigeon/lib/objc_generator.dart index 87e0994e3b66..d147be3b1fe9 100644 --- a/packages/pigeon/lib/objc_generator.dart +++ b/packages/pigeon/lib/objc_generator.dart @@ -79,49 +79,45 @@ const Map _objcTypeForDartTypeMap = { 'Map': 'NSDictionary', }; -const Map _propertyTypeForDartTypeMap = { - 'String': 'copy', - 'bool': 'strong', - 'int': 'strong', - 'double': 'strong', - 'Uint8List': 'strong', - 'Int32List': 'strong', - 'Int64List': 'strong', - 'Float64List': 'strong', - 'List': 'strong', - 'Map': 'strong', -}; - -/// Converts a [List] of [TypeArgument]s to a comma separated [String] to be -/// used in objc code. String _flattenTypeArguments(String? classPrefix, List args) { - return args - .map((TypeArgument e) => e.typeArguments == null - ? '${_objcTypeForDartType(classPrefix, e.dataType)} *' - : '${_objcTypeForDartType(classPrefix, e.dataType)}<${_flattenTypeArguments(classPrefix, e.typeArguments!)}> *') + final String result = args + .map((TypeArgument e) => '${_objcTypeForDartType(classPrefix, e)} *') .reduce((String value, String element) => '$value, $element'); + return result; } String? _objcTypePtrForPrimitiveDartType(String? classPrefix, Field field) { return _objcTypeForDartTypeMap.containsKey(field.dataType) - ? field.typeArguments == null - ? '${_objcTypeForDartTypeMap[field.dataType]} *' - : '${_objcTypeForDartTypeMap[field.dataType]}<${_flattenTypeArguments(classPrefix, field.typeArguments!)}> *' + ? '${_objcTypeForDartType(classPrefix, field)} *' : 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 _objcTypeForDartType( + String? classPrefix, T field) { + return _objcTypeForDartTypeMap.containsKey(field.dataType) + ? field.typeArguments == null + ? _objcTypeForDartTypeMap[field.dataType]! + : '${_objcTypeForDartTypeMap[field.dataType]}<${_flattenTypeArguments(classPrefix, field.typeArguments!)}>' + : _className(classPrefix, field.dataType); } -String _propertyTypeForDartType(String type) { - final String? result = _propertyTypeForDartTypeMap[type]; +String _propertyTypeForDartType(Field field) { + const Map propertyTypeForDartTypeMap = { + 'String': 'copy', + 'bool': 'strong', + 'int': 'strong', + 'double': 'strong', + 'Uint8List': 'strong', + 'Int32List': 'strong', + 'Int64List': 'strong', + 'Float64List': 'strong', + 'List': 'strong', + 'Map': 'strong', + }; + + final String? result = propertyTypeForDartTypeMap[field.dataType]; if (result == null) { - return 'assign'; + return 'strong'; } else { return result; } @@ -139,12 +135,10 @@ void _writeClassDeclarations( ? (String x) => _className(prefix, x) : (String x) => '${_className(prefix, x)} *'); late final String propertyType; - if (hostDatatype.isBuiltin) { - propertyType = _propertyTypeForDartType(field.dataType); - } else if (enumNames.contains(field.dataType)) { + if (enumNames.contains(field.dataType)) { propertyType = 'assign'; } else { - propertyType = 'strong'; + propertyType = _propertyTypeForDartType(field); } final String nullability = hostDatatype.datatype.contains('*') ? ', nullable' : ''; @@ -240,7 +234,7 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { indent.writeln('@protocol $apiName'); for (final Method func in api.methods) { final String returnTypeName = - _objcTypeForDartType(options.prefix, func.returnType.dataType); + _objcTypeForDartType(options.prefix, func.returnType); if (func.isAsynchronous) { if (func.returnType.dataType == 'void') { if (func.arguments.isEmpty) { @@ -248,7 +242,7 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { '-(void)${func.name}:(void(^)(FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.arguments[0].dataType); + _objcTypeForDartType(options.prefix, func.arguments[0]); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)(FlutterError *_Nullable))completion;'); } @@ -258,7 +252,7 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { '-(void)${func.name}:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.arguments[0].dataType); + _objcTypeForDartType(options.prefix, func.arguments[0]); indent.writeln( '-(void)${func.name}:(nullable $argType *)input completion:(void(^)($returnTypeName *_Nullable, FlutterError *_Nullable))completion;'); } @@ -272,7 +266,7 @@ void _writeHostApiDeclaration(Indent indent, Api api, ObjcOptions options) { '-($returnType)${func.name}:(FlutterError *_Nullable *_Nonnull)error;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.arguments[0].dataType); + _objcTypeForDartType(options.prefix, func.arguments[0]); indent.writeln( '-($returnType)${func.name}:($argType*)input error:(FlutterError *_Nullable *_Nonnull)error;'); } @@ -292,14 +286,14 @@ void _writeFlutterApiDeclaration(Indent indent, Api api, ObjcOptions options) { '- (instancetype)initWithBinaryMessenger:(id)binaryMessenger;'); for (final Method func in api.methods) { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType.dataType); + _objcTypeForDartType(options.prefix, func.returnType); final String callbackType = _callbackForType(func.returnType.dataType, returnType); if (func.arguments.isEmpty) { indent.writeln('- (void)${func.name}:($callbackType)completion;'); } else { final String argType = - _objcTypeForDartType(options.prefix, func.arguments[0].dataType); + _objcTypeForDartType(options.prefix, func.arguments[0]); indent.writeln( '- (void)${func.name}:($argType*)input completion:($callbackType)completion;'); } @@ -416,13 +410,13 @@ void _writeHostApiSource(Indent indent, ObjcOptions options, Api api) { '[channel setMessageHandler:^(id _Nullable message, FlutterReply callback) '); indent.scoped('{', '}];', () { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType.dataType); + _objcTypeForDartType(options.prefix, func.returnType); String syncCall; if (func.arguments.isEmpty) { syncCall = '[api ${func.name}:&error]'; } else { - final String argType = _objcTypeForDartType( - options.prefix, func.arguments[0].dataType); + final String argType = + _objcTypeForDartType(options.prefix, func.arguments[0]); indent.writeln('$argType *input = message;'); syncCall = '[api ${func.name}:input error:&error]'; } @@ -501,7 +495,7 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { indent.addln(''); for (final Method func in api.methods) { final String returnType = - _objcTypeForDartType(options.prefix, func.returnType.dataType); + _objcTypeForDartType(options.prefix, func.returnType); final String callbackType = _callbackForType(func.returnType.dataType, returnType); @@ -511,7 +505,7 @@ void _writeFlutterApiSource(Indent indent, ObjcOptions options, Api api) { sendArgument = 'nil'; } else { final String argType = - _objcTypeForDartType(options.prefix, func.arguments[0].dataType); + _objcTypeForDartType(options.prefix, func.arguments[0]); indent.write( '- (void)${func.name}:($argType*)input completion:($callbackType)completion '); sendArgument = 'input'; diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 9ef5f9e9b4e5..8bb56c076ace 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -115,6 +115,42 @@ void main() { expect(code, contains('result.enum1 = [dict[@"enum1"] integerValue];')); }); + test('gen one class header with enum', () { + final Root root = Root( + apis: [], + classes: [ + Class( + name: 'Foobar', + fields: [ + Field( + name: 'field1', + dataType: 'String', + isNullable: true, + ), + Field( + name: 'enum1', + dataType: 'Enum1', + isNullable: true, + ), + ], + ), + ], + enums: [ + Enum( + name: 'Enum1', + members: [ + 'one', + 'two', + ], + ) + ], + ); + final StringBuffer sink = StringBuffer(); + generateObjcHeader(const ObjcOptions(header: 'foo.h'), root, sink); + final String code = sink.toString(); + expect(code, contains('@property(nonatomic, assign) Enum1 enum1')); + }); + test('gen one api header', () { final Root root = Root(apis: [ Api(name: 'Api', location: ApiLocation.host, methods: [ @@ -1007,7 +1043,7 @@ void main() { expect(code, startsWith('// hello world')); }); - test('generics', () { + test('field generics', () { final Class klass = Class( name: 'Foobar', fields: [ @@ -1032,4 +1068,113 @@ void main() { final String code = sink.toString(); expect(code, contains('NSArray * field1')); }); + + test('host generics argument', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.host, methods: [ + Method( + name: 'doit', + returnType: Field(dataType: 'void', isNullable: false, name: ''), + arguments: [ + Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]) + ]) + ]) + ], + classes: [], + enums: [], + ); + { + final StringBuffer sink = StringBuffer(); + generateObjcHeader( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('doit:(NSArray*)input')); + } + { + final StringBuffer sink = StringBuffer(); + generateObjcSource( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('NSArray *input = message')); + } + }); + + test('flutter generics argument', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.flutter, methods: [ + Method( + name: 'doit', + returnType: Field(dataType: 'void', isNullable: false, name: ''), + arguments: [ + Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]) + ]) + ]) + ], + classes: [], + enums: [], + ); + { + final StringBuffer sink = StringBuffer(); + generateObjcHeader( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('doit:(NSArray*)input')); + } + { + final StringBuffer sink = StringBuffer(); + generateObjcSource( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('doit:(NSArray*)input')); + } + }); + + test('host nested generic argument', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.host, methods: [ + Method( + name: 'doit', + returnType: Field(dataType: 'void', isNullable: false, name: ''), + arguments: [ + Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument( + dataType: 'List', + isNullable: true, + typeArguments: [ + TypeArgument(dataType: 'bool', isNullable: true) + ]), + ]) + ]) + ]) + ], + classes: [], + enums: [], + ); + { + final StringBuffer sink = StringBuffer(); + generateObjcHeader( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('doit:(NSArray *>*)input')); + } + }); } From 4adeb46fc3f4f1d1b59eaee59a61e6703593723a Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Mon, 26 Jul 2021 16:47:50 -0700 Subject: [PATCH 21/30] dart support for return types --- packages/pigeon/lib/dart_generator.dart | 6 +-- packages/pigeon/lib/pigeon_lib.dart | 7 --- packages/pigeon/test/dart_generator_test.dart | 50 +++++++++++++++++++ packages/pigeon/test/pigeon_lib_test.dart | 21 ++++---- 4 files changed, 63 insertions(+), 21 deletions(-) diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index da9503bce770..3a7fe353370d 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -126,7 +126,7 @@ final BinaryMessenger$nullTag _binaryMessenger; sendArgument = 'arg'; } indent.write( - 'Future<${func.returnType.dataType}> ${func.name}($argSignature) async ', + 'Future<${_addGenericTypes(func.returnType, nullTag)}> ${func.name}($argSignature) async ', ); indent.scoped('{', '}', () { final String channelName = makeChannelName(api, func); @@ -182,8 +182,8 @@ void _writeFlutterApi( for (final Method func in api.methods) { final bool isAsync = func.isAsynchronous; final String returnType = isAsync - ? 'Future<${func.returnType.dataType}>' - : func.returnType.dataType; + ? 'Future<${_addGenericTypes(func.returnType, nullTag)}>' + : _addGenericTypes(func.returnType, nullTag); final String argSignature = func.arguments.isEmpty ? '' : '${_addGenericTypes(func.arguments[0], nullTag)} arg'; diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index b1f3c1229323..4547e5d343e2 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -410,13 +410,6 @@ List _validateAst(Root root, String source) { lineNumber: _calculateLineNumberNullable(source, method.offset), )); } - if (method.returnType.typeArguments != null) { - result.add(Error( - message: - 'Generic type arguments for primitive return values aren\'t yet supported: "${method.returnType.dataType}" in API: "${api.name}" method: "${method.name} (https://github.com/flutter/flutter/issues/86963)"', - lineNumber: _calculateLineNumberNullable(source, method.offset), - )); - } if (method.arguments.length > 1) { result.add(Error( message: diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index fc3458bbee99..542207f09209 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -690,4 +690,54 @@ void main() { final String code = sink.toString(); expect(code, contains('doit(List arg')); }); + + test('host generics return', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.host, methods: [ + Method( + name: 'doit', + returnType: Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]), + arguments: []) + ]) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + generateDart(const DartOptions(isNullSafe: true), root, sink); + final String code = sink.toString(); + expect(code, contains('Future> doit(')); + }); + + test('host generics return', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.flutter, methods: [ + Method( + name: 'doit', + returnType: Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]), + arguments: []) + ]) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + generateDart(const DartOptions(isNullSafe: true), root, sink); + final String code = sink.toString(); + expect(code, contains('List doit(')); + }); } diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index fe8043d59e34..8a0908923aeb 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -620,16 +620,14 @@ abstract class Api { } '''; final ParseResults parseResult = _parseSource(code); - expect(parseResult.errors.length, equals(1)); - // TODO(gaaclarke): Make this not an error, https://github.com/flutter/flutter/issues/86963. - // expect( - // parseResult - // .root.apis[0].methods[0].returnType.typeArguments![0].dataType, - // 'double'); - // expect( - // parseResult - // .root.apis[0].methods[0].returnType.typeArguments![0].isNullable, - // isTrue); + expect( + parseResult + .root.apis[0].methods[0].returnType.typeArguments![0].dataType, + 'double'); + expect( + parseResult + .root.apis[0].methods[0].returnType.typeArguments![0].isNullable, + isTrue); }); test('argument generics', () { @@ -641,7 +639,8 @@ abstract class Api { '''; final ParseResults parseResult = _parseSource(code); expect( - parseResult.root.apis[0].methods[0].arguments[0].typeArguments![0].dataType, + parseResult + .root.apis[0].methods[0].arguments[0].typeArguments![0].dataType, 'double'); expect( parseResult From 30002a8b973f5196aebfc51a05650fa2e26bc741 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Mon, 26 Jul 2021 17:09:09 -0700 Subject: [PATCH 22/30] implemented java return values --- packages/pigeon/lib/java_generator.dart | 41 ++++++-------- packages/pigeon/test/dart_generator_test.dart | 26 ++++----- packages/pigeon/test/java_generator_test.dart | 54 +++++++++++++++++++ 3 files changed, 83 insertions(+), 38 deletions(-) diff --git a/packages/pigeon/lib/java_generator.dart b/packages/pigeon/lib/java_generator.dart index e222401f210d..88bffad05e01 100644 --- a/packages/pigeon/lib/java_generator.dart +++ b/packages/pigeon/lib/java_generator.dart @@ -110,16 +110,19 @@ void _writeHostApi(Indent indent, Api api) { for (final Method method in api.methods) { final String returnType = method.isAsynchronous ? 'void' - : _javaTypeForDartTypePassthrough(method.returnType.dataType); + : _javaTypeForDartType(method.returnType) ?? + method.returnType.dataType; final List argSignature = []; if (method.arguments.isNotEmpty) { - final String argType = _javaTypeForDartType(method.arguments[0]) ?? method.arguments[0].dataType; + final String argType = _javaTypeForDartType(method.arguments[0]) ?? + method.arguments[0].dataType; argSignature.add('$argType arg'); } if (method.isAsynchronous) { final String returnType = method.returnType.dataType == 'void' ? 'Void' - : method.returnType.dataType; + : _javaTypeForDartType(method.returnType) ?? + method.returnType.dataType; argSignature.add('Result<$returnType> result'); } indent.writeln('$returnType ${method.name}(${argSignature.join(', ')});'); @@ -153,14 +156,16 @@ static MessageCodec getCodec() { indent.write('channel.setMessageHandler((message, reply) -> '); indent.scoped('{', '});', () { final String returnType = - _javaTypeForDartTypePassthrough(method.returnType.dataType); + _javaTypeForDartType(method.returnType) ?? + method.returnType.dataType; indent.writeln('Map wrapped = new HashMap<>();'); indent.write('try '); indent.scoped('{', '}', () { final List methodArgument = []; if (method.arguments.isNotEmpty) { - final String argType = _javaTypeForDartTypePassthrough( - method.arguments[0].dataType); + final String argType = + _javaTypeForDartType(method.arguments[0]) ?? + method.arguments[0].dataType; indent.writeln('@SuppressWarnings("ConstantConditions")'); indent.writeln('$argType input = ($argType)message;'); indent.write('if (input == null) '); @@ -239,13 +244,14 @@ static MessageCodec getCodec() { final String channelName = makeChannelName(api, func); final String returnType = func.returnType.dataType == 'void' ? 'Void' - : _javaTypeForDartTypePassthrough(func.returnType.dataType); + : _javaTypeForDartType(func.returnType) ?? func.returnType.dataType; String sendArgument; if (func.arguments.isEmpty) { indent.write('public void ${func.name}(Reply<$returnType> callback) '); sendArgument = 'null'; } else { - final String argType = _javaTypeForDartType(func.arguments[0]) ?? func.arguments[0].dataType; + final String argType = _javaTypeForDartType(func.arguments[0]) ?? + func.arguments[0].dataType; indent.write( 'public void ${func.name}($argType argInput, Reply<$returnType> callback) '); sendArgument = 'argInput'; @@ -289,26 +295,11 @@ String _makeSetter(Field field) { /// used in Java code. String _flattenTypeArguments(List args) { return args - .map((TypeArgument e) => e.typeArguments == null - ? _javaTypeForDartTypePassthrough(e.dataType) - : '${_javaTypeForDartTypePassthrough(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') + .map((TypeArgument e) => _javaTypeForDartType(e) ?? e.dataType) .reduce((String value, String element) => '$value, $element'); } -String _javaTypeForDartTypePassthrough(String type) { - const Map map = { - 'int': 'Long', - 'bool': 'Boolean', - 'double': 'Double', - 'Int32List': 'int[]', - 'Uint8List': 'byte[]', - 'Int64List': 'long[]', - 'Float64List': 'double[]', - }; - return map[type] ?? type; -} - -String? _javaTypeForDartType(Field field) { +String? _javaTypeForDartType(TypedEntity field) { const Map javaTypeForDartTypeMap = { 'bool': 'Boolean', 'int': 'Long', diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index 542207f09209..a547f1b0d539 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -698,12 +698,12 @@ void main() { Method( name: 'doit', returnType: Field( - name: 'arg', - dataType: 'List', - isNullable: false, - typeArguments: [ - TypeArgument(dataType: 'int', isNullable: true) - ]), + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]), arguments: []) ]) ], @@ -716,19 +716,19 @@ void main() { expect(code, contains('Future> doit(')); }); - test('host generics return', () { + test('host generics return', () { final Root root = Root( apis: [ Api(name: 'Api', location: ApiLocation.flutter, methods: [ Method( name: 'doit', returnType: Field( - name: 'arg', - dataType: 'List', - isNullable: false, - typeArguments: [ - TypeArgument(dataType: 'int', isNullable: true) - ]), + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]), arguments: []) ]) ], diff --git a/packages/pigeon/test/java_generator_test.dart b/packages/pigeon/test/java_generator_test.dart index b2e3ab3af7d0..d2048cf4e23f 100644 --- a/packages/pigeon/test/java_generator_test.dart +++ b/packages/pigeon/test/java_generator_test.dart @@ -528,4 +528,58 @@ void main() { final String code = sink.toString(); expect(code, contains('doit(List arg')); }); + + test('host generics return', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.host, methods: [ + Method( + name: 'doit', + returnType: Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]), + arguments: []) + ]) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const JavaOptions javaOptions = JavaOptions(className: 'Messages'); + generateJava(javaOptions, root, sink); + final String code = sink.toString(); + expect(code, contains('List doit(')); + expect(code, contains('List output =')); + }); + + test('flutter generics return', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.flutter, methods: [ + Method( + name: 'doit', + returnType: Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]), + arguments: []) + ]) + ], + classes: [], + enums: [], + ); + final StringBuffer sink = StringBuffer(); + const JavaOptions javaOptions = JavaOptions(className: 'Messages'); + generateJava(javaOptions, root, sink); + final String code = sink.toString(); + expect(code, contains('doit(Reply> callback)')); + expect(code, contains('List output =')); + }); } From 071633761c57f27e3e574f3e010f31392640de35 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 27 Jul 2021 11:17:45 -0700 Subject: [PATCH 23/30] implemented objc return types --- packages/pigeon/test/objc_generator_test.dart | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/packages/pigeon/test/objc_generator_test.dart b/packages/pigeon/test/objc_generator_test.dart index 8bb56c076ace..9bca1ab9f988 100644 --- a/packages/pigeon/test/objc_generator_test.dart +++ b/packages/pigeon/test/objc_generator_test.dart @@ -1177,4 +1177,74 @@ void main() { expect(code, contains('doit:(NSArray *>*)input')); } }); + + test('host generics return', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.host, methods: [ + Method( + name: 'doit', + returnType: Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]), + arguments: []) + ]) + ], + classes: [], + enums: [], + ); + { + final StringBuffer sink = StringBuffer(); + generateObjcHeader( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('-(nullable NSArray *)doit:')); + } + { + final StringBuffer sink = StringBuffer(); + generateObjcSource( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('NSArray *output =')); + } + }); + + test('host generics return', () { + final Root root = Root( + apis: [ + Api(name: 'Api', location: ApiLocation.flutter, methods: [ + Method( + name: 'doit', + returnType: Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]), + arguments: []) + ]) + ], + classes: [], + enums: [], + ); + { + final StringBuffer sink = StringBuffer(); + generateObjcHeader( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('doit:(void(^)(NSArray*')); + } + { + final StringBuffer sink = StringBuffer(); + generateObjcSource( + const ObjcOptions(header: 'foo.h', prefix: 'ABC'), root, sink); + final String code = sink.toString(); + expect(code, contains('doit:(void(^)(NSArray*')); + } + }); } From fa1d5b561038e7af6300f6d9bd1116e68f2989d2 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 27 Jul 2021 11:40:54 -0700 Subject: [PATCH 24/30] formatter --- packages/pigeon/lib/ast.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index c590febbf04f..fe8994da6651 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -78,8 +78,10 @@ class Api extends Node { abstract class TypedEntity { /// The data-type of the entity (ex 'String' or 'int'). String get dataType; + /// The type arguments to the entity. List? get typeArguments; + /// True if the type is nullable. bool get isNullable; } From f6ee67f69941281b98bc25541d191d84a6a6aebc Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 27 Jul 2021 13:51:20 -0700 Subject: [PATCH 25/30] List -> List --- .../java/com/example/android_unit_tests/PrimitiveTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index f64db1f14006..941528bc6b9c 100644 --- 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 @@ -94,7 +94,7 @@ public void primitiveMap() { boolean[] didCall = {false}; api.aMap( Collections.singletonMap("hello", 1), - (Map result) -> { + (Map result) -> { didCall[0] = true; assertEquals(result, Collections.singletonMap("hello", 1)); }); @@ -108,7 +108,7 @@ public void primitiveList() { boolean[] didCall = {false}; api.aList( Collections.singletonList("hello"), - (List result) -> { + (List result) -> { didCall[0] = true; assertEquals(result, Collections.singletonList("hello")); }); From 482daa9839d7fba4eb4fc57a680019714756d745 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 27 Jul 2021 15:12:55 -0700 Subject: [PATCH 26/30] added generics to the primitive.dart pigeon --- packages/pigeon/lib/ast.dart | 2 +- packages/pigeon/lib/pigeon_lib.dart | 14 +++++++++++++- packages/pigeon/pigeons/primitive.dart | 3 ++- packages/pigeon/test/pigeon_lib_test.dart | 2 ++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/packages/pigeon/lib/ast.dart b/packages/pigeon/lib/ast.dart index fe8994da6651..b9b316b09e32 100644 --- a/packages/pigeon/lib/ast.dart +++ b/packages/pigeon/lib/ast.dart @@ -42,7 +42,7 @@ class Method extends Node { @override String toString() { - return '(Api name:$name returnType:$returnType argType:$arguments isAsynchronous:$isAsynchronous)'; + return '(Method name:$name returnType:$returnType argType:$arguments isAsynchronous:$isAsynchronous)'; } } diff --git a/packages/pigeon/lib/pigeon_lib.dart b/packages/pigeon/lib/pigeon_lib.dart index 4547e5d343e2..05f86f2f07f9 100644 --- a/packages/pigeon/lib/pigeon_lib.dart +++ b/packages/pigeon/lib/pigeon_lib.dart @@ -644,6 +644,16 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { ); } + static T? getFirstChildOfType(dart_ast.AstNode entity) { + for (final dart_ast_syntactic_entity.SyntacticEntity child + in entity.childEntities) { + if (child is T) { + return child as T; + } + } + return null; + } + @override Object? visitMethodDeclaration(dart_ast.MethodDeclaration node) { final dart_ast.FormalParameterList parameters = node.parameters!; @@ -655,7 +665,9 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor { name: node.name.name, returnType: Field( name: '', - dataType: node.returnType.toString(), + dataType: getFirstChildOfType( + node.returnType!)! + .name, typeArguments: typeAnnotationsToTypeArguments( (node.returnType as dart_ast.NamedType?)!.typeArguments), isNullable: node.returnType!.question != null), diff --git a/packages/pigeon/pigeons/primitive.dart b/packages/pigeon/pigeons/primitive.dart index 0a3dfcd9f942..6be1f4552be9 100644 --- a/packages/pigeon/pigeons/primitive.dart +++ b/packages/pigeon/pigeons/primitive.dart @@ -29,5 +29,6 @@ abstract class PrimitiveFlutterApi { // ignore: always_specify_types List aList(List value); Int32List anInt32List(Int32List value); - void aBoolList(List value); + List aBoolList(List value); + Map aStringIntMap(Map value); } diff --git a/packages/pigeon/test/pigeon_lib_test.dart b/packages/pigeon/test/pigeon_lib_test.dart index 8a0908923aeb..780c2c97acab 100644 --- a/packages/pigeon/test/pigeon_lib_test.dart +++ b/packages/pigeon/test/pigeon_lib_test.dart @@ -620,6 +620,7 @@ abstract class Api { } '''; final ParseResults parseResult = _parseSource(code); + expect(parseResult.root.apis[0].methods[0].returnType.dataType, 'List'); expect( parseResult .root.apis[0].methods[0].returnType.typeArguments![0].dataType, @@ -638,6 +639,7 @@ abstract class Api { } '''; final ParseResults parseResult = _parseSource(code); + expect(parseResult.root.apis[0].methods[0].arguments[0].dataType, 'List'); expect( parseResult .root.apis[0].methods[0].arguments[0].typeArguments![0].dataType, From 3a2f8bb59866ec46f992932a89115339f534e7b8 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 27 Jul 2021 16:17:43 -0700 Subject: [PATCH 27/30] added better testing for dart --- packages/pigeon/lib/dart_generator.dart | 12 +- packages/pigeon/lib/java_generator.dart.orig | 486 ++++++++++++++++++ packages/pigeon/pigeons/primitive.dart | 3 +- .../lib/primitive.dart | 285 ++++++++++ .../test/primitive_test.dart | 61 +++ .../test/primitive_test.mocks.dart | 44 ++ packages/pigeon/run_tests.sh | 11 +- packages/pigeon/test/dart_generator_test.dart | 14 +- 8 files changed, 908 insertions(+), 8 deletions(-) create mode 100644 packages/pigeon/lib/java_generator.dart.orig create mode 100644 packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart create mode 100644 packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart create mode 100644 packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.mocks.dart diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 3a7fe353370d..0b8c401b8ac5 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -137,9 +137,13 @@ final BinaryMessenger$nullTag _binaryMessenger; '\'$channelName\', codec, binaryMessenger: _binaryMessenger);', ); }); + final String returnType = func.returnType.dataType; + final String castCall = func.returnType.typeArguments != null + ? '.cast<${_flattenTypeArguments(func.returnType.typeArguments!, nullTag)}>()' + : ''; final String returnStatement = func.returnType.dataType == 'void' ? '// noop' - : 'return (replyMap[\'${Keys.result}\'] as ${func.returnType.dataType}$nullTag)$unwrapOperator;'; + : 'return (replyMap[\'${Keys.result}\'] as $returnType$nullTag)$unwrapOperator$castCall;'; indent.format(''' final Map$nullTag replyMap =\n\t\tawait channel.send($sendArgument) as Map$nullTag; if (replyMap == null) { @@ -217,7 +221,8 @@ void _writeFlutterApi( 'channel.$messageHandlerSetter((Object$nullTag message) async ', ); indent.scoped('{', '});', () { - final String returnType = func.returnType.dataType; + final String returnType = + _addGenericTypes(func.returnType, nullTag); final bool isAsync = func.isAsynchronous; final String emptyReturnStatement = isMockHandler ? 'return {};' @@ -229,7 +234,8 @@ void _writeFlutterApi( indent.writeln('// ignore message'); call = 'api.${func.name}()'; } else { - final String argType = func.arguments[0].dataType; + final String argType = + _addGenericTypes(func.arguments[0], nullTag); indent.writeln( 'assert(message != null, \'Argument for $channelName was null. Expected $argType.\');', ); diff --git a/packages/pigeon/lib/java_generator.dart.orig b/packages/pigeon/lib/java_generator.dart.orig new file mode 100644 index 000000000000..f49900e9dfa9 --- /dev/null +++ b/packages/pigeon/lib/java_generator.dart.orig @@ -0,0 +1,486 @@ +// 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 'ast.dart'; +import 'generator_tools.dart'; + +/// Options that control how Java code will be generated. +class JavaOptions { + /// Creates a [JavaOptions] object + const JavaOptions({ + this.className, + this.package, + this.copyrightHeader, + }); + + /// The name of the class that will house all the generated classes. + final String? className; + + /// The package where the generated class will live. + final String? package; + + /// A copyright header that will get prepended to generated code. + final Iterable? copyrightHeader; + + /// Creates a [JavaOptions] from a Map representation where: + /// `x = JavaOptions.fromMap(x.toMap())`. + static JavaOptions fromMap(Map map) { + return JavaOptions( + className: map['className'] as String?, + package: map['package'] as String?, + copyrightHeader: map['copyrightHeader'] as Iterable?, + ); + } + + /// Converts a [JavaOptions] to a Map representation where: + /// `x = JavaOptions.fromMap(x.toMap())`. + Map toMap() { + final Map result = { + if (className != null) 'className': className!, + if (package != null) 'package': package!, + if (copyrightHeader != null) 'copyrightHeader': copyrightHeader!, + }; + return result; + } + + /// Overrides any non-null parameters from [options] into this to make a new + /// [JavaOptions]. + JavaOptions merge(JavaOptions options) { + return JavaOptions.fromMap(mergeMaps(toMap(), options.toMap())); + } +} + +String _getCodecName(Api api) => '${api.name}Codec'; + +void _writeCodec(Indent indent, Api api) { + final String codecName = _getCodecName(api); + indent.write('private static class $codecName extends StandardMessageCodec '); + indent.scoped('{', '}', () { + indent + .writeln('public static final $codecName INSTANCE = new $codecName();'); + indent.writeln('private $codecName() {}'); + if (getCodecClasses(api).isNotEmpty) { + indent.writeln('@Override'); + indent.write( + 'protected Object readValueOfType(byte type, ByteBuffer buffer) '); + indent.scoped('{', '}', () { + indent.write('switch (type) '); + indent.scoped('{', '}', () { + for (final EnumeratedClass customClass in getCodecClasses(api)) { + indent.write('case (byte)${customClass.enumeration}: '); + indent.writeScoped('', '', () { + indent.writeln( + 'return ${customClass.name}.fromMap((Map) readValue(buffer));'); + }); + } + indent.write('default:'); + indent.writeScoped('', '', () { + indent.writeln('return super.readValueOfType(type, buffer);'); + }); + }); + }); + indent.writeln('@Override'); + indent.write( + 'protected void writeValue(ByteArrayOutputStream stream, Object value) '); + indent.writeScoped('{', '}', () { + for (final EnumeratedClass customClass in getCodecClasses(api)) { + indent.write('if (value instanceof ${customClass.name}) '); + indent.scoped('{', '} else ', () { + indent.writeln('stream.write(${customClass.enumeration});'); + indent.writeln( + 'writeValue(stream, ((${customClass.name}) value).toMap());'); + }); + } + indent.scoped('{', '}', () { + indent.writeln('super.writeValue(stream, value);'); + }); + }); + } + }); +} + +String _boxedType(String type) { + const Map map = { + '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); + + indent.writeln( + '/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/'); + indent.write('public interface ${api.name} '); + indent.scoped('{', '}', () { + for (final Method method in api.methods) { + final String returnType = method.isAsynchronous + ? 'void' + : _boxedType(method.returnType.dataType); + final List argSignature = []; + if (method.arguments.isNotEmpty) { + final String argType = _boxedType(method.arguments[0].dataType); + argSignature.add('$argType arg'); + } + if (method.isAsynchronous) { + final String returnType = method.returnType.dataType == 'void' + ? 'Void' + : method.returnType.dataType; + argSignature.add('Result<$returnType> result'); + } + indent.writeln('$returnType ${method.name}(${argSignature.join(', ')});'); + } + indent.addln(''); + final String codecName = _getCodecName(api); + indent.format(''' +/** The codec used by ${api.name}. */ +static MessageCodec getCodec() { +\treturn $codecName.INSTANCE; +} +'''); + indent.writeln( + '/** Sets up an instance of `${api.name}` to handle messages through the `binaryMessenger`. */'); + indent.write( + 'static void setup(BinaryMessenger binaryMessenger, ${api.name} api) '); + indent.scoped('{', '}', () { + for (final Method method in api.methods) { + final String channelName = makeChannelName(api, method); + indent.write(''); + indent.scoped('{', '}', () { + indent.writeln('BasicMessageChannel channel ='); + indent.inc(); + indent.inc(); + indent.writeln( + 'new BasicMessageChannel<>(binaryMessenger, "$channelName", getCodec());'); + indent.dec(); + indent.dec(); + indent.write('if (api != null) '); + indent.scoped('{', '} else {', () { + indent.write('channel.setMessageHandler((message, reply) -> '); + indent.scoped('{', '});', () { + final String returnType = _boxedType(method.returnType.dataType); + indent.writeln('Map wrapped = new HashMap<>();'); + indent.write('try '); + indent.scoped('{', '}', () { + final List methodArgument = []; + if (method.arguments.isNotEmpty) { + final String argType = _boxedType(method.arguments[0].dataType); + indent.writeln('@SuppressWarnings("ConstantConditions")'); + 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.dataType == 'void' ? 'null' : 'result'; + methodArgument.add( + 'result -> { ' + 'wrapped.put("${Keys.result}", $resultValue); ' + 'reply.reply(wrapped); ' + '}', + ); + } + final String call = + 'api.${method.name}(${methodArgument.join(', ')})'; + if (method.isAsynchronous) { + indent.writeln('$call;'); + } else if (method.returnType.dataType == 'void') { + indent.writeln('$call;'); + indent.writeln('wrapped.put("${Keys.result}", null);'); + } else { + indent.writeln('$returnType output = $call;'); + indent.writeln('wrapped.put("${Keys.result}", output);'); + } + }); + indent.write('catch (Error | RuntimeException exception) '); + indent.scoped('{', '}', () { + indent.writeln( + 'wrapped.put("${Keys.error}", wrapError(exception));'); + if (method.isAsynchronous) { + indent.writeln('reply.reply(wrapped);'); + } + }); + if (!method.isAsynchronous) { + indent.writeln('reply.reply(wrapped);'); + } + }); + }); + indent.scoped(null, '}', () { + indent.writeln('channel.setMessageHandler(null);'); + }); + }); + } + }); + }); +} + +void _writeFlutterApi(Indent indent, Api api) { + assert(api.location == ApiLocation.flutter); + indent.writeln( + '/** Generated class from Pigeon that represents Flutter messages that can be called from Java.*/'); + indent.write('public static class ${api.name} '); + indent.scoped('{', '}', () { + indent.writeln('private final BinaryMessenger binaryMessenger;'); + indent.write('public ${api.name}(BinaryMessenger argBinaryMessenger)'); + indent.scoped('{', '}', () { + indent.writeln('this.binaryMessenger = argBinaryMessenger;'); + }); + indent.write('public interface Reply '); + indent.scoped('{', '}', () { + indent.writeln('void reply(T reply);'); + }); + final String codecName = _getCodecName(api); + indent.format(''' +static MessageCodec getCodec() { +\treturn $codecName.INSTANCE; +} +'''); + for (final Method func in api.methods) { + final String channelName = makeChannelName(api, func); + final String returnType = func.returnType.dataType == 'void' + ? 'Void' + : _boxedType(func.returnType.dataType); + String sendArgument; + if (func.arguments.isEmpty) { + indent.write('public void ${func.name}(Reply<$returnType> callback) '); + sendArgument = 'null'; + } else { + final String argType = _boxedType(func.arguments[0].dataType); + indent.write( + 'public void ${func.name}($argType argInput, Reply<$returnType> callback) '); + sendArgument = 'argInput'; + } + indent.scoped('{', '}', () { + indent.writeln('BasicMessageChannel channel ='); + indent.inc(); + indent.inc(); + indent.writeln( + 'new BasicMessageChannel<>(binaryMessenger, "$channelName", getCodec());'); + indent.dec(); + indent.dec(); + indent.write('channel.send($sendArgument, channelReply -> '); + indent.scoped('{', '});', () { + if (func.returnType.dataType == 'void') { + indent.writeln('callback.reply(null);'); + } else { + indent.writeln('@SuppressWarnings("ConstantConditions")'); + indent.writeln('$returnType output = ($returnType)channelReply;'); + indent.writeln('callback.reply(output);'); + } + }); + }); + } + }); +} + +String _makeGetter(Field field) { + final String uppercased = + field.name.substring(0, 1).toUpperCase() + field.name.substring(1); + return 'get$uppercased'; +} + +String _makeSetter(Field field) { + final String uppercased = + field.name.substring(0, 1).toUpperCase() + field.name.substring(1); + return 'set$uppercased'; +} + +String _flattenTypeArguments(List args) { + return args + .map((TypeArgument e) => e.typeArguments == null + ? _boxedType(e.dataType) + : '${_boxedType(e.dataType)}<${_flattenTypeArguments(e.typeArguments!)}>') + .reduce((String value, String element) => '$value, $element'); +} + +String? _javaTypeForDartType(Field field) { + const Map javaTypeForDartTypeMap = { + 'bool': 'Boolean', + 'int': 'Long', + 'String': 'String', + 'double': 'Double', + 'Uint8List': 'byte[]', + 'Int32List': 'int[]', + 'Int64List': 'long[]', + 'Float64List': 'double[]', + 'Map': 'Map', + }; + if (javaTypeForDartTypeMap.containsKey(field.dataType)) { + return javaTypeForDartTypeMap[field.dataType]; + } else if (field.dataType == 'List') { + if (field.typeArguments == null) { + return 'List'; + } else { + return 'List<${_flattenTypeArguments(field.typeArguments!)}>'; + } + } else { + return null; + } +} + +String _castObject( + Field field, List classes, List enums, String varName) { + final HostDatatype hostDatatype = + getHostDatatype(field, classes, enums, _javaTypeForDartType); + if (field.dataType == 'int') { + return '($varName == null) ? null : (($varName instanceof Integer) ? (Integer)$varName : (${hostDatatype.datatype})$varName)'; + } else if (!hostDatatype.isBuiltin && + classes.map((Class x) => x.name).contains(field.dataType)) { + return '${hostDatatype.datatype}.fromMap((Map)$varName)'; + } else { + return '(${hostDatatype.datatype})$varName'; + } +} + +/// Generates the ".java" file for the AST represented by [root] to [sink] with the +/// provided [options]. +void generateJava(JavaOptions options, Root root, StringSink sink) { + final Set rootClassNameSet = + root.classes.map((Class x) => x.name).toSet(); + final Set rootEnumNameSet = + root.enums.map((Enum x) => x.name).toSet(); + final Indent indent = Indent(sink); + if (options.copyrightHeader != null) { + addLines(indent, options.copyrightHeader!, linePrefix: '// '); + } + indent.writeln('// $generatedCodeWarning'); + indent.writeln('// $seeAlsoWarning'); + indent.addln(''); + if (options.package != null) { + indent.writeln('package ${options.package};'); + } + indent.addln(''); + indent.writeln('import io.flutter.plugin.common.BasicMessageChannel;'); + indent.writeln('import io.flutter.plugin.common.BinaryMessenger;'); + indent.writeln('import io.flutter.plugin.common.MessageCodec;'); + indent.writeln('import io.flutter.plugin.common.StandardMessageCodec;'); + indent.writeln('import java.io.ByteArrayOutputStream;'); + indent.writeln('import java.nio.ByteBuffer;'); + indent.writeln('import java.util.List;'); + indent.writeln('import java.util.Map;'); + indent.writeln('import java.util.HashMap;'); + + indent.addln(''); + indent.writeln('/** Generated class from Pigeon. */'); + indent.writeln( + '@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"})'); + indent.write('public class ${options.className!} '); + indent.scoped('{', '}', () { + for (final Enum anEnum in root.enums) { + indent.writeln(''); + indent.write('public enum ${anEnum.name} '); + indent.scoped('{', '}', () { + int index = 0; + for (final String member in anEnum.members) { + indent.writeln( + '$member($index)${index == anEnum.members.length - 1 ? ';' : ','}'); + index++; + } + indent.writeln(''); + // We use explicit indexing here as use of the ordinal() method is + // discouraged. The toMap and fromMap API matches class API to allow + // the same code to work with enums and classes, but this + // can also be done directly in the host and flutter APIs. + indent.writeln('private int index;'); + indent.write('private ${anEnum.name}(final int index) '); + indent.scoped('{', '}', () { + indent.writeln('this.index = index;'); + }); + }); + } + + for (final Class klass in root.classes) { + indent.addln(''); + indent.writeln( + '/** Generated class from Pigeon that represents data sent in messages. */'); + indent.write('public static class ${klass.name} '); + indent.scoped('{', '}', () { + for (final Field field in klass.fields) { + final HostDatatype hostDatatype = getHostDatatype( + field, root.classes, root.enums, _javaTypeForDartType); + indent.writeln('private ${hostDatatype.datatype} ${field.name};'); + indent.writeln( + 'public ${hostDatatype.datatype} ${_makeGetter(field)}() { return ${field.name}; }'); + indent.writeln( + 'public void ${_makeSetter(field)}(${hostDatatype.datatype} setterArg) { this.${field.name} = setterArg; }'); + indent.addln(''); + } + indent.write('Map toMap() '); + indent.scoped('{', '}', () { + indent.writeln('Map toMapResult = new HashMap<>();'); + for (final Field field in klass.fields) { + final HostDatatype hostDatatype = getHostDatatype( + field, root.classes, root.enums, _javaTypeForDartType); + String toWriteValue = ''; + if (!hostDatatype.isBuiltin && + rootClassNameSet.contains(field.dataType)) { + toWriteValue = '${field.name}.toMap()'; + } else if (!hostDatatype.isBuiltin && + rootEnumNameSet.contains(field.dataType)) { + toWriteValue = '${field.name}.index'; + } else { + toWriteValue = field.name; + } + indent.writeln('toMapResult.put("${field.name}", $toWriteValue);'); + } + indent.writeln('return toMapResult;'); + }); + indent.write('static ${klass.name} fromMap(Map map) '); + indent.scoped('{', '}', () { + indent.writeln('${klass.name} fromMapResult = new ${klass.name}();'); + for (final Field field in klass.fields) { + indent.writeln('Object ${field.name} = map.get("${field.name}");'); + if (rootEnumNameSet.contains(field.dataType)) { + indent.writeln( + 'fromMapResult.${field.name} = ${field.dataType}.values()[(int)${field.name}];'); + } else { + indent.writeln( + 'fromMapResult.${field.name} = ${_castObject(field, root.classes, root.enums, field.name)};'); + } + } + indent.writeln('return fromMapResult;'); + }); + }); + } + + if (root.apis.any((Api api) => + api.location == ApiLocation.host && + api.methods.any((Method it) => it.isAsynchronous))) { + indent.addln(''); + indent.write('public interface Result '); + indent.scoped('{', '}', () { + indent.writeln('void success(T result);'); + }); + } + + for (final Api api in root.apis) { + _writeCodec(indent, api); + indent.addln(''); + if (api.location == ApiLocation.host) { + _writeHostApi(indent, api); + } else if (api.location == ApiLocation.flutter) { + _writeFlutterApi(indent, api); + } + } + + indent.format(''' +private static Map wrapError(Throwable exception) { +\tMap errorMap = new HashMap<>(); +\terrorMap.put("${Keys.errorMessage}", exception.toString()); +\terrorMap.put("${Keys.errorCode}", exception.getClass().getSimpleName()); +\terrorMap.put("${Keys.errorDetails}", null); +\treturn errorMap; +}'''); + }); +} diff --git a/packages/pigeon/pigeons/primitive.dart b/packages/pigeon/pigeons/primitive.dart index 6be1f4552be9..cc8eea5cc49c 100644 --- a/packages/pigeon/pigeons/primitive.dart +++ b/packages/pigeon/pigeons/primitive.dart @@ -15,7 +15,8 @@ abstract class PrimitiveHostApi { // ignore: always_specify_types List aList(List value); Int32List anInt32List(Int32List value); - void aBoolList(List value); + List aBoolList(List value); + Map aStringIntMap(Map value); } @FlutterApi() diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart new file mode 100644 index 000000000000..14246585dcb4 --- /dev/null +++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart @@ -0,0 +1,285 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Autogenerated from Pigeon (v0.3.0), do not edit directly. +// See also: https://pub.dev/packages/pigeon +// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name +// @dart = 2.12 +import 'dart:async'; +import 'dart:typed_data' show Uint8List, Int32List, Int64List, Float64List; + +import 'package:flutter/foundation.dart' show WriteBuffer, ReadBuffer; +import 'package:flutter/services.dart'; + +class _PrimitiveHostApiCodec extends StandardMessageCodec { + const _PrimitiveHostApiCodec(); +} + +class PrimitiveHostApi { + /// Constructor for [PrimitiveHostApi]. The [binaryMessenger] named argument is + /// available for dependency injection. If it is left null, the default + /// BinaryMessenger will be used which routes to the host platform. + PrimitiveHostApi({BinaryMessenger? binaryMessenger}) + : _binaryMessenger = binaryMessenger; + + final BinaryMessenger? _binaryMessenger; + + static const MessageCodec codec = _PrimitiveHostApiCodec(); + + Future inc(int arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.inc', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as int?)!; + } + } + + Future aBool(bool arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.aBool', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as bool?)!; + } + } + + Future> aBoolList(List arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.aBoolList', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as List?)!.cast(); + } + } + + Future> aStringIntMap(Map arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.aStringIntMap', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as Map?)!.cast(); + } + } +} + +class _PrimitiveFlutterApiCodec extends StandardMessageCodec { + const _PrimitiveFlutterApiCodec(); +} + +abstract class PrimitiveFlutterApi { + static const MessageCodec codec = _PrimitiveFlutterApiCodec(); + + int inc(int arg); + bool aBool(bool arg); + String aString(String arg); + double aDouble(double arg); + Map aMap(Map arg); + List aList(List arg); + Int32List anInt32List(Int32List arg); + List aBoolList(List arg); + Map aStringIntMap(Map arg); + static void setup(PrimitiveFlutterApi? api) { + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.inc', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.inc was null. Expected int.'); + final int input = (message as int?)!; + final int output = api.inc(input); + return output; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.aBool', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.aBool was null. Expected bool.'); + final bool input = (message as bool?)!; + final bool output = api.aBool(input); + return output; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.aString', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.aString was null. Expected String.'); + final String input = (message as String?)!; + final String output = api.aString(input); + return output; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.aDouble', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.aDouble was null. Expected double.'); + final double input = (message as double?)!; + final double output = api.aDouble(input); + return output; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.aMap', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.aMap was null. Expected Map.'); + final Map input = + (message as Map?)!; + final Map output = api.aMap(input); + return output; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.aList', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.aList was null. Expected List.'); + final List input = (message as List?)!; + final List output = api.aList(input); + return output; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.anInt32List', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.anInt32List was null. Expected Int32List.'); + final Int32List input = (message as Int32List?)!; + final Int32List output = api.anInt32List(input); + return output; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.aBoolList', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.aBoolList was null. Expected List.'); + final List input = (message as List?)!; + final List output = api.aBoolList(input); + return output; + }); + } + } + { + const BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveFlutterApi.aStringIntMap', codec); + if (api == null) { + channel.setMessageHandler(null); + } else { + channel.setMessageHandler((Object? message) async { + assert(message != null, + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.aStringIntMap was null. Expected Map.'); + final Map input = (message as Map?)!; + final Map output = api.aStringIntMap(input); + return output; + }); + } + } + } +} diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart new file mode 100644 index 000000000000..a9eb1232f455 --- /dev/null +++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart @@ -0,0 +1,61 @@ +// 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:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:flutter_unit_tests/primitive.dart'; +import 'package:mockito/annotations.dart'; +import 'package:mockito/mockito.dart'; +import 'primitive_test.mocks.dart'; + +@GenerateMocks([BinaryMessenger]) +void main() { + test('test anInt', () async { + final BinaryMessenger mockMessenger = MockBinaryMessenger(); + when(mockMessenger.send('dev.flutter.pigeon.PrimitiveHostApi.inc', any)) + .thenAnswer((Invocation realInvocation) async { + const MessageCodec codec = PrimitiveHostApi.codec; + final Object? input = + codec.decodeMessage(realInvocation.positionalArguments[1]); + return codec.encodeMessage({'result': input!}); + }); + final PrimitiveHostApi api = + PrimitiveHostApi(binaryMessenger: mockMessenger); + final int result = await api.inc(1); + expect(result, 1); + }); + + test('test List', () async { + final BinaryMessenger mockMessenger = MockBinaryMessenger(); + when(mockMessenger.send( + 'dev.flutter.pigeon.PrimitiveHostApi.aBoolList', any)) + .thenAnswer((Invocation realInvocation) async { + const MessageCodec codec = PrimitiveHostApi.codec; + final Object? input = + codec.decodeMessage(realInvocation.positionalArguments[1]); + return codec.encodeMessage({'result': input!}); + }); + final PrimitiveHostApi api = + PrimitiveHostApi(binaryMessenger: mockMessenger); + final List result = await api.aBoolList([true]); + expect(result[0], true); + }); + + test('test Map', () async { + final BinaryMessenger mockMessenger = MockBinaryMessenger(); + when(mockMessenger.send( + 'dev.flutter.pigeon.PrimitiveHostApi.aStringIntMap', any)) + .thenAnswer((Invocation realInvocation) async { + const MessageCodec codec = PrimitiveHostApi.codec; + final Object? input = + codec.decodeMessage(realInvocation.positionalArguments[1]); + return codec.encodeMessage({'result': input!}); + }); + final PrimitiveHostApi api = + PrimitiveHostApi(binaryMessenger: mockMessenger); + final Map result = + await api.aStringIntMap({'hello': 1}); + expect(result['hello'], 1); + }); +} diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.mocks.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.mocks.dart new file mode 100644 index 000000000000..814ea419359e --- /dev/null +++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.mocks.dart @@ -0,0 +1,44 @@ +// Mocks generated by Mockito 5.0.7 from annotations +// in flutter_unit_tests/test/null_safe_test.dart. +// Do not manually edit this file. + +import 'dart:async' as _i3; +import 'dart:typed_data' as _i4; +import 'dart:ui' as _i5; + +import 'package:flutter/src/services/binary_messenger.dart' as _i2; +import 'package:mockito/mockito.dart' as _i1; + +// ignore_for_file: comment_references +// ignore_for_file: unnecessary_parenthesis +// ignore_for_file: always_specify_types +// Added manually; several methods have moved to +// flutter_test/lib/src/deprecated.dart on master, but that hasn't reached +// stable yet. +// ignore_for_file: override_on_non_overriding_member + +/// A class which mocks [BinaryMessenger]. +/// +/// See the documentation for Mockito's code generation for more information. +class MockBinaryMessenger extends _i1.Mock implements _i2.BinaryMessenger { + MockBinaryMessenger() { + _i1.throwOnMissingStub(this); + } + + @override + _i3.Future handlePlatformMessage(String? channel, _i4.ByteData? data, + _i5.PlatformMessageResponseCallback? callback) => + (super.noSuchMethod( + Invocation.method(#handlePlatformMessage, [channel, data, callback]), + returnValue: Future.value(null), + returnValueForMissingStub: + Future.value()) as _i3.Future); + @override + _i3.Future<_i4.ByteData?>? send(String? channel, _i4.ByteData? message) => + (super.noSuchMethod(Invocation.method(#send, [channel, message])) + as _i3.Future<_i4.ByteData?>?); + @override + void setMessageHandler(String? channel, _i2.MessageHandler? handler) => super + .noSuchMethod(Invocation.method(#setMessageHandler, [channel, handler]), + returnValueForMissingStub: null); +} diff --git a/packages/pigeon/run_tests.sh b/packages/pigeon/run_tests.sh index 341967574189..2ed2c295b38f 100755 --- a/packages/pigeon/run_tests.sh +++ b/packages/pigeon/run_tests.sh @@ -194,17 +194,22 @@ test_running_without_arguments() { } run_flutter_unittests() { + local flutter_tests="platform_tests/flutter_null_safe_unit_tests" pushd $PWD $run_pigeon \ --input pigeons/flutter_unittests.dart \ - --dart_out platform_tests/flutter_null_safe_unit_tests/lib/null_safe_pigeon.dart + --dart_out "$flutter_tests/lib/null_safe_pigeon.dart" $run_pigeon \ --input pigeons/all_datatypes.dart \ - --dart_out platform_tests/flutter_null_safe_unit_tests/lib/all_datatypes.dart - cd platform_tests/flutter_null_safe_unit_tests + --dart_out "$flutter_tests/lib/all_datatypes.dart" + $run_pigeon \ + --input pigeons/primitive.dart \ + --dart_out "$flutter_tests/lib/primitive.dart" + cd "$flutter_tests" flutter pub get flutter test test/null_safe_test.dart flutter test test/all_datatypes_test.dart + flutter test test/primitive_test.dart popd } diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index a547f1b0d539..e90062a914c1 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -714,6 +714,7 @@ void main() { generateDart(const DartOptions(isNullSafe: true), root, sink); final String code = sink.toString(); expect(code, contains('Future> doit(')); + expect(code, contains('return (replyMap[\'result\'] as List?)!.cast();')); }); test('host generics return', () { @@ -729,7 +730,15 @@ void main() { typeArguments: [ TypeArgument(dataType: 'int', isNullable: true) ]), - arguments: []) + arguments: [ + Field( + name: 'arg', + dataType: 'List', + isNullable: false, + typeArguments: [ + TypeArgument(dataType: 'int', isNullable: true) + ]) + ]) ]) ], classes: [], @@ -739,5 +748,8 @@ void main() { generateDart(const DartOptions(isNullSafe: true), root, sink); final String code = sink.toString(); expect(code, contains('List doit(')); + expect( + code, contains('final List input = (message as List?)!')); + expect(code, contains('final List output = api.doit(input)')); }); } From 11c71d57f9111dea6d3d5a03d79103b17b0d0782 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Tue, 27 Jul 2021 16:42:10 -0700 Subject: [PATCH 28/30] did some cleanup to factor out cast calls --- packages/pigeon/lib/dart_generator.dart | 26 ++++++++++++++----- .../lib/all_datatypes.dart | 3 ++- .../lib/primitive.dart | 5 ++-- packages/pigeon/test/dart_generator_test.dart | 5 +++- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 0b8c401b8ac5..4fd94ad50c39 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -92,6 +92,18 @@ void _writeCodec(Indent indent, String codecName, Api api) { }); } +String _makeGenericTypeArguments(TypedEntity entity, String nullTag) { + return entity.typeArguments != null + ? '${entity.dataType}<${entity.typeArguments!.map((TypeArgument e) => 'Object$nullTag').reduce((String value, String element) => '$value, $element')}>' + : entity.dataType; +} + +String _makeGenericCastCall(TypedEntity entity, String nullTag) { + return entity.typeArguments != null + ? '.cast<${_flattenTypeArguments(entity.typeArguments!, nullTag)}>()' + : ''; +} + void _writeHostApi(DartOptions opt, Indent indent, Api api) { assert(api.location == ApiLocation.host); final String codecName = _getCodecName(api); @@ -137,10 +149,9 @@ final BinaryMessenger$nullTag _binaryMessenger; '\'$channelName\', codec, binaryMessenger: _binaryMessenger);', ); }); - final String returnType = func.returnType.dataType; - final String castCall = func.returnType.typeArguments != null - ? '.cast<${_flattenTypeArguments(func.returnType.typeArguments!, nullTag)}>()' - : ''; + final String returnType = + _makeGenericTypeArguments(func.returnType, nullTag); + final String castCall = _makeGenericCastCall(func.returnType, nullTag); final String returnStatement = func.returnType.dataType == 'void' ? '// noop' : 'return (replyMap[\'${Keys.result}\'] as $returnType$nullTag)$unwrapOperator$castCall;'; @@ -393,9 +404,12 @@ pigeonMap['${field.name}'] != null pigeonMap['${field.name}'] != null \t\t? ${field.dataType}.values[pigeonMap['${field.name}']$unwrapOperator as int] \t\t: null''', leadingSpace: false, trailingNewline: false); - } else if (field.dataType == 'Map' && field.typeArguments != null) { + } else if (field.typeArguments != null) { + final String genericType = + _makeGenericTypeArguments(field, nullTag); + final String castCall = _makeGenericCastCall(field, nullTag); indent.add( - '(pigeonMap[\'${field.name}\'] as Map$nullTag)$nullTag.cast<${_flattenTypeArguments(field.typeArguments!, nullTag)}>()', + '(pigeonMap[\'${field.name}\'] as $genericType$nullTag)$nullTag$castCall', ); } else { indent.add( 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 dd60777ef72f..adf2c866aa95 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 @@ -56,7 +56,8 @@ class Everything { ..aFloatArray = pigeonMap['aFloatArray'] as Float64List? ..aList = pigeonMap['aList'] as List? ..aMap = pigeonMap['aMap'] as Map? - ..nestedList = pigeonMap['nestedList'] as List?>? + ..nestedList = + (pigeonMap['nestedList'] as List?)?.cast?>() ..mapWithAnnotations = (pigeonMap['mapWithAnnotations'] as Map?) ?.cast(); diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart index 14246585dcb4..c9a2a729498a 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart +++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart @@ -98,7 +98,7 @@ class PrimitiveHostApi { details: error['details'], ); } else { - return (replyMap['result'] as List?)!.cast(); + return (replyMap['result'] as List?)!.cast(); } } @@ -123,7 +123,8 @@ class PrimitiveHostApi { details: error['details'], ); } else { - return (replyMap['result'] as Map?)!.cast(); + return (replyMap['result'] as Map?)! + .cast(); } } } diff --git a/packages/pigeon/test/dart_generator_test.dart b/packages/pigeon/test/dart_generator_test.dart index e90062a914c1..225704e073f2 100644 --- a/packages/pigeon/test/dart_generator_test.dart +++ b/packages/pigeon/test/dart_generator_test.dart @@ -714,7 +714,10 @@ void main() { generateDart(const DartOptions(isNullSafe: true), root, sink); final String code = sink.toString(); expect(code, contains('Future> doit(')); - expect(code, contains('return (replyMap[\'result\'] as List?)!.cast();')); + expect( + code, + contains( + 'return (replyMap[\'result\'] as List?)!.cast();')); }); test('host generics return', () { From 15188a8bff10731efbc88301bfaeb52aae6330a4 Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Thu, 29 Jul 2021 14:06:07 -0700 Subject: [PATCH 29/30] rebase fixes --- .../android_unit_tests/PrimitiveTest.java | 2 +- .../lib/primitive.dart | 137 +++++++++++++++++- .../test/primitive_test.dart | 4 +- 3 files changed, 134 insertions(+), 9 deletions(-) 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 index 941528bc6b9c..d557d2154049 100644 --- 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 @@ -36,7 +36,7 @@ public void primitiveInt() { BinaryMessenger binaryMessenger = makeMockBinaryMessenger(); PrimitiveFlutterApi api = new PrimitiveFlutterApi(binaryMessenger); boolean[] didCall = {false}; - api.inc( + api.anInt( 1L, (Long result) -> { didCall[0] = true; diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart index c9a2a729498a..bd1f674d0e82 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart +++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart @@ -27,9 +27,9 @@ class PrimitiveHostApi { static const MessageCodec codec = _PrimitiveHostApiCodec(); - Future inc(int arg) async { + Future anInt(int arg) async { final BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.PrimitiveHostApi.inc', codec, + 'dev.flutter.pigeon.PrimitiveHostApi.anInt', codec, binaryMessenger: _binaryMessenger); final Map? replyMap = await channel.send(arg) as Map?; @@ -77,6 +77,131 @@ class PrimitiveHostApi { } } + Future aString(String arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.aString', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as String?)!; + } + } + + Future aDouble(double arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.aDouble', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as double?)!; + } + } + + Future> aMap(Map arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.aMap', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as Map?)!; + } + } + + Future> aList(List arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.aList', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as List?)!; + } + } + + Future anInt32List(Int32List arg) async { + final BasicMessageChannel channel = BasicMessageChannel( + 'dev.flutter.pigeon.PrimitiveHostApi.anInt32List', codec, + binaryMessenger: _binaryMessenger); + final Map? replyMap = + await channel.send(arg) as Map?; + if (replyMap == null) { + throw PlatformException( + code: 'channel-error', + message: 'Unable to establish connection on channel.', + details: null, + ); + } else if (replyMap['error'] != null) { + final Map error = + (replyMap['error'] as Map?)!; + throw PlatformException( + code: (error['code'] as String?)!, + message: error['message'] as String?, + details: error['details'], + ); + } else { + return (replyMap['result'] as Int32List?)!; + } + } + Future> aBoolList(List arg) async { final BasicMessageChannel channel = BasicMessageChannel( 'dev.flutter.pigeon.PrimitiveHostApi.aBoolList', codec, @@ -136,7 +261,7 @@ class _PrimitiveFlutterApiCodec extends StandardMessageCodec { abstract class PrimitiveFlutterApi { static const MessageCodec codec = _PrimitiveFlutterApiCodec(); - int inc(int arg); + int anInt(int arg); bool aBool(bool arg); String aString(String arg); double aDouble(double arg); @@ -148,15 +273,15 @@ abstract class PrimitiveFlutterApi { static void setup(PrimitiveFlutterApi? api) { { const BasicMessageChannel channel = BasicMessageChannel( - 'dev.flutter.pigeon.PrimitiveFlutterApi.inc', codec); + 'dev.flutter.pigeon.PrimitiveFlutterApi.anInt', codec); if (api == null) { channel.setMessageHandler(null); } else { channel.setMessageHandler((Object? message) async { assert(message != null, - 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.inc was null. Expected int.'); + 'Argument for dev.flutter.pigeon.PrimitiveFlutterApi.anInt was null. Expected int.'); final int input = (message as int?)!; - final int output = api.inc(input); + final int output = api.anInt(input); return output; }); } diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart index a9eb1232f455..3c20172496a9 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart +++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/test/primitive_test.dart @@ -13,7 +13,7 @@ import 'primitive_test.mocks.dart'; void main() { test('test anInt', () async { final BinaryMessenger mockMessenger = MockBinaryMessenger(); - when(mockMessenger.send('dev.flutter.pigeon.PrimitiveHostApi.inc', any)) + when(mockMessenger.send('dev.flutter.pigeon.PrimitiveHostApi.anInt', any)) .thenAnswer((Invocation realInvocation) async { const MessageCodec codec = PrimitiveHostApi.codec; final Object? input = @@ -22,7 +22,7 @@ void main() { }); final PrimitiveHostApi api = PrimitiveHostApi(binaryMessenger: mockMessenger); - final int result = await api.inc(1); + final int result = await api.anInt(1); expect(result, 1); }); From 505c3b48e29415584a92286869a6113de32f913f Mon Sep 17 00:00:00 2001 From: Aaron Clarke Date: Fri, 30 Jul 2021 15:19:23 -0700 Subject: [PATCH 30/30] fixed cast call to remove warning --- packages/pigeon/lib/dart_generator.dart | 16 ++++++++-------- .../lib/primitive.dart | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/pigeon/lib/dart_generator.dart b/packages/pigeon/lib/dart_generator.dart index 4fd94ad50c39..d544ee33410a 100644 --- a/packages/pigeon/lib/dart_generator.dart +++ b/packages/pigeon/lib/dart_generator.dart @@ -95,7 +95,7 @@ void _writeCodec(Indent indent, String codecName, Api api) { String _makeGenericTypeArguments(TypedEntity entity, String nullTag) { return entity.typeArguments != null ? '${entity.dataType}<${entity.typeArguments!.map((TypeArgument e) => 'Object$nullTag').reduce((String value, String element) => '$value, $element')}>' - : entity.dataType; + : _addGenericTypes(entity, nullTag); } String _makeGenericCastCall(TypedEntity entity, String nullTag) { @@ -294,18 +294,18 @@ String _flattenTypeArguments(List args, String nullTag) { /// Creates the type declaration for use in Dart code from a [Field] making sure /// that type arguments are used for primitive generic types. -String _addGenericTypes(Field field, String nullTag) { - switch (field.dataType) { +String _addGenericTypes(TypedEntity entity, String nullTag) { + switch (entity.dataType) { case 'List': - return (field.typeArguments == null) + return (entity.typeArguments == null) ? 'List' - : 'List<${_flattenTypeArguments(field.typeArguments!, nullTag)}>'; + : 'List<${_flattenTypeArguments(entity.typeArguments!, nullTag)}>'; case 'Map': - return (field.typeArguments == null) + return (entity.typeArguments == null) ? 'Map' - : 'Map<${_flattenTypeArguments(field.typeArguments!, nullTag)}>'; + : 'Map<${_flattenTypeArguments(entity.typeArguments!, nullTag)}>'; default: - return field.dataType; + return entity.dataType; } } diff --git a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart index bd1f674d0e82..ae36e10b22c4 100644 --- a/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart +++ b/packages/pigeon/platform_tests/flutter_null_safe_unit_tests/lib/primitive.dart @@ -148,7 +148,7 @@ class PrimitiveHostApi { details: error['details'], ); } else { - return (replyMap['result'] as Map?)!; + return (replyMap['result'] as Map?)!; } } @@ -173,7 +173,7 @@ class PrimitiveHostApi { details: error['details'], ); } else { - return (replyMap['result'] as List?)!; + return (replyMap['result'] as List?)!; } }