diff --git a/protobuf/CHANGELOG.md b/protobuf/CHANGELOG.md index f48bd8bc5..7fa100fca 100644 --- a/protobuf/CHANGELOG.md +++ b/protobuf/CHANGELOG.md @@ -1,3 +1,19 @@ +## 4.0.0-dev + +* The following types and members are now removed: + + - `PbEventMixin` + - `PbFieldChange` + - `EventBuffer` + - `GeneratedMessage.createRepeatedField` + - `GeneratedMessage.createMapField` + + These were used to implement events, which are unused internally. To keep API + surface small (to make it easier to change the library or migrate to another + library) these types and members are removed. ([#738]) + +[#738]: https://github.com/google/protobuf.dart/issues/738 + ## 3.1.0 * `CodedBufferReader` `readBytes` now copies the returned bytes to avoid diff --git a/protobuf/lib/meta.dart b/protobuf/lib/meta.dart index 519bbd052..2b249d18d 100644 --- a/protobuf/lib/meta.dart +++ b/protobuf/lib/meta.dart @@ -21,9 +21,6 @@ const GeneratedMessage_reservedNames = [ 'clone', 'copyWith', 'createEmptyInstance', - 'createMapField', - 'createRepeatedField', - 'eventPlugin', 'extensionsAreInitialized', 'freeze', 'getDefaultForField', diff --git a/protobuf/lib/protobuf.dart b/protobuf/lib/protobuf.dart index 63e6e3f77..ec5ae7e6d 100644 --- a/protobuf/lib/protobuf.dart +++ b/protobuf/lib/protobuf.dart @@ -28,7 +28,6 @@ part 'src/protobuf/coded_buffer.dart'; part 'src/protobuf/coded_buffer_reader.dart'; part 'src/protobuf/coded_buffer_writer.dart'; part 'src/protobuf/consts.dart'; -part 'src/protobuf/event_plugin.dart'; part 'src/protobuf/exceptions.dart'; part 'src/protobuf/extension.dart'; part 'src/protobuf/extension_field_set.dart'; diff --git a/protobuf/lib/src/protobuf/event_plugin.dart b/protobuf/lib/src/protobuf/event_plugin.dart deleted file mode 100644 index 8e752d380..000000000 --- a/protobuf/lib/src/protobuf/event_plugin.dart +++ /dev/null @@ -1,31 +0,0 @@ -part of '../../protobuf.dart'; - -/// An `EventPlugin` receives callbacks when the fields of a [GeneratedMessage] -/// change. -/// -/// A [GeneratedMessage] mixin can install a plugin by overriding the -/// [GeneratedMessage.eventPlugin] property. The intent is provide mechanism, -/// not policy; each mixin defines its own public API, perhaps using streams. -/// -/// This is a low-level, synchronous API. Event handlers are called in the -/// middle of protobuf changes. To avoid exposing half-finished changes to user -/// code, plugins should buffer events and send them asynchronously. (See -/// `event_mixin.dart` for an example.) -abstract class EventPlugin { - /// Initializes the plugin. - /// - /// [GeneratedMessage] calls this once in its constructors. - void attach(GeneratedMessage parent); - - /// If false, [GeneratedMessage] will skip calls to event handlers. - bool get hasObservers; - - /// Called before setting a field. - /// - /// For repeated fields, this will be called when the list is created. - /// (For example in [GeneratedMessage.getField] and merge methods.) - void beforeSetField(FieldInfo fi, Object? newValue); - - /// Called before clearing a field. - void beforeClearField(FieldInfo fi); -} diff --git a/protobuf/lib/src/protobuf/extension_field_set.dart b/protobuf/lib/src/protobuf/extension_field_set.dart index 723390938..f90bb9096 100644 --- a/protobuf/lib/src/protobuf/extension_field_set.dart +++ b/protobuf/lib/src/protobuf/extension_field_set.dart @@ -39,7 +39,7 @@ class _ExtensionFieldSet { /// /// If it doesn't exist, creates the list and saves the extension. /// Suitable for public API and decoders. - List _ensureRepeatedField(Extension fi) { + PbList _ensureRepeatedField(Extension fi) { assert(!_isReadOnly); assert(fi.isRepeated); assert(fi.extendee == '' || fi.extendee == _parent._messageName); @@ -50,17 +50,17 @@ class _ExtensionFieldSet { return _addInfoAndCreateList(fi); } - List _getList(Extension fi) { + PbList _getList(Extension fi) { final value = _values[fi.tagNumber]; if (value != null) return value; _checkNotInUnknown(fi); - if (_isReadOnly) return List.unmodifiable(const []); + if (_isReadOnly) return PbList.unmodifiable(); return _addInfoAndCreateList(fi); } - List _addInfoAndCreateList(Extension fi) { + PbList _addInfoAndCreateList(Extension fi) { _validateInfo(fi); - final newList = fi._createRepeatedField(_parent._message!); + final newList = fi._createRepeatedField(); _addInfoUnchecked(fi); _setFieldUnchecked(fi, newList); return newList; @@ -76,10 +76,6 @@ class _ExtensionFieldSet { void _clearField(Extension fi) { _ensureWritable(); _validateInfo(fi); - final eventPlugin = _parent._eventPlugin; - if (eventPlugin != null && eventPlugin.hasObservers) { - eventPlugin.beforeClearField(fi); - } _values.remove(fi.tagNumber); } @@ -134,10 +130,6 @@ class _ExtensionFieldSet { } void _setFieldUnchecked(Extension fi, value) { - final eventPlugin = _parent._eventPlugin; - if (eventPlugin != null && eventPlugin.hasObservers) { - eventPlugin.beforeSetField(fi, value); - } // If there was already an unknown field with the same tag number, // overwrite it. _parent._unknownFields?.clearField(fi.tagNumber); diff --git a/protobuf/lib/src/protobuf/field_info.dart b/protobuf/lib/src/protobuf/field_info.dart index 070d5ea88..59a3509cc 100644 --- a/protobuf/lib/src/protobuf/field_info.dart +++ b/protobuf/lib/src/protobuf/field_info.dart @@ -215,23 +215,20 @@ class FieldInfo { } } - /// Creates a repeated field to be attached to the given message. - /// - /// Delegates actual list creation to the message, so that it can - /// be overridden by a mixin. - List _createRepeatedField(GeneratedMessage m) { + /// Creates a repeated field. + PbList _createRepeatedField() { assert(isRepeated); - return m.createRepeatedField(tagNumber, this); + return PbList(check: check!); } - /// Same as above, but allow a tighter typed List to be created. - List _createRepeatedFieldWithType(GeneratedMessage m) { + /// Same as above, but allow a tighter typed [PbList] to be created. + PbList _createRepeatedFieldWithType() { assert(isRepeated); - return m.createRepeatedField(tagNumber, this as FieldInfo); + return PbList(check: check!); } /// Convenience method to thread this FieldInfo's reified type parameter to - /// _FieldSet._ensureRepeatedField. + /// `_FieldSet._ensureRepeatedField`. List _ensureRepeatedField(BuilderInfo meta, _FieldSet fs) { return fs._ensureRepeatedField(meta, this); } @@ -292,12 +289,12 @@ class MapFieldInfo extends FieldInfo?> { FieldInfo get valueFieldInfo => mapEntryBuilderInfo.fieldInfo[PbMap._valueFieldNumber]!; - Map _ensureMapField(BuilderInfo meta, _FieldSet fs) { + PbMap _ensureMapField(BuilderInfo meta, _FieldSet fs) { return fs._ensureMapField(meta, this); } - Map _createMapField(GeneratedMessage m) { + PbMap _createMapField() { assert(isMapField); - return m.createMapField(tagNumber, this); + return PbMap(keyFieldType, valueFieldType); } } diff --git a/protobuf/lib/src/protobuf/field_set.dart b/protobuf/lib/src/protobuf/field_set.dart index fc3db2b5f..fe5b7e042 100644 --- a/protobuf/lib/src/protobuf/field_set.dart +++ b/protobuf/lib/src/protobuf/field_set.dart @@ -21,7 +21,6 @@ void _throwFrozenMessageModificationError(String messageName, /// JavaScript. class _FieldSet { final GeneratedMessage? _message; - final EventPlugin? _eventPlugin; /// The value of each non-extension field in a fixed-length array. /// The index of a field can be found in [FieldInfo.index]. @@ -74,7 +73,7 @@ class _FieldSet { /// the index is not present, the oneof field is unset. final Map? _oneofCases; - _FieldSet(this._message, BuilderInfo meta, this._eventPlugin) + _FieldSet(this._message, BuilderInfo meta) : _values = _makeValueList(meta.byIndex.length), _oneofCases = meta.oneofs.isEmpty ? null : {}; @@ -227,10 +226,6 @@ class _FieldSet { assert(tagNumber == fi.tagNumber); // Clear a non-extension field - final eventPlugin = _eventPlugin; - if (eventPlugin != null && eventPlugin.hasObservers) { - eventPlugin.beforeClearField(fi); - } _values[fi.index!] = null; final oneofIndex = meta.oneofs[tagNumber]; @@ -302,7 +297,7 @@ class _FieldSet { /// Creates and stores the repeated field if it doesn't exist. /// If it's an extension and the list doesn't exist, validates and stores it. /// Suitable for decoders. - List _ensureRepeatedField(BuilderInfo meta, FieldInfo fi) { + PbList _ensureRepeatedField(BuilderInfo meta, FieldInfo fi) { assert(!_isReadOnly); assert(fi.isRepeated); if (fi.index == null) { @@ -311,7 +306,7 @@ class _FieldSet { final value = _getFieldOrNull(fi); if (value != null) return value; - final newValue = fi._createRepeatedField(_message!); + final newValue = fi._createRepeatedField(); _setNonExtensionFieldUnchecked(meta, fi, newValue); return newValue; } @@ -324,9 +319,9 @@ class _FieldSet { final value = _getFieldOrNull(fi); if (value != null) return value; - final newValue = fi._createMapField(_message!); + final newValue = fi._createMapField(); _setNonExtensionFieldUnchecked(meta, fi, newValue); - return newValue as PbMap; + return newValue; } /// Sets a non-extended field and fires events. @@ -341,14 +336,6 @@ class _FieldSet { _oneofCases![oneofIndex] = tag; } - // It is important that the callback to the observers is not moved to the - // beginning of this method but happens just before the value is set. - // Otherwise the observers will be notified about 'clearField' and - // 'setField' events in an incorrect order. - final eventPlugin = _eventPlugin; - if (eventPlugin != null && eventPlugin.hasObservers) { - eventPlugin.beforeSetField(fi, value); - } _values[fi.index!] = value; } @@ -394,7 +381,7 @@ class _FieldSet { return fi.readonlyDefault; } - final list = fi._createRepeatedFieldWithType(_message!); + final list = fi._createRepeatedFieldWithType(); _setNonExtensionFieldUnchecked(_meta, fi, list); return list; } @@ -412,7 +399,7 @@ class _FieldSet { PbMap(fi.keyFieldType, fi.valueFieldType)); } - final map = fi._createMapField(_message!); + final map = fi._createMapField(); _setNonExtensionFieldUnchecked(_meta, fi, map); return map; } @@ -486,10 +473,6 @@ class _FieldSet { if (value == null) { _$check(index, value); // throw exception for null value } - final eventPlugin = _eventPlugin; - if (eventPlugin != null && eventPlugin.hasObservers) { - eventPlugin.beforeSetField(_nonExtensionInfoByIndex(index), value); - } final meta = _meta; final tag = meta.byIndex[index].tagNumber; final oneofIndex = meta.oneofs[tag]; @@ -516,25 +499,8 @@ class _FieldSet { if (_unknownFields != null) { _unknownFields!.clear(); } - - final extensions = _extensions; - - final eventPlugin = _eventPlugin; - if (eventPlugin != null && eventPlugin.hasObservers) { - for (final fi in _infos) { - if (_values[fi.index!] != null) { - eventPlugin.beforeClearField(fi); - } - } - if (extensions != null) { - for (final key in extensions._tagNumbers) { - final fi = extensions._getInfoOrNull(key)!; - eventPlugin.beforeClearField(fi); - } - } - } if (_values.isNotEmpty) _values.fillRange(0, _values.length, null); - extensions?._clearValues(); + _extensions?._clearValues(); } bool _equals(_FieldSet o) { @@ -882,15 +848,13 @@ class _FieldSet { if (fieldInfo.isMapField) { final PbMap? map = _values[index]; if (map != null) { - _values[index] = (fieldInfo as MapFieldInfo) - ._createMapField(_message!) + _values[index] = (fieldInfo as MapFieldInfo)._createMapField() ..addAll(map); } } else if (fieldInfo.isRepeated) { final PbList? list = _values[index]; if (list != null) { - _values[index] = fieldInfo._createRepeatedField(_message!) - ..addAll(list); + _values[index] = fieldInfo._createRepeatedField()..addAll(list); } } } diff --git a/protobuf/lib/src/protobuf/generated_message.dart b/protobuf/lib/src/protobuf/generated_message.dart index 6da4bdfd7..6239e0ec5 100644 --- a/protobuf/lib/src/protobuf/generated_message.dart +++ b/protobuf/lib/src/protobuf/generated_message.dart @@ -31,17 +31,22 @@ abstract class GeneratedMessage { _FieldSet get _fieldSet => __fieldSet!; GeneratedMessage() { - __fieldSet = _FieldSet(this, info_, eventPlugin); - if (eventPlugin != null) eventPlugin!.attach(this); + __fieldSet = _FieldSet(this, info_); + + // The following two returns confuse dart2js into avoiding inlining the + // constructor *body*. A `@pragma('dart2js:never-inline')` annotation on + // the constructor affects inlining of the generative constructor factory, + // not the constructor body that is called from all the subclasses. + // + // TODO(http://dartbug.com/49475): Remove this when there is an annotation + // that will give the desired result. + return; + return; // ignore: dead_code } // Overridden by subclasses. BuilderInfo get info_; - /// Subclasses can override this getter to be notified of changes - /// to protobuf fields. - EventPlugin? get eventPlugin => null; - /// Creates a deep copy of the fields in this message. /// (The generated code uses [mergeFromMessage].) @Deprecated('Using this can add significant size overhead to your binary. ' @@ -331,19 +336,6 @@ abstract class GeneratedMessage { /// default value if it is not set. dynamic getField(int tagNumber) => _fieldSet._getField(tagNumber); - /// Creates List implementing a mutable repeated field. - /// - /// Mixins may override this method to change the List type. To ensure - /// that the protobuf can be encoded correctly, the returned List must - /// validate all items added to it. This can most easily be done - /// using the [FieldInfo.check] function. - List createRepeatedField(int tagNumber, FieldInfo fi) => - PbList(check: fi.check!); - - /// Creates a Map representing a map field. - Map createMapField(int tagNumber, MapFieldInfo fi) => - PbMap(fi.keyFieldType, fi.valueFieldType); - /// Returns the value of a field, ignoring any defaults. /// /// For unset or cleared fields, returns null. diff --git a/protobuf/lib/src/protobuf/json.dart b/protobuf/lib/src/protobuf/json.dart index 9f66e109d..a59d2ca50 100644 --- a/protobuf/lib/src/protobuf/json.dart +++ b/protobuf/lib/src/protobuf/json.dart @@ -139,10 +139,10 @@ void _appendJsonList(BuilderInfo meta, _FieldSet fs, List jsonList, void _appendJsonMap(BuilderInfo meta, _FieldSet fs, List jsonList, MapFieldInfo fi, ExtensionRegistry? registry) { final entryMeta = fi.mapEntryBuilderInfo; - final map = fi._ensureMapField(meta, fs) as PbMap; + final map = fi._ensureMapField(meta, fs); for (final jsonEntryDynamic in jsonList) { final jsonEntry = jsonEntryDynamic as Map; - final entryFieldSet = _FieldSet(null, entryMeta, null); + final entryFieldSet = _FieldSet(null, entryMeta); final convertedKey = _convertJsonValue( entryMeta, entryFieldSet, diff --git a/protobuf/lib/src/protobuf/mixins/event_mixin.dart b/protobuf/lib/src/protobuf/mixins/event_mixin.dart deleted file mode 100644 index b402242c6..000000000 --- a/protobuf/lib/src/protobuf/mixins/event_mixin.dart +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:async' show StreamController, scheduleMicrotask; -import 'dart:collection' show UnmodifiableListView; - -import '../../../protobuf.dart' show EventPlugin, FieldInfo, GeneratedMessage; - -/// Provides a stream of changes to fields in a [GeneratedMessage]. -/// (Experimental.) -/// -/// This mixin is enabled via an option in dart_options.proto in -/// dart-protoc-plugin. -mixin PbEventMixin { - final eventPlugin = EventBuffer(); - - /// A stream of changes to fields in the GeneratedMessage. - /// - /// Events are buffered and delivered via a microtask or in - /// the next call to [deliverChanges], whichever happens first. - Stream> get changes => eventPlugin.changes; - - /// Delivers buffered field change events synchronously, - /// instead of waiting for the microtask to run. - void deliverChanges() => eventPlugin.deliverChanges(); -} - -/// A change to a field in a [GeneratedMessage]. -class PbFieldChange { - final GeneratedMessage? message; - final FieldInfo info; - final Object? oldValue; - final Object? newValue; - - PbFieldChange(this.message, this.info, this.oldValue, this.newValue); - - int get tag => info.tagNumber; -} - -/// A buffering implementation of event delivery. -/// (Loosely based on package:observe's ChangeNotifier.) -class EventBuffer extends EventPlugin { - // An EventBuffer is created for each GeneratedMessage, so - // initialization should be fast; create fields lazily. - - GeneratedMessage? _parent; - StreamController>? _controller; - - // If _buffer is non-null, at least one event is in the buffer - // and a microtask has been scheduled to empty it. - List? _buffer; - - @override - void attach(GeneratedMessage parent) { - assert(_parent == null); - ArgumentError.checkNotNull(parent, 'parent'); - _parent = parent; - } - - Stream> get changes { - final controller = _controller ??= StreamController.broadcast(sync: true); - return controller.stream; - } - - @override - bool get hasObservers => _controller != null && _controller!.hasListener; - - void deliverChanges() { - final records = _buffer; - _buffer = null; - if (records != null && hasObservers) { - _controller!.add(UnmodifiableListView(records)); - } - } - - void addEvent(PbFieldChange change) { - if (!hasObservers) return; - if (_buffer == null) { - _buffer = []; - scheduleMicrotask(deliverChanges); - } - _buffer!.add(change); - } - - @override - void beforeSetField(FieldInfo fi, Object? newValue) { - var oldValue = _parent!.getFieldOrNull(fi.tagNumber); - oldValue ??= fi.readonlyDefault; - if (identical(oldValue, newValue)) return; - addEvent(PbFieldChange(_parent, fi, oldValue, newValue)); - } - - @override - void beforeClearField(FieldInfo fi) { - final oldValue = _parent!.getFieldOrNull(fi.tagNumber); - if (oldValue == null) return; - final newValue = fi.readonlyDefault; - addEvent(PbFieldChange(_parent, fi, oldValue, newValue)); - } -} diff --git a/protobuf/lib/src/protobuf/pb_map.dart b/protobuf/lib/src/protobuf/pb_map.dart index c8f6ef731..5d9bc6064 100644 --- a/protobuf/lib/src/protobuf/pb_map.dart +++ b/protobuf/lib/src/protobuf/pb_map.dart @@ -99,7 +99,7 @@ class PbMap extends MapBase { final length = input.readInt32(); final oldLimit = input._currentLimit; input._currentLimit = input._bufferPos + length; - final entryFieldSet = _FieldSet(null, mapEntryMeta, null); + final entryFieldSet = _FieldSet(null, mapEntryMeta); _mergeFromCodedBufferReader(mapEntryMeta, entryFieldSet, input, registry); input.checkLastTagWas(0); input._currentLimit = oldLimit; diff --git a/protobuf/pubspec.yaml b/protobuf/pubspec.yaml index 00faaf7f1..aeaf84223 100644 --- a/protobuf/pubspec.yaml +++ b/protobuf/pubspec.yaml @@ -1,5 +1,5 @@ name: protobuf -version: 3.1.0 +version: 4.0.0-dev description: >- Runtime library for protocol buffers support. Use with package:protoc_plugin to generate dart code for your '.proto' files. diff --git a/protobuf/test/event_test.dart b/protobuf/test/event_test.dart deleted file mode 100644 index 9be7a9a95..000000000 --- a/protobuf/test/event_test.dart +++ /dev/null @@ -1,294 +0,0 @@ -// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -// Tests event delivery using PbEventMixin. - -import 'package:protobuf/protobuf.dart'; -import 'package:protobuf/src/protobuf/mixins/event_mixin.dart' - show PbEventMixin, PbFieldChange; -import 'package:test/test.dart' show expect, test; - -import 'mock_util.dart' show MockMessage, mockInfo; - -class Rec extends MockMessage with PbEventMixin { - @override - BuilderInfo get info_ => _info; - static final _info = mockInfo('Rec', Rec.new); - @override - Rec createEmptyInstance() => Rec(); -} - -Extension comment = Extension('Rec', 'comment', 6, PbFieldType.OS); - -void main() { - test('Events are sent when setting and clearing a non-repeated field', () { - final log = makeLog(); - final r = Rec(); - r.changes.listen(log.add); - - r.val = 123; - r.deliverChanges(); - checkLogOnce(log, [1, 42, 123]); - - r.val = 456; - r.deliverChanges(); - checkLogOnce(log, [1, 123, 456]); - - r.val = 456; // no change - r.deliverChanges(); - checkLog(log, []); - - r.clearField(1); - r.deliverChanges(); - checkLogOnce(log, [1, 456, 42]); - - r.clearField(1); // no change - r.deliverChanges(); - checkLog(log, []); - }); - - test('Events are sent when creating and clearing a repeated field', () { - final log = makeLog(); - final r = Rec(); - r.changes.listen(log.add); - - // Accessing a repeated field replaces the default, - // read-only [] with a mutable [], - // which counts as a change. - final list = r.int32s; - r.deliverChanges(); - checkLogOnce(log, [4, [], []]); - - // No event yet for modifying a repeated field. - list.add(123); - r.deliverChanges(); - checkLog(log, []); - - r.clearField(4); - r.deliverChanges(); - checkLogOnce(log, [ - 4, - [123], - [] - ]); - }); - - test('Events are sent when clearing multiple fields', () { - final log = makeLog(); - final r = Rec() - ..val = 123 - ..str = 'hello' - ..child = Rec() - ..int32s.add(456); - - r.changes.listen((List changes) { - // verify that we are not called until all fields are cleared - checkHasAllFields(r, false); - log.add(changes); - }); - - r.clear(); - r.deliverChanges(); - checkLog(log, [ - [ - [1, 123, 42], - [2, 'hello', ''], - [3, '', ''], - [ - 4, - [456], - [] - ] - ] - ]); - }); - - test('Events are sent when merging from another protobuf', () { - final log = makeLog(); - final src = Rec() - ..val = 123 - ..str = 'hello' - ..child = Rec() - ..int32s.add(456); - - final dest = Rec(); - dest.changes.listen((List changes) { - checkHasAllFields(dest, true); - log.add(changes); - }); - - dest.mergeFromMessage(src); - dest.deliverChanges(); - checkLog(log, [ - [ - [1, 42, 123], - [2, '', 'hello'], - [3, '', ''], - [ - 4, - [], - [456] - ] - ] - ]); - }); - - test('Events are sent when merging JSON', () { - final log = makeLog(); - final r = Rec(); - r.changes.listen((List changes) { - // verify that we are not called until all fields are set - checkHasAllFields(r, true); - log.add(changes); - }); - - r.mergeFromJson('{"1": 123, "2": "hello", "3": {}, "4": [456]}'); - // The changes should not include the repeated message. - r.deliverChanges(); - checkLog(log, [ - [ - [1, 42, 123], - [2, '', 'hello'], - [3, '', ''], - [ - 4, - [], - [456] - ] - ] - ]); - }); - - test('Events are sent when merging binary', () { - final log = makeLog(); - - final bytes = (Rec() - ..val = 123 - ..str = 'hello' - ..child = Rec() - ..int32s.add(456)) - .writeToBuffer(); - - final r = Rec(); - r.changes.listen((List changes) { - // verify that we are not called until all fields are set - checkHasAllFields(r, true); - log.add(changes); - }); - - r.mergeFromBuffer(bytes); - // The changes should not include the repeated message. - r.deliverChanges(); - checkLog(log, [ - [ - [1, 42, 123], - [2, '', 'hello'], - [3, '', ''], - [ - 4, - [], - [456] - ] - ] - ]); - }); - - test('Events are sent for extensions', () { - final log = makeLog(); - final r = Rec(); - r.changes.listen(log.add); - - final tag = comment.tagNumber; - void setComment(String value) { - r.setExtension(comment, value); - expect(r.getExtension(comment), value); - r.deliverChanges(); - checkLogOnce(log, [tag, '', value]); - } - - void clear(String expected) { - r.clear(); - r.deliverChanges(); - checkLogOnce(log, [tag, expected, '']); - } - - setComment('hello'); - clear('hello'); - - setComment('hello'); - r.setField(6, 'hi'); - r.deliverChanges(); - checkLogOnce(log, [tag, 'hello', 'hi']); - clear('hi'); - - setComment('hello'); - r.clearExtension(comment); - r.deliverChanges(); - checkLogOnce(log, [tag, 'hello', '']); - - setComment('hello'); - r.clearField(comment.tagNumber); - r.deliverChanges(); - checkLogOnce(log, [tag, 'hello', '']); - - final registry = ExtensionRegistry()..add(comment); - r.mergeFromJson('{"$tag": "hello"}', registry); - expect(r.getExtension(comment), 'hello'); - r.deliverChanges(); - checkLogOnce(log, [tag, '', 'hello']); - clear('hello'); - - final src = Rec()..setExtension(comment, 'hello'); - r.mergeFromMessage(src); - expect(r.getExtension(comment), 'hello'); - r.deliverChanges(); - checkLogOnce(log, [tag, '', 'hello']); - clear('hello'); - - final bytes = src.writeToBuffer(); - r.mergeFromBuffer(bytes, registry); - expect(r.getExtension(comment), 'hello'); - r.deliverChanges(); - checkLogOnce(log, [tag, '', 'hello']); - clear('hello'); - }); -} - -List> makeLog() => >[]; - -void checkLogOnce(List> log, List expectedEntry) => - checkLog(log, [ - [expectedEntry] - ]); - -void checkLog(List> log, List> expected) { - final actual = >[]; - for (final list in log) { - final tuples = []; - for (final item in list) { - tuples.add(toTuple(item)); - } - actual.add(tuples); - } - log.clear(); - expect(actual, expected); -} - -void checkHasAllFields(Rec r, bool expected) { - expect(r.hasField(1), expected); - expect(r.hasField(2), expected); - expect(r.hasField(3), expected); - expect(r.hasField(4), expected); -} - -List toTuple(PbFieldChange fc) { - dynamic fixValue(v) { - if (v is GeneratedMessage) { - return ''; - } - return v; - } - - return [fc.tag, fixValue(fc.oldValue), fixValue(fc.newValue)]; -} diff --git a/protoc_plugin/CHANGELOG.md b/protoc_plugin/CHANGELOG.md index 925278b81..566346ce9 100644 --- a/protoc_plugin/CHANGELOG.md +++ b/protoc_plugin/CHANGELOG.md @@ -1,3 +1,9 @@ +## 22.0.0-dev + +* Remove `PbEventMixin` mixin. ([#738]) + +[#738]: https://github.com/google/protobuf.dart/issues/738 + ## 21.1.2 * Fix a bug in comment parsing. ([#871], [#879]) diff --git a/protoc_plugin/lib/mixins.dart b/protoc_plugin/lib/mixins.dart index f577d6966..ee04fbf33 100644 --- a/protoc_plugin/lib/mixins.dart +++ b/protoc_plugin/lib/mixins.dart @@ -12,7 +12,6 @@ import 'indenting_writer.dart'; PbMixin? findMixin(String name) { const exportedMixins = { 'PbMapMixin': _pbMapMixin, - 'PbEventMixin': _pbEventMixin, }; return exportedMixins[name]; } @@ -86,10 +85,6 @@ const _pbMapMixin = PbMixin('PbMapMixin', importFrom: 'package:protobuf/src/protobuf/mixins/map_mixin.dart', parent: _mapMixin); -const _pbEventMixin = PbMixin('PbEventMixin', - importFrom: 'package:protobuf/src/protobuf/mixins/event_mixin.dart', - reservedNames: ['changes', 'deliverChanges']); - const List _reservedNamesForMap = [ '[]', '[]=', diff --git a/protoc_plugin/pubspec.yaml b/protoc_plugin/pubspec.yaml index 2c7928774..14c96de1a 100644 --- a/protoc_plugin/pubspec.yaml +++ b/protoc_plugin/pubspec.yaml @@ -1,5 +1,5 @@ name: protoc_plugin -version: 21.1.2 +version: 22.0.0-dev description: A protobuf protoc compiler plugin used to generate Dart code. repository: https://github.com/google/protobuf.dart/tree/master/protoc_plugin diff --git a/protoc_plugin/test/reserved_names_test.dart b/protoc_plugin/test/reserved_names_test.dart index 92ad1d4e1..8298ad013 100644 --- a/protoc_plugin/test/reserved_names_test.dart +++ b/protoc_plugin/test/reserved_names_test.dart @@ -10,8 +10,6 @@ import 'package:protobuf/meta.dart' // Import the libraries we will access via the mirrors. // ignore_for_file: unused_import import 'package:protobuf/protobuf.dart' show GeneratedMessage, ProtobufEnum; -import 'package:protobuf/src/protobuf/mixins/event_mixin.dart' - show PbEventMixin; import 'package:protobuf/src/protobuf/mixins/map_mixin.dart' show PbMapMixin; import 'package:protoc_plugin/mixins.dart' show findMixin; import 'package:test/test.dart'; @@ -58,15 +56,4 @@ void main() { expect( actual.toList()..sort(), containsAllInOrder(expected.toList()..sort())); }); - - test('PbEventMixin reserved names are up to date', () { - final meta = findMixin('PbEventMixin')!; - final actual = Set.from(meta.findReservedNames()); - - final expected = findMemberNames(meta.importFrom, #PbEventMixin) - ..removeAll(GeneratedMessage_reservedNames); - - expect( - actual.toList()..sort(), containsAllInOrder(expected.toList()..sort())); - }); }