Repository: passsy/kt.dart (dart)

Issue:
KMutableEntry.setValue doesn't change value in collection
`KMutableEntry.setValue` doesn't change the underlying collection. Here is a valid test which is currently failing

```dart
final pokemon = mutableMapOf({
  1: "Bulbasaur",
  2: "Ivysaur",
});

pokemon.entries.forEach((entry) {
  entry.setValue(entry.value.toUpperCase());
});

// throws because pokemon is unchanged
expect(
    pokemon,
    mapOf({
      1: "BULBASAUR",
      2: "IVYSAUR",
    }));
```

Pull request description:
As Dart's only way to reference an object is using itself, My suggestion is to pass `DartMutableMap` to all entries so it can be changed the proper way.

Closes [#55](https://github.com/passsy/kt.dart/issues/55)

Patch:
diff --git a/lib/src/collection/impl/map_mutable.dart b/lib/src/collection/impl/map_mutable.dart
index e1192b4..28b7630 100644
--- a/lib/src/collection/impl/map_mutable.dart
+++ b/lib/src/collection/impl/map_mutable.dart
@@ -19,7 +19,7 @@ class DartMutableMap<K, V> extends Object implements KtMutableMap<K, V> {
 
   @override
   Iterable<KtMapEntry<K, V>> get iter =>
-      _map.entries.map((entry) => _MutableEntry.from(entry));
+      _map.entries.map((entry) => _MutableEntry.from(entry, this));
 
   @override
   Map<K, V> asMap() => _map;
@@ -31,8 +31,8 @@ class DartMutableMap<K, V> extends Object implements KtMutableMap<K, V> {
   bool containsValue(V value) => _map.containsValue(value);
 
   @override
-  KtMutableSet<KtMutableMapEntry<K, V>> get entries =>
-      linkedSetFrom(_map.entries.map((entry) => _MutableEntry.from(entry)));
+  KtMutableSet<KtMutableMapEntry<K, V>> get entries => linkedSetFrom(
+      _map.entries.map((entry) => _MutableEntry.from(entry, this)));
 
   @override
   V? get(K key) => _map[key];
@@ -121,14 +121,21 @@ class DartMutableMap<K, V> extends Object implements KtMutableMap<K, V> {
 }
 
 class _MutableEntry<K, V> implements KtMutableMapEntry<K, V> {
-  _MutableEntry(this._key, this._value);
+  _MutableEntry(this._key, this._value, this._parent);
 
-  factory _MutableEntry.from(MapEntry<K, V> entry) =>
-      _MutableEntry(entry.key, entry.value);
+  factory _MutableEntry.from(
+    MapEntry<K, V> entry,
+    DartMutableMap<K, V> parent,
+  ) =>
+      _MutableEntry(entry.key, entry.value, parent);
 
   K _key;
   V _value;
 
+  /// Object reference for the [DartMutableMap] which contains this
+  /// [_MutableEntry].
+  DartMutableMap<K, V> _parent;
+
   @override
   K get key => _key;
 
@@ -137,12 +144,9 @@ class _MutableEntry<K, V> implements KtMutableMapEntry<K, V> {
 
   @override
   V setValue(V newValue) {
-    // setting _value here is wrong because is is a copy of the original value.
-    // setValue should modify the underlying list, not the copy
-    // see how kotlin solved this:
-    // https://github.com/JetBrains/kotlin/blob/ba6da7c40a6cc502508faf6e04fa105b96bc7777/libraries/stdlib/js/src/kotlin/collections/InternalHashCodeMap.kt
-    throw UnimplementedError(
-        "setValue() in not yet implemented. Please vote for https://github.com/passsy/dart_kollection/issues/55 for prioritization");
+    final oldValue = _value;
+    _parent._map.update(key, (value) => value = newValue);
+    return oldValue;
   }
 
   @override


Test patch:
diff --git a/test/collection/map_mutable_test.dart b/test/collection/map_mutable_test.dart
index fae0142..6fe055c 100644
--- a/test/collection/map_mutable_test.dart
+++ b/test/collection/map_mutable_test.dart
@@ -1,8 +1,6 @@
 import "package:kt_dart/collection.dart";
 import "package:test/test.dart";
 
-import "../test/assert_dart.dart";
-
 void main() {
   group("KtMutableMap", () {
     group("mutableMapFrom", () {
@@ -71,25 +69,16 @@ void testMutableMap(
     });
 
     test("set value for mutable entry", () {
-      final pokemon = mutableMapFrom({
-        1: "Bulbasaur",
-        2: "Ivysaur",
-      });
+      final pokemon = mutableMapFrom({1: "Bulbasaur", 2: "Ivysaur"});
+
+      pokemon.entries.forEach((entry) {
+        final oldValue = entry.value;
+        final newValue = entry.value.toUpperCase();
 
-      final e = catchException(() {
-        pokemon.entries.forEach((entry) {
-          entry.setValue(entry.value.toUpperCase());
-        });
+        expect(entry.setValue(newValue), oldValue);
       });
 
-      // TODO exchange error check with assertion once https://github.com/passsy/dart_kollection/issues/55 has been fixed
-      expect(e, const TypeMatcher<UnimplementedError>());
-      // expect(
-      //    pokemon,
-      //     mapFrom({
-      //       1: "BULBASAUR",
-      //      2: "IVYSAUR",
-      //    }));
+      expect(pokemon, mapFrom({1: "BULBASAUR", 2: "IVYSAUR"}));
     });
   });
 }