Visitar URL original
Pigeon : Support for asynchronous methods/Functions (#201) · creatorpiyush/packages@a7db2b5 · GitHub
Skip to content

Commit a7db2b5

Browse files
xsahil03xgaaclarke
andauthored
Pigeon : Support for asynchronous methods/Functions (flutter#201)
(Android only currently) Co-authored-by: Aaron Clarke <aaclarke@google.com>
1 parent 9a3a835 commit a7db2b5

8 files changed

Lines changed: 315 additions & 33 deletions

File tree

‎packages/pigeon/lib/ast.dart‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class Node {}
1717
/// Represents a method on an [Api].
1818
class Method extends Node {
1919
/// Parametric constructor for [Method].
20-
Method({this.name, this.returnType, this.argType});
20+
Method({this.name, this.returnType, this.argType, this.isAsynchronous});
2121

2222
/// The name of the method.
2323
String name;
@@ -27,6 +27,9 @@ class Method extends Node {
2727

2828
/// The data-type of the argument.
2929
String argType;
30+
31+
/// Whether the receiver of this method is expected to return synchronously or not.
32+
bool isAsynchronous;
3033
}
3134

3235
/// Represents a collection of [Method]s that are hosted ona given [location].

‎packages/pigeon/lib/dart_generator.dart‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,12 @@ void _writeFlutterApi(Indent indent, Api api,
6666
indent.write('abstract class ${api.name} ');
6767
indent.scoped('{', '}', () {
6868
for (Method func in api.methods) {
69+
final bool isAsync = func.isAsynchronous;
70+
final String returnType =
71+
isAsync ? 'Future<${func.returnType}>' : '${func.returnType}';
6972
final String argSignature =
7073
func.argType == 'void' ? '' : '${func.argType} arg';
71-
indent.writeln('${func.returnType} ${func.name}($argSignature);');
74+
indent.writeln('$returnType ${func.name}($argSignature);');
7275
}
7376
indent.write('static void setup(${api.name} api) ');
7477
indent.scoped('{', '}', () {
@@ -92,6 +95,7 @@ void _writeFlutterApi(Indent indent, Api api,
9295
indent.scoped('{', '});', () {
9396
final String argType = func.argType;
9497
final String returnType = func.returnType;
98+
final bool isAsync = func.isAsynchronous;
9599
String call;
96100
if (argType == 'void') {
97101
call = 'api.${func.name}()';
@@ -108,7 +112,11 @@ void _writeFlutterApi(Indent indent, Api api,
108112
indent.writeln('return <dynamic, dynamic>{};');
109113
}
110114
} else {
111-
indent.writeln('final $returnType output = $call;');
115+
if (isAsync) {
116+
indent.writeln('final $returnType output = await $call;');
117+
} else {
118+
indent.writeln('final $returnType output = $call;');
119+
}
112120
const String returnExpresion = 'output._toMap()';
113121
final String returnStatement = isMockHandler
114122
? 'return <dynamic, dynamic>{\'${Keys.result}\': $returnExpresion};'

‎packages/pigeon/lib/java_generator.dart‎

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,30 @@ class JavaOptions {
2929

3030
void _writeHostApi(Indent indent, Api api) {
3131
assert(api.location == ApiLocation.host);
32+
33+
if (api.methods.any((Method it) => it.isAsynchronous)) {
34+
indent.write('public interface Result<T> ');
35+
indent.scoped('{', '}', () {
36+
indent.writeln('void success(T result);');
37+
});
38+
indent.addln('');
39+
}
40+
3241
indent.writeln(
3342
'/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/');
3443
indent.write('public interface ${api.name} ');
3544
indent.scoped('{', '}', () {
3645
for (Method method in api.methods) {
37-
final String argSignature =
38-
method.argType == 'void' ? '' : '${method.argType} arg';
39-
indent.writeln('${method.returnType} ${method.name}($argSignature);');
46+
final String returnType =
47+
method.isAsynchronous ? 'void' : method.returnType;
48+
final List<String> argSignature = <String>[];
49+
if (method.argType != 'void') {
50+
argSignature.add('${method.argType} arg');
51+
}
52+
if (method.isAsynchronous) {
53+
argSignature.add('Result<${method.returnType}> result');
54+
}
55+
indent.writeln('$returnType ${method.name}(${argSignature.join(', ')});');
4056
}
4157
indent.addln('');
4258
indent.writeln(
@@ -65,17 +81,26 @@ void _writeHostApi(Indent indent, Api api) {
6581
'HashMap<String, HashMap> wrapped = new HashMap<>();');
6682
indent.write('try ');
6783
indent.scoped('{', '}', () {
68-
String methodArgument;
69-
if (argType == 'void') {
70-
methodArgument = '';
71-
} else {
84+
final List<String> methodArgument = <String>[];
85+
if (argType != 'void') {
7286
indent.writeln('@SuppressWarnings("ConstantConditions")');
7387
indent.writeln(
7488
'$argType input = $argType.fromMap((HashMap)message);');
75-
methodArgument = 'input';
89+
methodArgument.add('input');
7690
}
77-
final String call = 'api.${method.name}($methodArgument)';
78-
if (method.returnType == 'void') {
91+
if (method.isAsynchronous) {
92+
methodArgument.add(
93+
'result -> { '
94+
'wrapped.put("${Keys.result}", result.toMap()); '
95+
'reply.reply(wrapped); '
96+
'}',
97+
);
98+
}
99+
final String call =
100+
'api.${method.name}(${methodArgument.join(', ')})';
101+
if (method.isAsynchronous) {
102+
indent.writeln('$call;');
103+
} else if (method.returnType == 'void') {
79104
indent.writeln('$call;');
80105
indent.writeln('wrapped.put("${Keys.result}", null);');
81106
} else {
@@ -88,8 +113,13 @@ void _writeHostApi(Indent indent, Api api) {
88113
indent.scoped('{', '}', () {
89114
indent.writeln(
90115
'wrapped.put("${Keys.error}", wrapError(exception));');
116+
if (method.isAsynchronous) {
117+
indent.writeln('reply.reply(wrapped);');
118+
}
91119
});
92-
indent.writeln('reply.reply(wrapped);');
120+
if (!method.isAsynchronous) {
121+
indent.writeln('reply.reply(wrapped);');
122+
}
93123
});
94124
});
95125
indent.scoped(null, '}', () {

‎packages/pigeon/lib/pigeon_lib.dart‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ const List<String> _validTypes = <String>[
2727
'Map',
2828
];
2929

30+
class _Asynchronous {
31+
const _Asynchronous();
32+
}
33+
34+
/// Metadata to annotate a Api method as asynchronous
35+
const _Asynchronous async = _Asynchronous();
36+
3037
/// Metadata to annotate a Pigeon API implemented by the host-platform.
3138
///
3239
/// The abstract class with this annotation groups a collection of Dart↔host
@@ -224,14 +231,20 @@ class Pigeon {
224231
final List<Method> functions = <Method>[];
225232
for (DeclarationMirror declaration in apiMirror.declarations.values) {
226233
if (declaration is MethodMirror && !declaration.isConstructor) {
234+
final bool isAsynchronous =
235+
declaration.metadata.any((InstanceMirror it) {
236+
return MirrorSystem.getName(it.type.simpleName) ==
237+
'${async.runtimeType}';
238+
});
227239
functions.add(Method()
228240
..name = MirrorSystem.getName(declaration.simpleName)
229241
..argType = declaration.parameters.isEmpty
230242
? 'void'
231243
: MirrorSystem.getName(
232244
declaration.parameters[0].type.simpleName)
233245
..returnType =
234-
MirrorSystem.getName(declaration.returnType.simpleName));
246+
MirrorSystem.getName(declaration.returnType.simpleName)
247+
..isAsynchronous = isAsynchronous);
235248
}
236249
}
237250
final HostApi hostApi = _getHostApi(apiMirror);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright 2020 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'package:pigeon/pigeon.dart';
6+
7+
class Value {
8+
int number;
9+
}
10+
11+
@HostApi()
12+
abstract class Api2Host {
13+
@async
14+
Value calculate(Value value);
15+
}
16+
17+
@FlutterApi()
18+
abstract class Api2Flutter {
19+
@async
20+
Value calculate(Value value);
21+
}

‎packages/pigeon/run_tests.sh‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ test_pigeon_android ./pigeons/void_arg_host.dart
9696
test_pigeon_android ./pigeons/void_arg_flutter.dart
9797
test_pigeon_android ./pigeons/list.dart
9898
test_pigeon_android ./pigeons/all_datatypes.dart
99+
test_pigeon_android ./pigeons/async_handlers.dart
99100
test_pigeon_ios ./pigeons/message.dart
100101
test_pigeon_ios ./pigeons/host2flutter.dart
101102
test_pigeon_ios ./pigeons/voidhost.dart
@@ -104,6 +105,8 @@ test_pigeon_ios ./pigeons/void_arg_host.dart
104105
test_pigeon_ios ./pigeons/void_arg_flutter.dart
105106
test_pigeon_ios ./pigeons/list.dart
106107
test_pigeon_ios ./pigeons/all_datatypes.dart
108+
# Not implemented yet.
109+
# test_pigeon_ios ./pigeons/async_handlers.dart
107110

108111
###############################################################################
109112
# Mock handler flutter tests.

0 commit comments

Comments
 (0)