Add toString to delegating collections in package:collection.

BUG= http://dartbug.com/16274
R=sgjesse@google.com

Review URL: https://codereview.chromium.org//141703009

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/collection@32057 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/lib/wrappers.dart b/lib/wrappers.dart
index ec78f5c..1097c3e 100644
--- a/lib/wrappers.dart
+++ b/lib/wrappers.dart
@@ -89,6 +89,8 @@
   Set<E> toSet() => _base.toSet();
 
   Iterable<E> where(bool test(E element)) => _base.where(test);
+
+  String toString() => _base.toString();
 }
 
 
@@ -331,4 +333,6 @@
   V remove(Object key) => _base.remove(key);
 
   Iterable<V> get values => _base.values;
+
+  String toString() => _base.toString();
 }
diff --git a/test/wrapper_test.dart b/test/wrapper_test.dart
index 875a70a..86a0ddd 100644
--- a/test/wrapper_test.dart
+++ b/test/wrapper_test.dart
@@ -37,6 +37,10 @@
   noSuchMethod(Invocation m) => new _Equals(equals = getWrappedObject((m2) {
     testInvocations(m, m2);
   }));
+
+  toString() => new _Equals(equals = getWrappedObject((m2) {
+    testInvocations(TO_STRING_INVOCATION, m2);
+  }));
 }
 
 // An object with a field called "equals", only introduced into the
@@ -46,6 +50,27 @@
   _Equals(this.equals);
 }
 
+class SyntheticInvocation implements Invocation {
+  static const int METHOD = 0x00;
+  static const int GETTER = 0x01;
+  static const int SETTER = 0x02;
+  final Symbol memberName;
+  final List positionalArguments;
+  final Map namedArguments;
+  final int _type;
+  const SyntheticInvocation(this.memberName,
+                            this.positionalArguments,
+                            this.namedArguments,
+                            this._type);
+  bool get isMethod => _type == METHOD;
+
+  bool get isGetter => _type == GETTER;
+
+  bool get isSetter => _type == SETTER;
+
+  bool get isAccessor => isGetter || isSetter;
+}
+
 // Parameterization of noSuchMethod.
 class NSM {
   Function _action;
@@ -53,11 +78,15 @@
   noSuchMethod(Invocation i) => _action(i);
 }
 
+const TO_STRING_INVOCATION = const SyntheticInvocation(
+  #toString, const[], const{}, SyntheticInvocation.METHOD);
+
 // LikeNSM, but has types Iterable, Set and List to allow it as
 // argument to DelegatingIterable/Set/List.
 class IterableNSM extends NSM implements Iterable, Set, List, Queue {
   IterableNSM(action(Invocation i)) : super(action);
   noSuchMethod(Invocation i) => super.noSuchMethod(i);  // Silence warnings
+  toString() => super.noSuchMethod(TO_STRING_INVOCATION);
 }
 
 // Expector that wraps in DelegatingIterable.
@@ -92,6 +121,7 @@
 class MapNSM extends NSM implements Map {
   MapNSM(action(Invocation i)) : super(action);
   noSuchMethod(Invocation i) => super.noSuchMethod(i);
+  toString() => super.noSuchMethod(TO_STRING_INVOCATION);
 }
 
 // Expector that wraps in DelegatingMap.
@@ -146,6 +176,7 @@
     expect.toList(growable: true).equals.toList(growable: true);
     expect.toList(growable: false).equals.toList(growable: false);
     expect.toSet().equals.toSet();
+    expect.toString().equals.toString();
     expect.where(func1).equals.where(func1);
   }
 
@@ -231,6 +262,7 @@
     expect.putIfAbsent(val, func0).equals.putIfAbsent(val, func0);
     expect.remove(val).equals.remove(val);
     expect.values.equals.values;
+    expect.toString().equals.toString();
   }
 
   test("Iterable", () {