-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Pigeon : Support for asynchronous methods/Functions #201
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 8 commits
5ade5a5
6c18031
76c4433
4dedf30
e78437e
15296a5
f06d842
595bc5d
8f20a39
666bf38
2ea5e55
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 |
|---|---|---|
|
|
@@ -29,14 +29,30 @@ class JavaOptions { | |
|
|
||
| void _writeHostApi(Indent indent, Api api) { | ||
| assert(api.location == ApiLocation.host); | ||
|
|
||
| if (api.methods.any((Method it) => it.isAsynchronous)) { | ||
| indent.write('public interface Result<T> '); | ||
| indent.scoped('{', '}', () { | ||
| indent.writeln('void success(T result);'); | ||
| }); | ||
| indent.addln(''); | ||
| } | ||
|
|
||
| indent.writeln( | ||
| '/** Generated interface from Pigeon that represents a handler of messages from Flutter.*/'); | ||
| indent.write('public interface ${api.name} '); | ||
| indent.scoped('{', '}', () { | ||
| for (Method method in api.methods) { | ||
| final String argSignature = | ||
| method.argType == 'void' ? '' : '${method.argType} arg'; | ||
| indent.writeln('${method.returnType} ${method.name}($argSignature);'); | ||
| final String returnType = | ||
| method.isAsynchronous ? 'void' : method.returnType; | ||
| final List<String> argSignature = <String>[]; | ||
| if (method.argType != 'void') { | ||
| argSignature.add('${method.argType} arg'); | ||
| } | ||
| if (method.isAsynchronous) { | ||
| argSignature.add('Result<${method.returnType}> result'); | ||
| } | ||
| indent.writeln('$returnType ${method.name}(${argSignature.join(',')});'); | ||
|
Member
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. nit:
Member
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. Done. |
||
| } | ||
| indent.addln(''); | ||
| indent.writeln( | ||
|
|
@@ -65,17 +81,26 @@ void _writeHostApi(Indent indent, Api api) { | |
| 'HashMap<String, HashMap> wrapped = new HashMap<>();'); | ||
| indent.write('try '); | ||
| indent.scoped('{', '}', () { | ||
| String methodArgument; | ||
| if (argType == 'void') { | ||
| methodArgument = ''; | ||
| } else { | ||
| final List<String> methodArgument = <String>[]; | ||
| if (argType != 'void') { | ||
| indent.writeln('@SuppressWarnings("ConstantConditions")'); | ||
| indent.writeln( | ||
| '$argType input = $argType.fromMap((HashMap)message);'); | ||
| methodArgument = 'input'; | ||
| methodArgument.add('input'); | ||
| } | ||
| final String call = 'api.${method.name}($methodArgument)'; | ||
| if (method.returnType == 'void') { | ||
| if (method.isAsynchronous) { | ||
| methodArgument.add( | ||
| 'result -> {' | ||
| 'wrapped.put("${Keys.result}", result.toMap());' | ||
| 'reply.reply(wrapped);' | ||
| '}', | ||
| ); | ||
| } | ||
| final String call = | ||
| 'api.${method.name}(${methodArgument.join(',')})'; | ||
| if (method.isAsynchronous) { | ||
| indent.writeln('$call;'); | ||
| } else if (method.returnType == 'void') { | ||
| indent.writeln('$call;'); | ||
| indent.writeln('wrapped.put("${Keys.result}", null);'); | ||
| } else { | ||
|
|
@@ -88,8 +113,13 @@ void _writeHostApi(Indent indent, Api api) { | |
| indent.scoped('{', '}', () { | ||
| indent.writeln( | ||
| 'wrapped.put("${Keys.error}", wrapError(exception));'); | ||
| if (method.isAsynchronous) { | ||
| indent.writeln('reply.reply(wrapped);'); | ||
| } | ||
| }); | ||
| indent.writeln('reply.reply(wrapped);'); | ||
| if (!method.isAsynchronous) { | ||
| indent.writeln('reply.reply(wrapped);'); | ||
| } | ||
| }); | ||
| }); | ||
| indent.scoped(null, '}', () { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,13 @@ const List<String> _validTypes = <String>[ | |
| 'Map', | ||
| ]; | ||
|
|
||
| class _Asynchronous { | ||
| const _Asynchronous(); | ||
| } | ||
|
|
||
| /// Metadata to annotate a Api method as asynchronous | ||
| const _Asynchronous async = _Asynchronous(); | ||
|
|
||
| /// Metadata to annotate a Pigeon API implemented by the host-platform. | ||
| /// | ||
| /// The abstract class with this annotation groups a collection of Dart↔host | ||
|
|
@@ -224,14 +231,20 @@ class Pigeon { | |
| final List<Method> functions = <Method>[]; | ||
| for (DeclarationMirror declaration in apiMirror.declarations.values) { | ||
| if (declaration is MethodMirror && !declaration.isConstructor) { | ||
| final bool isAsynchronous = | ||
|
Member
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. Can you switch this so that it is reading in the
Contributor
Author
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. @gaaclarke by adding an @HostApi
abstract class Api {
Future<Foo> doit() async;
}will look more like a broken code as it won't compile. Maybe we can try reading @HostApi
abstract class Api {
Future<Foo> doit();
}
Member
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. Why do you think that looks like broken code? It looks correct to me.
Contributor
Author
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. Because this doesn't compile. It needs a function body. (Due to @HostApi()
abstract class Api {
Future<Foo> doit() async;
} |
||
| declaration.metadata.any((InstanceMirror it) { | ||
| return MirrorSystem.getName(it.type.simpleName) == | ||
| '${async.runtimeType}'; | ||
|
Member
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. Is there no way to do equality checks on the type directly instead of resorting to string checks? |
||
| }); | ||
| functions.add(Method() | ||
| ..name = MirrorSystem.getName(declaration.simpleName) | ||
| ..argType = declaration.parameters.isEmpty | ||
| ? 'void' | ||
| : MirrorSystem.getName( | ||
| declaration.parameters[0].type.simpleName) | ||
| ..returnType = | ||
| MirrorSystem.getName(declaration.returnType.simpleName)); | ||
| MirrorSystem.getName(declaration.returnType.simpleName) | ||
| ..isAsynchronous = isAsynchronous); | ||
| } | ||
| } | ||
| final HostApi hostApi = _getHostApi(apiMirror); | ||
|
|
||
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.
/// Whether the receiver of this method is expected to return synchronously or not.
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.
Done.