@@ -94,6 +94,33 @@ class ObjCSelector {
9494 final String value;
9595}
9696
97+ /// Type of TaskQueue which determines how handlers are dispatched for
98+ /// HostApi's.
99+ enum TaskQueueType {
100+ /// Handlers are invoked serially on the default thread. This is the value if
101+ /// unspecified.
102+ serial,
103+
104+ /// Handlers are invoked serially on a background thread.
105+ serialBackgroundThread,
106+
107+ // TODO(gaaclarke): Add support for concurrent task queues.
108+ // /// Handlers are invoked concurrently on a background thread.
109+ // concurrentBackgroundThread,
110+ }
111+
112+ /// Metadata annotation to control how handlers are dispatched for HostApi's.
113+ /// Note that the TaskQueue API might not be available on the target version of
114+ /// Flutter, see also:
115+ /// https://docs.flutter.dev/development/platform-integration/platform-channels.
116+ class TaskQueue {
117+ /// The constructor for a TaskQueue.
118+ const TaskQueue ({required this .type});
119+
120+ /// The type of the TaskQueue.
121+ final TaskQueueType type;
122+ }
123+
97124/// Represents an error as a result of parsing and generating code.
98125class Error {
99126 /// Parametric constructor for Error.
@@ -507,6 +534,13 @@ List<Error> _validateAst(Root root, String source) {
507534 ));
508535 }
509536 }
537+ if (method.taskQueueType != TaskQueueType .serial &&
538+ api.location != ApiLocation .host) {
539+ result.add (Error (
540+ message: 'Unsupported TaskQueue specification on ${method .name }' ,
541+ lineNumber: _calculateLineNumberNullable (source, method.offset),
542+ ));
543+ }
510544 }
511545 }
512546
@@ -757,6 +791,18 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor<Object?> {
757791 return null ;
758792 }
759793
794+ T ? _stringToEnum <T >(List <T > values, String ? str) {
795+ if (str == null ) {
796+ return null ;
797+ }
798+ for (final T value in values) {
799+ if (value.toString () == str) {
800+ return value;
801+ }
802+ }
803+ return null ;
804+ }
805+
760806 @override
761807 Object ? visitMethodDeclaration (dart_ast.MethodDeclaration node) {
762808 final dart_ast.FormalParameterList parameters = node.parameters! ;
@@ -770,6 +816,17 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor<Object?> {
770816 .asNullable< dart_ast.SimpleStringLiteral > ()
771817 ? .value ??
772818 '' ;
819+ final dart_ast.ArgumentList ? taskQueueArguments =
820+ _findMetadata (node.metadata, 'TaskQueue' )? .arguments;
821+ final String ? taskQueueTypeName = taskQueueArguments == null
822+ ? null
823+ : getFirstChildOfType< dart_ast.NamedExpression > (taskQueueArguments)
824+ ? .expression
825+ .asNullable< dart_ast.PrefixedIdentifier > ()
826+ ? .name;
827+ final TaskQueueType taskQueueType =
828+ _stringToEnum (TaskQueueType .values, taskQueueTypeName) ??
829+ TaskQueueType .serial;
773830 if (_currentApi != null ) {
774831 // Methods without named return types aren't supported.
775832 final dart_ast.TypeAnnotation returnType = node.returnType! ;
@@ -785,7 +842,8 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor<Object?> {
785842 arguments: arguments,
786843 isAsynchronous: isAsynchronous,
787844 objcSelector: objcSelector,
788- offset: node.offset));
845+ offset: node.offset,
846+ taskQueueType: taskQueueType));
789847 } else if (_currentClass != null ) {
790848 _errors.add (Error (
791849 message:
0 commit comments