Skip to content
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

Add new Dart 2 Map, Iterable, and List methods to multimap stuff #425

Merged
merged 6 commits into from
Mar 23, 2018
Merged
Show file tree
Hide file tree
Changes from 3 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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
#### Master

* New: The map returned by `Multimap.asMap()` now includes real
implementations of `get entries` and `removeWhere`. This class also has
"real" implementations of `addEntries`, `map`, `update`, and `updateAll`,
which just throw an `UnsupportedError`, as inserts and updates are not
allowed on map views.
* New: The list keys of `ListMultimap` now include real implementations of
`operator +`, `indexWhere`, and `lastIndexWhere`.
* New: The iterable keys of `ListMultimap` and `SetMultimap` now include a
real implementation of `followedBy`, and accept the `orElse` parameter on
`singleWhere`.

#### 0.28.0 - 2018-01-19

* BREAKING CHANGE: The signature of `MultiMap`'s `update` stub has changed
Expand Down
73 changes: 28 additions & 45 deletions lib/src/collection/multimap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -309,51 +309,44 @@ class _WrappedMap<K, V, C extends Iterable<V>> implements Map<K, C> {
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_getter
Iterable<Null> get entries {
// Change Iterable<Null> to Iterable<MapEntry<K, V>> when
// the MapEntry class has been added.
throw new UnimplementedError("entries");
Iterable<MapEntry<K, C>> get entries {
return keys.map((K key) => new MapEntry<K, C>(key, this[key]));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps:

Iterable<MapEntry<K, C>> get entries => _multimap._map.entries;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
void addEntries(Iterable<Object> entries) {
// Change Iterable<Object> to Iterable<MapEntry<K, V>> when
// the MapEntry class has been added.
throw new UnimplementedError("addEntries");
void addEntries(Iterable<MapEntry<K, C>> entries) {
throw new UnsupportedError("Insert unsupported on map view");
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
Map<K2, V2> map<K2, V2>(Object transform(K key, C value)) {
// Change Object to MapEntry<K2, V2> when
// the MapEntry class has been added.
throw new UnimplementedError("map");
Map<K2, C2> map<K2, C2>(MapEntry<K2, C2> transform(K key, C value)) {
var result = <K2, C2>{};
for (var key in this.keys) {
var entry = transform(key, this[key]);
result[entry.key] = entry.value;
}
return result;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  Map<K2, C2> map<K2, C2>(MapEntry<K2, C2> transform(K key, C value)) =>
      _multimap._map.map(transform);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
C update(K key, C update(C value), {C ifAbsent()}) {
throw new UnimplementedError("update");
throw new UnsupportedError("Update unsupported on map view");
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
void updateAll(C update(K key, C value)) {
throw new UnimplementedError("updateAll");
throw new UnsupportedError("Update unsupported on map view");
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
void removeWhere(bool test(K key, C value)) {
throw new UnimplementedError("removeWhere");
var keysToRemove = <K>[];
for (var key in keys) {
if (test(key, this[key])) keysToRemove.add(key);
}
for (var key in keysToRemove) {
_multimap.removeAll(key);
}
}
}

Expand Down Expand Up @@ -430,10 +423,9 @@ class _WrappedIterable<K, V, C extends Iterable<V>> implements Iterable<V> {
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
Iterable<V> followedBy(Iterable<V> other) {
throw new UnimplementedError("followedBy");
_syncDelegate();
return _delegate.followedBy(other);
}

void forEach(void f(V element)) {
Expand Down Expand Up @@ -499,9 +491,8 @@ class _WrappedIterable<K, V, C extends Iterable<V>> implements Iterable<V> {
}

V singleWhere(bool test(V element), {V orElse()}) {
if (orElse != null) throw new UnimplementedError("singleWhere:orElse");
_syncDelegate();
return _delegate.singleWhere(test);
return _delegate.singleWhere(test, orElse: orElse);
}

Iterable<V> skip(int n) {
Expand Down Expand Up @@ -565,10 +556,9 @@ class _WrappedList<K, V> extends _WrappedIterable<K, V, List<V>>
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
List<V> operator +(List<V> other) {
throw new UnimplementedError("+");
_syncDelegate();
return _delegate + other;
}

void add(V value) {
Expand Down Expand Up @@ -609,8 +599,6 @@ class _WrappedList<K, V> extends _WrappedIterable<K, V, List<V>>
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_setter
void set first(V value) {
if (this.isEmpty) throw new RangeError.index(0, this);
this[0] = value;
Expand All @@ -627,10 +615,9 @@ class _WrappedList<K, V> extends _WrappedIterable<K, V, List<V>>
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
int indexWhere(bool test(V element), [int start = 0]) {
throw new UnimplementedError("indexWhere");
_syncDelegate();
return _delegate.indexWhere(test, start);
}

void insert(int index, V element) {
Expand All @@ -648,8 +635,6 @@ class _WrappedList<K, V> extends _WrappedIterable<K, V, List<V>>
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_setter
void set last(V value) {
if (this.isEmpty) throw new RangeError.index(0, this);
this[this.length - 1] = value;
Expand All @@ -661,10 +646,8 @@ class _WrappedList<K, V> extends _WrappedIterable<K, V, List<V>>
}

@override
// TODO: Dart 2.0 requires this method to be implemented.
// ignore: override_on_non_overriding_method
int lastIndexWhere(bool test(V element), [int start]) {
throw new UnimplementedError("lastIndexWhere");
return _delegate.lastIndexWhere(test, start);
}

void set length(int newLength) {
Expand Down
36 changes: 36 additions & 0 deletions test/collection/multimap_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,21 @@ void main() {
expect(() => map['k1'] = ['1', '2', '3'], throwsUnsupportedError);
});

test('addEntries should throw UnsupportedError', () {
expect(() => map.addEntries(<MapEntry<String, List<String>>>[]),
throwsUnsupportedError);
});

test('update should throw UnsupportedError', () {
expect(() => map.update('k1', (_) => ['1', '2', '3']),
throwsUnsupportedError);
});

test('updateAll should throw UnsupportedError', () {
expect(() => map.updateAll((_, __) => ['1', '2', '3']),
throwsUnsupportedError);
});

test('containsKey() should return false for missing key', () {
expect(map.containsKey('k3'), isFalse);
});
Expand Down Expand Up @@ -928,6 +943,27 @@ void main() {
expect(mmap.containsKey('k1'), false);
});

test('should something about entries in returned map view', () {
var mmap = new SetMultimap<String, String>()
..add('k1', 'v1')
..add('k1', 'v2');
Map map = mmap.asMap();
expect(map.entries, hasLength(1));
expect(map.entries.single.key, equals('k1'));
expect(map.entries.single.value, unorderedEquals(['v1', 'v2']));
});

test('should map from returned map view', () {
var mmap = new SetMultimap<String, String>()
..add('k1', 'v1')
..add('k1', 'v2');
Map map = mmap.asMap();
var newMap = map.map((k, v) => new MapEntry(k, v.join(',')));
expect(newMap, hasLength(1));
expect(newMap, contains('k1'));
expect(newMap, containsValue('v1,v2'));
});

test('should reflect clearing of returned map view', () {
var mmap = new SetMultimap<String, String>()
..add('k1', 'v1')
Expand Down