-
Notifications
You must be signed in to change notification settings - Fork 3.8k
[pigeon] implemented generics for fields #416
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
43da42e
7d4f275
bd04fa8
3e75a35
5cebd68
8e9de1d
ceafca5
d4e133a
f4ab00d
e0819cf
6ea9b5b
69744ac
9860126
845897d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,26 +21,18 @@ class Method extends Node { | |
| required this.name, | ||
| required this.returnType, | ||
| required this.argType, | ||
| this.isArgNullable = false, | ||
| this.isAsynchronous = false, | ||
| this.isReturnNullable = false, | ||
| this.offset, | ||
| }); | ||
|
|
||
| /// The name of the method. | ||
| 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; | ||
|
|
||
| /// 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; | ||
|
|
@@ -82,6 +74,30 @@ class Api extends Node { | |
| } | ||
| } | ||
|
|
||
| /// A parameter to a generic entity. For example, "String" to "List<String>". | ||
| class TypeArgument { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't this a TypedEntity? |
||
| /// Constructor for [TypeArgument]. | ||
| TypeArgument({ | ||
| required this.dataType, | ||
| required this.isNullable, | ||
| this.typeArguments, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These three arguments are a |
||
| }); | ||
|
|
||
| /// A string representation of the base datatype. | ||
| final String dataType; | ||
|
|
||
| /// The type arguments to this [TypeArgument]. | ||
| final List<TypeArgument>? typeArguments; | ||
|
|
||
| /// True if the type is nullable. | ||
| final bool isNullable; | ||
|
|
||
| @override | ||
| String toString() { | ||
| return '(TypeArgument dataType:$dataType isNullable:$isNullable typeArguments:$typeArguments)'; | ||
|
stuartmorgan-g marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
|
||
| /// Represents a field on a [Class]. | ||
| class Field extends Node { | ||
| /// Parametric constructor for [Field]. | ||
|
|
@@ -106,11 +122,11 @@ class Field extends Node { | |
| bool isNullable; | ||
|
|
||
| /// Type parameters used for generics. | ||
| List<Field>? typeArguments; | ||
| List<TypeArgument>? typeArguments; | ||
|
|
||
| @override | ||
| String toString() { | ||
| return '(Field name:$name dataType:$dataType)'; | ||
| return '(Field name:$name dataType:$dataType typeArguments:$typeArguments)'; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that you still have the bug here that will be fixed by replacing the fields here with |
||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,12 +121,12 @@ final BinaryMessenger$nullTag _binaryMessenger; | |
| } | ||
| String argSignature = ''; | ||
| String sendArgument = 'null'; | ||
| if (func.argType != 'void') { | ||
| argSignature = '${func.argType} arg'; | ||
| if (func.argType.dataType != 'void') { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm curious: why was avoiding LoD violations so important for |
||
| argSignature = '${func.argType.dataType} arg'; | ||
| 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<Object$nullTag, Object$nullTag>$nullTag replyMap =\n\t\tawait channel.send($sendArgument) as Map<Object$nullTag, Object$nullTag>$nullTag; | ||
| if (replyMap == null) { | ||
|
|
@@ -181,10 +181,11 @@ void _writeFlutterApi( | |
| indent.addln(''); | ||
| for (final Method func in api.methods) { | ||
| final bool isAsync = func.isAsynchronous; | ||
| final String returnType = | ||
| isAsync ? 'Future<${func.returnType}>' : func.returnType; | ||
| 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'; | ||
|
stuartmorgan-g marked this conversation as resolved.
|
||
| indent.writeln('$returnType ${func.name}($argSignature);'); | ||
| } | ||
| indent.write('static void setup(${api.name}$nullTag api) '); | ||
|
|
@@ -215,12 +216,12 @@ void _writeFlutterApi( | |
| 'channel.$messageHandlerSetter((Object$nullTag message) async ', | ||
| ); | ||
| indent.scoped('{', '});', () { | ||
| final String argType = func.argType; | ||
| final String returnType = func.returnType; | ||
| final String argType = func.argType.dataType; | ||
| final String returnType = func.returnType.dataType; | ||
| final bool isAsync = func.isAsynchronous; | ||
| final String emptyReturnStatement = isMockHandler | ||
| ? 'return <Object$nullTag, Object$nullTag>{};' | ||
| : func.returnType == 'void' | ||
| : func.returnType.dataType == 'void' | ||
| ? 'return;' | ||
| : 'return null;'; | ||
| String call; | ||
|
|
@@ -263,14 +264,30 @@ void _writeFlutterApi( | |
| }); | ||
| } | ||
|
|
||
| String _addGenericTypes(String dataType, String nullTag) { | ||
| switch (dataType) { | ||
| /// Converts a [List] of [TypeArgument]s to a comma separated [String] to be | ||
| /// used in Dart code. | ||
| String _flattenTypeArguments(List<TypeArgument> args, String nullTag) { | ||
|
stuartmorgan-g marked this conversation as resolved.
|
||
| 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'); | ||
| } | ||
|
|
||
| /// 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) { | ||
|
stuartmorgan-g marked this conversation as resolved.
|
||
| switch (field.dataType) { | ||
| case 'List': | ||
| return 'List<Object$nullTag>$nullTag'; | ||
| return (field.typeArguments == null) | ||
| ? 'List<Object$nullTag>$nullTag' | ||
| : 'List<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and below, consider a local for |
||
| case 'Map': | ||
| return 'Map<Object$nullTag, Object$nullTag>$nullTag'; | ||
| return (field.typeArguments == null) | ||
| ? 'Map<Object$nullTag, Object$nullTag>$nullTag' | ||
| : 'Map<${_flattenTypeArguments(field.typeArguments!, nullTag)}>$nullTag'; | ||
| default: | ||
| return '$dataType$nullTag'; | ||
| return '${field.dataType}$nullTag'; | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -315,7 +332,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) { | ||
|
|
@@ -365,9 +382,13 @@ 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<Object$nullTag, Object$nullTag>$nullTag)$nullTag.cast<${_flattenTypeArguments(field.typeArguments!, nullTag)}>()', | ||
| ); | ||
| } 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 ? ';' : ''); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment and name for both of these indicate that they are a type, so they should be
TypeDeclarations rather thanFields.