LCOV - code coverage report
Current view: top level - collection-1.14.3/lib/src - wrappers.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 8 159 5.0 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
       2             : // for details. All rights reserved. Use of this source code is governed by a
       3             : // BSD-style license that can be found in the LICENSE file.
       4             : 
       5             : import "dart:collection";
       6             : import "dart:math" as math;
       7             : 
       8             : import "typed_wrappers.dart";
       9             : import "unmodifiable_wrappers.dart";
      10             : 
      11             : typedef K _KeyForValue<K, V>(V value);
      12             : 
      13             : /// A base class for delegating iterables.
      14             : ///
      15             : /// Subclasses can provide a [_base] that should be delegated to. Unlike
      16             : /// [DelegatingIterable], this allows the base to be created on demand.
      17             : abstract class _DelegatingIterableBase<E> implements Iterable<E> {
      18             :   Iterable<E> get _base;
      19             : 
      20           5 :   const _DelegatingIterableBase();
      21             : 
      22           0 :   bool any(bool test(E element)) => _base.any(test);
      23             : 
      24           0 :   bool contains(Object element) => _base.contains(element);
      25             : 
      26           0 :   E elementAt(int index) => _base.elementAt(index);
      27             : 
      28           0 :   bool every(bool test(E element)) => _base.every(test);
      29             : 
      30           0 :   Iterable<T> expand<T>(Iterable<T> f(E element)) => _base.expand(f);
      31             : 
      32           0 :   E get first => _base.first;
      33             : 
      34             :   E firstWhere(bool test(E element), {E orElse()}) =>
      35           0 :       _base.firstWhere(test, orElse: orElse);
      36             : 
      37             :   T fold<T>(T initialValue, T combine(T previousValue, E element)) =>
      38           0 :       _base.fold(initialValue, combine);
      39             : 
      40           0 :   void forEach(void f(E element)) => _base.forEach(f);
      41             : 
      42           0 :   bool get isEmpty => _base.isEmpty;
      43             : 
      44           0 :   bool get isNotEmpty => _base.isNotEmpty;
      45             : 
      46          10 :   Iterator<E> get iterator => _base.iterator;
      47             : 
      48           0 :   String join([String separator = ""]) => _base.join(separator);
      49             : 
      50           0 :   E get last => _base.last;
      51             : 
      52             :   E lastWhere(bool test(E element), {E orElse()}) =>
      53           0 :       _base.lastWhere(test, orElse: orElse);
      54             : 
      55          10 :   int get length => _base.length;
      56             : 
      57           0 :   Iterable<T> map<T>(T f(E element)) => _base.map(f);
      58             : 
      59           0 :   E reduce(E combine(E value, E element)) => _base.reduce(combine);
      60             : 
      61           0 :   E get single => _base.single;
      62             : 
      63           0 :   E singleWhere(bool test(E element)) => _base.singleWhere(test);
      64             : 
      65           0 :   Iterable<E> skip(int n) => _base.skip(n);
      66             : 
      67           0 :   Iterable<E> skipWhile(bool test(E value)) => _base.skipWhile(test);
      68             : 
      69           0 :   Iterable<E> take(int n) => _base.take(n);
      70             : 
      71           0 :   Iterable<E> takeWhile(bool test(E value)) => _base.takeWhile(test);
      72             : 
      73           0 :   List<E> toList({bool growable: true}) => _base.toList(growable: growable);
      74             : 
      75           0 :   Set<E> toSet() => _base.toSet();
      76             : 
      77          10 :   Iterable<E> where(bool test(E element)) => _base.where(test);
      78             : 
      79           0 :   String toString() => _base.toString();
      80             : }
      81             : 
      82             : /// An [Iterable] that delegates all operations to a base iterable.
      83             : ///
      84             : /// This class can be used to hide non-`Iterable` methods of an iterable object,
      85             : /// or it can be extended to add extra functionality on top of an existing
      86             : /// iterable object.
      87             : class DelegatingIterable<E> extends _DelegatingIterableBase<E> {
      88             :   final Iterable<E> _base;
      89             : 
      90             :   /// Creates a wrapper that forwards operations to [base].
      91           5 :   const DelegatingIterable(Iterable<E> base) : _base = base;
      92             : 
      93             :   /// Creates a wrapper that asserts the types of values in [base].
      94             :   ///
      95             :   /// This soundly converts an [Iterable] without a generic type to an
      96             :   /// `Iterable<E>` by asserting that its elements are instances of `E` whenever
      97             :   /// they're accessed. If they're not, it throws a [CastError].
      98             :   ///
      99             :   /// This forwards all operations to [base], so any changes in [base] will be
     100             :   /// reflected in [this]. If [base] is already an `Iterable<E>`, it's returned
     101             :   /// unmodified.
     102             :   static Iterable<E> typed<E>(Iterable base) =>
     103           0 :       base is Iterable<E> ? base : new TypeSafeIterable<E>(base);
     104             : }
     105             : 
     106             : /// A [List] that delegates all operations to a base list.
     107             : ///
     108             : /// This class can be used to hide non-`List` methods of a list object, or it
     109             : /// can be extended to add extra functionality on top of an existing list
     110             : /// object.
     111             : class DelegatingList<E> extends DelegatingIterable<E> implements List<E> {
     112           0 :   const DelegatingList(List<E> base) : super(base);
     113             : 
     114             :   /// Creates a wrapper that asserts the types of values in [base].
     115             :   ///
     116             :   /// This soundly converts a [List] without a generic type to a `List<E>` by
     117             :   /// asserting that its elements are instances of `E` whenever they're
     118             :   /// accessed. If they're not, it throws a [CastError]. Note that even if an
     119             :   /// operation throws a [CastError], it may still mutate the underlying
     120             :   /// collection.
     121             :   ///
     122             :   /// This forwards all operations to [base], so any changes in [base] will be
     123             :   /// reflected in [this]. If [base] is already a `List<E>`, it's returned
     124             :   /// unmodified.
     125             :   static List<E> typed<E>(List base) =>
     126           0 :       base is List<E> ? base : new TypeSafeList<E>(base);
     127             : 
     128           0 :   List<E> get _listBase => _base;
     129             : 
     130           0 :   E operator [](int index) => _listBase[index];
     131             : 
     132             :   void operator []=(int index, E value) {
     133           0 :     _listBase[index] = value;
     134             :   }
     135             : 
     136             :   void add(E value) {
     137           0 :     _listBase.add(value);
     138             :   }
     139             : 
     140             :   void addAll(Iterable<E> iterable) {
     141           0 :     _listBase.addAll(iterable);
     142             :   }
     143             : 
     144           0 :   Map<int, E> asMap() => _listBase.asMap();
     145             : 
     146             :   void clear() {
     147           0 :     _listBase.clear();
     148             :   }
     149             : 
     150             :   void fillRange(int start, int end, [E fillValue]) {
     151           0 :     _listBase.fillRange(start, end, fillValue);
     152             :   }
     153             : 
     154           0 :   Iterable<E> getRange(int start, int end) => _listBase.getRange(start, end);
     155             : 
     156           0 :   int indexOf(E element, [int start = 0]) => _listBase.indexOf(element, start);
     157             : 
     158             :   void insert(int index, E element) {
     159           0 :     _listBase.insert(index, element);
     160             :   }
     161             : 
     162             :   void insertAll(int index, Iterable<E> iterable) {
     163           0 :     _listBase.insertAll(index, iterable);
     164             :   }
     165             : 
     166             :   int lastIndexOf(E element, [int start]) =>
     167           0 :       _listBase.lastIndexOf(element, start);
     168             : 
     169             :   void set length(int newLength) {
     170           0 :     _listBase.length = newLength;
     171             :   }
     172             : 
     173           0 :   bool remove(Object value) => _listBase.remove(value);
     174             : 
     175           0 :   E removeAt(int index) => _listBase.removeAt(index);
     176             : 
     177           0 :   E removeLast() => _listBase.removeLast();
     178             : 
     179             :   void removeRange(int start, int end) {
     180           0 :     _listBase.removeRange(start, end);
     181             :   }
     182             : 
     183             :   void removeWhere(bool test(E element)) {
     184           0 :     _listBase.removeWhere(test);
     185             :   }
     186             : 
     187             :   void replaceRange(int start, int end, Iterable<E> iterable) {
     188           0 :     _listBase.replaceRange(start, end, iterable);
     189             :   }
     190             : 
     191             :   void retainWhere(bool test(E element)) {
     192           0 :     _listBase.retainWhere(test);
     193             :   }
     194             : 
     195           0 :   Iterable<E> get reversed => _listBase.reversed;
     196             : 
     197             :   void setAll(int index, Iterable<E> iterable) {
     198           0 :     _listBase.setAll(index, iterable);
     199             :   }
     200             : 
     201             :   void setRange(int start, int end, Iterable<E> iterable, [int skipCount = 0]) {
     202           0 :     _listBase.setRange(start, end, iterable, skipCount);
     203             :   }
     204             : 
     205             :   void shuffle([math.Random random]) {
     206           0 :     _listBase.shuffle(random);
     207             :   }
     208             : 
     209             :   void sort([int compare(E a, E b)]) {
     210           0 :     _listBase.sort(compare);
     211             :   }
     212             : 
     213           0 :   List<E> sublist(int start, [int end]) => _listBase.sublist(start, end);
     214             : }
     215             : 
     216             : /// A [Set] that delegates all operations to a base set.
     217             : ///
     218             : /// This class can be used to hide non-`Set` methods of a set object, or it can
     219             : /// be extended to add extra functionality on top of an existing set object.
     220             : class DelegatingSet<E> extends DelegatingIterable<E> implements Set<E> {
     221           5 :   const DelegatingSet(Set<E> base) : super(base);
     222             : 
     223             :   /// Creates a wrapper that asserts the types of values in [base].
     224             :   ///
     225             :   /// This soundly converts a [Set] without a generic type to a `Set<E>` by
     226             :   /// asserting that its elements are instances of `E` whenever they're
     227             :   /// accessed. If they're not, it throws a [CastError]. Note that even if an
     228             :   /// operation throws a [CastError], it may still mutate the underlying
     229             :   /// collection.
     230             :   ///
     231             :   /// This forwards all operations to [base], so any changes in [base] will be
     232             :   /// reflected in [this]. If [base] is already a `Set<E>`, it's returned
     233             :   /// unmodified.
     234             :   static Set<E> typed<E>(Set base) =>
     235           0 :       base is Set<E> ? base : new TypeSafeSet<E>(base);
     236             : 
     237           5 :   Set<E> get _setBase => _base;
     238             : 
     239           0 :   bool add(E value) => _setBase.add(value);
     240             : 
     241             :   void addAll(Iterable<E> elements) {
     242           0 :     _setBase.addAll(elements);
     243             :   }
     244             : 
     245             :   void clear() {
     246           0 :     _setBase.clear();
     247             :   }
     248             : 
     249           0 :   bool containsAll(Iterable<Object> other) => _setBase.containsAll(other);
     250             : 
     251           0 :   Set<E> difference(Set<Object> other) => _setBase.difference(other);
     252             : 
     253           0 :   Set<E> intersection(Set<Object> other) => _setBase.intersection(other);
     254             : 
     255           0 :   E lookup(Object element) => _setBase.lookup(element);
     256             : 
     257           0 :   bool remove(Object value) => _setBase.remove(value);
     258             : 
     259             :   void removeAll(Iterable<Object> elements) {
     260           0 :     _setBase.removeAll(elements);
     261             :   }
     262             : 
     263             :   void removeWhere(bool test(E element)) {
     264           0 :     _setBase.removeWhere(test);
     265             :   }
     266             : 
     267             :   void retainAll(Iterable<Object> elements) {
     268           0 :     _setBase.retainAll(elements);
     269             :   }
     270             : 
     271             :   void retainWhere(bool test(E element)) {
     272           0 :     _setBase.retainWhere(test);
     273             :   }
     274             : 
     275          10 :   Set<E> union(Set<E> other) => _setBase.union(other);
     276             : 
     277           0 :   Set<E> toSet() => new DelegatingSet<E>(_setBase.toSet());
     278             : }
     279             : 
     280             : /// A [Queue] that delegates all operations to a base queue.
     281             : ///
     282             : /// This class can be used to hide non-`Queue` methods of a queue object, or it
     283             : /// can be extended to add extra functionality on top of an existing queue
     284             : /// object.
     285             : class DelegatingQueue<E> extends DelegatingIterable<E> implements Queue<E> {
     286           0 :   const DelegatingQueue(Queue<E> queue) : super(queue);
     287             : 
     288             :   /// Creates a wrapper that asserts the types of values in [base].
     289             :   ///
     290             :   /// This soundly converts a [Queue] without a generic type to a `Queue<E>` by
     291             :   /// asserting that its elements are instances of `E` whenever they're
     292             :   /// accessed. If they're not, it throws a [CastError]. Note that even if an
     293             :   /// operation throws a [CastError], it may still mutate the underlying
     294             :   /// collection.
     295             :   ///
     296             :   /// This forwards all operations to [base], so any changes in [base] will be
     297             :   /// reflected in [this]. If [base] is already a `Queue<E>`, it's returned
     298             :   /// unmodified.
     299             :   static Queue<E> typed<E>(Queue base) =>
     300           0 :       base is Queue<E> ? base : new TypeSafeQueue<E>(base);
     301             : 
     302           0 :   Queue<E> get _baseQueue => _base;
     303             : 
     304             :   void add(E value) {
     305           0 :     _baseQueue.add(value);
     306             :   }
     307             : 
     308             :   void addAll(Iterable<E> iterable) {
     309           0 :     _baseQueue.addAll(iterable);
     310             :   }
     311             : 
     312             :   void addFirst(E value) {
     313           0 :     _baseQueue.addFirst(value);
     314             :   }
     315             : 
     316             :   void addLast(E value) {
     317           0 :     _baseQueue.addLast(value);
     318             :   }
     319             : 
     320             :   void clear() {
     321           0 :     _baseQueue.clear();
     322             :   }
     323             : 
     324           0 :   bool remove(Object object) => _baseQueue.remove(object);
     325             : 
     326             :   void removeWhere(bool test(E element)) {
     327           0 :     _baseQueue.removeWhere(test);
     328             :   }
     329             : 
     330             :   void retainWhere(bool test(E element)) {
     331           0 :     _baseQueue.retainWhere(test);
     332             :   }
     333             : 
     334           0 :   E removeFirst() => _baseQueue.removeFirst();
     335             : 
     336           0 :   E removeLast() => _baseQueue.removeLast();
     337             : }
     338             : 
     339             : /// A [Map] that delegates all operations to a base map.
     340             : ///
     341             : /// This class can be used to hide non-`Map` methods of an object that extends
     342             : /// `Map`, or it can be extended to add extra functionality on top of an
     343             : /// existing map object.
     344             : class DelegatingMap<K, V> implements Map<K, V> {
     345             :   final Map<K, V> _base;
     346             : 
     347           0 :   const DelegatingMap(Map<K, V> base) : _base = base;
     348             : 
     349             :   /// Creates a wrapper that asserts the types of keys and values in [base].
     350             :   ///
     351             :   /// This soundly converts a [Map] without generic types to a `Map<K, V>` by
     352             :   /// asserting that its keys are instances of `E` and its values are instances
     353             :   /// of `V` whenever they're accessed. If they're not, it throws a [CastError].
     354             :   /// Note that even if an operation throws a [CastError], it may still mutate
     355             :   /// the underlying collection.
     356             :   ///
     357             :   /// This forwards all operations to [base], so any changes in [base] will be
     358             :   /// reflected in [this]. If [base] is already a `Map<K, V>`, it's returned
     359             :   /// unmodified.
     360             :   static Map<K, V> typed<K, V>(Map base) =>
     361           0 :       base is Map<K, V> ? base : new TypeSafeMap<K, V>(base);
     362             : 
     363           0 :   V operator [](Object key) => _base[key];
     364             : 
     365             :   void operator []=(K key, V value) {
     366           0 :     _base[key] = value;
     367             :   }
     368             : 
     369             :   void addAll(Map<K, V> other) {
     370           0 :     _base.addAll(other);
     371             :   }
     372             : 
     373             :   void clear() {
     374           0 :     _base.clear();
     375             :   }
     376             : 
     377           0 :   bool containsKey(Object key) => _base.containsKey(key);
     378             : 
     379           0 :   bool containsValue(Object value) => _base.containsValue(value);
     380             : 
     381             :   void forEach(void f(K key, V value)) {
     382           0 :     _base.forEach(f);
     383             :   }
     384             : 
     385           0 :   bool get isEmpty => _base.isEmpty;
     386             : 
     387           0 :   bool get isNotEmpty => _base.isNotEmpty;
     388             : 
     389           0 :   Iterable<K> get keys => _base.keys;
     390             : 
     391           0 :   int get length => _base.length;
     392             : 
     393           0 :   V putIfAbsent(K key, V ifAbsent()) => _base.putIfAbsent(key, ifAbsent);
     394             : 
     395           0 :   V remove(Object key) => _base.remove(key);
     396             : 
     397           0 :   Iterable<V> get values => _base.values;
     398             : 
     399           0 :   String toString() => _base.toString();
     400             : }
     401             : 
     402             : /// An unmodifiable [Set] view of the keys of a [Map].
     403             : ///
     404             : /// The set delegates all operations to the underlying map.
     405             : ///
     406             : /// A `Map` can only contain each key once, so its keys can always
     407             : /// be viewed as a `Set` without any loss, even if the [Map.keys]
     408             : /// getter only shows an [Iterable] view of the keys.
     409             : ///
     410             : /// Note that [lookup] is not supported for this set.
     411             : class MapKeySet<E> extends _DelegatingIterableBase<E>
     412             :     with UnmodifiableSetMixin<E> {
     413             :   final Map<E, dynamic> _baseMap;
     414             : 
     415           0 :   MapKeySet(Map<E, dynamic> base) : _baseMap = base;
     416             : 
     417           0 :   Iterable<E> get _base => _baseMap.keys;
     418             : 
     419           0 :   bool contains(Object element) => _baseMap.containsKey(element);
     420             : 
     421           0 :   bool get isEmpty => _baseMap.isEmpty;
     422             : 
     423           0 :   bool get isNotEmpty => _baseMap.isNotEmpty;
     424             : 
     425           0 :   int get length => _baseMap.length;
     426             : 
     427           0 :   String toString() => "{${_base.join(', ')}}";
     428             : 
     429           0 :   bool containsAll(Iterable<Object> other) => other.every(contains);
     430             : 
     431             :   /// Returns a new set with the the elements of [this] that are not in [other].
     432             :   ///
     433             :   /// That is, the returned set contains all the elements of this [Set] that are
     434             :   /// not elements of [other] according to `other.contains`.
     435             :   ///
     436             :   /// Note that the returned set will use the default equality operation, which
     437             :   /// may be different than the equality operation [this] uses.
     438             :   Set<E> difference(Set<Object> other) =>
     439           0 :       where((element) => !other.contains(element)).toSet();
     440             : 
     441             :   /// Returns a new set which is the intersection between [this] and [other].
     442             :   ///
     443             :   /// That is, the returned set contains all the elements of this [Set] that are
     444             :   /// also elements of [other] according to `other.contains`.
     445             :   ///
     446             :   /// Note that the returned set will use the default equality operation, which
     447             :   /// may be different than the equality operation [this] uses.
     448           0 :   Set<E> intersection(Set<Object> other) => where(other.contains).toSet();
     449             : 
     450             :   /// Throws an [UnsupportedError] since there's no corresponding method for
     451             :   /// [Map]s.
     452             :   E lookup(Object element) =>
     453           0 :       throw new UnsupportedError("MapKeySet doesn't support lookup().");
     454             : 
     455             :   /// Returns a new set which contains all the elements of [this] and [other].
     456             :   ///
     457             :   /// That is, the returned set contains all the elements of this [Set] and all
     458             :   /// the elements of [other].
     459             :   ///
     460             :   /// Note that the returned set will use the default equality operation, which
     461             :   /// may be different than the equality operation [this] uses.
     462           0 :   Set<E> union(Set<E> other) => toSet()..addAll(other);
     463             : }
     464             : 
     465             : /// Creates a modifiable [Set] view of the values of a [Map].
     466             : ///
     467             : /// The `Set` view assumes that the keys of the `Map` can be uniquely determined
     468             : /// from the values. The `keyForValue` function passed to the constructor finds
     469             : /// the key for a single value. The `keyForValue` function should be consistent
     470             : /// with equality. If `value1 == value2` then `keyForValue(value1)` and
     471             : /// `keyForValue(value2)` should be considered equal keys by the underlying map,
     472             : /// and vice versa.
     473             : ///
     474             : /// Modifying the set will modify the underlying map based on the key returned
     475             : /// by `keyForValue`.
     476             : ///
     477             : /// If the `Map` contents are not compatible with the `keyForValue` function,
     478             : /// the set will not work consistently, and may give meaningless responses or do
     479             : /// inconsistent updates.
     480             : ///
     481             : /// This set can, for example, be used on a map from database record IDs to the
     482             : /// records. It exposes the records as a set, and allows for writing both
     483             : /// `recordSet.add(databaseRecord)` and `recordMap[id]`.
     484             : ///
     485             : /// Effectively, the map will act as a kind of index for the set.
     486             : class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> {
     487             :   final Map<K, V> _baseMap;
     488             :   final _KeyForValue<K, V> _keyForValue;
     489             : 
     490             :   /// Creates a new [MapValueSet] based on [base].
     491             :   ///
     492             :   /// [keyForValue] returns the key in the map that should be associated with
     493             :   /// the given value. The set's notion of equality is identical to the equality
     494             :   /// of the return values of [keyForValue].
     495             :   MapValueSet(Map<K, V> base, K keyForValue(V value))
     496             :       : _baseMap = base,
     497           0 :         _keyForValue = keyForValue;
     498             : 
     499           0 :   Iterable<V> get _base => _baseMap.values;
     500             : 
     501             :   bool contains(Object element) {
     502           0 :     if (element != null && element is! V) return false;
     503           0 :     var key = _keyForValue(element as V);
     504             : 
     505           0 :     return _baseMap.containsKey(key);
     506             :   }
     507             : 
     508           0 :   bool get isEmpty => _baseMap.isEmpty;
     509             : 
     510           0 :   bool get isNotEmpty => _baseMap.isNotEmpty;
     511             : 
     512           0 :   int get length => _baseMap.length;
     513             : 
     514           0 :   String toString() => toSet().toString();
     515             : 
     516             :   bool add(V value) {
     517           0 :     K key = _keyForValue(value);
     518             :     bool result = false;
     519           0 :     _baseMap.putIfAbsent(key, () {
     520             :       result = true;
     521             :       return value;
     522             :     });
     523             :     return result;
     524             :   }
     525             : 
     526           0 :   void addAll(Iterable<V> elements) => elements.forEach(add);
     527             : 
     528           0 :   void clear() => _baseMap.clear();
     529             : 
     530           0 :   bool containsAll(Iterable<Object> other) => other.every(contains);
     531             : 
     532             :   /// Returns a new set with the the elements of [this] that are not in [other].
     533             :   ///
     534             :   /// That is, the returned set contains all the elements of this [Set] that are
     535             :   /// not elements of [other] according to `other.contains`.
     536             :   ///
     537             :   /// Note that the returned set will use the default equality operation, which
     538             :   /// may be different than the equality operation [this] uses.
     539             :   Set<V> difference(Set<Object> other) =>
     540           0 :       where((element) => !other.contains(element)).toSet();
     541             : 
     542             :   /// Returns a new set which is the intersection between [this] and [other].
     543             :   ///
     544             :   /// That is, the returned set contains all the elements of this [Set] that are
     545             :   /// also elements of [other] according to `other.contains`.
     546             :   ///
     547             :   /// Note that the returned set will use the default equality operation, which
     548             :   /// may be different than the equality operation [this] uses.
     549           0 :   Set<V> intersection(Set<Object> other) => where(other.contains).toSet();
     550             : 
     551             :   V lookup(Object element) {
     552           0 :     if (element != null && element is! V) return null;
     553           0 :     var key = _keyForValue(element as V);
     554             : 
     555           0 :     return _baseMap[key];
     556             :   }
     557             : 
     558             :   bool remove(Object element) {
     559           0 :     if (element != null && element is! V) return false;
     560           0 :     var key = _keyForValue(element as V);
     561             : 
     562           0 :     if (!_baseMap.containsKey(key)) return false;
     563           0 :     _baseMap.remove(key);
     564             :     return true;
     565             :   }
     566             : 
     567           0 :   void removeAll(Iterable<Object> elements) => elements.forEach(remove);
     568             : 
     569             :   void removeWhere(bool test(V element)) {
     570           0 :     var toRemove = [];
     571           0 :     _baseMap.forEach((key, value) {
     572           0 :       if (test(value)) toRemove.add(key);
     573             :     });
     574           0 :     toRemove.forEach(_baseMap.remove);
     575             :   }
     576             : 
     577             :   void retainAll(Iterable<Object> elements) {
     578           0 :     var valuesToRetain = new Set<V>.identity();
     579           0 :     for (var element in elements) {
     580           0 :       if (element != null && element is! V) continue;
     581           0 :       var key = _keyForValue(element as V);
     582             : 
     583           0 :       if (!_baseMap.containsKey(key)) continue;
     584           0 :       valuesToRetain.add(_baseMap[key]);
     585             :     }
     586             : 
     587           0 :     var keysToRemove = [];
     588           0 :     _baseMap.forEach((k, v) {
     589           0 :       if (!valuesToRetain.contains(v)) keysToRemove.add(k);
     590             :     });
     591           0 :     keysToRemove.forEach(_baseMap.remove);
     592             :   }
     593             : 
     594             :   void retainWhere(bool test(V element)) =>
     595           0 :       removeWhere((element) => !test(element));
     596             : 
     597             :   /// Returns a new set which contains all the elements of [this] and [other].
     598             :   ///
     599             :   /// That is, the returned set contains all the elements of this [Set] and all
     600             :   /// the elements of [other].
     601             :   ///
     602             :   /// Note that the returned set will use the default equality operation, which
     603             :   /// may be different than the equality operation [this] uses.
     604           0 :   Set<V> union(Set<V> other) => toSet()..addAll(other);
     605             : }

Generated by: LCOV version 1.13