Remove usage of Maps.mapToString() (#71)
diff --git a/lib/src/canonicalized_map.dart b/lib/src/canonicalized_map.dart
index 122bb35..117cd63 100644
--- a/lib/src/canonicalized_map.dart
+++ b/lib/src/canonicalized_map.dart
@@ -153,9 +153,40 @@
Iterable<V> get values => _base.values.map((pair) => pair.last);
- String toString() => Maps.mapToString(this);
+ String toString() {
+ // Detect toString() cycles.
+ if (_isToStringVisiting(this)) {
+ return '{...}';
+ }
+
+ var result = new StringBuffer();
+ try {
+ _toStringVisiting.add(this);
+ result.write('{');
+ bool first = true;
+ forEach((k, v) {
+ if (!first) {
+ result.write(', ');
+ }
+ first = false;
+ result.write('$k: $v');
+ });
+ result.write('}');
+ } finally {
+ assert(identical(_toStringVisiting.last, this));
+ _toStringVisiting.removeLast();
+ }
+
+ return result.toString();
+ }
bool _isValidKey(Object key) =>
(key == null || key is K) &&
(_isValidKeyFn == null || _isValidKeyFn(key));
}
+
+/// A collection used to identify cyclic maps during toString() calls.
+final List _toStringVisiting = [];
+
+/// Check if we are currently visiting `o` in a toString() call.
+bool _isToStringVisiting(o) => _toStringVisiting.any((e) => identical(o, e));
diff --git a/test/canonicalized_map_test.dart b/test/canonicalized_map_test.dart
index 716e738..f48778d 100644
--- a/test/canonicalized_map_test.dart
+++ b/test/canonicalized_map_test.dart
@@ -132,6 +132,35 @@
});
});
+ group("CanonicalizedMap builds an informative string representation", () {
+ var map;
+ setUp(() {
+ map = new CanonicalizedMap<int, String, dynamic>(int.parse,
+ isValidKey: (s) => new RegExp(r"^\d+$").hasMatch(s as String));
+ });
+
+ test("for an empty map", () {
+ expect(map.toString(), equals('{}'));
+ });
+
+ test("for a map with one value", () {
+ map.addAll({"1": "value 1"});
+ expect(map.toString(), equals('{1: value 1}'));
+ });
+
+ test("for a map with multiple values", () {
+ map.addAll(
+ {"1": "value 1", "01": "value 01", "2": "value 2", "03": "value 03"});
+ expect(
+ map.toString(), equals('{01: value 01, 2: value 2, 03: value 03}'));
+ });
+
+ test("for a map with a loop", () {
+ map.addAll({"1": "value 1", "2": map});
+ expect(map.toString(), equals('{1: value 1, 2: {...}}'));
+ });
+ });
+
group("CanonicalizedMap.from", () {
test("canonicalizes its keys", () {
var map = new CanonicalizedMap.from(