-
Notifications
You must be signed in to change notification settings - Fork 3.6k
[pigeon] Adds annotation options to omit shared classes used in Event Channels #8566
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
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 |
|---|---|---|
|
|
@@ -169,7 +169,13 @@ class ProxyApi { | |
| /// defined return type of the method definition. | ||
| class EventChannelApi { | ||
| /// Constructor. | ||
| const EventChannelApi(); | ||
| const EventChannelApi({this.kotlinOptions, this.swiftOptions}); | ||
|
|
||
| /// Options for Kotlin generated code for Event Channels. | ||
| final KotlinEventChannelOptions? kotlinOptions; | ||
|
|
||
| /// Options for Swift generated code for Event Channels. | ||
| final SwiftEventChannelOptions? swiftOptions; | ||
| } | ||
|
|
||
| /// Metadata to annotation methods to control the selector used for objc output. | ||
|
|
@@ -1082,6 +1088,8 @@ List<Error> _validateAst(Root root, String source) { | |
| } | ||
| } | ||
|
|
||
| bool containsEventChannelApi = false; | ||
|
|
||
| for (final Api api in root.apis) { | ||
| final String? matchingPrefix = _findMatchingPrefixOrNull( | ||
| api.name, | ||
|
|
@@ -1093,6 +1101,15 @@ List<Error> _validateAst(Root root, String source) { | |
| 'API name must not begin with "$matchingPrefix" in API "${api.name}"', | ||
| )); | ||
| } | ||
| if (api is AstEventChannelApi) { | ||
| if (containsEventChannelApi) { | ||
| result.add(Error( | ||
| message: | ||
| 'Event Channel methods must all be included in a single EventChannelApi', | ||
|
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. Do we have an issue tracking this? It's definitely low priority, but it's an unintuitive restriction.
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. I can fix it in this pr, it's not super complex. The main issue is that naming collisions aren't managed properly, since all of the methods end up top level when generated.
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. It doesn't need to be in this PR, just seemed worth filing so we had a tracker.
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. filed flutter/flutter#162828 |
||
| )); | ||
| } | ||
| containsEventChannelApi = true; | ||
| } | ||
| if (api is AstProxyApi) { | ||
| result.addAll(_validateProxyApi( | ||
| api, | ||
|
|
@@ -1885,9 +1902,43 @@ class _RootBuilder extends dart_ast_visitor.RecursiveAstVisitor<Object?> { | |
| _documentationCommentsParser(node.documentationComment?.tokens), | ||
| ); | ||
| } else if (_hasMetadata(node.metadata, 'EventChannelApi')) { | ||
| final dart_ast.Annotation annotation = node.metadata.firstWhere( | ||
| (dart_ast.Annotation element) => | ||
| element.name.name == 'EventChannelApi', | ||
| ); | ||
|
|
||
| final Map<String, Object?> annotationMap = <String, Object?>{}; | ||
| for (final dart_ast.Expression expression | ||
| in annotation.arguments!.arguments) { | ||
| if (expression is dart_ast.NamedExpression) { | ||
| annotationMap[expression.name.label.name] = | ||
| _expressionToMap(expression.expression); | ||
| } | ||
| } | ||
|
|
||
| SwiftEventChannelOptions? swiftOptions; | ||
| KotlinEventChannelOptions? kotlinOptions; | ||
| final Map<String, Object?>? swiftOptionsMap = | ||
| annotationMap['swiftOptions'] as Map<String, Object?>?; | ||
| if (swiftOptionsMap != null) { | ||
| swiftOptions = SwiftEventChannelOptions( | ||
| includeSharedClasses: | ||
| swiftOptionsMap['includeSharedClasses'] as bool? ?? true, | ||
| ); | ||
| } | ||
| final Map<String, Object?>? kotlinOptionsMap = | ||
| annotationMap['kotlinOptions'] as Map<String, Object?>?; | ||
| if (kotlinOptionsMap != null) { | ||
| kotlinOptions = KotlinEventChannelOptions( | ||
| includeSharedClasses: | ||
| kotlinOptionsMap['includeSharedClasses'] as bool? ?? true, | ||
| ); | ||
| } | ||
| _currentApi = AstEventChannelApi( | ||
| name: node.name.lexeme, | ||
| methods: <Method>[], | ||
| swiftOptions: swiftOptions, | ||
| kotlinOptions: kotlinOptions, | ||
| documentationComments: | ||
| _documentationCommentsParser(node.documentationComment?.tokens), | ||
| ); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| // 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:pigeon/pigeon.dart'; | ||
|
|
||
| // This file exists to test compilation for multi-file event channel usage. | ||
|
|
||
| @EventChannelApi( | ||
| swiftOptions: SwiftEventChannelOptions(includeSharedClasses: false), | ||
| kotlinOptions: KotlinEventChannelOptions(includeSharedClasses: false)) | ||
| abstract class EventChannelMethods { | ||
| int streamIntsAgain(); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| // 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, 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, unnecessary_import, no_leading_underscores_for_local_identifiers | ||
|
|
||
| import 'dart:async'; | ||
| import 'dart:typed_data' show Float64List, Int32List, Int64List, Uint8List; | ||
|
|
||
| import 'package:flutter/foundation.dart' show ReadBuffer, WriteBuffer; | ||
| import 'package:flutter/services.dart'; | ||
|
|
||
| class _PigeonCodec extends StandardMessageCodec { | ||
| const _PigeonCodec(); | ||
| @override | ||
| void writeValue(WriteBuffer buffer, Object? value) { | ||
| if (value is int) { | ||
| buffer.putUint8(4); | ||
| buffer.putInt64(value); | ||
| } else { | ||
| super.writeValue(buffer, value); | ||
| } | ||
| } | ||
|
|
||
| @override | ||
| Object? readValueOfType(int type, ReadBuffer buffer) { | ||
| switch (type) { | ||
| default: | ||
| return super.readValueOfType(type, buffer); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| const StandardMethodCodec pigeonMethodCodec = | ||
| StandardMethodCodec(_PigeonCodec()); | ||
|
|
||
| Stream<int> streamIntsAgain({String instanceName = ''}) { | ||
| if (instanceName.isNotEmpty) { | ||
| instanceName = '.$instanceName'; | ||
| } | ||
| final EventChannel streamIntsAgainChannel = EventChannel( | ||
| 'dev.flutter.pigeon.pigeon_integration_tests.EventChannelMethods.streamIntsAgain$instanceName', | ||
| pigeonMethodCodec); | ||
| return streamIntsAgainChannel.receiveBroadcastStream().map((dynamic event) { | ||
| return event as int; | ||
| }); | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.