From 7c693dafd64ddedf1f2dae548fe69ef2be82bef7 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 9 Feb 2022 08:03:01 -0800 Subject: [PATCH 1/6] Remove dynamic calls --- analysis_options.yaml | 1 + protobuf/analysis_options.yaml | 1 + protobuf/benchmarks/common.dart | 4 +++ protobuf/lib/src/protobuf/coded_buffer.dart | 11 +++++--- .../lib/src/protobuf/coded_buffer_reader.dart | 2 +- .../lib/src/protobuf/coded_buffer_writer.dart | 26 ++++++++++++------- .../lib/src/protobuf/extension_field_set.dart | 4 +-- .../lib/src/protobuf/extension_registry.dart | 4 +-- protobuf/lib/src/protobuf/field_set.dart | 9 ++++--- protobuf/lib/src/protobuf/json.dart | 8 ++++-- protobuf/lib/src/protobuf/utils.dart | 2 +- protobuf/test/json_test.dart | 4 +++ protobuf/test/list_test.dart | 3 +++ protobuf/test/map_mixin_test.dart | 4 +++ protobuf/test/message_test.dart | 3 +++ protobuf/test/readonly_message_test.dart | 3 +++ 16 files changed, 65 insertions(+), 24 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 91f543368..c09381b6f 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -2,6 +2,7 @@ linter: rules: - always_require_non_null_named_parameters - annotate_overrides + - avoid_dynamic_calls - avoid_empty_else - avoid_function_literals_in_foreach_calls - avoid_init_to_null diff --git a/protobuf/analysis_options.yaml b/protobuf/analysis_options.yaml index e84124713..1b9b71a27 100644 --- a/protobuf/analysis_options.yaml +++ b/protobuf/analysis_options.yaml @@ -2,6 +2,7 @@ include: package:lints/recommended.yaml linter: rules: + - avoid_dynamic_calls - comment_references - directives_ordering - prefer_relative_imports diff --git a/protobuf/benchmarks/common.dart b/protobuf/benchmarks/common.dart index 24a206813..8ae38e049 100644 --- a/protobuf/benchmarks/common.dart +++ b/protobuf/benchmarks/common.dart @@ -8,6 +8,10 @@ /// both on the VM and when compiled to JavaScript. library common; +// TODO(https://github.com/google/protobuf.dart/issues/578): Remove remaining +// dynamic calls. +// ignore_for_file: avoid_dynamic_calls + import 'dart:typed_data'; import 'package:benchmark_harness/benchmark_harness.dart'; diff --git a/protobuf/lib/src/protobuf/coded_buffer.dart b/protobuf/lib/src/protobuf/coded_buffer.dart index 45c3f4e09..6100eef71 100644 --- a/protobuf/lib/src/protobuf/coded_buffer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer.dart @@ -195,7 +195,7 @@ void _mergeFromCodedBufferReader(BuilderInfo meta, _FieldSet fs, } void _readPackable(BuilderInfo meta, _FieldSet fs, CodedBufferReader input, - int wireType, FieldInfo fi, Function readFunc) { + int wireType, FieldInfo fi, Object Function() readFunc) { void readToList(List list) => list.add(readFunc()); _readPackableToList(meta, fs, input, wireType, fi, readToList); } @@ -222,8 +222,13 @@ void _readPackableToListEnum( _readPackableToList(meta, fs, input, wireType, fi, readToList); } -void _readPackableToList(BuilderInfo meta, _FieldSet fs, - CodedBufferReader input, int wireType, FieldInfo fi, Function readToList) { +void _readPackableToList( + BuilderInfo meta, + _FieldSet fs, + CodedBufferReader input, + int wireType, + FieldInfo fi, + void Function(List) readToList) { var list = fs._ensureRepeatedField(meta, fi); if (wireType == WIRETYPE_LENGTH_DELIMITED) { diff --git a/protobuf/lib/src/protobuf/coded_buffer_reader.dart b/protobuf/lib/src/protobuf/coded_buffer_reader.dart index 7dfe56a2f..5384b50aa 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_reader.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_reader.dart @@ -35,7 +35,7 @@ class CodedBufferReader { bool isAtEnd() => _bufferPos >= _currentLimit; - void _withLimit(int byteLimit, callback) { + void _withLimit(int byteLimit, void Function() callback) { if (byteLimit < 0) { throw ArgumentError( 'CodedBufferReader encountered an embedded string or message' diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart index b1821d898..38643b330 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart @@ -64,11 +64,12 @@ class CodedBufferWriter { _commitChunk(true); } - void writeField(int fieldNumber, int fieldType, fieldValue) { + void writeField(int fieldNumber, int fieldType, Object? fieldValue) { final valueType = fieldType & ~0x07; if ((fieldType & PbFieldType._PACKED_BIT) != 0) { - if (!fieldValue.isEmpty) { + fieldValue as List; + if (fieldValue.isNotEmpty) { _writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); final mark = _startLengthDelimited(); for (var value in fieldValue) { @@ -82,17 +83,18 @@ class CodedBufferWriter { final wireFormat = _wireTypes[_valueTypeIndex(valueType)]; if ((fieldType & PbFieldType._MAP_BIT) != 0) { + fieldValue as PbMap; final keyWireFormat = - _wireTypes[_valueTypeIndex(fieldValue.keyFieldType)]; + _wireTypes[_valueTypeIndex(fieldValue.keyFieldType!)]; final valueWireFormat = - _wireTypes[_valueTypeIndex(fieldValue.valueFieldType)]; + _wireTypes[_valueTypeIndex(fieldValue.valueFieldType!)]; fieldValue.forEach((key, value) { _writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); final mark = _startLengthDelimited(); - _writeValue( - PbMap._keyFieldNumber, fieldValue.keyFieldType, key, keyWireFormat); - _writeValue(PbMap._valueFieldNumber, fieldValue.valueFieldType, value, + _writeValue(PbMap._keyFieldNumber, fieldValue.keyFieldType!, key, + keyWireFormat); + _writeValue(PbMap._valueFieldNumber, fieldValue.valueFieldType!, value, valueWireFormat); _endLengthDelimited(mark); }); @@ -100,6 +102,7 @@ class CodedBufferWriter { } if ((fieldType & PbFieldType._REPEATED_BIT) != 0) { + fieldValue as PbList; for (var i = 0; i < fieldValue.length; i++) { _writeValue(fieldNumber, valueType, fieldValue[i], wireFormat); } @@ -349,9 +352,11 @@ class CodedBufferWriter { _writeFloat(value); break; case PbFieldType._ENUM_BIT: + value as ProtobufEnum; _writeVarint32(value.value & 0xffffffff); break; case PbFieldType._GROUP_BIT: + value as GeneratedMessage; value.writeToCodedBufferWriter(this); break; case PbFieldType._INT32_BIT: @@ -386,15 +391,16 @@ class CodedBufferWriter { break; case PbFieldType._MESSAGE_BIT: final mark = _startLengthDelimited(); + value as GeneratedMessage; value.writeToCodedBufferWriter(this); _endLengthDelimited(mark); break; } } - void _writeBytesNoTag(dynamic value) { - writeInt32NoTag(value.length); - writeRawBytes(value); + void _writeBytesNoTag(Object value) { + writeInt32NoTag((value as List).length); + writeRawBytes(value as TypedData); } void _writeTag(int fieldNumber, int wireFormat) { diff --git a/protobuf/lib/src/protobuf/extension_field_set.dart b/protobuf/lib/src/protobuf/extension_field_set.dart index 2497e0361..9723b7470 100644 --- a/protobuf/lib/src/protobuf/extension_field_set.dart +++ b/protobuf/lib/src/protobuf/extension_field_set.dart @@ -172,10 +172,10 @@ class _ExtensionFieldSet { _isReadOnly = true; for (var field in _info.values) { if (field.isRepeated) { - final entries = _values[field.tagNumber]; + final entries = _values[field.tagNumber] as PbList?; if (entries == null) continue; if (field.isGroupOrMessage) { - for (var subMessage in entries as List) { + for (var subMessage in entries) { subMessage.freeze(); } } diff --git a/protobuf/lib/src/protobuf/extension_registry.dart b/protobuf/lib/src/protobuf/extension_registry.dart index be1f3d134..879580a60 100644 --- a/protobuf/lib/src/protobuf/extension_registry.dart +++ b/protobuf/lib/src/protobuf/extension_registry.dart @@ -134,7 +134,7 @@ T _reparseMessage( resultMap ??= ensureResult()._fieldSet._values[field.index!]; if (field.isRepeated) { - final messageEntries = message._fieldSet._values[field.index!]; + final messageEntries = message._fieldSet._values[field.index!] as List?; if (messageEntries == null) continue; if (field.isGroupOrMessage) { for (var i = 0; i < messageEntries.length; i++) { @@ -146,7 +146,7 @@ T _reparseMessage( } } } else if (field is MapFieldInfo) { - final messageMap = message._fieldSet._values[field.index!]; + final messageMap = message._fieldSet._values[field.index!] as PbMap?; if (messageMap == null) continue; if (_isGroupOrMessage(field.valueFieldType!)) { for (var key in messageMap.keys) { diff --git a/protobuf/lib/src/protobuf/field_set.dart b/protobuf/lib/src/protobuf/field_set.dart index f137aad50..1021e777f 100644 --- a/protobuf/lib/src/protobuf/field_set.dart +++ b/protobuf/lib/src/protobuf/field_set.dart @@ -175,7 +175,7 @@ class _FieldSet { _frozenState = true; for (var field in _meta.sortedByTag) { if (field.isRepeated) { - final entries = _values[field.index!]; + final entries = _values[field.index!] as PbList?; if (entries == null) continue; if (field.isGroupOrMessage) { for (var subMessage in entries as List) { @@ -668,7 +668,9 @@ class _FieldSet { } else if (!_isEnum(fi.type)) { hash = _HashUtils._combine(hash, value.hashCode); } else if (fi.isRepeated) { - hash = _HashUtils._hashObjects(value.map((enm) => enm.value)); + value as List; + hash = _HashUtils._hashObjects( + value.map((enm) => (enm as ProtobufEnum).value)); } else { ProtobufEnum enm = value; hash = _HashUtils._combine(hash, enm.value); @@ -802,6 +804,7 @@ class _FieldSet { var mustClone = _isGroupOrMessage(otherFi.type); if (fi!.isMapField) { + fieldValue as Map; var f = fi as MapFieldInfo; mustClone = _isGroupOrMessage(f.valueFieldType!); var map = f._ensureMapField(meta, this) as PbMap; @@ -832,7 +835,7 @@ class _FieldSet { } if (otherFi.isGroupOrMessage) { - final currentFi = isExtension! + GeneratedMessage? currentFi = isExtension! ? _ensureExtensions()._getFieldOrNull(fi as Extension) : _values[fi.index!]; diff --git a/protobuf/lib/src/protobuf/json.dart b/protobuf/lib/src/protobuf/json.dart index c2c736853..ad6afe8ac 100644 --- a/protobuf/lib/src/protobuf/json.dart +++ b/protobuf/lib/src/protobuf/json.dart @@ -5,10 +5,11 @@ part of protobuf; Map _writeToJsonMap(_FieldSet fs) { - dynamic convertToMap(dynamic fieldValue, int fieldType) { + dynamic convertToMap(Object? fieldValue, int fieldType) { var baseType = PbFieldType._baseType(fieldType); if (_isRepeated(fieldType)) { + fieldValue as List; return List.from(fieldValue.map((e) => convertToMap(e, baseType))); } @@ -27,6 +28,7 @@ Map _writeToJsonMap(_FieldSet fs) { // Encode 'bytes' as a base64-encoded string. return base64Encode(fieldValue as List); case PbFieldType._ENUM_BIT: + fieldValue as ProtobufEnum; return fieldValue.value; // assume |value| < 2^52 case PbFieldType._INT64_BIT: case PbFieldType._SINT64_BIT: @@ -34,16 +36,18 @@ Map _writeToJsonMap(_FieldSet fs) { return fieldValue.toString(); case PbFieldType._UINT64_BIT: case PbFieldType._FIXED64_BIT: + fieldValue as Int64; return fieldValue.toStringUnsigned(); case PbFieldType._GROUP_BIT: case PbFieldType._MESSAGE_BIT: + fieldValue as GeneratedMessage; return fieldValue.writeToJsonMap(); default: throw 'Unknown type $fieldType'; } } - List _writeMap(dynamic fieldValue, MapFieldInfo fi) => + List _writeMap(Map fieldValue, MapFieldInfo fi) => List.from(fieldValue.entries.map((MapEntry e) => { '${PbMap._keyFieldNumber}': convertToMap(e.key, fi.keyFieldType!), '${PbMap._valueFieldNumber}': diff --git a/protobuf/lib/src/protobuf/utils.dart b/protobuf/lib/src/protobuf/utils.dart index 0c7e4e531..011be8efb 100644 --- a/protobuf/lib/src/protobuf/utils.dart +++ b/protobuf/lib/src/protobuf/utils.dart @@ -31,7 +31,7 @@ bool _areMapsEqual(Map lhs, Map rhs) { } bool _areByteDataEqual(ByteData lhs, ByteData rhs) { - Uint8List asBytes(d) => + Uint8List asBytes(ByteData d) => Uint8List.view(d.buffer, d.offsetInBytes, d.lengthInBytes); return _areListsEqual(asBytes(lhs), asBytes(rhs)); } diff --git a/protobuf/test/json_test.dart b/protobuf/test/json_test.dart index 6291ad8c7..11c733dba 100644 --- a/protobuf/test/json_test.dart +++ b/protobuf/test/json_test.dart @@ -3,6 +3,10 @@ // There are more JSON tests in the dart-protoc-plugin package. library json_test; +// TODO(https://github.com/google/protobuf.dart/issues/578): Remove remaining +// dynamic calls. +// ignore_for_file: avoid_dynamic_calls + import 'dart:convert'; import 'package:fixnum/fixnum.dart' show Int64; diff --git a/protobuf/test/list_test.dart b/protobuf/test/list_test.dart index f47086301..33833b73a 100755 --- a/protobuf/test/list_test.dart +++ b/protobuf/test/list_test.dart @@ -92,6 +92,9 @@ void main() { test('PbList validates items', () { expect(() { + // TODO(https://github.com/google/protobuf.dart/issues/578): Remove + // remaining dynamic calls. + // ignore: avoid_dynamic_calls (PbList() as dynamic).add('hello'); }, throwsA(TypeMatcher())); }); diff --git a/protobuf/test/map_mixin_test.dart b/protobuf/test/map_mixin_test.dart index 2e40c5bcb..e3a6dbdf0 100644 --- a/protobuf/test/map_mixin_test.dart +++ b/protobuf/test/map_mixin_test.dart @@ -7,6 +7,10 @@ // There are more tests in the dart-protoc-plugin package. library map_mixin_test; +// TODO(https://github.com/google/protobuf.dart/issues/578): Remove remaining +// dynamic calls. +// ignore_for_file: avoid_dynamic_calls + import 'dart:collection' show MapMixin; import 'package:protobuf/protobuf.dart'; diff --git a/protobuf/test/message_test.dart b/protobuf/test/message_test.dart index 7e147f3b9..3f9a32207 100644 --- a/protobuf/test/message_test.dart +++ b/protobuf/test/message_test.dart @@ -22,6 +22,9 @@ class Rec extends MockMessage { Matcher throwsError(Type expectedType, String expectedMessage) => throwsA(predicate((dynamic x) { expect(x.runtimeType, expectedType); + // TODO(https://github.com/google/protobuf.dart/issues/578): Remove + // remaining dynamic calls. + // ignore: avoid_dynamic_calls expect(x!.message, expectedMessage); return true; })); diff --git a/protobuf/test/readonly_message_test.dart b/protobuf/test/readonly_message_test.dart index 782390a3d..b985ba4ad 100644 --- a/protobuf/test/readonly_message_test.dart +++ b/protobuf/test/readonly_message_test.dart @@ -18,6 +18,9 @@ import 'package:test/test.dart'; Matcher throwsError(Type expectedType, Matcher expectedMessage) => throwsA(predicate((dynamic x) { expect(x.runtimeType, expectedType); + // TODO(https://github.com/google/protobuf.dart/issues/578): Remove + // remaining dynamic calls. + // ignore: avoid_dynamic_calls expect(x!.message, expectedMessage); return true; })); From 51768613886f81f598aa8b9804426e19b54f75be Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 9 Feb 2022 08:09:53 -0800 Subject: [PATCH 2/6] whoops --- analysis_options.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index c09381b6f..91f543368 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -2,7 +2,6 @@ linter: rules: - always_require_non_null_named_parameters - annotate_overrides - - avoid_dynamic_calls - avoid_empty_else - avoid_function_literals_in_foreach_calls - avoid_init_to_null From 3ed448b16345d6950b4edf0381a5a2bc19a2fcdc Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Wed, 9 Feb 2022 14:50:41 -0800 Subject: [PATCH 3/6] Fix bug found in internal presubmit --- protobuf/lib/src/protobuf/coded_buffer_writer.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart index 38643b330..6e462b384 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart @@ -102,7 +102,7 @@ class CodedBufferWriter { } if ((fieldType & PbFieldType._REPEATED_BIT) != 0) { - fieldValue as PbList; + fieldValue as List; for (var i = 0; i < fieldValue.length; i++) { _writeValue(fieldNumber, valueType, fieldValue[i], wireFormat); } From 1c8d541f15259b4131489ea66410aaaa54eca6bd Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 10 Feb 2022 12:42:18 -0800 Subject: [PATCH 4/6] Feedback --- protobuf/lib/protobuf.dart | 8 +++- .../lib/src/protobuf/coded_buffer_writer.dart | 37 +++++++++---------- .../lib/src/protobuf/extension_field_set.dart | 4 +- protobuf/lib/src/protobuf/field_set.dart | 10 ++--- protobuf/lib/src/protobuf/json.dart | 12 +++--- 5 files changed, 38 insertions(+), 33 deletions(-) diff --git a/protobuf/lib/protobuf.dart b/protobuf/lib/protobuf.dart index e2d5cdcb2..f7fc90c4b 100644 --- a/protobuf/lib/protobuf.dart +++ b/protobuf/lib/protobuf.dart @@ -6,7 +6,13 @@ library protobuf; import 'dart:collection' show ListBase, MapBase; import 'dart:convert' - show base64Decode, base64Encode, jsonEncode, jsonDecode, Utf8Codec; + show + base64Decode, + base64Encode, + jsonEncode, + jsonDecode, + Utf8Codec, + Utf8Encoder; import 'dart:math' as math; import 'dart:typed_data' show TypedData, Uint8List, ByteData, Endian; diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart index 6e462b384..b02501f54 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart @@ -68,11 +68,11 @@ class CodedBufferWriter { final valueType = fieldType & ~0x07; if ((fieldType & PbFieldType._PACKED_BIT) != 0) { - fieldValue as List; - if (fieldValue.isNotEmpty) { + final listValue = fieldValue as List; + if (listValue.isNotEmpty) { _writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); final mark = _startLengthDelimited(); - for (var value in fieldValue) { + for (var value in listValue) { _writeValueAs(valueType, value); } _endLengthDelimited(mark); @@ -83,11 +83,10 @@ class CodedBufferWriter { final wireFormat = _wireTypes[_valueTypeIndex(valueType)]; if ((fieldType & PbFieldType._MAP_BIT) != 0) { - fieldValue as PbMap; - final keyWireFormat = - _wireTypes[_valueTypeIndex(fieldValue.keyFieldType!)]; + final mapValue = fieldValue as PbMap; + final keyWireFormat = _wireTypes[_valueTypeIndex(mapValue.keyFieldType!)]; final valueWireFormat = - _wireTypes[_valueTypeIndex(fieldValue.valueFieldType!)]; + _wireTypes[_valueTypeIndex(mapValue.valueFieldType!)]; fieldValue.forEach((key, value) { _writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); @@ -102,9 +101,9 @@ class CodedBufferWriter { } if ((fieldType & PbFieldType._REPEATED_BIT) != 0) { - fieldValue as List; - for (var i = 0; i < fieldValue.length; i++) { - _writeValue(fieldNumber, valueType, fieldValue[i], wireFormat); + final listValue = fieldValue as List; + for (var i = 0; i < listValue.length; i++) { + _writeValue(fieldNumber, valueType, listValue[i], wireFormat); } return; } @@ -343,7 +342,7 @@ class CodedBufferWriter { value is TypedData ? value : Uint8List.fromList(value)); break; case PbFieldType._STRING_BIT: - _writeBytesNoTag(_utf8.encode(value)); + _writeBytesNoTag(const Utf8Encoder().convert(value)); break; case PbFieldType._DOUBLE_BIT: _writeDouble(value); @@ -352,12 +351,12 @@ class CodedBufferWriter { _writeFloat(value); break; case PbFieldType._ENUM_BIT: - value as ProtobufEnum; - _writeVarint32(value.value & 0xffffffff); + final enumValue = value as ProtobufEnum; + _writeVarint32(enumValue.value & 0xffffffff); break; case PbFieldType._GROUP_BIT: - value as GeneratedMessage; - value.writeToCodedBufferWriter(this); + final messageValue = value as GeneratedMessage; + messageValue.writeToCodedBufferWriter(this); break; case PbFieldType._INT32_BIT: _writeVarint64(Int64(value)); @@ -391,16 +390,16 @@ class CodedBufferWriter { break; case PbFieldType._MESSAGE_BIT: final mark = _startLengthDelimited(); - value as GeneratedMessage; - value.writeToCodedBufferWriter(this); + final messageValue = value as GeneratedMessage; + messageValue.writeToCodedBufferWriter(this); _endLengthDelimited(mark); break; } } - void _writeBytesNoTag(Object value) { + void _writeBytesNoTag(TypedData value) { writeInt32NoTag((value as List).length); - writeRawBytes(value as TypedData); + writeRawBytes(value); } void _writeTag(int fieldNumber, int wireFormat) { diff --git a/protobuf/lib/src/protobuf/extension_field_set.dart b/protobuf/lib/src/protobuf/extension_field_set.dart index 9723b7470..651a89e6c 100644 --- a/protobuf/lib/src/protobuf/extension_field_set.dart +++ b/protobuf/lib/src/protobuf/extension_field_set.dart @@ -172,11 +172,11 @@ class _ExtensionFieldSet { _isReadOnly = true; for (var field in _info.values) { if (field.isRepeated) { - final entries = _values[field.tagNumber] as PbList?; + final entries = _values[field.tagNumber] as PbList?; if (entries == null) continue; if (field.isGroupOrMessage) { for (var subMessage in entries) { - subMessage.freeze(); + (subMessage as GeneratedMessage).freeze(); } } _values[field.tagNumber] = entries.toFrozenPbList(); diff --git a/protobuf/lib/src/protobuf/field_set.dart b/protobuf/lib/src/protobuf/field_set.dart index 1021e777f..2221f0e55 100644 --- a/protobuf/lib/src/protobuf/field_set.dart +++ b/protobuf/lib/src/protobuf/field_set.dart @@ -668,9 +668,9 @@ class _FieldSet { } else if (!_isEnum(fi.type)) { hash = _HashUtils._combine(hash, value.hashCode); } else if (fi.isRepeated) { - value as List; + final listValue = value as List; hash = _HashUtils._hashObjects( - value.map((enm) => (enm as ProtobufEnum).value)); + listValue.map((enm) => (enm as ProtobufEnum).value)); } else { ProtobufEnum enm = value; hash = _HashUtils._combine(hash, enm.value); @@ -804,16 +804,16 @@ class _FieldSet { var mustClone = _isGroupOrMessage(otherFi.type); if (fi!.isMapField) { - fieldValue as Map; + final mapValue = fieldValue as Map; var f = fi as MapFieldInfo; mustClone = _isGroupOrMessage(f.valueFieldType!); var map = f._ensureMapField(meta, this) as PbMap; if (mustClone) { - for (MapEntry entry in fieldValue.entries) { + for (MapEntry entry in mapValue.entries) { map[entry.key] = (entry.value as GeneratedMessage).deepCopy(); } } else { - map.addAll(fieldValue); + map.addAll(mapValue); } return; } diff --git a/protobuf/lib/src/protobuf/json.dart b/protobuf/lib/src/protobuf/json.dart index ad6afe8ac..507576ed0 100644 --- a/protobuf/lib/src/protobuf/json.dart +++ b/protobuf/lib/src/protobuf/json.dart @@ -28,20 +28,20 @@ Map _writeToJsonMap(_FieldSet fs) { // Encode 'bytes' as a base64-encoded string. return base64Encode(fieldValue as List); case PbFieldType._ENUM_BIT: - fieldValue as ProtobufEnum; - return fieldValue.value; // assume |value| < 2^52 + final enumValue = fieldValue as ProtobufEnum; + return enumValue.value; // assume |value| < 2^52 case PbFieldType._INT64_BIT: case PbFieldType._SINT64_BIT: case PbFieldType._SFIXED64_BIT: return fieldValue.toString(); case PbFieldType._UINT64_BIT: case PbFieldType._FIXED64_BIT: - fieldValue as Int64; - return fieldValue.toStringUnsigned(); + final int64Value = fieldValue as Int64; + return int64Value.toStringUnsigned(); case PbFieldType._GROUP_BIT: case PbFieldType._MESSAGE_BIT: - fieldValue as GeneratedMessage; - return fieldValue.writeToJsonMap(); + final messageValue = fieldValue as GeneratedMessage; + return messageValue.writeToJsonMap(); default: throw 'Unknown type $fieldType'; } From 624e245759bfd6f5a072c2c3b505c45adfbe8bd6 Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 10 Feb 2022 13:07:02 -0800 Subject: [PATCH 5/6] crash --- protobuf/lib/src/protobuf/coded_buffer_writer.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart index b02501f54..91aa3aedb 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart @@ -355,8 +355,14 @@ class CodedBufferWriter { _writeVarint32(enumValue.value & 0xffffffff); break; case PbFieldType._GROUP_BIT: - final messageValue = value as GeneratedMessage; - messageValue.writeToCodedBufferWriter(this); + if (value is UnknownFieldSet) { + // This class is not in the GeneratedMessage type hierarchy but does + // happen to have a method called `writeToCodedBufferWriter`. + value.writeToCodedBufferWriter(this); + } else { + final messageValue = value as GeneratedMessage; + messageValue.writeToCodedBufferWriter(this); + } break; case PbFieldType._INT32_BIT: _writeVarint64(Int64(value)); From 2e6c2dcdd1d0adca0488c8f76f261b0874e98eed Mon Sep 17 00:00:00 2001 From: Sam Rawlins Date: Thu, 10 Feb 2022 13:40:28 -0800 Subject: [PATCH 6/6] Remove all explicit casts --- protobuf/analysis_options.yaml | 1 - protobuf/benchmarks/common.dart | 4 -- .../lib/src/protobuf/coded_buffer_writer.dart | 47 ++++++++----------- .../lib/src/protobuf/extension_field_set.dart | 6 +-- .../lib/src/protobuf/extension_registry.dart | 5 +- protobuf/lib/src/protobuf/field_set.dart | 14 +++--- protobuf/lib/src/protobuf/json.dart | 16 +++---- protobuf/test/json_test.dart | 4 -- protobuf/test/list_test.dart | 3 -- protobuf/test/map_mixin_test.dart | 4 -- protobuf/test/message_test.dart | 3 -- protobuf/test/readonly_message_test.dart | 3 -- 12 files changed, 41 insertions(+), 69 deletions(-) diff --git a/protobuf/analysis_options.yaml b/protobuf/analysis_options.yaml index 1b9b71a27..e84124713 100644 --- a/protobuf/analysis_options.yaml +++ b/protobuf/analysis_options.yaml @@ -2,7 +2,6 @@ include: package:lints/recommended.yaml linter: rules: - - avoid_dynamic_calls - comment_references - directives_ordering - prefer_relative_imports diff --git a/protobuf/benchmarks/common.dart b/protobuf/benchmarks/common.dart index 8ae38e049..24a206813 100644 --- a/protobuf/benchmarks/common.dart +++ b/protobuf/benchmarks/common.dart @@ -8,10 +8,6 @@ /// both on the VM and when compiled to JavaScript. library common; -// TODO(https://github.com/google/protobuf.dart/issues/578): Remove remaining -// dynamic calls. -// ignore_for_file: avoid_dynamic_calls - import 'dart:typed_data'; import 'package:benchmark_harness/benchmark_harness.dart'; diff --git a/protobuf/lib/src/protobuf/coded_buffer_writer.dart b/protobuf/lib/src/protobuf/coded_buffer_writer.dart index 91aa3aedb..218d36fda 100644 --- a/protobuf/lib/src/protobuf/coded_buffer_writer.dart +++ b/protobuf/lib/src/protobuf/coded_buffer_writer.dart @@ -64,15 +64,14 @@ class CodedBufferWriter { _commitChunk(true); } - void writeField(int fieldNumber, int fieldType, Object? fieldValue) { + void writeField(int fieldNumber, int fieldType, dynamic fieldValue) { final valueType = fieldType & ~0x07; if ((fieldType & PbFieldType._PACKED_BIT) != 0) { - final listValue = fieldValue as List; - if (listValue.isNotEmpty) { + if (fieldValue.isNotEmpty) { _writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); final mark = _startLengthDelimited(); - for (var value in listValue) { + for (var value in fieldValue) { _writeValueAs(valueType, value); } _endLengthDelimited(mark); @@ -83,17 +82,17 @@ class CodedBufferWriter { final wireFormat = _wireTypes[_valueTypeIndex(valueType)]; if ((fieldType & PbFieldType._MAP_BIT) != 0) { - final mapValue = fieldValue as PbMap; - final keyWireFormat = _wireTypes[_valueTypeIndex(mapValue.keyFieldType!)]; + final keyWireFormat = + _wireTypes[_valueTypeIndex(fieldValue.keyFieldType)]; final valueWireFormat = - _wireTypes[_valueTypeIndex(mapValue.valueFieldType!)]; + _wireTypes[_valueTypeIndex(fieldValue.valueFieldType)]; fieldValue.forEach((key, value) { _writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED); final mark = _startLengthDelimited(); - _writeValue(PbMap._keyFieldNumber, fieldValue.keyFieldType!, key, - keyWireFormat); - _writeValue(PbMap._valueFieldNumber, fieldValue.valueFieldType!, value, + _writeValue( + PbMap._keyFieldNumber, fieldValue.keyFieldType, key, keyWireFormat); + _writeValue(PbMap._valueFieldNumber, fieldValue.valueFieldType, value, valueWireFormat); _endLengthDelimited(mark); }); @@ -101,9 +100,8 @@ class CodedBufferWriter { } if ((fieldType & PbFieldType._REPEATED_BIT) != 0) { - final listValue = fieldValue as List; - for (var i = 0; i < listValue.length; i++) { - _writeValue(fieldNumber, valueType, listValue[i], wireFormat); + for (var i = 0; i < fieldValue.length; i++) { + _writeValue(fieldNumber, valueType, fieldValue[i], wireFormat); } return; } @@ -351,18 +349,12 @@ class CodedBufferWriter { _writeFloat(value); break; case PbFieldType._ENUM_BIT: - final enumValue = value as ProtobufEnum; - _writeVarint32(enumValue.value & 0xffffffff); + // `value` is [ProtobufEnum]. + _writeVarint32(value.value & 0xffffffff); break; case PbFieldType._GROUP_BIT: - if (value is UnknownFieldSet) { - // This class is not in the GeneratedMessage type hierarchy but does - // happen to have a method called `writeToCodedBufferWriter`. - value.writeToCodedBufferWriter(this); - } else { - final messageValue = value as GeneratedMessage; - messageValue.writeToCodedBufferWriter(this); - } + // `value` is [GeneratedMessage] or [UnknownFieldSet]. + value.writeToCodedBufferWriter(this); break; case PbFieldType._INT32_BIT: _writeVarint64(Int64(value)); @@ -396,15 +388,16 @@ class CodedBufferWriter { break; case PbFieldType._MESSAGE_BIT: final mark = _startLengthDelimited(); - final messageValue = value as GeneratedMessage; - messageValue.writeToCodedBufferWriter(this); + // `value` is [GeneratedMessage]. + value.writeToCodedBufferWriter(this); _endLengthDelimited(mark); break; } } - void _writeBytesNoTag(TypedData value) { - writeInt32NoTag((value as List).length); + void _writeBytesNoTag(dynamic value) { + // `value` is [TypedData]&[List]. + writeInt32NoTag(value.length); writeRawBytes(value); } diff --git a/protobuf/lib/src/protobuf/extension_field_set.dart b/protobuf/lib/src/protobuf/extension_field_set.dart index 651a89e6c..2497e0361 100644 --- a/protobuf/lib/src/protobuf/extension_field_set.dart +++ b/protobuf/lib/src/protobuf/extension_field_set.dart @@ -172,11 +172,11 @@ class _ExtensionFieldSet { _isReadOnly = true; for (var field in _info.values) { if (field.isRepeated) { - final entries = _values[field.tagNumber] as PbList?; + final entries = _values[field.tagNumber]; if (entries == null) continue; if (field.isGroupOrMessage) { - for (var subMessage in entries) { - (subMessage as GeneratedMessage).freeze(); + for (var subMessage in entries as List) { + subMessage.freeze(); } } _values[field.tagNumber] = entries.toFrozenPbList(); diff --git a/protobuf/lib/src/protobuf/extension_registry.dart b/protobuf/lib/src/protobuf/extension_registry.dart index 879580a60..5328c9e80 100644 --- a/protobuf/lib/src/protobuf/extension_registry.dart +++ b/protobuf/lib/src/protobuf/extension_registry.dart @@ -134,7 +134,7 @@ T _reparseMessage( resultMap ??= ensureResult()._fieldSet._values[field.index!]; if (field.isRepeated) { - final messageEntries = message._fieldSet._values[field.index!] as List?; + final /*List*/ messageEntries = message._fieldSet._values[field.index!]; if (messageEntries == null) continue; if (field.isGroupOrMessage) { for (var i = 0; i < messageEntries.length; i++) { @@ -146,7 +146,8 @@ T _reparseMessage( } } } else if (field is MapFieldInfo) { - final messageMap = message._fieldSet._values[field.index!] as PbMap?; + final /*PbMap*/ messageMap = message._fieldSet._values[field.index!]; + if (messageMap == null) continue; if (_isGroupOrMessage(field.valueFieldType!)) { for (var key in messageMap.keys) { diff --git a/protobuf/lib/src/protobuf/field_set.dart b/protobuf/lib/src/protobuf/field_set.dart index 2221f0e55..7186ef880 100644 --- a/protobuf/lib/src/protobuf/field_set.dart +++ b/protobuf/lib/src/protobuf/field_set.dart @@ -175,7 +175,7 @@ class _FieldSet { _frozenState = true; for (var field in _meta.sortedByTag) { if (field.isRepeated) { - final entries = _values[field.index!] as PbList?; + final /*PbList*/ entries = _values[field.index!]; if (entries == null) continue; if (field.isGroupOrMessage) { for (var subMessage in entries as List) { @@ -668,9 +668,9 @@ class _FieldSet { } else if (!_isEnum(fi.type)) { hash = _HashUtils._combine(hash, value.hashCode); } else if (fi.isRepeated) { - final listValue = value as List; + // `value` is [List]. hash = _HashUtils._hashObjects( - listValue.map((enm) => (enm as ProtobufEnum).value)); + value.map((/*ProtobufEnum*/ enm) => enm.value)); } else { ProtobufEnum enm = value; hash = _HashUtils._combine(hash, enm.value); @@ -804,16 +804,16 @@ class _FieldSet { var mustClone = _isGroupOrMessage(otherFi.type); if (fi!.isMapField) { - final mapValue = fieldValue as Map; + // `fieldValue` is [Map]. var f = fi as MapFieldInfo; mustClone = _isGroupOrMessage(f.valueFieldType!); var map = f._ensureMapField(meta, this) as PbMap; if (mustClone) { - for (MapEntry entry in mapValue.entries) { + for (MapEntry entry in fieldValue.entries) { map[entry.key] = (entry.value as GeneratedMessage).deepCopy(); } } else { - map.addAll(mapValue); + map.addAll(fieldValue); } return; } @@ -835,7 +835,7 @@ class _FieldSet { } if (otherFi.isGroupOrMessage) { - GeneratedMessage? currentFi = isExtension! + final GeneratedMessage? currentFi = isExtension! ? _ensureExtensions()._getFieldOrNull(fi as Extension) : _values[fi.index!]; diff --git a/protobuf/lib/src/protobuf/json.dart b/protobuf/lib/src/protobuf/json.dart index 507576ed0..dbb467c8d 100644 --- a/protobuf/lib/src/protobuf/json.dart +++ b/protobuf/lib/src/protobuf/json.dart @@ -5,11 +5,11 @@ part of protobuf; Map _writeToJsonMap(_FieldSet fs) { - dynamic convertToMap(Object? fieldValue, int fieldType) { + dynamic convertToMap(dynamic fieldValue, int fieldType) { var baseType = PbFieldType._baseType(fieldType); if (_isRepeated(fieldType)) { - fieldValue as List; + // `fieldValue` is [List]. return List.from(fieldValue.map((e) => convertToMap(e, baseType))); } @@ -28,20 +28,20 @@ Map _writeToJsonMap(_FieldSet fs) { // Encode 'bytes' as a base64-encoded string. return base64Encode(fieldValue as List); case PbFieldType._ENUM_BIT: - final enumValue = fieldValue as ProtobufEnum; - return enumValue.value; // assume |value| < 2^52 + // `fieldValue` is [ProtobufEnum]. + return fieldValue.value; // assume |value| < 2^52 case PbFieldType._INT64_BIT: case PbFieldType._SINT64_BIT: case PbFieldType._SFIXED64_BIT: return fieldValue.toString(); case PbFieldType._UINT64_BIT: case PbFieldType._FIXED64_BIT: - final int64Value = fieldValue as Int64; - return int64Value.toStringUnsigned(); + // `fieldValue` is [Int64]. + return fieldValue.toStringUnsigned(); case PbFieldType._GROUP_BIT: case PbFieldType._MESSAGE_BIT: - final messageValue = fieldValue as GeneratedMessage; - return messageValue.writeToJsonMap(); + // `fieldValue` is [GeneratedMessage]. + return fieldValue.writeToJsonMap(); default: throw 'Unknown type $fieldType'; } diff --git a/protobuf/test/json_test.dart b/protobuf/test/json_test.dart index 11c733dba..6291ad8c7 100644 --- a/protobuf/test/json_test.dart +++ b/protobuf/test/json_test.dart @@ -3,10 +3,6 @@ // There are more JSON tests in the dart-protoc-plugin package. library json_test; -// TODO(https://github.com/google/protobuf.dart/issues/578): Remove remaining -// dynamic calls. -// ignore_for_file: avoid_dynamic_calls - import 'dart:convert'; import 'package:fixnum/fixnum.dart' show Int64; diff --git a/protobuf/test/list_test.dart b/protobuf/test/list_test.dart index 33833b73a..f47086301 100755 --- a/protobuf/test/list_test.dart +++ b/protobuf/test/list_test.dart @@ -92,9 +92,6 @@ void main() { test('PbList validates items', () { expect(() { - // TODO(https://github.com/google/protobuf.dart/issues/578): Remove - // remaining dynamic calls. - // ignore: avoid_dynamic_calls (PbList() as dynamic).add('hello'); }, throwsA(TypeMatcher())); }); diff --git a/protobuf/test/map_mixin_test.dart b/protobuf/test/map_mixin_test.dart index e3a6dbdf0..2e40c5bcb 100644 --- a/protobuf/test/map_mixin_test.dart +++ b/protobuf/test/map_mixin_test.dart @@ -7,10 +7,6 @@ // There are more tests in the dart-protoc-plugin package. library map_mixin_test; -// TODO(https://github.com/google/protobuf.dart/issues/578): Remove remaining -// dynamic calls. -// ignore_for_file: avoid_dynamic_calls - import 'dart:collection' show MapMixin; import 'package:protobuf/protobuf.dart'; diff --git a/protobuf/test/message_test.dart b/protobuf/test/message_test.dart index 3f9a32207..7e147f3b9 100644 --- a/protobuf/test/message_test.dart +++ b/protobuf/test/message_test.dart @@ -22,9 +22,6 @@ class Rec extends MockMessage { Matcher throwsError(Type expectedType, String expectedMessage) => throwsA(predicate((dynamic x) { expect(x.runtimeType, expectedType); - // TODO(https://github.com/google/protobuf.dart/issues/578): Remove - // remaining dynamic calls. - // ignore: avoid_dynamic_calls expect(x!.message, expectedMessage); return true; })); diff --git a/protobuf/test/readonly_message_test.dart b/protobuf/test/readonly_message_test.dart index b985ba4ad..782390a3d 100644 --- a/protobuf/test/readonly_message_test.dart +++ b/protobuf/test/readonly_message_test.dart @@ -18,9 +18,6 @@ import 'package:test/test.dart'; Matcher throwsError(Type expectedType, Matcher expectedMessage) => throwsA(predicate((dynamic x) { expect(x.runtimeType, expectedType); - // TODO(https://github.com/google/protobuf.dart/issues/578): Remove - // remaining dynamic calls. - // ignore: avoid_dynamic_calls expect(x!.message, expectedMessage); return true; }));