Skip to content

Collection: Major version, use 3.0 language features. #859

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions pkgs/collection/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
10 changes: 0 additions & 10 deletions pkgs/collection/lib/algorithms.dart

This file was deleted.

9 changes: 0 additions & 9 deletions pkgs/collection/lib/equality.dart

This file was deleted.

9 changes: 0 additions & 9 deletions pkgs/collection/lib/iterable_zip.dart

This file was deleted.

9 changes: 0 additions & 9 deletions pkgs/collection/lib/priority_queue.dart

This file was deleted.

7 changes: 4 additions & 3 deletions pkgs/collection/lib/src/boollist.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool> {
abstract final class BoolList with ListMixin<bool> {
static const int _entryShift = 5;

static const int _bitsPerEntry = 32;
Expand Down Expand Up @@ -180,7 +180,7 @@ abstract /*mixin*/ class BoolList with ListMixin<bool> {
}
}

class _GrowableBoolList extends BoolList {
final class _GrowableBoolList extends BoolList {
static const int _growthFactor = 2;

_GrowableBoolList._withCapacity(int length, int capacity)
Expand Down Expand Up @@ -228,7 +228,8 @@ class _GrowableBoolList extends BoolList {
}
}

class _NonGrowableBoolList extends BoolList with NonGrowableListMixin<bool> {
final class _NonGrowableBoolList extends BoolList
with NonGrowableListMixin<bool> {
_NonGrowableBoolList._withCapacity(int length, int capacity)
: super._(
Uint32List(BoolList._lengthInWords(capacity)),
Expand Down
61 changes: 37 additions & 24 deletions pkgs/collection/lib/src/canonicalized_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<C, K, V> implements Map<K, V> {
final C Function(K) _canonicalize;

Expand All @@ -25,9 +28,10 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
/// 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
Expand All @@ -39,9 +43,11 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
/// 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<K, V> other, C Function(K key) canonicalize,
{bool Function(K key)? isValidKey})
: _canonicalize = canonicalize,
CanonicalizedMap.from(
Map<K, V> other,
C Function(K key) canonicalize, {
bool Function(K key)? isValidKey,
}) : _canonicalize = canonicalize,
_isValidKeyFn = isValidKey {
addAll(other);
}
Expand All @@ -56,15 +62,19 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
/// methods that take arbitrary objects. It can be used to filter out keys
/// that can't be canonicalized.
CanonicalizedMap.fromEntries(
Iterable<MapEntry<K, V>> entries, C Function(K key) canonicalize,
{bool Function(K key)? isValidKey})
: _canonicalize = canonicalize,
Iterable<MapEntry<K, V>> entries,
C Function(K key) canonicalize, {
bool Function(K key)? isValidKey,
}) : _canonicalize = canonicalize,
_isValidKeyFn = isValidKey {
addEntries(entries);
}

CanonicalizedMap._(
this._canonicalize, this._isValidKeyFn, Map<C, MapEntry<K, V>> base) {
this._canonicalize,
this._isValidKeyFn,
Map<C, MapEntry<K, V>> base,
) {
_base.addAll(base);
}

Expand Down Expand Up @@ -92,8 +102,11 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
}

@override
void addEntries(Iterable<MapEntry<K, V>> entries) => _base.addEntries(entries
.map((e) => MapEntry(_canonicalize(e.key), MapEntry(e.key, e.value))));
void addEntries(Iterable<MapEntry<K, V>> entries) => _base.addEntries(
entries.map(
(e) => MapEntry(_canonicalize(e.key), MapEntry(e.key, e.value)),
),
);

@override
Map<K2, V2> cast<K2, V2>() => _base.cast<K2, V2>();
Expand Down Expand Up @@ -156,19 +169,18 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
void removeWhere(bool Function(K key, V value) test) =>
_base.removeWhere((_, pair) => test(pair.key, pair.value));

@Deprecated('Use cast instead')
Map<K2, V2> retype<K2, V2>() => cast<K2, V2>();

@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) =>
Expand Down Expand Up @@ -196,5 +208,6 @@ class CanonicalizedMap<C, K, V> implements Map<K, V> {
/// Creates a `Map<C,V>` (with the canonicalized keys).
/// See [toMap].
Map<C, V> toMapOfCanonicalKeys() => Map<C, V>.fromEntries(
_base.entries.map((e) => MapEntry<C, V>(e.key, e.value.value)));
_base.entries.map((e) => MapEntry<C, V>(e.key, e.value.value)),
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> extends IterableBase<T> {
final class CombinedIterableView<T> extends IterableBase<T> {
/// The iterables that this combines.
final Iterable<Iterable<T>> _iterables;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/// The iterator for `CombinedIterableView` and `CombinedListView`.
///
/// Moves through each iterable's iterator in sequence.
class CombinedIterator<T> implements Iterator<T> {
final class CombinedIterator<T> implements Iterator<T> {
/// The iterators that this combines, or `null` if done iterating.
///
/// Because this comes from a call to [Iterable.map], it's lazy and will
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> extends ListBase<T>
final class CombinedListView<T> extends ListBase<T>
implements UnmodifiableListView<T> {
static Never _throw() {
throw UnsupportedError('Cannot modify an unmodifiable List');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<K, V> extends UnmodifiableMapBase<K, V> {
final class CombinedMapView<K, V> extends UnmodifiableMapBase<K, V> {
final Iterable<Map<K, V>> _maps;

/// Create a new combined view of multiple maps.
Expand Down
6 changes: 6 additions & 0 deletions pkgs/collection/lib/src/comparators.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 1 addition & 4 deletions pkgs/collection/lib/src/empty_unmodifiable_set.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'unmodifiable_wrappers.dart';
import 'wrappers.dart';

/// An unmodifiable, empty set which can be constant.
class EmptyUnmodifiableSet<E> extends IterableBase<E>
final class EmptyUnmodifiableSet<E> extends IterableBase<E>
with UnmodifiableSetMixin<E>
implements UnmodifiableSetView<E> {
const EmptyUnmodifiableSet();
Expand All @@ -27,9 +27,6 @@ class EmptyUnmodifiableSet<E> extends IterableBase<E>
Iterable<E> followedBy(Iterable<E> other) => DelegatingIterable(other);
@override
E? lookup(Object? element) => null;
@Deprecated('Use cast instead')
@override
EmptyUnmodifiableSet<T> retype<T>() => EmptyUnmodifiableSet<T>();
@override
E singleWhere(bool Function(E) test, {E Function()? orElse}) =>
orElse != null ? orElse() : throw StateError('No element');
Expand Down
29 changes: 15 additions & 14 deletions pkgs/collection/lib/src/equality.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import 'comparators.dart';
const int _hashMask = 0x7fffffff;

/// A generic equality relation on objects.
abstract class Equality<E> {
abstract interface class Equality<E> {
const factory Equality() = DefaultEquality<E>;

/// Compare two elements for being equal.
Expand Down Expand Up @@ -46,7 +46,7 @@ abstract class Equality<E> {
///
/// It's also possible to pass an additional equality instance that should be
/// used to compare the value itself.
class EqualityBy<E, F> implements Equality<E> {
final class EqualityBy<E, F> implements Equality<E> {
final F Function(E) _comparisonKey;

final Equality<F> _inner;
Expand Down Expand Up @@ -81,7 +81,7 @@ class EqualityBy<E, F> implements Equality<E> {
/// 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<E> implements Equality<E> {
final class DefaultEquality<E> implements Equality<E> {
const DefaultEquality();
@override
bool equals(Object? e1, Object? e2) => e1 == e2;
Expand All @@ -92,7 +92,7 @@ class DefaultEquality<E> implements Equality<E> {
}

/// Equality of objects that compares only the identity of the objects.
class IdentityEquality<E> implements Equality<E> {
final class IdentityEquality<E> implements Equality<E> {
const IdentityEquality();
@override
bool equals(E e1, E e2) => identical(e1, e2);
Expand All @@ -109,7 +109,7 @@ class IdentityEquality<E> implements Equality<E> {
/// 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<E> implements Equality<Iterable<E>> {
final class IterableEquality<E> implements Equality<Iterable<E>> {
final Equality<E?> _elementEquality;
const IterableEquality(
[Equality<E> elementEquality = const DefaultEquality<Never>()])
Expand Down Expand Up @@ -161,7 +161,7 @@ class IterableEquality<E> implements Equality<Iterable<E>> {
/// 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<E> implements Equality<List<E>> {
final class ListEquality<E> implements Equality<List<E>> {
final Equality<E> _elementEquality;
const ListEquality(
[Equality<E> elementEquality = const DefaultEquality<Never>()])
Expand Down Expand Up @@ -202,7 +202,7 @@ class ListEquality<E> implements Equality<List<E>> {
bool isValidKey(Object? o) => o is List<E>;
}

abstract class _UnorderedEquality<E, T extends Iterable<E>>
abstract final class _UnorderedEquality<E, T extends Iterable<E>>
implements Equality<T> {
final Equality<E> _elementEquality;

Expand Down Expand Up @@ -251,7 +251,8 @@ abstract class _UnorderedEquality<E, T extends Iterable<E>>
/// 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<E> extends _UnorderedEquality<E, Iterable<E>> {
final class UnorderedIterableEquality<E>
extends _UnorderedEquality<E, Iterable<E>> {
const UnorderedIterableEquality(
[super.elementEquality = const DefaultEquality<Never>()]);

Expand All @@ -271,7 +272,7 @@ class UnorderedIterableEquality<E> extends _UnorderedEquality<E, Iterable<E>> {
/// 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<E> extends _UnorderedEquality<E, Set<E>> {
final class SetEquality<E> extends _UnorderedEquality<E, Set<E>> {
const SetEquality([super.elementEquality = const DefaultEquality<Never>()]);

@override
Expand All @@ -282,7 +283,7 @@ class SetEquality<E> extends _UnorderedEquality<E, Set<E>> {
///
/// 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;
Expand All @@ -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<K, V> implements Equality<Map<K, V>> {
final class MapEquality<K, V> implements Equality<Map<K, V>> {
final Equality<K> _keyEquality;
final Equality<V> _valueEquality;
const MapEquality(
Expand Down Expand Up @@ -372,7 +373,7 @@ class MapEquality<K, V> implements Equality<Map<K, V>> {
/// 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<E> implements Equality<E> {
final class MultiEquality<E> implements Equality<E> {
final Iterable<Equality<E>> _equalities;

const MultiEquality(Iterable<Equality<E>> equalities)
Expand Down Expand Up @@ -418,7 +419,7 @@ class MultiEquality<E> implements Equality<E> {
///
/// 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<Never>()])
Expand Down Expand Up @@ -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<String> {
final class CaseInsensitiveEquality implements Equality<String> {
const CaseInsensitiveEquality();

@override
Expand Down
Loading
Loading