diff --git a/pkgs/collection/CHANGELOG.md b/pkgs/collection/CHANGELOG.md index 30f8c3f7a..dbffb8ccb 100644 --- a/pkgs/collection/CHANGELOG.md +++ b/pkgs/collection/CHANGELOG.md @@ -1,3 +1,12 @@ +## 2.0.0 + +- Breaking changes: + - Adds `final`, `base` and `interface` to classes intended to be so. + - Removes deprecated declarations. Most has been replaced by functionality + in the platform libraries, or better functionality in other libraries. + - Removes deprecated top-level libraries. + Implement `package:collection/collection.dart` and use `show` or `hide` + to control the imported names if necessary, or desired. ## 1.20.0-wip diff --git a/pkgs/collection/lib/algorithms.dart b/pkgs/collection/lib/algorithms.dart deleted file mode 100644 index ac4324239..000000000 --- a/pkgs/collection/lib/algorithms.dart +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) 2013, 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 `collection.dart` instead. -@Deprecated('Will be removed in collection 2.0.0.') -library; - -export 'src/algorithms.dart' - show binarySearch, insertionSort, lowerBound, mergeSort, reverse, shuffle; diff --git a/pkgs/collection/lib/equality.dart b/pkgs/collection/lib/equality.dart deleted file mode 100644 index 5dc158cae..000000000 --- a/pkgs/collection/lib/equality.dart +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2013, 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 `collection.dart` instead. -@Deprecated('Will be removed in collection 2.0.0.') -library; - -export 'src/equality.dart'; diff --git a/pkgs/collection/lib/iterable_zip.dart b/pkgs/collection/lib/iterable_zip.dart deleted file mode 100644 index bd0b1ef09..000000000 --- a/pkgs/collection/lib/iterable_zip.dart +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2013, 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 `collection.dart` instead. -@Deprecated('Will be removed in collection 2.0.0.') -library; - -export 'src/iterable_zip.dart'; diff --git a/pkgs/collection/lib/priority_queue.dart b/pkgs/collection/lib/priority_queue.dart deleted file mode 100644 index 7505ce479..000000000 --- a/pkgs/collection/lib/priority_queue.dart +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright (c) 2014, 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 `collection.dart` instead. -@Deprecated('Will be removed in collection 2.0.0.') -library; - -export 'src/priority_queue.dart'; diff --git a/pkgs/collection/lib/src/boollist.dart b/pkgs/collection/lib/src/boollist.dart index b026d858a..b7b1893da 100644 --- a/pkgs/collection/lib/src/boollist.dart +++ b/pkgs/collection/lib/src/boollist.dart @@ -10,7 +10,7 @@ import 'unmodifiable_wrappers.dart' show NonGrowableListMixin; /// A space-efficient list of boolean values. /// /// Uses list of integers as internal storage to reduce memory usage. -abstract /*mixin*/ class BoolList with ListMixin { +abstract final class BoolList with ListMixin { static const int _entryShift = 5; static const int _bitsPerEntry = 32; @@ -180,7 +180,7 @@ abstract /*mixin*/ class BoolList with ListMixin { } } -class _GrowableBoolList extends BoolList { +final class _GrowableBoolList extends BoolList { static const int _growthFactor = 2; _GrowableBoolList._withCapacity(int length, int capacity) @@ -228,7 +228,8 @@ class _GrowableBoolList extends BoolList { } } -class _NonGrowableBoolList extends BoolList with NonGrowableListMixin { +final class _NonGrowableBoolList extends BoolList + with NonGrowableListMixin { _NonGrowableBoolList._withCapacity(int length, int capacity) : super._( Uint32List(BoolList._lengthInWords(capacity)), diff --git a/pkgs/collection/lib/src/canonicalized_map.dart b/pkgs/collection/lib/src/canonicalized_map.dart index 3dc6e37cb..7db44fd7d 100644 --- a/pkgs/collection/lib/src/canonicalized_map.dart +++ b/pkgs/collection/lib/src/canonicalized_map.dart @@ -4,12 +4,15 @@ import 'dart:collection'; +import 'package:meta/meta.dart'; + /// A map whose keys are converted to canonical values of type `C`. /// /// This is useful for using case-insensitive String keys, for example. It's /// more efficient than a [LinkedHashMap] with a custom equality operator /// because it only canonicalizes each key once, rather than doing so for each /// comparison. +@sealed // TODO: Make `final` when no longer extended. class CanonicalizedMap implements Map { final C Function(K) _canonicalize; @@ -25,9 +28,10 @@ class CanonicalizedMap implements Map { /// The [isValidKey] function is called before calling [canonicalize] for /// methods that take arbitrary objects. It can be used to filter out keys /// that can't be canonicalized. - CanonicalizedMap(C Function(K key) canonicalize, - {bool Function(K key)? isValidKey}) - : _canonicalize = canonicalize, + CanonicalizedMap( + C Function(K key) canonicalize, { + bool Function(K key)? isValidKey, + }) : _canonicalize = canonicalize, _isValidKeyFn = isValidKey; /// Creates a canonicalized map that is initialized with the key/value pairs @@ -39,9 +43,11 @@ class CanonicalizedMap implements Map { /// The [isValidKey] function is called before calling [canonicalize] for /// methods that take arbitrary objects. It can be used to filter out keys /// that can't be canonicalized. - CanonicalizedMap.from(Map other, C Function(K key) canonicalize, - {bool Function(K key)? isValidKey}) - : _canonicalize = canonicalize, + CanonicalizedMap.from( + Map other, + C Function(K key) canonicalize, { + bool Function(K key)? isValidKey, + }) : _canonicalize = canonicalize, _isValidKeyFn = isValidKey { addAll(other); } @@ -56,15 +62,19 @@ class CanonicalizedMap implements Map { /// methods that take arbitrary objects. It can be used to filter out keys /// that can't be canonicalized. CanonicalizedMap.fromEntries( - Iterable> entries, C Function(K key) canonicalize, - {bool Function(K key)? isValidKey}) - : _canonicalize = canonicalize, + Iterable> entries, + C Function(K key) canonicalize, { + bool Function(K key)? isValidKey, + }) : _canonicalize = canonicalize, _isValidKeyFn = isValidKey { addEntries(entries); } CanonicalizedMap._( - this._canonicalize, this._isValidKeyFn, Map> base) { + this._canonicalize, + this._isValidKeyFn, + Map> base, + ) { _base.addAll(base); } @@ -92,8 +102,11 @@ class CanonicalizedMap implements Map { } @override - void addEntries(Iterable> entries) => _base.addEntries(entries - .map((e) => MapEntry(_canonicalize(e.key), MapEntry(e.key, e.value)))); + void addEntries(Iterable> entries) => _base.addEntries( + entries.map( + (e) => MapEntry(_canonicalize(e.key), MapEntry(e.key, e.value)), + ), + ); @override Map cast() => _base.cast(); @@ -156,19 +169,18 @@ class CanonicalizedMap implements Map { void removeWhere(bool Function(K key, V value) test) => _base.removeWhere((_, pair) => test(pair.key, pair.value)); - @Deprecated('Use cast instead') - Map retype() => cast(); - @override V update(K key, V Function(V) update, {V Function()? ifAbsent}) => - _base.update(_canonicalize(key), (pair) { - var value = pair.value; - var newValue = update(value); - if (identical(newValue, value)) return pair; - return MapEntry(key, newValue); - }, - ifAbsent: - ifAbsent == null ? null : () => MapEntry(key, ifAbsent())).value; + _base.update( + _canonicalize(key), + (pair) { + var value = pair.value; + var newValue = update(value); + if (identical(newValue, value)) return pair; + return MapEntry(key, newValue); + }, + ifAbsent: ifAbsent == null ? null : () => MapEntry(key, ifAbsent()), + ).value; @override void updateAll(V Function(K key, V value) update) => @@ -196,5 +208,6 @@ class CanonicalizedMap implements Map { /// Creates a `Map` (with the canonicalized keys). /// See [toMap]. Map toMapOfCanonicalKeys() => Map.fromEntries( - _base.entries.map((e) => MapEntry(e.key, e.value.value))); + _base.entries.map((e) => MapEntry(e.key, e.value.value)), + ); } diff --git a/pkgs/collection/lib/src/combined_wrappers/combined_iterable.dart b/pkgs/collection/lib/src/combined_wrappers/combined_iterable.dart index 281f8a28b..8242034ec 100644 --- a/pkgs/collection/lib/src/combined_wrappers/combined_iterable.dart +++ b/pkgs/collection/lib/src/combined_wrappers/combined_iterable.dart @@ -13,7 +13,7 @@ import 'combined_iterator.dart'; /// lazily accessing individual iterable instances. This means that if the /// underlying iterables change, the [CombinedIterableView] will reflect those /// changes. -class CombinedIterableView extends IterableBase { +final class CombinedIterableView extends IterableBase { /// The iterables that this combines. final Iterable> _iterables; diff --git a/pkgs/collection/lib/src/combined_wrappers/combined_iterator.dart b/pkgs/collection/lib/src/combined_wrappers/combined_iterator.dart index 0d6088a97..3bc6f8517 100644 --- a/pkgs/collection/lib/src/combined_wrappers/combined_iterator.dart +++ b/pkgs/collection/lib/src/combined_wrappers/combined_iterator.dart @@ -5,7 +5,7 @@ /// The iterator for `CombinedIterableView` and `CombinedListView`. /// /// Moves through each iterable's iterator in sequence. -class CombinedIterator implements Iterator { +final class CombinedIterator implements Iterator { /// The iterators that this combines, or `null` if done iterating. /// /// Because this comes from a call to [Iterable.map], it's lazy and will diff --git a/pkgs/collection/lib/src/combined_wrappers/combined_list.dart b/pkgs/collection/lib/src/combined_wrappers/combined_list.dart index f0cd44764..c78bd45d5 100644 --- a/pkgs/collection/lib/src/combined_wrappers/combined_list.dart +++ b/pkgs/collection/lib/src/combined_wrappers/combined_list.dart @@ -15,7 +15,7 @@ import 'combined_iterator.dart'; /// /// The index operator (`[]`) and [length] property of a [CombinedListView] are /// both `O(lists)` rather than `O(1)`. A [CombinedListView] is unmodifiable. -class CombinedListView extends ListBase +final class CombinedListView extends ListBase implements UnmodifiableListView { static Never _throw() { throw UnsupportedError('Cannot modify an unmodifiable List'); diff --git a/pkgs/collection/lib/src/combined_wrappers/combined_map.dart b/pkgs/collection/lib/src/combined_wrappers/combined_map.dart index 18db6e7ed..cdc53fd41 100644 --- a/pkgs/collection/lib/src/combined_wrappers/combined_map.dart +++ b/pkgs/collection/lib/src/combined_wrappers/combined_map.dart @@ -19,7 +19,7 @@ import 'combined_iterable.dart'; /// /// The `length` getter is `O(M)` where M is the total number of entries in /// all maps, since it has to remove duplicate entries. -class CombinedMapView extends UnmodifiableMapBase { +final class CombinedMapView extends UnmodifiableMapBase { final Iterable> _maps; /// Create a new combined view of multiple maps. diff --git a/pkgs/collection/lib/src/comparators.dart b/pkgs/collection/lib/src/comparators.dart index 6e5d36318..e79fd3c3b 100644 --- a/pkgs/collection/lib/src/comparators.dart +++ b/pkgs/collection/lib/src/comparators.dart @@ -151,6 +151,12 @@ int compareAsciiLowerCase(String a, String b) { /// ordering, where lexical ordering would put the `1` before the `7`, ignoring /// that the `1` is part of a larger number. /// +/// If a digit sequence differs only in the number of leading zeros, +/// and therefore have the same numerical value, the one with +/// fewer leading zeros is ordered before the one with more. +/// +/// Numbers are unsigned. A prior `-` is not considered a minus sign. +/// /// Example: /// The following strings are in the order they would be sorted by using this /// comparison function: diff --git a/pkgs/collection/lib/src/empty_unmodifiable_set.dart b/pkgs/collection/lib/src/empty_unmodifiable_set.dart index 74fd39a14..2b1a62321 100644 --- a/pkgs/collection/lib/src/empty_unmodifiable_set.dart +++ b/pkgs/collection/lib/src/empty_unmodifiable_set.dart @@ -8,7 +8,7 @@ import 'unmodifiable_wrappers.dart'; import 'wrappers.dart'; /// An unmodifiable, empty set which can be constant. -class EmptyUnmodifiableSet extends IterableBase +final class EmptyUnmodifiableSet extends IterableBase with UnmodifiableSetMixin implements UnmodifiableSetView { const EmptyUnmodifiableSet(); @@ -27,9 +27,6 @@ class EmptyUnmodifiableSet extends IterableBase Iterable followedBy(Iterable other) => DelegatingIterable(other); @override E? lookup(Object? element) => null; - @Deprecated('Use cast instead') - @override - EmptyUnmodifiableSet retype() => EmptyUnmodifiableSet(); @override E singleWhere(bool Function(E) test, {E Function()? orElse}) => orElse != null ? orElse() : throw StateError('No element'); diff --git a/pkgs/collection/lib/src/equality.dart b/pkgs/collection/lib/src/equality.dart index 0e1df23da..ce27bf931 100644 --- a/pkgs/collection/lib/src/equality.dart +++ b/pkgs/collection/lib/src/equality.dart @@ -9,7 +9,7 @@ import 'comparators.dart'; const int _hashMask = 0x7fffffff; /// A generic equality relation on objects. -abstract class Equality { +abstract interface class Equality { const factory Equality() = DefaultEquality; /// Compare two elements for being equal. @@ -46,7 +46,7 @@ abstract class Equality { /// /// It's also possible to pass an additional equality instance that should be /// used to compare the value itself. -class EqualityBy implements Equality { +final class EqualityBy implements Equality { final F Function(E) _comparisonKey; final Equality _inner; @@ -81,7 +81,7 @@ class EqualityBy implements Equality { /// Note that [equals] and [hash] take `Object`s rather than `E`s. This allows /// `E` to be inferred as `Null` in const contexts where `E` wouldn't be a /// compile-time constant, while still allowing the class to be used at runtime. -class DefaultEquality implements Equality { +final class DefaultEquality implements Equality { const DefaultEquality(); @override bool equals(Object? e1, Object? e2) => e1 == e2; @@ -92,7 +92,7 @@ class DefaultEquality implements Equality { } /// Equality of objects that compares only the identity of the objects. -class IdentityEquality implements Equality { +final class IdentityEquality implements Equality { const IdentityEquality(); @override bool equals(E e1, E e2) => identical(e1, e2); @@ -109,7 +109,7 @@ class IdentityEquality implements Equality { /// The [equals] and [hash] methods accepts `null` values, /// even if the [isValidKey] returns `false` for `null`. /// The [hash] of `null` is `null.hashCode`. -class IterableEquality implements Equality> { +final class IterableEquality implements Equality> { final Equality _elementEquality; const IterableEquality( [Equality elementEquality = const DefaultEquality()]) @@ -161,7 +161,7 @@ class IterableEquality implements Equality> { /// The [equals] and [hash] methods accepts `null` values, /// even if the [isValidKey] returns `false` for `null`. /// The [hash] of `null` is `null.hashCode`. -class ListEquality implements Equality> { +final class ListEquality implements Equality> { final Equality _elementEquality; const ListEquality( [Equality elementEquality = const DefaultEquality()]) @@ -202,7 +202,7 @@ class ListEquality implements Equality> { bool isValidKey(Object? o) => o is List; } -abstract class _UnorderedEquality> +abstract final class _UnorderedEquality> implements Equality { final Equality _elementEquality; @@ -251,7 +251,8 @@ abstract class _UnorderedEquality> /// Two iterables are considered equal if they have the same number of elements, /// and the elements of one set can be paired with the elements /// of the other iterable, so that each pair are equal. -class UnorderedIterableEquality extends _UnorderedEquality> { +final class UnorderedIterableEquality + extends _UnorderedEquality> { const UnorderedIterableEquality( [super.elementEquality = const DefaultEquality()]); @@ -271,7 +272,7 @@ class UnorderedIterableEquality extends _UnorderedEquality> { /// The [equals] and [hash] methods accepts `null` values, /// even if the [isValidKey] returns `false` for `null`. /// The [hash] of `null` is `null.hashCode`. -class SetEquality extends _UnorderedEquality> { +final class SetEquality extends _UnorderedEquality> { const SetEquality([super.elementEquality = const DefaultEquality()]); @override @@ -282,7 +283,7 @@ class SetEquality extends _UnorderedEquality> { /// /// The class represents a map entry as a single object, /// using a combined hashCode and equality of the key and value. -class _MapEntry { +final class _MapEntry { final MapEquality equality; final Object? key; final Object? value; @@ -309,7 +310,7 @@ class _MapEntry { /// The [equals] and [hash] methods accepts `null` values, /// even if the [isValidKey] returns `false` for `null`. /// The [hash] of `null` is `null.hashCode`. -class MapEquality implements Equality> { +final class MapEquality implements Equality> { final Equality _keyEquality; final Equality _valueEquality; const MapEquality( @@ -372,7 +373,7 @@ class MapEquality implements Equality> { /// for `equals(e1, e2)` and `equals(e2, e1)`. This can happen if one equality /// considers only `e1` a valid key, and not `e2`, but an equality which is /// checked later, allows both. -class MultiEquality implements Equality { +final class MultiEquality implements Equality { final Iterable> _equalities; const MultiEquality(Iterable> equalities) @@ -418,7 +419,7 @@ class MultiEquality implements Equality { /// /// A list is only equal to another list, likewise for sets and maps. All other /// iterables are compared as iterables only. -class DeepCollectionEquality implements Equality { +final class DeepCollectionEquality implements Equality { final Equality _base; final bool _unordered; const DeepCollectionEquality([Equality base = const DefaultEquality()]) @@ -476,7 +477,7 @@ class DeepCollectionEquality implements Equality { /// String equality that's insensitive to differences in ASCII case. /// /// Non-ASCII characters are compared as-is, with no conversion. -class CaseInsensitiveEquality implements Equality { +final class CaseInsensitiveEquality implements Equality { const CaseInsensitiveEquality(); @override diff --git a/pkgs/collection/lib/src/equality_map.dart b/pkgs/collection/lib/src/equality_map.dart index 542977f69..fb8537d22 100644 --- a/pkgs/collection/lib/src/equality_map.dart +++ b/pkgs/collection/lib/src/equality_map.dart @@ -8,7 +8,7 @@ import 'equality.dart'; import 'wrappers.dart'; /// A [Map] whose key equality is determined by an [Equality] object. -class EqualityMap extends DelegatingMap { +final class EqualityMap extends DelegatingMap { /// Creates a map with equality based on [equality]. EqualityMap(Equality equality) : super(LinkedHashMap( diff --git a/pkgs/collection/lib/src/equality_set.dart b/pkgs/collection/lib/src/equality_set.dart index 8edbba5bd..529fc20ad 100644 --- a/pkgs/collection/lib/src/equality_set.dart +++ b/pkgs/collection/lib/src/equality_set.dart @@ -8,7 +8,7 @@ import 'equality.dart'; import 'wrappers.dart'; /// A [Set] whose key equality is determined by an [Equality] object. -class EqualitySet extends DelegatingSet { +final class EqualitySet extends DelegatingSet { /// Creates a set with equality based on [equality]. EqualitySet(Equality equality) : super(LinkedHashSet( diff --git a/pkgs/collection/lib/src/functions.dart b/pkgs/collection/lib/src/functions.dart index db8657417..04121583d 100644 --- a/pkgs/collection/lib/src/functions.dart +++ b/pkgs/collection/lib/src/functions.dart @@ -5,25 +5,9 @@ import 'dart:collection'; import 'dart:math' as math; +import 'list_extensions.dart' show ListExtensions; // For `reverseRange`. import 'utils.dart'; -/// Creates a new map from [map] with new keys and values. -/// -/// The return values of [key] are used as the keys and the return values of -/// [value] are used as the values for the new map. -@Deprecated('Use Map.map or a for loop in a Map literal.') -Map mapMap(Map map, - {K2 Function(K1, V1)? key, V2 Function(K1, V1)? value}) { - var keyFn = key ?? (mapKey, _) => mapKey as K2; - var valueFn = value ?? (_, mapValue) => mapValue as V2; - - var result = {}; - map.forEach((mapKey, mapValue) { - result[keyFn(mapKey, mapValue)] = valueFn(mapKey, mapValue); - }); - return result; -} - /// Returns a new map with all key/value pairs in both [map1] and [map2]. /// /// If there are keys that occur in both maps, the [value] function is used to @@ -109,45 +93,6 @@ S? maxBy(Iterable values, T Function(S) orderBy, return maxValue; } -/// Returns the [transitive closure][] of [graph]. -/// -/// [transitive closure]: https://en.wikipedia.org/wiki/Transitive_closure -/// -/// Interprets [graph] as a directed graph with a vertex for each key and edges -/// from each key to the values that the key maps to. -/// -/// Assumes that every vertex in the graph has a key to represent it, even if -/// that vertex has no outgoing edges. This isn't checked, but if it's not -/// satisfied, the function may crash or provide unexpected output. For example, -/// `{"a": ["b"]}` is not valid, but `{"a": ["b"], "b": []}` is. -@Deprecated('This method will be removed. Consider using package:graphs.') -Map> transitiveClosure(Map> graph) { - // This uses [Warshall's algorithm][], modified not to add a vertex from each - // node to itself. - // - // [Warshall's algorithm]: https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm#Applications_and_generalizations. - var result = >{}; - graph.forEach((vertex, edges) { - result[vertex] = Set.from(edges); - }); - - // Lists are faster to iterate than maps, so we create a list since we're - // iterating repeatedly. - var keys = graph.keys.toList(); - for (var vertex1 in keys) { - for (var vertex2 in keys) { - for (var vertex3 in keys) { - if (result[vertex2]!.contains(vertex1) && - result[vertex1]!.contains(vertex3)) { - result[vertex2]!.add(vertex3); - } - } - } - } - - return result; -} - /// Returns the [strongly connected components][] of [graph], in topological /// order. /// @@ -209,5 +154,5 @@ List> stronglyConnectedComponents(Map> graph) { // Tarjan's algorithm produces a reverse-topological sort, so we reverse it to // get a normal topological sort. - return result.reversed.toList(); + return result..reverseRange(0, result.length); } diff --git a/pkgs/collection/lib/src/iterable_extensions.dart b/pkgs/collection/lib/src/iterable_extensions.dart index 10f467608..8056adb6a 100644 --- a/pkgs/collection/lib/src/iterable_extensions.dart +++ b/pkgs/collection/lib/src/iterable_extensions.dart @@ -16,7 +16,7 @@ import 'utils.dart'; /// /// More specialized extension methods that only apply to /// iterables with specific element types include those of -/// [IterableComparableExtension] and [IterableNullableExtension]. +/// [IterableComparableExtension]. extension IterableExtension on Iterable { /// Selects [count] elements at random from this iterable. /// @@ -604,6 +604,8 @@ extension IterableExtension on Iterable { } /// Extensions that apply to iterables with a nullable element type. +/// @nodoc +@Deprecated('Use .nonNulls instead.') extension IterableNullableExtension on Iterable { /// The non-`null` elements of this `Iterable`. /// @@ -611,6 +613,7 @@ extension IterableNullableExtension on Iterable { /// of this iterable, in their original iteration order. /// /// For an `Iterable`, this method is equivalent to `.whereType()`. + /// @nodoc @Deprecated('Use .nonNulls instead.') Iterable whereNotNull() sync* { for (var element in this) { diff --git a/pkgs/collection/lib/src/iterable_zip.dart b/pkgs/collection/lib/src/iterable_zip.dart index 9671eaf3f..89a0316c2 100644 --- a/pkgs/collection/lib/src/iterable_zip.dart +++ b/pkgs/collection/lib/src/iterable_zip.dart @@ -13,7 +13,9 @@ import 'dart:collection'; /// combined into a single list, which becomes the next value of this /// [Iterable]'s [Iterator]. As soon as any of the iterators run out, /// the zipped iterator also stops. -class IterableZip extends IterableBase> { +/// @nodoc +@Deprecated('Use [i1, i2].zip from dart:collection') +final class IterableZip extends IterableBase> { final Iterable> _iterables; IterableZip(Iterable> iterables) : _iterables = iterables; @@ -27,7 +29,7 @@ class IterableZip extends IterableBase> { } } -class _IteratorZip implements Iterator> { +final class _IteratorZip implements Iterator> { final List> _iterators; List? _current; diff --git a/pkgs/collection/lib/src/priority_queue.dart b/pkgs/collection/lib/src/priority_queue.dart index 11b0348a2..41073b1b2 100644 --- a/pkgs/collection/lib/src/priority_queue.dart +++ b/pkgs/collection/lib/src/priority_queue.dart @@ -21,7 +21,7 @@ import 'utils.dart'; /// If elements override [Object.==], the `comparison` function must /// always give equal objects the same priority, /// otherwise [contains] or [remove] might not work correctly. -abstract class PriorityQueue { +abstract interface class PriorityQueue { /// Creates an empty [PriorityQueue]. /// /// The created [PriorityQueue] is a plain [HeapPriorityQueue]. @@ -168,7 +168,7 @@ abstract class PriorityQueue { /// and is linear, O(n). /// * The [toSet] operation effectively adds each element to the new set, taking /// an expected O(n*log(n)) time. -class HeapPriorityQueue implements PriorityQueue { +final class HeapPriorityQueue implements PriorityQueue { /// Initial capacity of a queue when created, or when added to after a /// [clear]. /// diff --git a/pkgs/collection/lib/src/queue_list.dart b/pkgs/collection/lib/src/queue_list.dart index a3eaba136..9fffa167c 100644 --- a/pkgs/collection/lib/src/queue_list.dart +++ b/pkgs/collection/lib/src/queue_list.dart @@ -5,11 +5,7 @@ import 'dart:collection'; /// A class that efficiently implements both [Queue] and [List]. -// TODO(nweiz): Currently this code is copied almost verbatim from -// dart:collection. The only changes are to implement List and to remove methods -// that are redundant with ListMixin. Remove or simplify it when issue 21330 is -// fixed. -class QueueList extends Object with ListMixin implements Queue { +interface class QueueList with ListMixin implements Queue { /// Adapts [source] to be a `QueueList`. /// /// Any time the class would produce an element that is not a [T], the element @@ -115,9 +111,6 @@ class QueueList extends Object with ListMixin implements Queue { QueueList cast() => QueueList._castFrom(this); - @Deprecated('Use cast instead') - QueueList retype() => cast(); - @override String toString() => IterableBase.iterableToFullString(this, '{', '}'); @@ -274,7 +267,7 @@ class QueueList extends Object with ListMixin implements Queue { } } -class _CastQueueList extends QueueList { +final class _CastQueueList extends QueueList { final QueueList _delegate; // Assigns invalid values for head/tail because it uses the delegate to hold diff --git a/pkgs/collection/lib/src/union_set.dart b/pkgs/collection/lib/src/union_set.dart index a34d7ad37..06cde03bf 100644 --- a/pkgs/collection/lib/src/union_set.dart +++ b/pkgs/collection/lib/src/union_set.dart @@ -13,7 +13,7 @@ import 'unmodifiable_wrappers.dart'; /// If an element is in multiple sets and the outer set is ordered, the version /// in the earliest inner set is preferred. Component sets are assumed to use /// `==` and `hashCode` for equality. -class UnionSet extends SetBase with UnmodifiableSetMixin { +final class UnionSet extends SetBase with UnmodifiableSetMixin { /// The set of sets that this provides a view of. final Set> _sets; diff --git a/pkgs/collection/lib/src/union_set_controller.dart b/pkgs/collection/lib/src/union_set_controller.dart index 498528e20..3600c525d 100644 --- a/pkgs/collection/lib/src/union_set_controller.dart +++ b/pkgs/collection/lib/src/union_set_controller.dart @@ -21,7 +21,7 @@ import 'union_set.dart'; /// } /// } /// ``` -class UnionSetController { +interface class UnionSetController { /// The [UnionSet] that provides a view of the union of sets in `this`. final UnionSet set; diff --git a/pkgs/collection/lib/src/unmodifiable_wrappers.dart b/pkgs/collection/lib/src/unmodifiable_wrappers.dart index a73a55b31..897ccdbc2 100644 --- a/pkgs/collection/lib/src/unmodifiable_wrappers.dart +++ b/pkgs/collection/lib/src/unmodifiable_wrappers.dart @@ -193,14 +193,4 @@ abstract mixin class UnmodifiableMapMixin implements Map { /// operations that change the map are disallowed. @override void clear() => _throw(); - - /// Throws an [UnsupportedError]. - // ignore: provide_deprecation_message - @deprecated - set first(Object? _) => _throw(); - - /// Throws an [UnsupportedError]. - // ignore: provide_deprecation_message - @deprecated - set last(Object? _) => _throw(); } diff --git a/pkgs/collection/lib/src/wrappers.dart b/pkgs/collection/lib/src/wrappers.dart index 859d0bcc4..a703e4e65 100644 --- a/pkgs/collection/lib/src/wrappers.dart +++ b/pkgs/collection/lib/src/wrappers.dart @@ -79,9 +79,6 @@ abstract class _DelegatingIterableBase implements Iterable { @override E reduce(E Function(E value, E element) combine) => _base.reduce(combine); - @Deprecated('Use cast instead') - Iterable retype() => cast(); - @override E get single => _base.single; @@ -129,18 +126,6 @@ class DelegatingIterable extends _DelegatingIterableBase { /// Creates a wrapper that forwards operations to [base]. const DelegatingIterable(Iterable base) : _base = base; - - /// Creates a wrapper that asserts the types of values in [base]. - /// - /// This soundly converts an [Iterable] without a generic type to an - /// `Iterable` by asserting that its elements are instances of `E` whenever - /// they're accessed. If they're not, it throws a [TypeError]. - /// - /// This forwards all operations to [base], so any changes in [base] will be - /// reflected in `this`. If [base] is already an `Iterable`, it's returned - /// unmodified. - @Deprecated('Use iterable.cast instead.') - static Iterable typed(Iterable base) => base.cast(); } /// A [List] that delegates all operations to a base list. @@ -154,20 +139,6 @@ class DelegatingList extends _DelegatingIterableBase implements List { const DelegatingList(List base) : _base = base; - /// Creates a wrapper that asserts the types of values in [base]. - /// - /// This soundly converts a [List] without a generic type to a `List` by - /// asserting that its elements are instances of `E` whenever they're - /// accessed. If they're not, it throws a [TypeError]. Note that even if an - /// operation throws a [TypeError], it may still mutate the underlying - /// collection. - /// - /// This forwards all operations to [base], so any changes in [base] will be - /// reflected in `this`. If [base] is already a `List`, it's returned - /// unmodified. - @Deprecated('Use list.cast instead.') - static List typed(List base) => base.cast(); - @override E operator [](int index) => _base[index]; @@ -278,10 +249,6 @@ class DelegatingList extends _DelegatingIterableBase implements List { _base.retainWhere(test); } - @Deprecated('Use cast instead') - @override - List retype() => cast(); - @override Iterable get reversed => _base.reversed; @@ -319,20 +286,6 @@ class DelegatingSet extends _DelegatingIterableBase implements Set { const DelegatingSet(Set base) : _base = base; - /// Creates a wrapper that asserts the types of values in [base]. - /// - /// This soundly converts a [Set] without a generic type to a `Set` by - /// asserting that its elements are instances of `E` whenever they're - /// accessed. If they're not, it throws a [TypeError]. Note that even if an - /// operation throws a [TypeError], it may still mutate the underlying - /// collection. - /// - /// This forwards all operations to [base], so any changes in [base] will be - /// reflected in `this`. If [base] is already a `Set`, it's returned - /// unmodified. - @Deprecated('Use set.cast instead.') - static Set typed(Set base) => base.cast(); - @override bool add(E value) => _base.add(value); @@ -379,10 +332,6 @@ class DelegatingSet extends _DelegatingIterableBase implements Set { _base.retainAll(elements); } - @Deprecated('Use cast instead') - @override - Set retype() => cast(); - @override void retainWhere(bool Function(E) test) { _base.retainWhere(test); @@ -407,20 +356,6 @@ class DelegatingQueue extends _DelegatingIterableBase const DelegatingQueue(Queue queue) : _base = queue; - /// Creates a wrapper that asserts the types of values in [base]. - /// - /// This soundly converts a [Queue] without a generic type to a `Queue` by - /// asserting that its elements are instances of `E` whenever they're - /// accessed. If they're not, it throws a [TypeError]. Note that even if an - /// operation throws a [TypeError], it may still mutate the underlying - /// collection. - /// - /// This forwards all operations to [base], so any changes in [base] will be - /// reflected in `this`. If [base] is already a `Queue`, it's returned - /// unmodified. - @Deprecated('Use queue.cast instead.') - static Queue typed(Queue base) => base.cast(); - @override void add(E value) { _base.add(value); @@ -462,10 +397,6 @@ class DelegatingQueue extends _DelegatingIterableBase _base.retainWhere(test); } - @Deprecated('Use cast instead') - @override - Queue retype() => cast(); - @override E removeFirst() => _base.removeFirst(); @@ -483,20 +414,6 @@ class DelegatingMap implements Map { const DelegatingMap(Map base) : _base = base; - /// Creates a wrapper that asserts the types of keys and values in [base]. - /// - /// This soundly converts a [Map] without generic types to a `Map` by - /// asserting that its keys are instances of `E` and its values are instances - /// of `V` whenever they're accessed. If they're not, it throws a [TypeError]. - /// Note that even if an operation throws a [TypeError], it may still mutate - /// the underlying collection. - /// - /// This forwards all operations to [base], so any changes in [base] will be - /// reflected in `this`. If [base] is already a `Map`, it's returned - /// unmodified. - @Deprecated('Use map.cast instead.') - static Map typed(Map base) => base.cast(); - @override V? operator [](Object? key) => _base[key]; @@ -563,9 +480,6 @@ class DelegatingMap implements Map { @override void removeWhere(bool Function(K, V) test) => _base.removeWhere(test); - @Deprecated('Use cast instead') - Map retype() => cast(); - @override Iterable get values => _base.values; @@ -589,7 +503,7 @@ class DelegatingMap implements Map { /// getter only shows an [Iterable] view of the keys. /// /// Note that [lookup] is not supported for this set. -class MapKeySet extends _DelegatingIterableBase +final class MapKeySet extends _DelegatingIterableBase with UnmodifiableSetMixin { final Map _baseMap; @@ -651,10 +565,6 @@ class MapKeySet extends _DelegatingIterableBase E lookup(Object? element) => throw UnsupportedError("MapKeySet doesn't support lookup()."); - @Deprecated('Use cast instead') - @override - Set retype() => Set.castFrom(this); - /// Returns a new set which contains all the elements of `this` and [other]. /// /// That is, the returned set contains all the elements of this [Set] and all @@ -687,7 +597,8 @@ class MapKeySet extends _DelegatingIterableBase /// `recordSet.add(databaseRecord)` and `recordMap[id]`. /// /// Effectively, the map will act as a kind of index for the set. -class MapValueSet extends _DelegatingIterableBase implements Set { +final class MapValueSet extends _DelegatingIterableBase + implements Set { final Map _baseMap; final K Function(V) _keyForValue; @@ -822,10 +733,6 @@ class MapValueSet extends _DelegatingIterableBase implements Set { void retainWhere(bool Function(V) test) => removeWhere((element) => !test(element)); - @Deprecated('Use cast instead') - @override - Set retype() => Set.castFrom(this); - /// Returns a new set which contains all the elements of `this` and [other]. /// /// That is, the returned set contains all the elements of this [Set] and all diff --git a/pkgs/collection/lib/wrappers.dart b/pkgs/collection/lib/wrappers.dart deleted file mode 100644 index be529ca25..000000000 --- a/pkgs/collection/lib/wrappers.dart +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright (c) 2013, 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 `collection.dart` instead. -@Deprecated('Will be removed in collection 2.0.0.') -library; - -export 'src/canonicalized_map.dart'; -export 'src/unmodifiable_wrappers.dart'; -export 'src/wrappers.dart'; diff --git a/pkgs/collection/pubspec.yaml b/pkgs/collection/pubspec.yaml index 26eb4b936..4a6239cbd 100644 --- a/pkgs/collection/pubspec.yaml +++ b/pkgs/collection/pubspec.yaml @@ -1,5 +1,5 @@ name: collection -version: 1.20.0-wip +version: 1.20.0-2.0.0.wip description: >- Collections and utilities functions and classes related to collections. repository: https://github.com/dart-lang/core/tree/main/pkgs/collection @@ -8,11 +8,15 @@ issue_tracker: https://github.com/dart-lang/core/issues?q=is%3Aissue+is%3Aopen+l topics: - collections - data-structures + - equality environment: - sdk: ^3.4.0 + sdk: ^3.6.0 + +dependencies: + meta: ^1.16.0 dev_dependencies: benchmark_harness: ^2.3.1 - dart_flutter_team_lints: ^3.0.0 - test: ^1.16.6 + dart_flutter_team_lints: ^3.3.0 + test: ^1.16.0 diff --git a/pkgs/collection/test/analysis_options.yaml b/pkgs/collection/test/analysis_options.yaml index 899b0f33c..2d2950532 100644 --- a/pkgs/collection/test/analysis_options.yaml +++ b/pkgs/collection/test/analysis_options.yaml @@ -1,6 +1,6 @@ include: ../analysis_options.yaml -# Turn off the avoid_dynamic_calls lint for the test/ directory. +# Turn off common lint violations for the test/ directory. analyzer: errors: avoid_dynamic_calls: ignore diff --git a/pkgs/collection/test/extensions_test.dart b/pkgs/collection/test/extensions_test.dart index dd9205977..3d909f1c1 100644 --- a/pkgs/collection/test/extensions_test.dart +++ b/pkgs/collection/test/extensions_test.dart @@ -2225,7 +2225,7 @@ Iterable iterable(Iterable values) sync* { yield* values; } -Never unreachable([dynamic _, dynamic __, dynamic ___]) => fail('Unreachable'); +Never unreachable([Object? _, Object? __, Object? ___]) => fail('Unreachable'); String toString(Object? o) => '$o'; diff --git a/pkgs/collection/test/functions_test.dart b/pkgs/collection/test/functions_test.dart index f60230332..11c2e3772 100644 --- a/pkgs/collection/test/functions_test.dart +++ b/pkgs/collection/test/functions_test.dart @@ -8,48 +8,6 @@ import 'package:collection/collection.dart'; import 'package:test/test.dart'; void main() { - group('mapMap()', () { - test('with an empty map returns an empty map', () { - expect( - mapMap({}, - key: expectAsync2((_, __) {}, count: 0), - value: expectAsync2((_, __) {}, count: 0)), - isEmpty); - }); - - test('with no callbacks, returns a copy of the map', () { - var map = {'foo': 1, 'bar': 2}; - var result = mapMap(map); - expect(result, equals({'foo': 1, 'bar': 2})); - - // The resulting map should be a copy. - result['foo'] = 3; - expect(map, equals({'foo': 1, 'bar': 2})); - }); - - test("maps the map's keys", () { - expect( - mapMap({'foo': 1, 'bar': 2}, - key: (dynamic key, dynamic value) => key[value]), - equals({'o': 1, 'r': 2})); - }); - - test("maps the map's values", () { - expect( - mapMap({'foo': 1, 'bar': 2}, - value: (dynamic key, dynamic value) => key[value]), - equals({'foo': 'o', 'bar': 'r'})); - }); - - test("maps both the map's keys and values", () { - expect( - mapMap({'foo': 1, 'bar': 2}, - key: (dynamic key, dynamic value) => '$key$value', - value: (dynamic key, dynamic value) => key[value]), - equals({'foo1': 'o', 'bar2': 'r'})); - }); - }); - group('mergeMaps()', () { test('with empty maps returns an empty map', () { expect( @@ -185,60 +143,6 @@ void main() { }); }); - group('transitiveClosure()', () { - test('returns an empty map for an empty graph', () { - expect(transitiveClosure({}), isEmpty); - }); - - test('returns the input when there are no transitive connections', () { - expect( - transitiveClosure({ - 'foo': ['bar'], - 'bar': [], - 'bang': ['qux', 'zap'], - 'qux': [], - 'zap': [] - }), - equals({ - 'foo': ['bar'], - 'bar': [], - 'bang': ['qux', 'zap'], - 'qux': [], - 'zap': [] - })); - }); - - test('flattens transitive connections', () { - expect( - transitiveClosure({ - 'qux': [], - 'bar': ['baz'], - 'baz': ['qux'], - 'foo': ['bar'] - }), - equals({ - 'foo': ['bar', 'baz', 'qux'], - 'bar': ['baz', 'qux'], - 'baz': ['qux'], - 'qux': [] - })); - }); - - test('handles loops', () { - expect( - transitiveClosure({ - 'foo': ['bar'], - 'bar': ['baz'], - 'baz': ['foo'] - }), - equals({ - 'foo': ['bar', 'baz', 'foo'], - 'bar': ['baz', 'foo', 'bar'], - 'baz': ['foo', 'bar', 'baz'] - })); - }); - }); - group('stronglyConnectedComponents()', () { test('returns an empty list for an empty graph', () { expect(stronglyConnectedComponents({}), isEmpty); diff --git a/pkgs/collection/test/iterable_zip_test.dart b/pkgs/collection/test/iterable_zip_test.dart index 3881c6af6..413c85a81 100644 --- a/pkgs/collection/test/iterable_zip_test.dart +++ b/pkgs/collection/test/iterable_zip_test.dart @@ -2,6 +2,8 @@ // 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. +// ignore_for_file: deprecated_member_use_from_same_package + import 'package:collection/collection.dart'; import 'package:test/test.dart';