pkg/matcher: reapply 36881,36896 working around Issue 19173

Reverted in 36912

R=sigmund@google.com

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

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/matcher@37036 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..98cd9f4
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,21 @@
+## 0.10.0+3
+
+* Removed `@deprecated` annotation on matchers due to 
+[Issue 19173](https://code.google.com/p/dart/issues/detail?id=19173)
+
+## 0.10.0+2
+
+* Added types to a number of constants.
+
+## 0.10.0+1
+
+* Matchers related to bad language use have been removed. These represent code
+structure that should rarely or never be validated in tests.
+    * `isAbstractClassInstantiationError`
+    * `throwsAbstractClassInstantiationError`
+    * `isFallThroughError`
+    * `throwsFallThroughError`
+
+* Added types to a number of method arguments.
+
+* The structure of the library and test code has been updated.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..cf165c1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
+Support for specifying test expectations, such as for unit tests.
+
+The matcher library provides a third-generation assertion mechanism, drawing
+inspiration from [Hamcrest](http://code.google.com/p/hamcrest/).
+
+For more information, see
+[Unit Testing with Dart](http://www.dartlang.org/articles/dart-unit-tests/).
diff --git a/lib/matcher.dart b/lib/matcher.dart
index 85694ef..99fe44b 100644
--- a/lib/matcher.dart
+++ b/lib/matcher.dart
@@ -2,31 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * Support for specifying test expectations, such as for unit tests.
- *
- * The matcher library provides a third-generation assertion mechanism, drawing
- * inspiration from [Hamcrest](http://code.google.com/p/hamcrest/).
- *
- * For more information, see
- * [Unit Testing with Dart]
- * (http://www.dartlang.org/articles/dart-unit-tests/).
- */
+/// Support for specifying test expectations, such as for unit tests.
 library matcher;
 
-import 'dart:async';
-
-import 'src/description.dart';
-import 'src/interfaces.dart';
-
+export 'src/core_matchers.dart';
 export 'src/description.dart';
+export 'src/error_matchers.dart';
+export 'src/expect.dart';
+export 'src/future_matchers.dart';
 export 'src/interfaces.dart';
-
-part 'src/core_matchers.dart';
-part 'src/expect.dart';
-part 'src/future_matchers.dart';
-part 'src/iterable_matchers.dart';
-part 'src/map_matchers.dart';
-part 'src/numeric_matchers.dart';
-part 'src/operator_matchers.dart';
-part 'src/string_matchers.dart';
+export 'src/iterable_matchers.dart';
+export 'src/map_matchers.dart';
+export 'src/numeric_matchers.dart';
+export 'src/operator_matchers.dart';
+export 'src/string_matchers.dart';
diff --git a/lib/mirror_matchers.dart b/lib/mirror_matchers.dart
index c836bc9..f397128 100644
--- a/lib/mirror_matchers.dart
+++ b/lib/mirror_matchers.dart
@@ -2,21 +2,17 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/**
- * The mirror matchers library provides some additional matchers that
- * make use of `dart:mirrors`.
- */
+/// The mirror matchers library provides some additional matchers that
+/// make use of `dart:mirrors`.
 library matcher.mirror_matchers;
 
 import 'dart:mirrors';
 
 import 'matcher.dart';
 
-/**
- * Returns a matcher that checks if a class instance has a property
- * with name [name], and optionally, if that property in turn satisfies
- * a [matcher].
- */
+/// Returns a matcher that checks if a class instance has a property
+/// with name [name], and optionally, if that property in turn satisfies
+/// a [matcher].
 Matcher hasProperty(String name, [matcher]) =>
   new _HasProperty(name, matcher == null ? null : wrapMatcher(matcher));
 
diff --git a/lib/src/core_matchers.dart b/lib/src/core_matchers.dart
index 7acd7b4..356476b 100644
--- a/lib/src/core_matchers.dart
+++ b/lib/src/core_matchers.dart
@@ -2,12 +2,16 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of matcher;
+library matcher.core_matchers;
 
-/**
- * Returns a matcher that matches empty strings, maps or iterables
- * (including collections).
- */
+import 'dart:async';
+
+import 'description.dart';
+import 'expect.dart';
+import 'interfaces.dart';
+
+/// Returns a matcher that matches empty strings, maps or iterables
+/// (including collections).
 const Matcher isEmpty = const _Empty();
 
 class _Empty extends Matcher {
@@ -24,10 +28,10 @@
   Description describe(Description description) => description.add('empty');
 }
 
-/** A matcher that matches any null value. */
+/// A matcher that matches any null value.
 const Matcher isNull = const _IsNull();
 
-/** A matcher that matches any non-null value. */
+/// A matcher that matches any non-null value.
 const Matcher isNotNull = const _IsNotNull();
 
 class _IsNull extends Matcher {
@@ -42,10 +46,10 @@
   Description describe(Description description) => description.add('not null');
 }
 
-/** A matcher that matches the Boolean value true. */
+/// A matcher that matches the Boolean value true.
 const Matcher isTrue = const _IsTrue();
 
-/** A matcher that matches anything except the Boolean value true. */
+/// A matcher that matches anything except the Boolean value true.
 const Matcher isFalse = const _IsFalse();
 
 class _IsTrue extends Matcher {
@@ -60,10 +64,8 @@
   Description describe(Description description) => description.add('false');
 }
 
-/**
- * Returns a matches that matches if the value is the same instance
- * as [expected], using [identical].
- */
+/// Returns a matches that matches if the value is the same instance
+/// as [expected], using [identical].
 Matcher same(expected) => new _IsSameAs(expected);
 
 class _IsSameAs extends Matcher {
@@ -75,18 +77,16 @@
       description.add('same instance as ').addDescriptionOf(_expected);
 }
 
-/**
- * Returns a matcher that matches if the value is structurally equal to
- * [expected].
- *
- * If [expected] is a [Matcher], then it matches using that. Otherwise it tests
- * for equality using `==` on the expected value.
- *
- * For [Iterable]s and [Map]s, this will recursively match the elements. To
- * handle cyclic structures a recursion depth [limit] can be provided. The
- * default limit is 100.
- */
-Matcher equals(expected, [limit=100]) =>
+/// Returns a matcher that matches if the value is structurally equal to
+/// [expected].
+///
+/// If [expected] is a [Matcher], then it matches using that. Otherwise it tests
+/// for equality using `==` on the expected value.
+///
+/// For [Iterable]s and [Map]s, this will recursively match the elements. To
+/// handle cyclic structures a recursion depth [limit] can be provided. The
+/// default limit is 100.
+Matcher equals(expected, [int limit=100]) =>
     expected is String
         ? new _StringEqualsMatcher(expected)
         : new _DeepMatcher(expected, limit);
@@ -96,7 +96,7 @@
   final int _limit;
   var count;
 
-  _DeepMatcher(this._expected, [limit = 1000]): this._limit = limit;
+  _DeepMatcher(this._expected, [int limit = 1000]) : this._limit = limit;
 
   // Returns a pair (reason, location)
   List _compareIterables(expected, actual, matcher, depth, location) {
@@ -235,7 +235,7 @@
   }
 }
 
-/** A special equality matcher for strings. */
+/// A special equality matcher for strings.
 class _StringEqualsMatcher extends Matcher {
   final String _value;
 
@@ -313,7 +313,7 @@
   }
 }
 
-/** A matcher that matches any value. */
+/// A matcher that matches any value.
 const Matcher anything = const _IsAnything();
 
 class _IsAnything extends Matcher {
@@ -322,84 +322,76 @@
   Description describe(Description description) => description.add('anything');
 }
 
-/**
- * Returns a matcher that matches if an object is an instance
- * of [type] (or a subtype).
- *
- * As types are not first class objects in Dart we can only
- * approximate this test by using a generic wrapper class.
- *
- * For example, to test whether 'bar' is an instance of type
- * 'Foo', we would write:
- *
- *     expect(bar, new isInstanceOf<Foo>());
- *
- * To get better error message, supply a name when creating the
- * Type wrapper; e.g.:
- *
- *     expect(bar, new isInstanceOf<Foo>('Foo'));
- *
- * Note that this does not currently work in dart2js; it will
- * match any type, and isNot(new isInstanceof<T>()) will always
- * fail. This is because dart2js currently ignores template type
- * parameters.
- */
+/// Returns a matcher that matches if an object is an instance
+/// of [type] (or a subtype).
+///
+/// As types are not first class objects in Dart we can only
+/// approximate this test by using a generic wrapper class.
+///
+/// For example, to test whether 'bar' is an instance of type
+/// 'Foo', we would write:
+///
+///     expect(bar, new isInstanceOf<Foo>());
+///
+/// To get better error message, supply a name when creating the
+/// Type wrapper; e.g.:
+///
+///     expect(bar, new isInstanceOf<Foo>('Foo'));
+///
+/// Note that this does not currently work in dart2js; it will
+/// match any type, and isNot(new isInstanceof<T>()) will always
+/// fail. This is because dart2js currently ignores template type
+/// parameters.
 class isInstanceOf<T> extends Matcher {
   final String _name;
-  const isInstanceOf([name = 'specified type']): this._name = name;
+  const isInstanceOf([name = 'specified type']) : this._name = name;
   bool matches(obj, Map matchState) => obj is T;
   // The description here is lame :-(
   Description describe(Description description) =>
       description.add('an instance of ${_name}');
 }
 
-/**
- * This can be used to match two kinds of objects:
- *
- *   * A [Function] that throws an exception when called. The function cannot
- *     take any arguments. If you want to test that a function expecting
- *     arguments throws, wrap it in another zero-argument function that calls
- *     the one you want to test.
- *
- *   * A [Future] that completes with an exception. Note that this creates an
- *     asynchronous expectation. The call to `expect()` that includes this will
- *     return immediately and execution will continue. Later, when the future
- *     completes, the actual expectation will run.
- */
+/// This can be used to match two kinds of objects:
+///
+///   * A [Function] that throws an exception when called. The function cannot
+///     take any arguments. If you want to test that a function expecting
+///     arguments throws, wrap it in another zero-argument function that calls
+///     the one you want to test.
+///
+///   * A [Future] that completes with an exception. Note that this creates an
+///     asynchronous expectation. The call to `expect()` that includes this will
+///     return immediately and execution will continue. Later, when the future
+///     completes, the actual expectation will run.
 const Matcher throws = const Throws();
 
-/**
- * This can be used to match two kinds of objects:
- *
- *   * A [Function] that throws an exception when called. The function cannot
- *     take any arguments. If you want to test that a function expecting
- *     arguments throws, wrap it in another zero-argument function that calls
- *     the one you want to test.
- *
- *   * A [Future] that completes with an exception. Note that this creates an
- *     asynchronous expectation. The call to `expect()` that includes this will
- *     return immediately and execution will continue. Later, when the future
- *     completes, the actual expectation will run.
- *
- * In both cases, when an exception is thrown, this will test that the exception
- * object matches [matcher]. If [matcher] is not an instance of [Matcher], it
- * will implicitly be treated as `equals(matcher)`.
- */
+/// This can be used to match two kinds of objects:
+///
+///   * A [Function] that throws an exception when called. The function cannot
+///     take any arguments. If you want to test that a function expecting
+///     arguments throws, wrap it in another zero-argument function that calls
+///     the one you want to test.
+///
+///   * A [Future] that completes with an exception. Note that this creates an
+///     asynchronous expectation. The call to `expect()` that includes this will
+///     return immediately and execution will continue. Later, when the future
+///     completes, the actual expectation will run.
+///
+/// In both cases, when an exception is thrown, this will test that the exception
+/// object matches [matcher]. If [matcher] is not an instance of [Matcher], it
+/// will implicitly be treated as `equals(matcher)`.
 Matcher throwsA(matcher) => new Throws(wrapMatcher(matcher));
 
-/**
- * A matcher that matches a function call against no exception.
- * The function will be called once. Any exceptions will be silently swallowed.
- * The value passed to expect() should be a reference to the function.
- * Note that the function cannot take arguments; to handle this
- * a wrapper will have to be created.
- */
+/// A matcher that matches a function call against no exception.
+/// The function will be called once. Any exceptions will be silently swallowed.
+/// The value passed to expect() should be a reference to the function.
+/// Note that the function cannot take arguments; to handle this
+/// a wrapper will have to be created.
 const Matcher returnsNormally = const _ReturnsNormally();
 
 class Throws extends Matcher {
   final Matcher _matcher;
 
-  const Throws([Matcher matcher]): this._matcher = matcher;
+  const Throws([Matcher matcher]) : this._matcher = matcher;
 
   bool matches(item, Map matchState) {
     if (item is! Function && item is! Future) return false;
@@ -409,7 +401,9 @@
       // Queue up an asynchronous expectation that validates when the future
       // completes.
       item.then((value) {
-        done(() => fail("Expected future to fail, but succeeded with '$value'."));
+        done(() {
+          fail("Expected future to fail, but succeeded with '$value'.");
+        });
       }, onError: (error, trace) {
         done(() {
           if (_matcher == null) return;
@@ -519,179 +513,29 @@
   Description describe(Description description) => description.add(_name);
 }
 
-/** A matcher for FormatExceptions. */
-const isFormatException = const _FormatException();
-
-/** A matcher for functions that throw FormatException. */
-const Matcher throwsFormatException = const Throws(isFormatException);
-
-class _FormatException extends TypeMatcher {
-  const _FormatException(): super("FormatException");
-  bool matches(item, Map matchState) => item is FormatException;
-}
-
-/** A matcher for Exceptions. */
-const isException = const _Exception();
-
-/** A matcher for functions that throw Exception. */
-const Matcher throwsException = const Throws(isException);
-
-class _Exception extends TypeMatcher {
-  const _Exception(): super("Exception");
-  bool matches(item, Map matchState) => item is Exception;
-}
-
-/** A matcher for ArgumentErrors. */
-const isArgumentError = const _ArgumentError();
-
-/** A matcher for functions that throw ArgumentError. */
-const Matcher throwsArgumentError = const Throws(isArgumentError);
-
-class _ArgumentError extends TypeMatcher {
-  const _ArgumentError(): super("ArgumentError");
-  bool matches(item, Map matchState) => item is ArgumentError;
-}
-
-/** A matcher for RangeErrors. */
-const isRangeError = const _RangeError();
-
-/** A matcher for functions that throw RangeError. */
-const Matcher throwsRangeError = const Throws(isRangeError);
-
-class _RangeError extends TypeMatcher {
-  const _RangeError(): super("RangeError");
-  bool matches(item, Map matchState) => item is RangeError;
-}
-
-/** A matcher for NoSuchMethodErrors. */
-const isNoSuchMethodError = const _NoSuchMethodError();
-
-/** A matcher for functions that throw NoSuchMethodError. */
-const Matcher throwsNoSuchMethodError = const Throws(isNoSuchMethodError);
-
-class _NoSuchMethodError extends TypeMatcher {
-  const _NoSuchMethodError(): super("NoSuchMethodError");
-  bool matches(item, Map matchState) => item is NoSuchMethodError;
-}
-
-/** A matcher for UnimplementedErrors. */
-const isUnimplementedError = const _UnimplementedError();
-
-/** A matcher for functions that throw Exception. */
-const Matcher throwsUnimplementedError = const Throws(isUnimplementedError);
-
-class _UnimplementedError extends TypeMatcher {
-  const _UnimplementedError(): super("UnimplementedError");
-  bool matches(item, Map matchState) => item is UnimplementedError;
-}
-
-/** A matcher for UnsupportedError. */
-const isUnsupportedError = const _UnsupportedError();
-
-/** A matcher for functions that throw UnsupportedError. */
-const Matcher throwsUnsupportedError = const Throws(isUnsupportedError);
-
-class _UnsupportedError extends TypeMatcher {
-  const _UnsupportedError(): super("UnsupportedError");
-  bool matches(item, Map matchState) => item is UnsupportedError;
-}
-
-/** A matcher for StateErrors. */
-const isStateError = const _StateError();
-
-/** A matcher for functions that throw StateError. */
-const Matcher throwsStateError = const Throws(isStateError);
-
-class _StateError extends TypeMatcher {
-  const _StateError(): super("StateError");
-  bool matches(item, Map matchState) => item is StateError;
-}
-
-/** A matcher for FallThroughError. */
-const isFallThroughError = const _FallThroughError();
-
-/** A matcher for functions that throw FallThroughError. */
-const Matcher throwsFallThroughError = const Throws(isFallThroughError);
-
-class _FallThroughError extends TypeMatcher {
-  const _FallThroughError(): super("FallThroughError");
-  bool matches(item, Map matchState) => item is FallThroughError;
-}
-
-/** A matcher for NullThrownError. */
-const isNullThrownError = const _NullThrownError();
-
-/** A matcher for functions that throw NullThrownError. */
-const Matcher throwsNullThrownError = const Throws(isNullThrownError);
-
-class _NullThrownError extends TypeMatcher {
-  const _NullThrownError(): super("NullThrownError");
-  bool matches(item, Map matchState) => item is NullThrownError;
-}
-
-/** A matcher for ConcurrentModificationError. */
-const isConcurrentModificationError = const _ConcurrentModificationError();
-
-/** A matcher for functions that throw ConcurrentModificationError. */
-const Matcher throwsConcurrentModificationError =
-    const Throws(isConcurrentModificationError);
-
-class _ConcurrentModificationError extends TypeMatcher {
-  const _ConcurrentModificationError(): super("ConcurrentModificationError");
-  bool matches(item, Map matchState) => item is ConcurrentModificationError;
-}
-
-/** A matcher for AbstractClassInstantiationError. */
-const isAbstractClassInstantiationError =
-    const _AbstractClassInstantiationError();
-
-/** A matcher for functions that throw AbstractClassInstantiationError. */
-const Matcher throwsAbstractClassInstantiationError =
-    const Throws(isAbstractClassInstantiationError);
-
-class _AbstractClassInstantiationError extends TypeMatcher {
-  const _AbstractClassInstantiationError() :
-  super("AbstractClassInstantiationError");
-  bool matches(item, Map matchState) => item is AbstractClassInstantiationError;
-}
-
-/** A matcher for CyclicInitializationError. */
-const isCyclicInitializationError = const _CyclicInitializationError();
-
-/** A matcher for functions that throw CyclicInitializationError. */
-const Matcher throwsCyclicInitializationError =
-    const Throws(isCyclicInitializationError);
-
-class _CyclicInitializationError extends TypeMatcher {
-  const _CyclicInitializationError(): super("CyclicInitializationError");
-  bool matches(item, Map matchState) => item is CyclicInitializationError;
-}
-
-/** A matcher for Map types. */
-const isMap = const _IsMap();
+/// A matcher for Map types.
+const Matcher isMap = const _IsMap();
 
 class _IsMap extends TypeMatcher {
-  const _IsMap(): super("Map");
+  const _IsMap() : super("Map");
   bool matches(item, Map matchState) => item is Map;
 }
 
-/** A matcher for List types. */
-const isList = const _IsList();
+/// A matcher for List types.
+const Matcher isList = const _IsList();
 
 class _IsList extends TypeMatcher {
-  const _IsList(): super("List");
+  const _IsList() : super("List");
   bool matches(item, Map matchState) => item is List;
 }
 
-/**
- * Returns a matcher that matches if an object has a length property
- * that matches [matcher].
- */
+/// Returns a matcher that matches if an object has a length property
+/// that matches [matcher].
 Matcher hasLength(matcher) => new _HasLength(wrapMatcher(matcher));
 
 class _HasLength extends Matcher {
   final Matcher _matcher;
-  const _HasLength([Matcher matcher = null]): this._matcher = matcher;
+  const _HasLength([Matcher matcher = null]) : this._matcher = matcher;
 
   bool matches(item, Map matchState) {
     try {
@@ -722,18 +566,15 @@
   }
 }
 
-/**
- * Returns a matcher that matches if the match argument contains
- * the expected value. For [String]s this means substring matching;
- * for [Map]s it means the map has the key, and for [Iterable]s
- * (including [Iterable]s) it means the iterable has a matching
- * element. In the case of iterables, [expected] can itself be a
- * matcher.
- */
+/// Returns a matcher that matches if the match argument contains
+/// the expected value. For [String]s this means substring matching;
+/// for [Map]s it means the map has the key, and for [Iterable]s
+/// (including [Iterable]s) it means the iterable has a matching
+/// element. In the case of iterables, [expected] can itself be a
+/// matcher.
 Matcher contains(expected) => new _Contains(expected);
 
 class _Contains extends Matcher {
-
   final _expected;
 
   const _Contains(this._expected);
@@ -767,14 +608,11 @@
   }
 }
 
-/**
- * Returns a matcher that matches if the match argument is in
- * the expected value. This is the converse of [contains].
- */
+/// Returns a matcher that matches if the match argument is in
+/// the expected value. This is the converse of [contains].
 Matcher isIn(expected) => new _In(expected);
 
 class _In extends Matcher {
-
   final _expected;
 
   const _In(this._expected);
@@ -794,18 +632,17 @@
       description.add('is in ').addDescriptionOf(_expected);
 }
 
-/**
- * Returns a matcher that uses an arbitrary function that returns
- * true or false for the actual value. For example:
- *
- *     expect(v, predicate((x) => ((x % 2) == 0), "is even"))
- */
-Matcher predicate(Function f, [description = 'satisfies function']) =>
+/// Returns a matcher that uses an arbitrary function that returns
+/// true or false for the actual value. For example:
+///
+///     expect(v, predicate((x) => ((x % 2) == 0), "is even"))
+Matcher predicate(bool f(value), [String description = 'satisfies function']) =>
     new _Predicate(f, description);
 
-class _Predicate extends Matcher {
+typedef bool _PredicateFunction(value);
 
-  final Function _matcher;
+class _Predicate extends Matcher {
+  final _PredicateFunction _matcher;
   final String _description;
 
   const _Predicate(this._matcher, this._description);
@@ -816,27 +653,25 @@
       description.add(_description);
 }
 
-/**
- * A useful utility class for implementing other matchers through inheritance.
- * Derived classes should call the base constructor with a feature name and
- * description, and an instance matcher, and should implement the
- * [featureValueOf] abstract method.
- *
- * The feature description will typically describe the item and the feature,
- * while the feature name will just name the feature. For example, we may
- * have a Widget class where each Widget has a price; we could make a
- * [CustomMatcher] that can make assertions about prices with:
- *
- *     class HasPrice extends CustomMatcher {
- *       const HasPrice(matcher) :
- *           super("Widget with price that is", "price", matcher);
- *       featureValueOf(actual) => actual.price;
- *     }
- *
- * and then use this for example like:
- *
- *      expect(inventoryItem, new HasPrice(greaterThan(0)));
- */
+/// A useful utility class for implementing other matchers through inheritance.
+/// Derived classes should call the base constructor with a feature name and
+/// description, and an instance matcher, and should implement the
+/// [featureValueOf] abstract method.
+///
+/// The feature description will typically describe the item and the feature,
+/// while the feature name will just name the feature. For example, we may
+/// have a Widget class where each Widget has a price; we could make a
+/// [CustomMatcher] that can make assertions about prices with:
+///
+///     class HasPrice extends CustomMatcher {
+///       const HasPrice(matcher) :
+///           super("Widget with price that is", "price", matcher);
+///       featureValueOf(actual) => actual.price;
+///     }
+///
+/// and then use this for example like:
+///
+///      expect(inventoryItem, new HasPrice(greaterThan(0)));
 class CustomMatcher extends Matcher {
   final String _featureDescription;
   final String _featureName;
@@ -845,7 +680,7 @@
   CustomMatcher(this._featureDescription, this._featureName, matcher)
       : this._matcher = wrapMatcher(matcher);
 
-  /** Override this to extract the interesting feature.*/
+  /// Override this to extract the interesting feature.
   featureValueOf(actual) => actual;
 
   bool matches(item, Map matchState) {
diff --git a/lib/src/description.dart b/lib/src/description.dart
index f8ebf09..f03934d 100644
--- a/lib/src/description.dart
+++ b/lib/src/description.dart
@@ -6,44 +6,39 @@
 
 import 'interfaces.dart';
 import 'pretty_print.dart';
-import 'utils.dart';
 
-/**
- * The default implementation of IDescription. This should rarely need
- * substitution, although conceivably it is a place where other languages
- * could be supported.
- */
+/// The default implementation of [Description]. This should rarely need
+/// substitution, although conceivably it is a place where other languages
+/// could be supported.
 class StringDescription implements Description {
-  var _out;
+  final StringBuffer _out = new StringBuffer();
 
-  /** Initialize the description with initial contents [init]. */
+  /// Initialize the description with initial contents [init].
   StringDescription([String init = '']) {
-    _out = init;
+    _out.write(init);
   }
 
   int get length => _out.length;
 
-  /** Get the description as a string. */
-  String toString() => _out;
+  /// Get the description as a string.
+  String toString() => _out.toString();
 
-  /** Append [text] to the description.  */
-  Description add(text) {
-    _out = '${_out}${text}';
+  /// Append [text] to the description.
+  Description add(String text) {
+    _out.write(text);
     return this;
   }
 
-  /** Change the value of the description. */
+  /// Change the value of the description.
   Description replace(String text) {
-    _out = text;
-    return this;
+    _out.clear();
+    return add(text);
   }
 
-  /**
-   * Appends a description of [value]. If it is an IMatcher use its
-   * describe method; if it is a string use its literal value after
-   * escaping any embedded control characters; otherwise use its
-   * toString() value and wrap it in angular "quotes".
-   */
+  /// Appends a description of [value]. If it is an IMatcher use its
+  /// describe method; if it is a string use its literal value after
+  /// escaping any embedded control characters; otherwise use its
+  /// toString() value and wrap it in angular "quotes".
   Description addDescriptionOf(value) {
     if (value is Matcher) {
       value.describe(this);
@@ -53,11 +48,9 @@
     return this;
   }
 
-  /**
-   * Append an [Iterable] [list] of objects to the description, using the
-   * specified [separator] and framing the list with [start]
-   * and [end].
-   */
+  /// Append an [Iterable] [list] of objects to the description, using the
+  /// specified [separator] and framing the list with [start]
+  /// and [end].
   Description addAll(String start, String separator, String end,
                        Iterable list) {
     var separate = false;
@@ -72,11 +65,4 @@
     add(end);
     return this;
   }
-
-  /** Escape the control characters in [string] so that they are visible. */
-  _addEscapedString(String string) {
-    add("'");
-    add(escapeString(string));
-    add("'");
-  }
 }
diff --git a/lib/src/error_matchers.dart b/lib/src/error_matchers.dart
new file mode 100644
index 0000000..cb716f5
--- /dev/null
+++ b/lib/src/error_matchers.dart
@@ -0,0 +1,173 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library matcher.error_matchers;
+
+import 'core_matchers.dart';
+import 'interfaces.dart';
+
+/// **DEPRECATED**
+///
+/// Will be removed in the next major release.
+// TODO(kevmoo): re-deprecate once 19173 is resolved
+//@deprecated
+const Matcher isAbstractClassInstantiationError =
+  const _AbstractClassInstantiationError();
+
+/// **DEPRECATED**
+///
+/// Will be removed in the next major release.
+// TODO(kevmoo): re-deprecate once 19173 is resolved
+//@deprecated
+const Matcher throwsAbstractClassInstantiationError =
+  const Throws(isAbstractClassInstantiationError);
+
+class _AbstractClassInstantiationError extends TypeMatcher {
+  const _AbstractClassInstantiationError() :
+  super("AbstractClassInstantiationError");
+  bool matches(item, Map matchState) => item is AbstractClassInstantiationError;
+}
+
+/// A matcher for ArgumentErrors.
+const Matcher isArgumentError = const _ArgumentError();
+
+/// A matcher for functions that throw ArgumentError.
+const Matcher throwsArgumentError = const Throws(isArgumentError);
+
+class _ArgumentError extends TypeMatcher {
+  const _ArgumentError(): super("ArgumentError");
+  bool matches(item, Map matchState) => item is ArgumentError;
+}
+
+/// A matcher for ConcurrentModificationError.
+const Matcher isConcurrentModificationError =
+    const _ConcurrentModificationError();
+
+/// A matcher for functions that throw ConcurrentModificationError.
+const Matcher throwsConcurrentModificationError =
+  const Throws(isConcurrentModificationError);
+
+class _ConcurrentModificationError extends TypeMatcher {
+  const _ConcurrentModificationError(): super("ConcurrentModificationError");
+  bool matches(item, Map matchState) => item is ConcurrentModificationError;
+}
+
+/// A matcher for CyclicInitializationError.
+const Matcher isCyclicInitializationError = const _CyclicInitializationError();
+
+/// A matcher for functions that throw CyclicInitializationError.
+const Matcher throwsCyclicInitializationError =
+  const Throws(isCyclicInitializationError);
+
+class _CyclicInitializationError extends TypeMatcher {
+  const _CyclicInitializationError(): super("CyclicInitializationError");
+  bool matches(item, Map matchState) => item is CyclicInitializationError;
+}
+
+/// A matcher for Exceptions.
+const Matcher isException = const _Exception();
+
+/// A matcher for functions that throw Exception.
+const Matcher throwsException = const Throws(isException);
+
+class _Exception extends TypeMatcher {
+  const _Exception(): super("Exception");
+  bool matches(item, Map matchState) => item is Exception;
+}
+
+/// **DEPRECATED**
+///
+/// Will be removed in the next major release.
+// TODO(kevmoo): re-deprecate once 19173 is resolved
+//@deprecated
+const Matcher isFallThroughError = const _FallThroughError();
+
+/// **DEPRECATED**
+///
+/// Will be removed in the next major release.
+// TODO(kevmoo): re-deprecate once 19173 is resolved
+//@deprecated
+const Matcher throwsFallThroughError = const Throws(isFallThroughError);
+
+class _FallThroughError extends TypeMatcher {
+  const _FallThroughError(): super("FallThroughError");
+  bool matches(item, Map matchState) => item is FallThroughError;
+}
+
+/// A matcher for FormatExceptions.
+const Matcher isFormatException = const _FormatException();
+
+/// A matcher for functions that throw FormatException.
+const Matcher throwsFormatException = const Throws(isFormatException);
+
+class _FormatException extends TypeMatcher {
+  const _FormatException(): super("FormatException");
+  bool matches(item, Map matchState) => item is FormatException;
+}
+
+/// A matcher for NoSuchMethodErrors.
+const Matcher isNoSuchMethodError = const _NoSuchMethodError();
+
+/// A matcher for functions that throw NoSuchMethodError.
+const Matcher throwsNoSuchMethodError = const Throws(isNoSuchMethodError);
+
+class _NoSuchMethodError extends TypeMatcher {
+  const _NoSuchMethodError(): super("NoSuchMethodError");
+  bool matches(item, Map matchState) => item is NoSuchMethodError;
+}
+
+/// A matcher for NullThrownError.
+const Matcher isNullThrownError = const _NullThrownError();
+
+/// A matcher for functions that throw NullThrownError.
+const Matcher throwsNullThrownError = const Throws(isNullThrownError);
+
+class _NullThrownError extends TypeMatcher {
+  const _NullThrownError(): super("NullThrownError");
+  bool matches(item, Map matchState) => item is NullThrownError;
+}
+
+/// A matcher for RangeErrors.
+const Matcher isRangeError = const _RangeError();
+
+/// A matcher for functions that throw RangeError.
+const Matcher throwsRangeError = const Throws(isRangeError);
+
+class _RangeError extends TypeMatcher {
+  const _RangeError(): super("RangeError");
+  bool matches(item, Map matchState) => item is RangeError;
+}
+
+/// A matcher for StateErrors.
+const Matcher isStateError = const _StateError();
+
+/// A matcher for functions that throw StateError.
+const Matcher throwsStateError = const Throws(isStateError);
+
+class _StateError extends TypeMatcher {
+  const _StateError(): super("StateError");
+  bool matches(item, Map matchState) => item is StateError;
+}
+
+/// A matcher for UnimplementedErrors.
+const Matcher isUnimplementedError = const _UnimplementedError();
+
+/// A matcher for functions that throw Exception.
+const Matcher throwsUnimplementedError = const Throws(isUnimplementedError);
+
+class _UnimplementedError extends TypeMatcher {
+  const _UnimplementedError(): super("UnimplementedError");
+  bool matches(item, Map matchState) => item is UnimplementedError;
+}
+
+/// A matcher for UnsupportedError.
+const Matcher isUnsupportedError = const _UnsupportedError();
+
+/// A matcher for functions that throw UnsupportedError.
+const Matcher throwsUnsupportedError = const Throws(isUnsupportedError);
+
+class _UnsupportedError extends TypeMatcher {
+  const _UnsupportedError(): super("UnsupportedError");
+  bool matches(item, Map matchState) => item is UnsupportedError;
+}
diff --git a/lib/src/expect.dart b/lib/src/expect.dart
index 2994163..073ef34 100644
--- a/lib/src/expect.dart
+++ b/lib/src/expect.dart
@@ -2,9 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of matcher;
+library matcher.expect;
 
-/** The objects thrown by the default failure handler. */
+import 'core_matchers.dart';
+import 'description.dart';
+import 'interfaces.dart';
+
+/// The objects thrown by the default failure handler.
 class TestFailure extends Error {
   final String message;
 
@@ -13,9 +17,7 @@
   String toString() => message;
 }
 
-/**
- * Useful utility for nesting match states.
- */
+/// Useful utility for nesting match states.
 
 void addStateInfo(Map matchState, Map values) {
   var innerState = new Map.from(matchState);
@@ -24,37 +26,33 @@
   matchState.addAll(values);
 }
 
-/**
- * Some matchers, like those for Futures and exception testing,
- * can fail in asynchronous sections, and throw exceptions.
- * A user of this library will typically want to catch and handle
- * such exceptions. The [wrapAsync] property is a function that
- * can wrap callbacks used by these Matchers so that they can be
- * used safely. For example, the unittest library will set this
- * to be `expectAsync`. By default this is an identity function.
- */
+/// Some matchers, like those for Futures and exception testing,
+/// can fail in asynchronous sections, and throw exceptions.
+/// A user of this library will typically want to catch and handle
+/// such exceptions. The [wrapAsync] property is a function that
+/// can wrap callbacks used by these Matchers so that they can be
+/// used safely. For example, the unittest library will set this
+/// to be `expectAsync`. By default this is an identity function.
 Function wrapAsync = (Function f, [id]) => f;
 
-/**
- * This is the main assertion function. It asserts that [actual]
- * matches the [matcher]. [reason] is optional and is typically not
- * supplied, as a reason is generated from the matcher; if [reason]
- * is included it is appended to the reason generated by the matcher.
- *
- * [matcher] can be a value in which case it will be wrapped in an
- * [equals] matcher.
- *
- * If the assertion fails, then the default behavior is to throw a
- * [TestFailure], but this behavior can be changed by calling
- * [configureExpectFailureHandler] and providing an alternative handler that
- * implements the [IFailureHandler] interface. It is also possible to
- * pass a [failureHandler] to [expect] as a final parameter for fine-
- * grained control.
- *
- * In some cases extra diagnostic info can be produced on failure (for
- * example, stack traces on mismatched exceptions). To enable these,
- * [verbose] should be specified as true;
- */
+/// This is the main assertion function. It asserts that [actual]
+/// matches the [matcher]. [reason] is optional and is typically not
+/// supplied, as a reason is generated from the matcher; if [reason]
+/// is included it is appended to the reason generated by the matcher.
+///
+/// [matcher] can be a value in which case it will be wrapped in an
+/// [equals] matcher.
+///
+/// If the assertion fails, then the default behavior is to throw a
+/// [TestFailure], but this behavior can be changed by calling
+/// [configureExpectFailureHandler] and providing an alternative handler that
+/// implements the [IFailureHandler] interface. It is also possible to
+/// pass a [failureHandler] to [expect] as a final parameter for fine-
+/// grained control.
+///
+/// In some cases extra diagnostic info can be produced on failure (for
+/// example, stack traces on mismatched exceptions). To enable these,
+/// [verbose] should be specified as true;
 void expect(actual, matcher, {String reason, FailureHandler failureHandler,
             bool verbose : false}) {
   matcher = wrapMatcher(matcher);
@@ -83,12 +81,10 @@
   failureHandler.fail(message);
 }
 
-/**
- * Takes an argument and returns an equivalent matcher.
- * If the argument is already a matcher this does nothing,
- * else if the argument is a function, it generates a predicate
- * function matcher, else it generates an equals matcher.
- */
+/// Takes an argument and returns an equivalent matcher.
+/// If the argument is already a matcher this does nothing,
+/// else if the argument is a function, it generates a predicate
+/// function matcher, else it generates an equals matcher.
 Matcher wrapMatcher(x) {
   if (x is Matcher) {
     return x;
@@ -118,12 +114,10 @@
   }
 }
 
-/**
- * Changes or resets to the default the failure handler for expect()
- * [handler] is a reference to the new handler; if this is omitted
- * or null then the failure handler is reset to the default, which
- * throws [TestFailure]s on [expect] assertion failures.
- */
+/// Changes or resets to the default the failure handler for expect()
+/// [handler] is a reference to the new handler; if this is omitted
+/// or null then the failure handler is reset to the default, which
+/// throws [TestFailure]s on [expect] assertion failures.
 void configureExpectFailureHandler([FailureHandler handler = null]) {
   if (handler == null) {
     handler = new DefaultFailureHandler();
@@ -160,17 +154,14 @@
   return description.toString();
 }
 
-/**
- * Changes or resets to default the failure message formatter for expect().
- * [formatter] is a reference to the new formatter; if this is omitted or
- * null then the failure formatter is reset to the default. The new
- * formatter is returned; this allows custom expect handlers to easily
- * get a reference to the default formatter.
- */
+/// Changes or resets to default the failure message formatter for expect().
+/// [formatter] is a reference to the new formatter; if this is omitted or
+/// null then the failure formatter is reset to the default. The new
+/// formatter is returned; this allows custom expect handlers to easily
+/// get a reference to the default formatter.
 ErrorFormatter configureExpectFormatter([ErrorFormatter formatter = null]) {
   if (formatter == null) {
     formatter = _defaultErrorFormatter;
   }
   return _assertErrorFormatter = formatter;
 }
-
diff --git a/lib/src/future_matchers.dart b/lib/src/future_matchers.dart
index c9e2742..4c5a391 100644
--- a/lib/src/future_matchers.dart
+++ b/lib/src/future_matchers.dart
@@ -2,31 +2,33 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of matcher;
+library matcher.future_matchers;
 
-/**
- * Matches a [Future] that completes successfully with a value. Note that this
- * creates an asynchronous expectation. The call to `expect()` that includes
- * this will return immediately and execution will continue. Later, when the
- * future completes, the actual expectation will run.
- *
- * To test that a Future completes with an exception, you can use [throws] and
- * [throwsA].
- */
+import 'dart:async';
+
+import 'core_matchers.dart';
+import 'expect.dart';
+import 'interfaces.dart';
+
+/// Matches a [Future] that completes successfully with a value. Note that this
+/// creates an asynchronous expectation. The call to `expect()` that includes
+/// this will return immediately and execution will continue. Later, when the
+/// future completes, the actual expectation will run.
+///
+/// To test that a Future completes with an exception, you can use [throws] and
+/// [throwsA].
 final Matcher completes = const _Completes(null, '');
 
-/**
- * Matches a [Future] that completes succesfully with a value that matches
- * [matcher]. Note that this creates an asynchronous expectation. The call to
- * `expect()` that includes this will return immediately and execution will
- * continue. Later, when the future completes, the actual expectation will run.
- *
- * To test that a Future completes with an exception, you can use [throws] and
- * [throwsA].
- *
- * [id] is an optional tag that can be used to identify the completion matcher
- * in error messages.
- */
+/// Matches a [Future] that completes succesfully with a value that matches
+/// [matcher]. Note that this creates an asynchronous expectation. The call to
+/// `expect()` that includes this will return immediately and execution will
+/// continue. Later, when the future completes, the actual expectation will run.
+///
+/// To test that a Future completes with an exception, you can use [throws] and
+/// [throwsA].
+///
+/// [id] is an optional tag that can be used to identify the completion matcher
+/// in error messages.
 Matcher completion(matcher, [String id = '']) =>
     new _Completes(wrapMatcher(matcher), id);
 
diff --git a/lib/src/interfaces.dart b/lib/src/interfaces.dart
index 71079e5..9fc1107 100644
--- a/lib/src/interfaces.dart
+++ b/lib/src/interfaces.dart
@@ -7,97 +7,80 @@
 // To decouple the reporting of errors, and allow for extensibility of
 // matchers, we make use of some interfaces.
 
-/**
- * The ErrorFormatter type is used for functions that
- * can be used to build up error reports upon [expect] failures.
- * There is one built-in implementation ([defaultErrorFormatter])
- * which is used by the default failure handler. If the failure handler
- * is replaced it may be desirable to replace the [stringDescription]
- * error formatter with another.
- */
+/// The ErrorFormatter type is used for functions that
+/// can be used to build up error reports upon [expect] failures.
+/// There is one built-in implementation ([defaultErrorFormatter])
+/// which is used by the default failure handler. If the failure handler
+/// is replaced it may be desirable to replace the [stringDescription]
+/// error formatter with another.
 typedef String ErrorFormatter(actual, Matcher matcher, String reason,
     Map matchState, bool verbose);
 
-/**
- * Matchers build up their error messages by appending to
- * Description objects. This interface is implemented by
- * StringDescription. This interface is unlikely to need
- * other implementations, but could be useful to replace in
- * some cases - e.g. language conversion.
- */
+/// Matchers build up their error messages by appending to
+/// Description objects. This interface is implemented by
+/// StringDescription. This interface is unlikely to need
+/// other implementations, but could be useful to replace in
+/// some cases - e.g. language conversion.
 abstract class Description {
   int get length;
 
-  /** Change the value of the description. */
+  /// Change the value of the description.
   Description replace(String text);
 
-  /** This is used to add arbitrary text to the description. */
+  /// This is used to add arbitrary text to the description.
   Description add(String text);
 
-  /** This is used to add a meaningful description of a value. */
+  /// This is used to add a meaningful description of a value.
   Description addDescriptionOf(value);
 
-  /**
-   * This is used to add a description of an [Iterable] [list],
-   * with appropriate [start] and [end] markers and inter-element [separator].
-   */
+  /// This is used to add a description of an [Iterable] [list],
+  /// with appropriate [start] and [end] markers and inter-element [separator].
   Description addAll(String start, String separator, String end, Iterable list);
 }
 
-/**
- * [expect] Matchers must implement/extend the Matcher class.
- * The base Matcher class has a generic implementation of [describeMismatch]
- * so this does not need to be provided unless a more clear description is
- * required. The other two methods ([matches] and [describe])
- * must always be provided as they are highly matcher-specific.
- */
+/// [expect] Matchers must implement/extend the Matcher class.
+/// The base Matcher class has a generic implementation of [describeMismatch]
+/// so this does not need to be provided unless a more clear description is
+/// required. The other two methods ([matches] and [describe])
+/// must always be provided as they are highly matcher-specific.
 abstract class Matcher {
   const Matcher();
 
-  /**
-   * This does the matching of the actual vs expected values.
-   * [item] is the actual value. [matchState] can be supplied
-   * and may be used to add details about the mismatch that are too
-   * costly to determine in [describeMismatch].
-   */
+  /// This does the matching of the actual vs expected values.
+  /// [item] is the actual value. [matchState] can be supplied
+  /// and may be used to add details about the mismatch that are too
+  /// costly to determine in [describeMismatch].
   bool matches(item, Map matchState);
 
-  /** This builds a textual description of the matcher. */
+  /// This builds a textual description of the matcher.
   Description describe(Description description);
 
-  /**
-   * This builds a textual description of a specific mismatch. [item]
-   * is the value that was tested by [matches]; [matchState] is
-   * the [Map] that was passed to and supplemented by [matches]
-   * with additional information about the mismact, and [mismatchDescription]
-   * is the [Description] that is being built to decribe the mismatch.
-   * A few matchers make use of the [verbose] flag to provide detailed
-   * information that is not typically included but can be of help in
-   * diagnosing failures, such as stack traces.
-   */
+  /// This builds a textual description of a specific mismatch. [item]
+  /// is the value that was tested by [matches]; [matchState] is
+  /// the [Map] that was passed to and supplemented by [matches]
+  /// with additional information about the mismact, and [mismatchDescription]
+  /// is the [Description] that is being built to decribe the mismatch.
+  /// A few matchers make use of the [verbose] flag to provide detailed
+  /// information that is not typically included but can be of help in
+  /// diagnosing failures, such as stack traces.
   Description describeMismatch(item, Description mismatchDescription,
       Map matchState, bool verbose) => mismatchDescription;
 }
 
-/**
- * Failed matches are reported using a default IFailureHandler.
- * The default implementation simply throws [TestFailure]s;
- * this can be replaced by some other implementation of
- * IFailureHandler by calling configureExpectHandler.
- */
+/// Failed matches are reported using a default IFailureHandler.
+/// The default implementation simply throws [TestFailure]s;
+/// this can be replaced by some other implementation of
+/// IFailureHandler by calling configureExpectHandler.
 abstract class FailureHandler {
-  /** This handles failures given a textual decription */
+  /// This handles failures given a textual decription
   void fail(String reason);
 
-  /**
-   * This handles failures given the actual [value], the [matcher]
-   * the [reason] (argument from [expect]), some additonal [matchState]
-   * generated by the [matcher], and a verbose flag which controls in
-   * some cases how much [matchState] information is used. It will use
-   * these to create a detailed error message (typically by calling
-   * an [ErrorFormatter]) and then call [fail] with this message.
-   */
+  /// This handles failures given the actual [value], the [matcher]
+  /// the [reason] (argument from [expect]), some additonal [matchState]
+  /// generated by the [matcher], and a verbose flag which controls in
+  /// some cases how much [matchState] information is used. It will use
+  /// these to create a detailed error message (typically by calling
+  /// an [ErrorFormatter]) and then call [fail] with this message.
   void failMatch(actual, Matcher matcher, String reason,
                  Map matchState, bool verbose);
 }
-
diff --git a/lib/src/iterable_matchers.dart b/lib/src/iterable_matchers.dart
index 1922aa1..ef7afb0 100644
--- a/lib/src/iterable_matchers.dart
+++ b/lib/src/iterable_matchers.dart
@@ -2,16 +2,19 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of matcher;
+library matcher.iterable_matchers;
 
-/**
- * Returns a matcher which matches [Iterable]s in which all elements
- * match the given [matcher].
- */
+import 'core_matchers.dart';
+import 'description.dart';
+import 'expect.dart';
+import 'interfaces.dart';
+
+/// Returns a matcher which matches [Iterable]s in which all elements
+/// match the given [matcher].
 Matcher everyElement(matcher) => new _EveryElement(wrapMatcher(matcher));
 
 class _EveryElement extends _IterableMatcher {
-  Matcher _matcher;
+  final Matcher _matcher;
 
   _EveryElement(Matcher this._matcher);
 
@@ -41,10 +44,10 @@
       mismatchDescription.add('has value ').addDescriptionOf(element).
           add(' which ');
       var subDescription = new StringDescription();
-      _matcher.describeMismatch(element, subDescription,
-            matchState['state'], verbose);
+      _matcher.describeMismatch(element, subDescription, matchState['state'],
+          verbose);
       if (subDescription.length > 0) {
-        mismatchDescription.add(subDescription);
+        mismatchDescription.add(subDescription.toString());
       } else {
         mismatchDescription.add("doesn't match ");
         _matcher.describe(mismatchDescription);
@@ -57,14 +60,12 @@
   }
 }
 
-/**
- * Returns a matcher which matches [Iterable]s in which at least one
- * element matches the given [matcher].
- */
+/// Returns a matcher which matches [Iterable]s in which at least one
+/// element matches the given [matcher].
 Matcher anyElement(matcher) => new _AnyElement(wrapMatcher(matcher));
 
 class _AnyElement extends _IterableMatcher {
-  Matcher _matcher;
+  final Matcher _matcher;
 
   _AnyElement(this._matcher);
 
@@ -76,11 +77,9 @@
       description.add('some element ').addDescriptionOf(_matcher);
 }
 
-/**
- * Returns a matcher which matches [Iterable]s that have the same
- * length and the same elements as [expected], and in the same order.
- * This is equivalent to equals but does not recurse.
- */
+/// Returns a matcher which matches [Iterable]s that have the same
+/// length and the same elements as [expected], and in the same order.
+/// This is equivalent to equals but does not recurse.
 
 Matcher orderedEquals(Iterable expected) => new _OrderedEquals(expected);
 
@@ -109,12 +108,10 @@
   }
 }
 
-/**
- * Returns a matcher which matches [Iterable]s that have the same
- * length and the same elements as [expected], but not necessarily in
- * the same order. Note that this is O(n^2) so should only be used on
- * small objects.
- */
+/// Returns a matcher which matches [Iterable]s that have the same
+/// length and the same elements as [expected], but not necessarily in
+/// the same order. Note that this is O(n^2) so should only be used on
+/// small objects.
 Matcher unorderedEquals(Iterable expected) => new _UnorderedEquals(expected);
 
 class _UnorderedEquals extends _UnorderedMatches {
@@ -131,10 +128,8 @@
         .add(' unordered');
 }
 
-/**
- * Iterable matchers match against [Iterable]s. We add this intermediate
- * class to give better mismatch error messages than the base Matcher class.
- */
+/// Iterable matchers match against [Iterable]s. We add this intermediate
+/// class to give better mismatch error messages than the base Matcher class.
 abstract class _IterableMatcher extends Matcher {
   const _IterableMatcher();
   Description describeMismatch(item, Description mismatchDescription,
@@ -150,12 +145,10 @@
   }
 }
 
-/**
- * Returns a matcher which matches [Iterable]s whose elements match the matchers
- * in [expected], but not necessarily in the same order.
- *
- *  Note that this is `O(n^2)` and so should only be used on small objects.
- */
+/// Returns a matcher which matches [Iterable]s whose elements match the
+/// matchers in [expected], but not necessarily in the same order.
+///
+///  Note that this is `O(n^2)` and so should only be used on small objects.
 Matcher unorderedMatches(Iterable expected) => new _UnorderedMatches(expected);
 
 class _UnorderedMatches extends Matcher {
@@ -216,20 +209,20 @@
       mismatchDescription.add(_test(item));
 }
 
-/**
- * A pairwise matcher for iterable. You can pass an arbitrary [comparator]
- * function that takes an expected and actual argument which will be applied
- * to each pair in order. [description]  should be a meaningful name for
- * the comparator.
- */
-Matcher pairwiseCompare(Iterable expected, Function comparator,
+/// A pairwise matcher for iterable. You can pass an arbitrary [comparator]
+/// function that takes an expected and actual argument which will be applied
+/// to each pair in order. [description]  should be a meaningful name for
+/// the comparator.
+Matcher pairwiseCompare(Iterable expected, bool comparator(a, b),
     String description) =>
         new _PairwiseCompare(expected, comparator, description);
 
+typedef bool _Comparator(a, b);
+
 class _PairwiseCompare extends _IterableMatcher {
-  Iterable _expected;
-  Function _comparator;
-  String _description;
+  final Iterable _expected;
+  final _Comparator _comparator;
+  final String _description;
 
   _PairwiseCompare(this._expected, this._comparator, this._description);
 
@@ -270,4 +263,3 @@
     }
   }
 }
-
diff --git a/lib/src/map_matchers.dart b/lib/src/map_matchers.dart
index 033e906..a560e50 100644
--- a/lib/src/map_matchers.dart
+++ b/lib/src/map_matchers.dart
@@ -2,11 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of matcher;
+library matcher.map_matchers;
 
-/**
- * Returns a matcher which matches maps containing the given [value].
- */
+import 'expect.dart';
+import 'interfaces.dart';
+
+/// Returns a matcher which matches maps containing the given [value].
 Matcher containsValue(value) => new _ContainsValue(value);
 
 class _ContainsValue extends Matcher {
@@ -19,10 +20,8 @@
       description.add('contains value ').addDescriptionOf(_value);
 }
 
-/**
- * Returns a matcher which matches maps containing the key-value pair
- * with [key] => [value].
- */
+/// Returns a matcher which matches maps containing the key-value pair
+/// with [key] => [value].
 Matcher containsPair(key, value) =>
     new _ContainsMapping(key, wrapMatcher(value));
 
diff --git a/lib/src/numeric_matchers.dart b/lib/src/numeric_matchers.dart
index 507a682..ae0b0ad 100644
--- a/lib/src/numeric_matchers.dart
+++ b/lib/src/numeric_matchers.dart
@@ -2,73 +2,55 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of matcher;
+library matcher.numeric_matchers;
 
-/**
- * Returns a matcher which matches if the match argument is greater
- * than the given [value].
- */
+import 'interfaces.dart';
+
+/// Returns a matcher which matches if the match argument is greater
+/// than the given [value].
 Matcher greaterThan(value) =>
   new _OrderingComparison(value, false, false, true, 'a value greater than');
 
-/**
- * Returns a matcher which matches if the match argument is greater
- * than or equal to the given [value].
- */
+/// Returns a matcher which matches if the match argument is greater
+/// than or equal to the given [value].
 Matcher greaterThanOrEqualTo(value) =>
   new _OrderingComparison(value, true, false, true,
       'a value greater than or equal to');
 
-/**
- * Returns a matcher which matches if the match argument is less
- * than the given [value].
- */
+/// Returns a matcher which matches if the match argument is less
+/// than the given [value].
 Matcher lessThan(value) =>
   new _OrderingComparison(value, false, true, false, 'a value less than');
 
-/**
- * Returns a matcher which matches if the match argument is less
- * than or equal to the given [value].
- */
+/// Returns a matcher which matches if the match argument is less
+/// than or equal to the given [value].
 Matcher lessThanOrEqualTo(value) =>
   new _OrderingComparison(value, true, true, false,
       'a value less than or equal to');
 
-/**
- * A matcher which matches if the match argument is zero.
- */
+/// A matcher which matches if the match argument is zero.
 const Matcher isZero =
   const _OrderingComparison(0, true, false, false, 'a value equal to');
 
 
-/**
- * A matcher which matches if the match argument is non-zero.
- */
+/// A matcher which matches if the match argument is non-zero.
 const Matcher isNonZero =
   const _OrderingComparison(0, false, true, true, 'a value not equal to');
 
-/**
- * A matcher which matches if the match argument is positive.
- */
+/// A matcher which matches if the match argument is positive.
 const Matcher isPositive =
   const _OrderingComparison(0, false, false, true, 'a positive value', false);
 
-/**
- * A matcher which matches if the match argument is zero or negative.
- */
+/// A matcher which matches if the match argument is zero or negative.
 const Matcher isNonPositive =
   const _OrderingComparison(0, true, true, false,
       'a non-positive value', false);
 
-/**
- * A matcher which matches if the match argument is negative.
- */
+/// A matcher which matches if the match argument is negative.
 const Matcher isNegative =
   const _OrderingComparison(0, false, true, false, 'a negative value', false);
 
-/**
- * A matcher which matches if the match argument is zero or positive.
- */
+/// A matcher which matches if the match argument is zero or positive.
 const Matcher isNonNegative =
   const _OrderingComparison(0, true, false, true,
       'a non-negative value', false);
@@ -77,18 +59,20 @@
   return value is num;
 }
 
+// TODO(kevmoo) Note that matchers that use _OrderingComparison only use
+// `==` and `<` operators to evaluate the match. Or change the matcher.
 class _OrderingComparison extends Matcher {
-  /** Expected value. */
+  /// Expected value.
   final _value;
-  /** What to return if actual == expected */
+  /// What to return if actual == expected
   final bool _equalValue;
-  /** What to return if actual < expected */
+  /// What to return if actual < expected
   final bool _lessThanValue;
-  /** What to return if actual > expected */
+  /// What to return if actual > expected
   final bool _greaterThanValue;
-  /** Textual name of the inequality */
+  /// Textual name of the inequality
   final String _comparisonDescription;
-  /** Whether to include the expected value in the description */
+  /// Whether to include the expected value in the description
   final bool _valueInDescription;
 
   const _OrderingComparison(
@@ -97,7 +81,7 @@
     this._lessThanValue,
     this._greaterThanValue,
     this._comparisonDescription,
-    [valueInDescription = true]) :
+    [bool valueInDescription = true]) :
       this._valueInDescription = valueInDescription;
 
   bool matches(item, Map matchState) {
@@ -126,12 +110,10 @@
   }
 }
 
-/**
- * Returns a matcher which matches if the match argument is within [delta]
- * of some [value]; i.e. if the match argument is greater than
- * than or equal [value]-[delta] and less than or equal to [value]+[delta].
- */
-Matcher closeTo(value, delta) => new _IsCloseTo(value, delta);
+/// Returns a matcher which matches if the match argument is within [delta]
+/// of some [value]; i.e. if the match argument is greater than
+/// than or equal [value]-[delta] and less than or equal to [value]+[delta].
+Matcher closeTo(num value, num delta) => new _IsCloseTo(value, delta);
 
 class _IsCloseTo extends Matcher {
   final num _value, _delta;
@@ -167,29 +149,25 @@
   }
 }
 
-/**
- * Returns a matcher which matches if the match argument is greater
- * than or equal to [low] and less than or equal to [high].
- */
-Matcher inInclusiveRange(low, high) => new _InRange(low, high, true, true);
+/// Returns a matcher which matches if the match argument is greater
+/// than or equal to [low] and less than or equal to [high].
+Matcher inInclusiveRange(num low, num high) =>
+    new _InRange(low, high, true, true);
 
-/**
- * Returns a matcher which matches if the match argument is greater
- * than [low] and less than [high].
- */
-Matcher inExclusiveRange(low, high) => new _InRange(low, high, false, false);
+/// Returns a matcher which matches if the match argument is greater
+/// than [low] and less than [high].
+Matcher inExclusiveRange(num low, num high) =>
+    new _InRange(low, high, false, false);
 
-/**
- * Returns a matcher which matches if the match argument is greater
- * than [low] and less than or equal to [high].
- */
-Matcher inOpenClosedRange(low, high) => new _InRange(low, high, false, true);
+/// Returns a matcher which matches if the match argument is greater
+/// than [low] and less than or equal to [high].
+Matcher inOpenClosedRange(num low, num high) =>
+    new _InRange(low, high, false, true);
 
-/**
- * Returns a matcher which matches if the match argument is greater
- * than or equal to a [low] and less than [high].
- */
-Matcher inClosedOpenRange(low, high) => new _InRange(low, high, true, false);
+/// Returns a matcher which matches if the match argument is greater
+/// than or equal to a [low] and less than [high].
+Matcher inClosedOpenRange(num low, num high) =>
+    new _InRange(low, high, true, false);
 
 class _InRange extends Matcher {
   final num _low, _high;
@@ -231,4 +209,3 @@
     }
   }
 }
-
diff --git a/lib/src/operator_matchers.dart b/lib/src/operator_matchers.dart
index fa17aba..fb79e8f 100644
--- a/lib/src/operator_matchers.dart
+++ b/lib/src/operator_matchers.dart
@@ -2,11 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of matcher;
+library matcher.operator_matchers;
 
-/**
- * This returns a matcher that inverts [matcher] to its logical negation.
- */
+import 'core_matchers.dart';
+import 'expect.dart';
+import 'interfaces.dart';
+
+/// This returns a matcher that inverts [matcher] to its logical negation.
 Matcher isNot(matcher) => new _IsNot(wrapMatcher(matcher));
 
 class _IsNot extends Matcher {
@@ -20,13 +22,11 @@
     description.add('not ').addDescriptionOf(_matcher);
 }
 
-/**
- * This returns a matcher that matches if all of the matchers passed as
- * arguments (up to 7) match. Instead of passing the matchers separately
- * they can be passed as a single List argument.
- * Any argument that is not a matcher is implicitly wrapped in a
- * Matcher to check for equality.
-*/
+/// This returns a matcher that matches if all of the matchers passed as
+/// arguments (up to 7) match. Instead of passing the matchers separately
+/// they can be passed as a single List argument.
+/// Any argument that is not a matcher is implicitly wrapped in a
+/// Matcher to check for equality.
 Matcher allOf(arg0,
              [arg1 = null,
               arg2 = null,
@@ -34,46 +34,11 @@
               arg4 = null,
               arg5 = null,
               arg6 = null]) {
-  if (arg0 is List) {
-    expect(arg1, isNull);
-    expect(arg2, isNull);
-    expect(arg3, isNull);
-    expect(arg4, isNull);
-    expect(arg5, isNull);
-    expect(arg6, isNull);
-    for (int i = 0; i < arg0.length; i++) {
-      arg0[i] = wrapMatcher(arg0[i]);
-    }
-    return new _AllOf(arg0);
-  } else {
-    List matchers = new List();
-    if (arg0 != null) {
-      matchers.add(wrapMatcher(arg0));
-    }
-    if (arg1 != null) {
-      matchers.add(wrapMatcher(arg1));
-    }
-    if (arg2 != null) {
-      matchers.add(wrapMatcher(arg2));
-    }
-    if (arg3 != null) {
-      matchers.add(wrapMatcher(arg3));
-    }
-    if (arg4 != null) {
-      matchers.add(wrapMatcher(arg4));
-    }
-    if (arg5 != null) {
-      matchers.add(wrapMatcher(arg5));
-    }
-    if (arg6 != null) {
-      matchers.add(wrapMatcher(arg6));
-    }
-    return new _AllOf(matchers);
-  }
+  return new _AllOf(_wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6));
 }
 
 class _AllOf extends Matcher {
-  final Iterable<Matcher> _matchers;
+  final List<Matcher> _matchers;
 
   const _AllOf(this._matchers);
 
@@ -99,17 +64,15 @@
       description.addAll('(', ' and ', ')', _matchers);
 }
 
-/**
- * Matches if any of the given matchers evaluate to true. The
- * arguments can be a set of matchers as separate parameters
- * (up to 7), or a List of matchers.
- *
- * The matchers are evaluated from left to right using short-circuit
- * evaluation, so evaluation stops as soon as a matcher returns true.
- *
- * Any argument that is not a matcher is implicitly wrapped in a
- * Matcher to check for equality.
-*/
+/// Matches if any of the given matchers evaluate to true. The
+/// arguments can be a set of matchers as separate parameters
+/// (up to 7), or a List of matchers.
+///
+/// The matchers are evaluated from left to right using short-circuit
+/// evaluation, so evaluation stops as soon as a matcher returns true.
+///
+/// Any argument that is not a matcher is implicitly wrapped in a
+/// Matcher to check for equality.
 
 Matcher anyOf(arg0,
                [arg1 = null,
@@ -118,59 +81,62 @@
                 arg4 = null,
                 arg5 = null,
                 arg6 = null]) {
-  if (arg0 is List) {
-    expect(arg1, isNull);
-    expect(arg2, isNull);
-    expect(arg3, isNull);
-    expect(arg4, isNull);
-    expect(arg5, isNull);
-    expect(arg6, isNull);
-    for (int i = 0; i < arg0.length; i++) {
-      arg0[i] = wrapMatcher(arg0[i]);
-    }
-    return new _AnyOf(arg0);
-  } else {
-    List matchers = new List();
-    if (arg0 != null) {
-      matchers.add(wrapMatcher(arg0));
-    }
-    if (arg1 != null) {
-      matchers.add(wrapMatcher(arg1));
-    }
-    if (arg2 != null) {
-      matchers.add(wrapMatcher(arg2));
-    }
-    if (arg3 != null) {
-      matchers.add(wrapMatcher(arg3));
-    }
-    if (arg4 != null) {
-      matchers.add(wrapMatcher(arg4));
-    }
-    if (arg5 != null) {
-      matchers.add(wrapMatcher(arg5));
-    }
-    if (arg6 != null) {
-      matchers.add(wrapMatcher(arg6));
-    }
-    return new _AnyOf(matchers);
-  }
+  return new _AnyOf(_wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6));
 }
 
 class _AnyOf extends Matcher {
-  final Iterable<Matcher> _matchers;
+  final List<Matcher> _matchers;
 
   const _AnyOf(this._matchers);
 
   bool matches(item, Map matchState) {
-     for (var matcher in _matchers) {
-       if (matcher.matches(item, matchState)) {
-         return true;
-       }
-     }
-     return false;
+    for (var matcher in _matchers) {
+      if (matcher.matches(item, matchState)) {
+        return true;
+      }
+    }
+    return false;
   }
 
   Description describe(Description description) =>
     description.addAll('(', ' or ', ')', _matchers);
 }
 
+List<Matcher> _wrapArgs(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
+  if (arg0 is List) {
+    // TODO(kevmoo) throw a more helpful error here if any of these args is
+    // not null
+    expect(arg1, isNull);
+    expect(arg2, isNull);
+    expect(arg3, isNull);
+    expect(arg4, isNull);
+    expect(arg5, isNull);
+    expect(arg6, isNull);
+
+    return arg0.map((a) => wrapMatcher(a)).toList();
+  }
+
+  List matchers = new List();
+  if (arg0 != null) {
+    matchers.add(wrapMatcher(arg0));
+  }
+  if (arg1 != null) {
+    matchers.add(wrapMatcher(arg1));
+  }
+  if (arg2 != null) {
+    matchers.add(wrapMatcher(arg2));
+  }
+  if (arg3 != null) {
+    matchers.add(wrapMatcher(arg3));
+  }
+  if (arg4 != null) {
+    matchers.add(wrapMatcher(arg4));
+  }
+  if (arg5 != null) {
+    matchers.add(wrapMatcher(arg5));
+  }
+  if (arg6 != null) {
+    matchers.add(wrapMatcher(arg6));
+  }
+  return matchers;
+}
diff --git a/lib/src/pretty_print.dart b/lib/src/pretty_print.dart
index 7deae06..eb13448 100644
--- a/lib/src/pretty_print.dart
+++ b/lib/src/pretty_print.dart
@@ -6,19 +6,16 @@
 
 import 'description.dart';
 import 'interfaces.dart';
-import 'utils.dart';
 
-/**
- * Returns a pretty-printed representation of [object].
- *
- * If [maxLineLength] is passed, this will attempt to ensure that each line is
- * no longer than [maxLineLength] characters long. This isn't guaranteed, since
- * individual objects may have string representations that are too long, but
- * most lines will be less than [maxLineLength] long.
- *
- * If [maxItems] is passed, [Iterable]s and [Map]s will only print their first
- * [maxItems] members or key/value pairs, respectively.
- */
+/// Returns a pretty-printed representation of [object].
+///
+/// If [maxLineLength] is passed, this will attempt to ensure that each line is
+/// no longer than [maxLineLength] characters long. This isn't guaranteed, since
+/// individual objects may have string representations that are too long, but
+/// most lines will be less than [maxLineLength] long.
+///
+/// If [maxItems] is passed, [Iterable]s and [Map]s will only print their first
+/// [maxItems] members or key/value pairs, respectively.
 String prettyPrint(object, {int maxLineLength, int maxItems}) {
   String _prettyPrint(object, int indent, Set seen, bool top) {
     // If the object is a matcher, use its description.
@@ -35,7 +32,7 @@
 
     if (object is Iterable) {
       // Print the type name for non-List iterables.
-      var type = object is List ? "" : typeName(object) + ":";
+      var type = object is List ? "" : _typeName(object) + ":";
 
       // Truncate the list of strings if it's longer than [maxItems].
       var strings = object.map(pp).toList();
@@ -83,7 +80,7 @@
     } else if (object is String) {
       // Escape strings and print each line on its own line.
       var lines = object.split("\n");
-      return "'" + lines.map(escapeString)
+      return "'" + lines.map(_escapeString)
           .join("\\n'\n${_indent(indent + 2)}'") + "'";
     } else {
       var value = object.toString().replaceAll("\n", _indent(indent) + "\n");
@@ -100,7 +97,7 @@
           object == null || defaultToString) {
         return value;
       } else {
-        return "${typeName(object)}:$value";
+        return "${_typeName(object)}:$value";
       }
     }
   }
@@ -109,3 +106,42 @@
 }
 
 String _indent(int length) => new List.filled(length, ' ').join('');
+
+/// Returns the name of the type of [x], or "Unknown" if the type name can't be
+/// determined.
+String _typeName(x) {
+  // dart2js blows up on some objects (e.g. window.navigator).
+  // So we play safe here.
+  try {
+    if (x == null) return "null";
+    var type = x.runtimeType.toString();
+    // TODO(nweiz): if the object's type is private, find a public superclass to
+    // display once there's a portable API to do that.
+    return type.startsWith("_") ? "?" : type;
+  } catch (e) {
+    return "?";
+  }
+}
+
+/// Returns [source] with any control characters replaced by their escape
+/// sequences.
+///
+/// This doesn't add quotes to the string, but it does escape single quote
+/// characters so that single quotes can be applied externally.
+String _escapeString(String source) =>
+  source.split("").map(_escapeChar).join("");
+
+/// Return the escaped form of a character [ch].
+String _escapeChar(String ch) {
+  if (ch == "'")
+    return "\\'";
+  else if (ch == '\n')
+    return '\\n';
+  else if (ch == '\r')
+    return '\\r';
+  else if (ch == '\t')
+    return '\\t';
+  else
+    return ch;
+}
+
diff --git a/lib/src/string_matchers.dart b/lib/src/string_matchers.dart
index f5e32ff..c498446 100644
--- a/lib/src/string_matchers.dart
+++ b/lib/src/string_matchers.dart
@@ -2,21 +2,21 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-part of matcher;
+library matcher.string_matchers;
 
-/**
- * Returns a matcher which matches if the match argument is a string and
- * is equal to [value] when compared case-insensitively.
- */
+import 'interfaces.dart';
+
+/// Returns a matcher which matches if the match argument is a string and
+/// is equal to [value] when compared case-insensitively.
 Matcher equalsIgnoringCase(String value) => new _IsEqualIgnoringCase(value);
 
 class _IsEqualIgnoringCase extends _StringMatcher {
   final String _value;
-  String _matchValue;
+  final String _matchValue;
 
-  _IsEqualIgnoringCase(this._value) {
-    _matchValue = _value.toLowerCase();
-  }
+  _IsEqualIgnoringCase(String value)
+      : _value = value,
+        _matchValue = value.toLowerCase();
 
   bool matches(item, Map matchState) =>
       item is String && _matchValue == item.toLowerCase();
@@ -25,24 +25,22 @@
       description.addDescriptionOf(_value).add(' ignoring case');
 }
 
-/**
- * Returns a matcher which matches if the match argument is a string and
- * is equal to [value] when compared with all runs of whitespace
- * collapsed to single spaces and leading and trailing whitespace removed.
- *
- * For example, `equalsIgnoringCase("hello world")` will match
- * "hello   world", "  hello world" and "hello world  ".
- */
-Matcher equalsIgnoringWhitespace(_string) =>
-    new _IsEqualIgnoringWhitespace(_string);
+/// Returns a matcher which matches if the match argument is a string and
+/// is equal to [value] when compared with all runs of whitespace
+/// collapsed to single spaces and leading and trailing whitespace removed.
+///
+/// For example, `equalsIgnoringCase("hello world")` will match
+/// "hello   world", "  hello world" and "hello world  ".
+Matcher equalsIgnoringWhitespace(String string) =>
+    new _IsEqualIgnoringWhitespace(string);
 
 class _IsEqualIgnoringWhitespace extends _StringMatcher {
   final String _value;
-  String _matchValue;
+  final String _matchValue;
 
-  _IsEqualIgnoringWhitespace(this._value) {
-    _matchValue = collapseWhitespace(_value);
-  }
+  _IsEqualIgnoringWhitespace(String value)
+      : _value = value,
+        _matchValue = collapseWhitespace(value);
 
   bool matches(item, Map matchState) =>
       item is String && _matchValue == collapseWhitespace(item);
@@ -63,33 +61,8 @@
   }
 }
 
-/**
- * Utility function to collapse whitespace runs to single spaces
- * and strip leading/trailing whitespace.
- */
-String collapseWhitespace(_string) {
-  bool isWhitespace(String ch) => (' \n\r\t'.indexOf(ch) >= 0);
-  StringBuffer result = new StringBuffer();
-  bool skipSpace = true;
-  for (var i = 0; i < _string.length; i++) {
-    var character = _string[i];
-    if (isWhitespace(character)) {
-      if (!skipSpace) {
-        result.write(' ');
-        skipSpace = true;
-      }
-    } else {
-      result.write(character);
-      skipSpace = false;
-    }
-  }
-  return result.toString().trim();
-}
-
-/**
- * Returns a matcher that matches if the match argument is a string and
- * starts with [prefixString].
- */
+/// Returns a matcher that matches if the match argument is a string and
+/// starts with [prefixString].
 Matcher startsWith(String prefixString) => new _StringStartsWith(prefixString);
 
 class _StringStartsWith extends _StringMatcher {
@@ -104,14 +77,11 @@
       description.add('a string starting with ').addDescriptionOf(_prefix);
 }
 
-/**
- * Returns a matcher that matches if the match argument is a string and
- * ends with [suffixString].
- */
+/// Returns a matcher that matches if the match argument is a string and
+/// ends with [suffixString].
 Matcher endsWith(String suffixString) => new _StringEndsWith(suffixString);
 
 class _StringEndsWith extends _StringMatcher {
-
   final String _suffix;
 
   const _StringEndsWith(this._suffix);
@@ -123,19 +93,16 @@
       description.add('a string ending with ').addDescriptionOf(_suffix);
 }
 
-/**
- * Returns a matcher that matches if the match argument is a string and
- * contains a given list of [substrings] in relative order.
- *
- * For example, `stringContainsInOrder(["a", "e", "i", "o", "u"])` will match
- * "abcdefghijklmnopqrstuvwxyz".
- */
+/// Returns a matcher that matches if the match argument is a string and
+/// contains a given list of [substrings] in relative order.
+///
+/// For example, `stringContainsInOrder(["a", "e", "i", "o", "u"])` will match
+/// "abcdefghijklmnopqrstuvwxyz".
 
-Matcher stringContainsInOrder(substrings) =>
+Matcher stringContainsInOrder(List<String> substrings) =>
     new _StringContainsInOrder(substrings);
 
 class _StringContainsInOrder extends _StringMatcher {
-
   final List<String> _substrings;
 
   const _StringContainsInOrder(this._substrings);
@@ -147,8 +114,7 @@
     var from_index = 0;
     for (var s in _substrings) {
       from_index = item.indexOf(s, from_index);
-      if (from_index < 0)
-        return false;
+      if (from_index < 0) return false;
     }
     return true;
   }
@@ -158,12 +124,10 @@
                                                   _substrings);
 }
 
-/**
- * Returns a matcher that matches if the match argument is a string and
- * matches the regular expression given by [re]. [re] can be a RegExp
- * instance or a string; in the latter case it will be used to create
- * a RegExp instance.
- */
+/// Returns a matcher that matches if the match argument is a string and
+/// matches the regular expression given by [re]. [re] can be a [RegExp]
+/// instance or a [String]; in the latter case it will be used to create
+/// a RegExp instance.
 Matcher matches(re) => new _MatchesRegExp(re);
 
 class _MatchesRegExp extends _StringMatcher {
@@ -202,3 +166,26 @@
     }
   }
 }
+
+/// Utility function to collapse whitespace runs to single spaces
+/// and strip leading/trailing whitespace.
+String collapseWhitespace(String string) {
+  var result = new StringBuffer();
+  var skipSpace = true;
+  for (var i = 0; i < string.length; i++) {
+    var character = string[i];
+    if (_isWhitespace(character)) {
+      if (!skipSpace) {
+        result.write(' ');
+        skipSpace = true;
+      }
+    } else {
+      result.write(character);
+      skipSpace = false;
+    }
+  }
+  return result.toString().trim();
+}
+
+bool _isWhitespace(String ch) =>
+    ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t';
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
deleted file mode 100644
index c2182c2..0000000
--- a/lib/src/utils.dart
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library matcher.utils;
-
-/**
- * Returns the name of the type of [x], or "Unknown" if the type name can't be
- * determined.
- */
-String typeName(x) {
-  // dart2js blows up on some objects (e.g. window.navigator).
-  // So we play safe here.
-  try {
-    if (x == null) return "null";
-    var type = x.runtimeType.toString();
-    // TODO(nweiz): if the object's type is private, find a public superclass to
-    // display once there's a portable API to do that.
-    return type.startsWith("_") ? "?" : type;
-  } catch (e) {
-    return "?";
-  }
-}
-
-/**
- * Returns [source] with any control characters replaced by their escape
- * sequences.
- *
- * This doesn't add quotes to the string, but it does escape single quote
- * characters so that single quotes can be applied externally.
- */
-String escapeString(String source) =>
-    source.split("").map(_escapeChar).join("");
-
-/** Return the escaped form of a character [ch]. */
-String _escapeChar(String ch) {
-  if (ch == "'")
-    return "\\'";
-  else if (ch == '\n')
-    return '\\n';
-  else if (ch == '\r')
-    return '\\r';
-  else if (ch == '\t')
-    return '\\t';
-  else
-    return ch;
-}
-
-/** Indent each line in [str] by two spaces. */
-String indent(String str) =>
-  str.replaceAll(new RegExp("^", multiLine: true), "  ");
-
-/** A pair of values. */
-class Pair<E, F> {
-  E first;
-  F last;
-
-  Pair(this.first, this.last);
-
-  String toString() => '($first, $last)';
-
-  bool operator ==(other) {
-    if (other is! Pair) return false;
-    return other.first == first && other.last == last;
-  }
-
-  int get hashCode => first.hashCode ^ last.hashCode;
-}
-
diff --git a/pubspec.yaml b/pubspec.yaml
index 63f8191..87ab0cf 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: matcher
-version: 0.10.0
+version: 0.10.0+3
 author: Dart Team <misc@dartlang.org>
 description: Support for specifying test expectations
 homepage: http://www.dartlang.org
diff --git a/test/core_matchers_test.dart b/test/core_matchers_test.dart
new file mode 100644
index 0000000..3f694f3
--- /dev/null
+++ b/test/core_matchers_test.dart
@@ -0,0 +1,211 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library matcher.core_matchers_test;
+
+import 'package:matcher/matcher.dart';
+import 'package:unittest/unittest.dart' show test, group;
+
+import 'test_utils.dart';
+
+void main() {
+  initUtils();
+
+  test('isTrue', () {
+    shouldPass(true, isTrue);
+    shouldFail(false, isTrue, "Expected: true Actual: <false>");
+  });
+
+  test('isFalse', () {
+    shouldPass(false, isFalse);
+    shouldFail(10, isFalse, "Expected: false Actual: <10>");
+    shouldFail(true, isFalse, "Expected: false Actual: <true>");
+  });
+
+  test('isNull', () {
+    shouldPass(null, isNull);
+    shouldFail(false, isNull, "Expected: null Actual: <false>");
+  });
+
+  test('isNotNull', () {
+    shouldPass(false, isNotNull);
+    shouldFail(null, isNotNull, "Expected: not null Actual: <null>");
+  });
+
+  test('same', () {
+    var a = new Map();
+    var b = new Map();
+    shouldPass(a, same(a));
+    shouldFail(b, same(a), "Expected: same instance as {} Actual: {}");
+  });
+
+  test('equals', () {
+    var a = new Map();
+    var b = new Map();
+    shouldPass(a, equals(a));
+    shouldPass(a, equals(b));
+  });
+
+  test('anything', () {
+    var a = new Map();
+    shouldPass(0, anything);
+    shouldPass(null, anything);
+    shouldPass(a, anything);
+    shouldFail(a, isNot(anything), "Expected: not anything Actual: {}");
+  });
+
+  test('throws', () {
+    shouldFail(doesNotThrow, throws,
+        matches(
+            r"Expected: throws"
+            r"  Actual: <Closure(: \(\) => dynamic "
+            r"from Function 'doesNotThrow': static\.)?>"
+            r"   Which: did not throw"));
+    shouldPass(doesThrow, throws);
+    shouldFail(true, throws,
+        "Expected: throws"
+        "  Actual: <true>"
+        "   Which: is not a Function or Future");
+  });
+
+  test('throwsA', () {
+    shouldPass(doesThrow, throwsA(equals('X')));
+    shouldFail(doesThrow, throwsA(equals('Y')),
+        matches(
+            r"Expected: throws 'Y'"
+            r"  Actual: <Closure(: \(\) => dynamic "
+            r"from Function 'doesThrow': static\.)?>"
+            r"   Which: threw 'X'"));
+  });
+
+  test('throwsA', () {
+    shouldPass(doesThrow, throwsA(equals('X')));
+    shouldFail(doesThrow, throwsA(equals('Y')),
+        matches("Expected: throws 'Y'.*"
+        "Actual: <Closure.*"
+        "Which: threw 'X'"));
+  });
+
+  test('returnsNormally', () {
+    shouldPass(doesNotThrow, returnsNormally);
+    shouldFail(doesThrow, returnsNormally,
+        matches(
+            r"Expected: return normally"
+            r"  Actual: <Closure(: \(\) => dynamic "
+            r"from Function 'doesThrow': static\.)?>"
+            r"   Which: threw 'X'"));
+  });
+
+
+  test('hasLength', () {
+    var a = new Map();
+    var b = new List();
+    shouldPass(a, hasLength(0));
+    shouldPass(b, hasLength(0));
+    shouldPass('a', hasLength(1));
+    shouldFail(0, hasLength(0), new PrefixMatcher(
+        "Expected: an object with length of <0> "
+        "Actual: <0> "
+        "Which: has no length property"));
+
+    b.add(0);
+    shouldPass(b, hasLength(1));
+    shouldFail(b, hasLength(2),
+        "Expected: an object with length of <2> "
+        "Actual: [0] "
+        "Which: has length of <1>");
+
+    b.add(0);
+    shouldFail(b, hasLength(1),
+        "Expected: an object with length of <1> "
+        "Actual: [0, 0] "
+        "Which: has length of <2>");
+    shouldPass(b, hasLength(2));
+  });
+
+  test('scalar type mismatch', () {
+    shouldFail('error', equals(5.1),
+        "Expected: <5.1> "
+        "Actual: 'error'");
+  });
+
+  test('nested type mismatch', () {
+    shouldFail(['error'], equals([5.1]),
+        "Expected: [5.1] "
+        "Actual: ['error'] "
+        "Which: was 'error' instead of <5.1> at location [0]");
+  });
+
+  test('doubly-nested type mismatch', () {
+    shouldFail([['error']], equals([[5.1]]),
+        "Expected: [[5.1]] "
+        "Actual: [['error']] "
+        "Which: was 'error' instead of <5.1> at location [0][0]");
+  });
+
+  test('doubly nested inequality', () {
+    var actual1 = [['foo', 'bar'], ['foo'], 3, []];
+    var expected1 = [['foo', 'bar'], ['foo'], 4, []];
+    var reason1 = "Expected: [['foo', 'bar'], ['foo'], 4, []] "
+        "Actual: [['foo', 'bar'], ['foo'], 3, []] "
+        "Which: was <3> instead of <4> at location [2]";
+
+    var actual2 = [['foo', 'barry'], ['foo'], 4, []];
+    var expected2 = [['foo', 'bar'], ['foo'], 4, []];
+    var reason2 = "Expected: [['foo', 'bar'], ['foo'], 4, []] "
+        "Actual: [['foo', 'barry'], ['foo'], 4, []] "
+        "Which: was 'barry' instead of 'bar' at location [0][1]";
+
+    var actual3 = [['foo', 'bar'], ['foo'], 4, {'foo':'bar'}];
+    var expected3 = [['foo', 'bar'], ['foo'], 4, {'foo':'barry'}];
+    var reason3 = "Expected: [['foo', 'bar'], ['foo'], 4, {'foo': 'barry'}] "
+        "Actual: [['foo', 'bar'], ['foo'], 4, {'foo': 'bar'}] "
+        "Which: was 'bar' instead of 'barry' at location [3]['foo']";
+
+    shouldFail(actual1, equals(expected1), reason1);
+    shouldFail(actual2, equals(expected2), reason2);
+    shouldFail(actual3, equals(expected3), reason3);
+  });
+
+  test('isInstanceOf', () {
+    shouldFail(0, new isInstanceOf<String>('String'),
+        "Expected: an instance of String Actual: <0>");
+    shouldPass('cow', new isInstanceOf<String>('String'));
+  });
+
+  group('Predicate Matchers', () {
+    test('isInstanceOf', () {
+      shouldFail(0, predicate((x) => x is String, "an instance of String"),
+          "Expected: an instance of String Actual: <0>");
+      shouldPass('cow', predicate((x) => x is String, "an instance of String"));
+    });
+  });
+
+  group('exception/error matchers', () {
+    test('throwsCyclicInitializationError', () {
+      expect(() => _Bicycle.foo, throwsCyclicInitializationError);
+    });
+
+    test('throwsConcurrentModificationError', () {
+      expect(() {
+        var a = { 'foo': 'bar' };
+        for (var k in a.keys) {
+          a.remove(k);
+        }
+      }, throwsConcurrentModificationError);
+    });
+
+    test('throwsNullThrownError', () {
+      expect(() => throw null, throwsNullThrownError);
+    });
+  });
+}
+
+class _Bicycle {
+  static final foo = bar();
+
+  static bar() {
+    return foo + 1;
+  }
+}
diff --git a/test/deprecated_matchers_test.dart b/test/deprecated_matchers_test.dart
new file mode 100644
index 0000000..b6acc1c
--- /dev/null
+++ b/test/deprecated_matchers_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library matcher.deprecated_matchers_test;
+
+import 'package:matcher/matcher.dart';
+import 'package:unittest/unittest.dart' show test, group;
+
+import 'test_utils.dart';
+
+void main() {
+  initUtils();
+
+  test('throwsAbstractClassInstantiationError', () {
+    expect(() => new _AbstractClass(), throwsAbstractClassInstantiationError);
+  });
+
+  test('throwsFallThroughError', () {
+    expect(() {
+      var a = 0;
+      switch (a) {
+        case 0:
+          a += 1;
+        case 1:
+          return;
+      }
+    }, throwsFallThroughError);
+  });
+}
+
+abstract class _AbstractClass {
+}
diff --git a/test/future_matchers_test.dart b/test/future_matchers_test.dart
new file mode 100644
index 0000000..6fac0de
--- /dev/null
+++ b/test/future_matchers_test.dart
@@ -0,0 +1,76 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library matcher.future_matchers_test;
+
+import 'dart:async';
+
+import 'package:matcher/matcher.dart';
+import 'package:unittest/unittest.dart' show test, group;
+
+import 'test_utils.dart';
+
+void main() {
+  initUtils();
+
+  test('completes - unexpected error', () {
+    var completer = new Completer();
+    completer.completeError('X');
+    shouldFail(completer.future, completes,
+        contains('Expected future to complete successfully, '
+                 'but it failed with X'),
+        isAsync: true);
+  });
+
+  test('completes - successfully', () {
+    var completer = new Completer();
+    completer.complete('1');
+    shouldPass(completer.future, completes, isAsync: true);
+  });
+
+  test('throws - unexpected to see normal completion', () {
+    var completer = new Completer();
+    completer.complete('1');
+    shouldFail(completer.future, throws,
+      contains("Expected future to fail, but succeeded with '1'"),
+      isAsync: true);
+  });
+
+  test('throws - expected to see exception', () {
+    var completer = new Completer();
+    completer.completeError('X');
+    shouldPass(completer.future, throws, isAsync: true);
+  });
+
+  test('throws - expected to see exception thrown later on', () {
+    var completer = new Completer();
+    var chained = completer.future.then((_) { throw 'X'; });
+    shouldPass(chained, throws, isAsync: true);
+    completer.complete('1');
+  });
+
+  test('throwsA - unexpected normal completion', () {
+    var completer = new Completer();
+    completer.complete('1');
+    shouldFail(completer.future, throwsA(equals('X')),
+      contains("Expected future to fail, but succeeded with '1'"),
+      isAsync: true);
+  });
+
+  test('throwsA - correct error', () {
+    var completer = new Completer();
+    completer.completeError('X');
+    shouldPass(completer.future, throwsA(equals('X')), isAsync: true);
+  });
+
+  test('throwsA - wrong error', () {
+    var completer = new Completer();
+    completer.completeError('X');
+    shouldFail(completer.future, throwsA(equals('Y')),
+        "Expected: 'Y' Actual: 'X' "
+        "Which: is different. "
+        "Expected: Y Actual: X ^ Differ at offset 0",
+        isAsync: true);
+  });
+}
diff --git a/test/iterable_matchers_test.dart b/test/iterable_matchers_test.dart
new file mode 100644
index 0000000..4570d52
--- /dev/null
+++ b/test/iterable_matchers_test.dart
@@ -0,0 +1,166 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library matcher.iterable_matchers_test;
+
+import 'package:matcher/matcher.dart';
+import 'package:unittest/unittest.dart' show test, group;
+
+import 'test_utils.dart';
+
+void main() {
+  initUtils();
+
+  test('isEmpty', () {
+    shouldPass([], isEmpty);
+    shouldFail([1], isEmpty, "Expected: empty Actual: [1]");
+  });
+
+  test('contains', () {
+    var d = [1, 2];
+    shouldPass(d, contains(1));
+    shouldFail(d, contains(0), "Expected: contains <0> "
+        "Actual: [1, 2]");
+  });
+
+  test('equals with matcher element', () {
+    var d = ['foo', 'bar'];
+    shouldPass(d, equals(['foo', startsWith('ba')]));
+    shouldFail(d, equals(['foo', endsWith('ba')]),
+        "Expected: ['foo', <a string ending with 'ba'>] "
+        "Actual: ['foo', 'bar'] "
+        "Which: does not match a string ending with 'ba' at location [1]");
+  });
+
+  test('isIn', () {
+    var d = [1, 2];
+    shouldPass(1, isIn(d));
+    shouldFail(0, isIn(d), "Expected: is in [1, 2] Actual: <0>");
+  });
+
+  test('everyElement', () {
+    var d = [1, 2];
+    var e = [1, 1, 1];
+    shouldFail(d, everyElement(1),
+        "Expected: every element(<1>) "
+        "Actual: [1, 2] "
+        "Which: has value <2> which doesn't match <1> at index 1");
+    shouldPass(e, everyElement(1));
+  });
+
+  test('nested everyElement', () {
+    var d = [['foo', 'bar'], ['foo'], []];
+    var e = [['foo', 'bar'], ['foo'], 3, []];
+    shouldPass(d, everyElement(anyOf(isEmpty, contains('foo'))));
+    shouldFail(d, everyElement(everyElement(equals('foo'))),
+        "Expected: every element(every element('foo')) "
+        "Actual: [['foo', 'bar'], ['foo'], []] "
+        "Which: has value ['foo', 'bar'] which has value 'bar' "
+        "which is different. Expected: foo Actual: bar ^ "
+        "Differ at offset 0 at index 1 at index 0");
+    shouldFail(d, everyElement(allOf(hasLength(greaterThan(0)),
+        contains('foo'))),
+         "Expected: every element((an object with length of a value "
+         "greater than <0> and contains 'foo')) "
+         "Actual: [['foo', 'bar'], ['foo'], []] "
+         "Which: has value [] which has length of <0> at index 2");
+    shouldFail(d, everyElement(allOf(contains('foo'),
+        hasLength(greaterThan(0)))),
+        "Expected: every element((contains 'foo' and "
+        "an object with length of a value greater than <0>)) "
+        "Actual: [['foo', 'bar'], ['foo'], []] "
+        "Which: has value [] which doesn't match (contains 'foo' and "
+        "an object with length of a value greater than <0>) at index 2");
+    shouldFail(e, everyElement(allOf(contains('foo'),
+        hasLength(greaterThan(0)))),
+        "Expected: every element((contains 'foo' and an object with "
+        "length of a value greater than <0>)) "
+        "Actual: [['foo', 'bar'], ['foo'], 3, []] "
+        "Which: has value <3> which is not a string, map or iterable "
+        "at index 2");
+  });
+
+  test('anyElement', () {
+    var d = [1, 2];
+    var e = [1, 1, 1];
+    shouldPass(d, anyElement(2));
+    shouldFail(e, anyElement(2),
+        "Expected: some element <2> Actual: [1, 1, 1]");
+  });
+
+  test('orderedEquals', () {
+    shouldPass([null], orderedEquals([null]));
+    var d = [1, 2];
+    shouldPass(d, orderedEquals([1, 2]));
+    shouldFail(d, orderedEquals([2, 1]),
+        "Expected: equals [2, 1] ordered "
+        "Actual: [1, 2] "
+        "Which: was <1> instead of <2> at location [0]");
+  });
+
+  test('unorderedEquals', () {
+    var d = [1, 2];
+    shouldPass(d, unorderedEquals([2, 1]));
+    shouldFail(d, unorderedEquals([1]),
+        "Expected: equals [1] unordered "
+        "Actual: [1, 2] "
+        "Which: has too many elements (2 > 1)");
+    shouldFail(d, unorderedEquals([3, 2, 1]),
+        "Expected: equals [3, 2, 1] unordered "
+        "Actual: [1, 2] "
+        "Which: has too few elements (2 < 3)");
+    shouldFail(d, unorderedEquals([3, 1]),
+        "Expected: equals [3, 1] unordered "
+        "Actual: [1, 2] "
+        "Which: has no match for <3> at index 0");
+  });
+
+  test('unorderedMatchess', () {
+    var d = [1, 2];
+    shouldPass(d, unorderedMatches([2, 1]));
+    shouldPass(d, unorderedMatches([greaterThan(1), greaterThan(0)]));
+    shouldFail(d, unorderedMatches([greaterThan(0)]),
+        "Expected: matches [a value greater than <0>] unordered "
+        "Actual: [1, 2] "
+        "Which: has too many elements (2 > 1)");
+    shouldFail(d, unorderedMatches([3, 2, 1]),
+        "Expected: matches [<3>, <2>, <1>] unordered "
+        "Actual: [1, 2] "
+        "Which: has too few elements (2 < 3)");
+    shouldFail(d, unorderedMatches([3, 1]),
+        "Expected: matches [<3>, <1>] unordered "
+        "Actual: [1, 2] "
+        "Which: has no match for <3> at index 0");
+    shouldFail(d, unorderedMatches([greaterThan(3), greaterThan(0)]),
+        "Expected: matches [a value greater than <3>, a value greater than "
+            "<0>] unordered "
+        "Actual: [1, 2] "
+        "Which: has no match for a value greater than <3> at index 0");
+  });
+
+  test('pairwise compare', () {
+    var c = [1, 2];
+    var d = [1, 2, 3];
+    var e = [1, 4, 9];
+    shouldFail('x', pairwiseCompare(e, (e,a) => a <= e,
+        "less than or equal"),
+        "Expected: pairwise less than or equal [1, 4, 9] "
+        "Actual: 'x' "
+        "Which: is not an Iterable");
+    shouldFail(c, pairwiseCompare(e, (e,a) => a <= e, "less than or equal"),
+        "Expected: pairwise less than or equal [1, 4, 9] "
+        "Actual: [1, 2] "
+        "Which: has length 2 instead of 3");
+    shouldPass(d, pairwiseCompare(e, (e,a) => a <= e, "less than or equal"));
+    shouldFail(d, pairwiseCompare(e, (e,a) => a < e, "less than"),
+        "Expected: pairwise less than [1, 4, 9] "
+        "Actual: [1, 2, 3] "
+        "Which: has <1> which is not less than <1> at index 0");
+    shouldPass(d, pairwiseCompare(e, (e,a) => a * a == e, "square root of"));
+    shouldFail(d, pairwiseCompare(e, (e,a) => a + a == e, "double"),
+        "Expected: pairwise double [1, 4, 9] "
+        "Actual: [1, 2, 3] "
+        "Which: has <1> which is not double <1> at index 0");
+  });
+}
diff --git a/test/matchers_test.dart b/test/matchers_test.dart
deleted file mode 100644
index e74d048..0000000
--- a/test/matchers_test.dart
+++ /dev/null
@@ -1,803 +0,0 @@
-// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library matcher.test;
-
-import 'dart:async';
-import 'dart:collection';
-
-import 'package:matcher/matcher.dart';
-import 'package:unittest/unittest.dart' show test, group;
-
-import 'test_utils.dart';
-
-void main() {
-
-  initUtils();
-
-  // Core matchers
-
-  group('Core matchers', () {
-
-    test('isTrue', () {
-      shouldPass(true, isTrue);
-      shouldFail(false, isTrue, "Expected: true Actual: <false>");
-    });
-
-    test('isFalse', () {
-      shouldPass(false, isFalse);
-      shouldFail(10, isFalse, "Expected: false Actual: <10>");
-      shouldFail(true, isFalse, "Expected: false Actual: <true>");
-    });
-
-    test('isNull', () {
-      shouldPass(null, isNull);
-      shouldFail(false, isNull, "Expected: null Actual: <false>");
-    });
-
-    test('isNotNull', () {
-      shouldPass(false, isNotNull);
-      shouldFail(null, isNotNull, "Expected: not null Actual: <null>");
-    });
-
-    test('same', () {
-      var a = new Map();
-      var b = new Map();
-      shouldPass(a, same(a));
-      shouldFail(b, same(a), "Expected: same instance as {} Actual: {}");
-    });
-
-    test('equals', () {
-      var a = new Map();
-      var b = new Map();
-      shouldPass(a, equals(a));
-      shouldPass(a, equals(b));
-    });
-
-    test('anything', () {
-      var a = new Map();
-      shouldPass(0, anything);
-      shouldPass(null, anything);
-      shouldPass(a, anything);
-      shouldFail(a, isNot(anything), "Expected: not anything Actual: {}");
-    });
-
-    test('throws', () {
-      shouldFail(doesNotThrow, throws,
-          matches(
-              r"Expected: throws"
-              r"  Actual: <Closure(: \(\) => dynamic "
-              r"from Function 'doesNotThrow': static\.)?>"
-              r"   Which: did not throw"));
-      shouldPass(doesThrow, throws);
-      shouldFail(true, throws,
-          "Expected: throws"
-          "  Actual: <true>"
-          "   Which: is not a Function or Future");
-    });
-
-    test('throwsA', () {
-      shouldPass(doesThrow, throwsA(equals('X')));
-      shouldFail(doesThrow, throwsA(equals('Y')),
-          matches(
-              r"Expected: throws 'Y'"
-              r"  Actual: <Closure(: \(\) => dynamic "
-              r"from Function 'doesThrow': static\.)?>"
-              r"   Which: threw 'X'"));
-    });
-
-    test('returnsNormally', () {
-      shouldPass(doesNotThrow, returnsNormally);
-      shouldFail(doesThrow, returnsNormally,
-          matches(
-              r"Expected: return normally"
-              r"  Actual: <Closure(: \(\) => dynamic "
-              r"from Function 'doesThrow': static\.)?>"
-              r"   Which: threw 'X'"));
-    });
-
-
-    test('hasLength', () {
-      var a = new Map();
-      var b = new List();
-      shouldPass(a, hasLength(0));
-      shouldPass(b, hasLength(0));
-      shouldPass('a', hasLength(1));
-      shouldFail(0, hasLength(0), new PrefixMatcher(
-          "Expected: an object with length of <0> "
-          "Actual: <0> "
-          "Which: has no length property"));
-
-      b.add(0);
-      shouldPass(b, hasLength(1));
-      shouldFail(b, hasLength(2),
-          "Expected: an object with length of <2> "
-          "Actual: [0] "
-          "Which: has length of <1>");
-
-      b.add(0);
-      shouldFail(b, hasLength(1),
-          "Expected: an object with length of <1> "
-          "Actual: [0, 0] "
-          "Which: has length of <2>");
-      shouldPass(b, hasLength(2));
-    });
-
-    test('scalar type mismatch', () {
-      shouldFail('error', equals(5.1),
-          "Expected: <5.1> "
-          "Actual: 'error'");
-    });
-
-    test('nested type mismatch', () {
-      shouldFail(['error'], equals([5.1]),
-          "Expected: [5.1] "
-          "Actual: ['error'] "
-          "Which: was 'error' instead of <5.1> at location [0]");
-    });
-
-    test('doubly-nested type mismatch', () {
-      shouldFail([['error']], equals([[5.1]]),
-          "Expected: [[5.1]] "
-          "Actual: [['error']] "
-          "Which: was 'error' instead of <5.1> at location [0][0]");
-    });
-
-    test('doubly nested inequality', () {
-      var actual1 = [['foo', 'bar'], ['foo'], 3, []];
-      var expected1 = [['foo', 'bar'], ['foo'], 4, []];
-      var reason1 = "Expected: [['foo', 'bar'], ['foo'], 4, []] "
-          "Actual: [['foo', 'bar'], ['foo'], 3, []] "
-          "Which: was <3> instead of <4> at location [2]";
-
-      var actual2 = [['foo', 'barry'], ['foo'], 4, []];
-      var expected2 = [['foo', 'bar'], ['foo'], 4, []];
-      var reason2 = "Expected: [['foo', 'bar'], ['foo'], 4, []] "
-          "Actual: [['foo', 'barry'], ['foo'], 4, []] "
-          "Which: was 'barry' instead of 'bar' at location [0][1]";
-
-      var actual3 = [['foo', 'bar'], ['foo'], 4, {'foo':'bar'}];
-      var expected3 = [['foo', 'bar'], ['foo'], 4, {'foo':'barry'}];
-      var reason3 = "Expected: [['foo', 'bar'], ['foo'], 4, {'foo': 'barry'}] "
-          "Actual: [['foo', 'bar'], ['foo'], 4, {'foo': 'bar'}] "
-          "Which: was 'bar' instead of 'barry' at location [3]['foo']";
-
-      shouldFail(actual1, equals(expected1), reason1);
-      shouldFail(actual2, equals(expected2), reason2);
-      shouldFail(actual3, equals(expected3), reason3);
-    });
-  });
-
-  group('Numeric Matchers', () {
-
-    test('greaterThan', () {
-      shouldPass(10, greaterThan(9));
-      shouldFail(9, greaterThan(10),
-        "Expected: a value greater than <10> "
-        "Actual: <9> "
-        "Which: is not a value greater than <10>");
-    });
-
-    test('greaterThanOrEqualTo', () {
-      shouldPass(10, greaterThanOrEqualTo(10));
-      shouldFail(9, greaterThanOrEqualTo(10),
-        "Expected: a value greater than or equal to <10> "
-        "Actual: <9> "
-        "Which: is not a value greater than or equal to <10>");
-    });
-
-    test('lessThan', () {
-      shouldFail(10, lessThan(9),
-          "Expected: a value less than <9> "
-          "Actual: <10> "
-          "Which: is not a value less than <9>");
-      shouldPass(9, lessThan(10));
-    });
-
-    test('lessThanOrEqualTo', () {
-      shouldPass(10, lessThanOrEqualTo(10));
-      shouldFail(11, lessThanOrEqualTo(10),
-        "Expected: a value less than or equal to <10> "
-        "Actual: <11> "
-        "Which: is not a value less than or equal to <10>");
-    });
-
-    test('isZero', () {
-      shouldPass(0, isZero);
-      shouldFail(1, isZero,
-          "Expected: a value equal to <0> "
-          "Actual: <1> "
-          "Which: is not a value equal to <0>");
-    });
-
-    test('isNonZero', () {
-      shouldFail(0, isNonZero,
-          "Expected: a value not equal to <0> "
-          "Actual: <0> "
-          "Which: is not a value not equal to <0>");
-      shouldPass(1, isNonZero);
-    });
-
-    test('isPositive', () {
-      shouldFail(-1, isPositive,
-          "Expected: a positive value "
-          "Actual: <-1> "
-          "Which: is not a positive value");
-      shouldFail(0, isPositive,
-          "Expected: a positive value "
-          "Actual: <0> "
-          "Which: is not a positive value");
-      shouldPass(1, isPositive);
-    });
-
-    test('isNegative', () {
-      shouldPass(-1, isNegative);
-      shouldFail(0, isNegative,
-          "Expected: a negative value "
-          "Actual: <0> "
-          "Which: is not a negative value");
-    });
-
-    test('isNonPositive', () {
-      shouldPass(-1, isNonPositive);
-      shouldPass(0, isNonPositive);
-      shouldFail(1, isNonPositive,
-          "Expected: a non-positive value "
-          "Actual: <1> "
-          "Which: is not a non-positive value");
-    });
-
-    test('isNonNegative', () {
-      shouldPass(1, isNonNegative);
-      shouldPass(0, isNonNegative);
-      shouldFail(-1, isNonNegative,
-        "Expected: a non-negative value "
-        "Actual: <-1> "
-        "Which: is not a non-negative value");
-    });
-
-    test('closeTo', () {
-      shouldPass(0, closeTo(0, 1));
-      shouldPass(-1, closeTo(0, 1));
-      shouldPass(1, closeTo(0, 1));
-      shouldFail(1.001, closeTo(0, 1),
-          "Expected: a numeric value within <1> of <0> "
-          "Actual: <1.001> "
-          "Which: differs by <1.001>");
-      shouldFail(-1.001, closeTo(0, 1),
-          "Expected: a numeric value within <1> of <0> "
-          "Actual: <-1.001> "
-          "Which: differs by <1.001>");
-    });
-
-    test('inInclusiveRange', () {
-      shouldFail(-1, inInclusiveRange(0,2),
-          "Expected: be in range from 0 (inclusive) to 2 (inclusive) "
-          "Actual: <-1>");
-      shouldPass(0, inInclusiveRange(0,2));
-      shouldPass(1, inInclusiveRange(0,2));
-      shouldPass(2, inInclusiveRange(0,2));
-      shouldFail(3, inInclusiveRange(0,2),
-          "Expected: be in range from 0 (inclusive) to 2 (inclusive) "
-          "Actual: <3>");
-    });
-
-    test('inExclusiveRange', () {
-      shouldFail(0, inExclusiveRange(0,2),
-          "Expected: be in range from 0 (exclusive) to 2 (exclusive) "
-          "Actual: <0>");
-      shouldPass(1, inExclusiveRange(0,2));
-      shouldFail(2, inExclusiveRange(0,2),
-          "Expected: be in range from 0 (exclusive) to 2 (exclusive) "
-          "Actual: <2>");
-    });
-
-    test('inOpenClosedRange', () {
-      shouldFail(0, inOpenClosedRange(0,2),
-          "Expected: be in range from 0 (exclusive) to 2 (inclusive) "
-          "Actual: <0>");
-      shouldPass(1, inOpenClosedRange(0,2));
-      shouldPass(2, inOpenClosedRange(0,2));
-    });
-
-    test('inClosedOpenRange', () {
-      shouldPass(0, inClosedOpenRange(0,2));
-      shouldPass(1, inClosedOpenRange(0,2));
-      shouldFail(2, inClosedOpenRange(0,2),
-          "Expected: be in range from 0 (inclusive) to 2 (exclusive) "
-          "Actual: <2>");
-    });
-  });
-
-  group('String Matchers', () {
-
-    test('isEmpty', () {
-      shouldPass('', isEmpty);
-      shouldFail(null, isEmpty,
-          "Expected: empty Actual: <null>");
-      shouldFail(0, isEmpty,
-          "Expected: empty Actual: <0>");
-      shouldFail('a', isEmpty, "Expected: empty Actual: 'a'");
-    });
-
-    test('equalsIgnoringCase', () {
-      shouldPass('hello', equalsIgnoringCase('HELLO'));
-      shouldFail('hi', equalsIgnoringCase('HELLO'),
-          "Expected: 'HELLO' ignoring case Actual: 'hi'");
-    });
-
-    test('equalsIgnoringWhitespace', () {
-      shouldPass(' hello   world  ', equalsIgnoringWhitespace('hello world'));
-      shouldFail(' helloworld  ', equalsIgnoringWhitespace('hello world'),
-          "Expected: 'hello world' ignoring whitespace "
-          "Actual: ' helloworld ' "
-          "Which: is 'helloworld' with whitespace compressed");
-    });
-
-    test('startsWith', () {
-      shouldPass('hello', startsWith(''));
-      shouldPass('hello', startsWith('hell'));
-      shouldPass('hello', startsWith('hello'));
-      shouldFail('hello', startsWith('hello '),
-          "Expected: a string starting with 'hello ' "
-          "Actual: 'hello'");
-    });
-
-    test('endsWith', () {
-      shouldPass('hello', endsWith(''));
-      shouldPass('hello', endsWith('lo'));
-      shouldPass('hello', endsWith('hello'));
-      shouldFail('hello', endsWith(' hello'),
-          "Expected: a string ending with ' hello' "
-          "Actual: 'hello'");
-    });
-
-    test('contains', () {
-      shouldPass('hello', contains(''));
-      shouldPass('hello', contains('h'));
-      shouldPass('hello', contains('o'));
-      shouldPass('hello', contains('hell'));
-      shouldPass('hello', contains('hello'));
-      shouldFail('hello', contains(' '),
-          "Expected: contains ' ' Actual: 'hello'");
-    });
-
-    test('stringContainsInOrder', () {
-      shouldPass('goodbye cruel world', stringContainsInOrder(['']));
-      shouldPass('goodbye cruel world', stringContainsInOrder(['goodbye']));
-      shouldPass('goodbye cruel world', stringContainsInOrder(['cruel']));
-      shouldPass('goodbye cruel world', stringContainsInOrder(['world']));
-      shouldPass('goodbye cruel world',
-                 stringContainsInOrder(['good', 'bye', 'world']));
-      shouldPass('goodbye cruel world',
-                 stringContainsInOrder(['goodbye', 'cruel']));
-      shouldPass('goodbye cruel world',
-                 stringContainsInOrder(['cruel', 'world']));
-      shouldPass('goodbye cruel world',
-        stringContainsInOrder(['goodbye', 'cruel', 'world']));
-      shouldFail('goodbye cruel world',
-        stringContainsInOrder(['goo', 'cruel', 'bye']),
-        "Expected: a string containing 'goo', 'cruel', 'bye' in order "
-        "Actual: 'goodbye cruel world'");
-    });
-
-    test('matches', () {
-      shouldPass('c0d', matches('[a-z][0-9][a-z]'));
-      shouldPass('c0d', matches(new RegExp('[a-z][0-9][a-z]')));
-      shouldFail('cOd', matches('[a-z][0-9][a-z]'),
-          "Expected: match '[a-z][0-9][a-z]' Actual: 'cOd'");
-    });
-  });
-
-  group('Iterable Matchers', () {
-
-    test('isEmpty', () {
-      shouldPass([], isEmpty);
-      shouldFail([1], isEmpty, "Expected: empty Actual: [1]");
-    });
-
-    test('contains', () {
-      var d = [1, 2];
-      shouldPass(d, contains(1));
-      shouldFail(d, contains(0), "Expected: contains <0> "
-          "Actual: [1, 2]");
-    });
-
-    test('equals with matcher element', () {
-      var d = ['foo', 'bar'];
-      shouldPass(d, equals(['foo', startsWith('ba')]));
-      shouldFail(d, equals(['foo', endsWith('ba')]),
-          "Expected: ['foo', <a string ending with 'ba'>] "
-          "Actual: ['foo', 'bar'] "
-          "Which: does not match a string ending with 'ba' at location [1]");
-    });
-
-    test('isIn', () {
-      var d = [1, 2];
-      shouldPass(1, isIn(d));
-      shouldFail(0, isIn(d), "Expected: is in [1, 2] Actual: <0>");
-    });
-
-    test('everyElement', () {
-      var d = [1, 2];
-      var e = [1, 1, 1];
-      shouldFail(d, everyElement(1),
-          "Expected: every element(<1>) "
-          "Actual: [1, 2] "
-          "Which: has value <2> which doesn't match <1> at index 1");
-      shouldPass(e, everyElement(1));
-    });
-
-    test('nested everyElement', () {
-      var d = [['foo', 'bar'], ['foo'], []];
-      var e = [['foo', 'bar'], ['foo'], 3, []];
-      shouldPass(d, everyElement(anyOf(isEmpty, contains('foo'))));
-      shouldFail(d, everyElement(everyElement(equals('foo'))),
-          "Expected: every element(every element('foo')) "
-          "Actual: [['foo', 'bar'], ['foo'], []] "
-          "Which: has value ['foo', 'bar'] which has value 'bar' "
-          "which is different. Expected: foo Actual: bar ^ "
-          "Differ at offset 0 at index 1 at index 0");
-      shouldFail(d, everyElement(allOf(hasLength(greaterThan(0)),
-          contains('foo'))),
-           "Expected: every element((an object with length of a value "
-           "greater than <0> and contains 'foo')) "
-           "Actual: [['foo', 'bar'], ['foo'], []] "
-           "Which: has value [] which has length of <0> at index 2");
-      shouldFail(d, everyElement(allOf(contains('foo'),
-          hasLength(greaterThan(0)))),
-          "Expected: every element((contains 'foo' and "
-          "an object with length of a value greater than <0>)) "
-          "Actual: [['foo', 'bar'], ['foo'], []] "
-          "Which: has value [] which doesn't match (contains 'foo' and "
-          "an object with length of a value greater than <0>) at index 2");
-      shouldFail(e, everyElement(allOf(contains('foo'),
-          hasLength(greaterThan(0)))),
-          "Expected: every element((contains 'foo' and an object with "
-          "length of a value greater than <0>)) "
-          "Actual: [['foo', 'bar'], ['foo'], 3, []] "
-          "Which: has value <3> which is not a string, map or iterable "
-          "at index 2");
-    });
-
-    test('anyElement', () {
-      var d = [1, 2];
-      var e = [1, 1, 1];
-      shouldPass(d, anyElement(2));
-      shouldFail(e, anyElement(2),
-          "Expected: some element <2> Actual: [1, 1, 1]");
-    });
-
-    test('orderedEquals', () {
-      shouldPass([null], orderedEquals([null]));
-      var d = [1, 2];
-      shouldPass(d, orderedEquals([1, 2]));
-      shouldFail(d, orderedEquals([2, 1]),
-          "Expected: equals [2, 1] ordered "
-          "Actual: [1, 2] "
-          "Which: was <1> instead of <2> at location [0]");
-    });
-
-    test('unorderedEquals', () {
-      var d = [1, 2];
-      shouldPass(d, unorderedEquals([2, 1]));
-      shouldFail(d, unorderedEquals([1]),
-          "Expected: equals [1] unordered "
-          "Actual: [1, 2] "
-          "Which: has too many elements (2 > 1)");
-      shouldFail(d, unorderedEquals([3, 2, 1]),
-          "Expected: equals [3, 2, 1] unordered "
-          "Actual: [1, 2] "
-          "Which: has too few elements (2 < 3)");
-      shouldFail(d, unorderedEquals([3, 1]),
-          "Expected: equals [3, 1] unordered "
-          "Actual: [1, 2] "
-          "Which: has no match for <3> at index 0");
-    });
-
-    test('unorderedMatchess', () {
-      var d = [1, 2];
-      shouldPass(d, unorderedMatches([2, 1]));
-      shouldPass(d, unorderedMatches([greaterThan(1), greaterThan(0)]));
-      shouldFail(d, unorderedMatches([greaterThan(0)]),
-          "Expected: matches [a value greater than <0>] unordered "
-          "Actual: [1, 2] "
-          "Which: has too many elements (2 > 1)");
-      shouldFail(d, unorderedMatches([3, 2, 1]),
-          "Expected: matches [<3>, <2>, <1>] unordered "
-          "Actual: [1, 2] "
-          "Which: has too few elements (2 < 3)");
-      shouldFail(d, unorderedMatches([3, 1]),
-          "Expected: matches [<3>, <1>] unordered "
-          "Actual: [1, 2] "
-          "Which: has no match for <3> at index 0");
-      shouldFail(d, unorderedMatches([greaterThan(3), greaterThan(0)]),
-          "Expected: matches [a value greater than <3>, a value greater than "
-              "<0>] unordered "
-          "Actual: [1, 2] "
-          "Which: has no match for a value greater than <3> at index 0");
-    });
-
-    test('pairwise compare', () {
-      var c = [1, 2];
-      var d = [1, 2, 3];
-      var e = [1, 4, 9];
-      shouldFail('x', pairwiseCompare(e, (e,a) => a <= e,
-          "less than or equal"),
-          "Expected: pairwise less than or equal [1, 4, 9] "
-          "Actual: 'x' "
-          "Which: is not an Iterable");
-      shouldFail(c, pairwiseCompare(e, (e,a) => a <= e, "less than or equal"),
-          "Expected: pairwise less than or equal [1, 4, 9] "
-          "Actual: [1, 2] "
-          "Which: has length 2 instead of 3");
-      shouldPass(d, pairwiseCompare(e, (e,a) => a <= e, "less than or equal"));
-      shouldFail(d, pairwiseCompare(e, (e,a) => a < e, "less than"),
-          "Expected: pairwise less than [1, 4, 9] "
-          "Actual: [1, 2, 3] "
-          "Which: has <1> which is not less than <1> at index 0");
-      shouldPass(d, pairwiseCompare(e, (e,a) => a * a == e, "square root of"));
-      shouldFail(d, pairwiseCompare(e, (e,a) => a + a == e, "double"),
-          "Expected: pairwise double [1, 4, 9] "
-          "Actual: [1, 2, 3] "
-          "Which: has <1> which is not double <1> at index 0");
-    });
-  });
-
-  group('Map Matchers', () {
-
-    test('isEmpty', () {
-      var a = new Map();
-      shouldPass({}, isEmpty);
-      shouldPass(a, isEmpty);
-      a['foo'] = 'bar';
-      shouldFail(a, isEmpty, "Expected: empty "
-          "Actual: {'foo': 'bar'}");
-    });
-
-    test('equals', () {
-      var a = new Map();
-      a['foo'] = 'bar';
-      var b = new Map();
-      b['foo'] = 'bar';
-      var c = new Map();
-      c['bar'] = 'foo';
-      shouldPass(a, equals(b));
-      shouldFail(b, equals(c),
-          "Expected: {'bar': 'foo'} "
-          "Actual: {'foo': 'bar'} "
-          "Which: is missing map key 'bar'");
-    });
-
-    test('equals with different lengths', () {
-      var a = new LinkedHashMap();
-      a['foo'] = 'bar';
-      var b = new LinkedHashMap();
-      b['foo'] = 'bar';
-      b['bar'] = 'foo';
-      var c = new LinkedHashMap();
-      c['bar'] = 'foo';
-      c['barrista'] = 'caffeine';
-      shouldFail(a, equals(b),
-          "Expected: {'foo': 'bar', 'bar': 'foo'} "
-          "Actual: {'foo': 'bar'} "
-          "Which: has different length and is missing map key 'bar'");
-      shouldFail(b, equals(a),
-          "Expected: {'foo': 'bar'} "
-          "Actual: {'foo': 'bar', 'bar': 'foo'} "
-          "Which: has different length and has extra map key 'bar'");
-      shouldFail(b, equals(c),
-          "Expected: {'bar': 'foo', 'barrista': 'caffeine'} "
-          "Actual: {'foo': 'bar', 'bar': 'foo'} "
-          "Which: is missing map key 'barrista'");
-      shouldFail(c, equals(b),
-          "Expected: {'foo': 'bar', 'bar': 'foo'} "
-          "Actual: {'bar': 'foo', 'barrista': 'caffeine'} "
-          "Which: is missing map key 'foo'");
-      shouldFail(a, equals(c),
-          "Expected: {'bar': 'foo', 'barrista': 'caffeine'} "
-          "Actual: {'foo': 'bar'} "
-          "Which: has different length and is missing map key 'bar'");
-      shouldFail(c, equals(a),
-          "Expected: {'foo': 'bar'} "
-          "Actual: {'bar': 'foo', 'barrista': 'caffeine'} "
-          "Which: has different length and is missing map key 'foo'");
-    });
-
-    test('equals with matcher value', () {
-      var a = new Map();
-      a['foo'] = 'bar';
-      shouldPass(a, equals({'foo': startsWith('ba')}));
-      shouldFail(a, equals({'foo': endsWith('ba')}),
-          "Expected: {'foo': <a string ending with 'ba'>} "
-          "Actual: {'foo': 'bar'} "
-          "Which: does not match a string ending with 'ba' "
-              "at location ['foo']");
-    });
-
-    test('contains', () {
-      var a = new Map();
-      a['foo'] = 'bar';
-      var b = new Map();
-      shouldPass(a, contains('foo'));
-      shouldFail(b, contains('foo'),
-          "Expected: contains 'foo' Actual: {}");
-      shouldFail(10, contains('foo'),
-          "Expected: contains 'foo' Actual: <10> "
-          "Which: is not a string, map or iterable");
-    });
-
-    test('containsValue', () {
-      var a = new Map();
-      a['foo'] = 'bar';
-      shouldPass(a, containsValue('bar'));
-      shouldFail(a, containsValue('ba'),
-          "Expected: contains value 'ba' "
-          "Actual: {'foo': 'bar'}");
-    });
-
-    test('containsPair', () {
-      var a = new Map();
-      a['foo'] = 'bar';
-      shouldPass(a, containsPair('foo', 'bar'));
-      shouldFail(a, containsPair('foo', 'ba'),
-          "Expected: contains pair 'foo' => 'ba' "
-          "Actual: {'foo': 'bar'} "
-          "Which: is different. Both strings start the same, but "
-          "the given value also has the following trailing characters: r");
-      shouldFail(a, containsPair('fo', 'bar'),
-          "Expected: contains pair 'fo' => 'bar' "
-          "Actual: {'foo': 'bar'} "
-          "Which: doesn't contain key 'fo'");
-    });
-
-    test('hasLength', () {
-      var a = new Map();
-      a['foo'] = 'bar';
-      var b = new Map();
-      shouldPass(a, hasLength(1));
-      shouldFail(b, hasLength(1),
-          "Expected: an object with length of <1> "
-          "Actual: {} "
-          "Which: has length of <0>");
-    });
-  });
-
-  group('Operator Matchers', () {
-
-    test('anyOf', () {
-      shouldFail(0, anyOf([equals(1), equals(2)]),
-          "Expected: (<1> or <2>) Actual: <0>");
-      shouldPass(1, anyOf([equals(1), equals(2)]));
-    });
-
-    test('allOf', () {
-      shouldPass(1, allOf([lessThan(10), greaterThan(0)]));
-      shouldFail(-1, allOf([lessThan(10), greaterThan(0)]),
-          "Expected: (a value less than <10> and a value greater than <0>) "
-          "Actual: <-1> "
-          "Which: is not a value greater than <0>");
-    });
-  });
-
-  group('Future Matchers', () {
-
-    test('completes - unexpected error', () {
-      var completer = new Completer();
-      completer.completeError('X');
-      shouldFail(completer.future, completes,
-          contains('Expected future to complete successfully, '
-                   'but it failed with X'),
-          isAsync: true);
-    });
-
-    test('completes - successfully', () {
-      var completer = new Completer();
-      completer.complete('1');
-      shouldPass(completer.future, completes, isAsync: true);
-    });
-
-    test('throws - unexpected to see normal completion', () {
-      var completer = new Completer();
-      completer.complete('1');
-      shouldFail(completer.future, throws,
-        contains("Expected future to fail, but succeeded with '1'"),
-        isAsync: true);
-    });
-
-    test('throws - expected to see exception', () {
-      var completer = new Completer();
-      completer.completeError('X');
-      shouldPass(completer.future, throws, isAsync: true);
-    });
-
-    test('throws - expected to see exception thrown later on', () {
-      var completer = new Completer();
-      var chained = completer.future.then((_) { throw 'X'; });
-      shouldPass(chained, throws, isAsync: true);
-      completer.complete('1');
-    });
-
-    test('throwsA - unexpected normal completion', () {
-      var completer = new Completer();
-      completer.complete('1');
-      shouldFail(completer.future, throwsA(equals('X')),
-        contains("Expected future to fail, but succeeded with '1'"),
-        isAsync: true);
-    });
-
-    test('throwsA - correct error', () {
-      var completer = new Completer();
-      completer.completeError('X');
-      shouldPass(completer.future, throwsA(equals('X')), isAsync: true);
-    });
-
-    test('throwsA - wrong error', () {
-      var completer = new Completer();
-      completer.completeError('X');
-      shouldFail(completer.future, throwsA(equals('Y')),
-          "Expected: 'Y' Actual: 'X' "
-          "Which: is different. "
-          "Expected: Y Actual: X ^ Differ at offset 0",
-          isAsync: true);
-    });
-  });
-
-  group('Predicate Matchers', () {
-    test('isInstanceOf', () {
-      shouldFail(0, predicate((x) => x is String, "an instance of String"),
-          "Expected: an instance of String Actual: <0>");
-      shouldPass('cow', predicate((x) => x is String, "an instance of String"));
-    });
-  });
-
-  group('exception/error matchers', () {
-    // TODO(gram): extend this to more types; for now this is just
-    // the types being added in this CL.
-
-    test('throwsCyclicInitializationError', () {
-      expect(() => _Bicycle.foo, throwsCyclicInitializationError);
-    });
-
-    test('throwsAbstractClassInstantiationError', () {
-      expect(() => new _AbstractClass(), throwsAbstractClassInstantiationError);
-    });
-
-    test('throwsConcurrentModificationError', () {
-      expect(() {
-        var a = { 'foo': 'bar' };
-        for (var k in a.keys) {
-          a.remove(k);
-        }
-      }, throwsConcurrentModificationError);
-      });
-
-    test('throwsNullThrownError', () {
-      expect(() => throw null, throwsNullThrownError);
-    });
-
-    test('throwsFallThroughError', () {
-      expect(() {
-        var a = 0;
-        switch (a) {
-          case 0:
-            a += 1;
-          case 1:
-            return;
-        }
-      }, throwsFallThroughError);
-    });
-  });
-}
-
-class _Bicycle {
-  static final foo = bar();
-
-  static bar() {
-    return foo + 1;
-  }
-}
-
-abstract class _AbstractClass {
-}
diff --git a/test/numeric_matchers_test.dart b/test/numeric_matchers_test.dart
new file mode 100644
index 0000000..60347bd
--- /dev/null
+++ b/test/numeric_matchers_test.dart
@@ -0,0 +1,152 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library matcher.numeric_matchers_test;
+
+import 'package:matcher/matcher.dart';
+import 'package:unittest/unittest.dart' show test, group;
+
+import 'test_utils.dart';
+
+void main() {
+  initUtils();
+
+  test('greaterThan', () {
+    shouldPass(10, greaterThan(9));
+    shouldFail(9, greaterThan(10),
+      "Expected: a value greater than <10> "
+      "Actual: <9> "
+      "Which: is not a value greater than <10>");
+  });
+
+  test('greaterThanOrEqualTo', () {
+    shouldPass(10, greaterThanOrEqualTo(10));
+    shouldFail(9, greaterThanOrEqualTo(10),
+      "Expected: a value greater than or equal to <10> "
+      "Actual: <9> "
+      "Which: is not a value greater than or equal to <10>");
+  });
+
+  test('lessThan', () {
+    shouldFail(10, lessThan(9),
+        "Expected: a value less than <9> "
+        "Actual: <10> "
+        "Which: is not a value less than <9>");
+    shouldPass(9, lessThan(10));
+  });
+
+  test('lessThanOrEqualTo', () {
+    shouldPass(10, lessThanOrEqualTo(10));
+    shouldFail(11, lessThanOrEqualTo(10),
+      "Expected: a value less than or equal to <10> "
+      "Actual: <11> "
+      "Which: is not a value less than or equal to <10>");
+  });
+
+  test('isZero', () {
+    shouldPass(0, isZero);
+    shouldFail(1, isZero,
+        "Expected: a value equal to <0> "
+        "Actual: <1> "
+        "Which: is not a value equal to <0>");
+  });
+
+  test('isNonZero', () {
+    shouldFail(0, isNonZero,
+        "Expected: a value not equal to <0> "
+        "Actual: <0> "
+        "Which: is not a value not equal to <0>");
+    shouldPass(1, isNonZero);
+  });
+
+  test('isPositive', () {
+    shouldFail(-1, isPositive,
+        "Expected: a positive value "
+        "Actual: <-1> "
+        "Which: is not a positive value");
+    shouldFail(0, isPositive,
+        "Expected: a positive value "
+        "Actual: <0> "
+        "Which: is not a positive value");
+    shouldPass(1, isPositive);
+  });
+
+  test('isNegative', () {
+    shouldPass(-1, isNegative);
+    shouldFail(0, isNegative,
+        "Expected: a negative value "
+        "Actual: <0> "
+        "Which: is not a negative value");
+  });
+
+  test('isNonPositive', () {
+    shouldPass(-1, isNonPositive);
+    shouldPass(0, isNonPositive);
+    shouldFail(1, isNonPositive,
+        "Expected: a non-positive value "
+        "Actual: <1> "
+        "Which: is not a non-positive value");
+  });
+
+  test('isNonNegative', () {
+    shouldPass(1, isNonNegative);
+    shouldPass(0, isNonNegative);
+    shouldFail(-1, isNonNegative,
+      "Expected: a non-negative value "
+      "Actual: <-1> "
+      "Which: is not a non-negative value");
+  });
+
+  test('closeTo', () {
+    shouldPass(0, closeTo(0, 1));
+    shouldPass(-1, closeTo(0, 1));
+    shouldPass(1, closeTo(0, 1));
+    shouldFail(1.001, closeTo(0, 1),
+        "Expected: a numeric value within <1> of <0> "
+        "Actual: <1.001> "
+        "Which: differs by <1.001>");
+    shouldFail(-1.001, closeTo(0, 1),
+        "Expected: a numeric value within <1> of <0> "
+        "Actual: <-1.001> "
+        "Which: differs by <1.001>");
+  });
+
+  test('inInclusiveRange', () {
+    shouldFail(-1, inInclusiveRange(0,2),
+        "Expected: be in range from 0 (inclusive) to 2 (inclusive) "
+        "Actual: <-1>");
+    shouldPass(0, inInclusiveRange(0,2));
+    shouldPass(1, inInclusiveRange(0,2));
+    shouldPass(2, inInclusiveRange(0,2));
+    shouldFail(3, inInclusiveRange(0,2),
+        "Expected: be in range from 0 (inclusive) to 2 (inclusive) "
+        "Actual: <3>");
+  });
+
+  test('inExclusiveRange', () {
+    shouldFail(0, inExclusiveRange(0,2),
+        "Expected: be in range from 0 (exclusive) to 2 (exclusive) "
+        "Actual: <0>");
+    shouldPass(1, inExclusiveRange(0,2));
+    shouldFail(2, inExclusiveRange(0,2),
+        "Expected: be in range from 0 (exclusive) to 2 (exclusive) "
+        "Actual: <2>");
+  });
+
+  test('inOpenClosedRange', () {
+    shouldFail(0, inOpenClosedRange(0,2),
+        "Expected: be in range from 0 (exclusive) to 2 (inclusive) "
+        "Actual: <0>");
+    shouldPass(1, inOpenClosedRange(0,2));
+    shouldPass(2, inOpenClosedRange(0,2));
+  });
+
+  test('inClosedOpenRange', () {
+    shouldPass(0, inClosedOpenRange(0,2));
+    shouldPass(1, inClosedOpenRange(0,2));
+    shouldFail(2, inClosedOpenRange(0,2),
+        "Expected: be in range from 0 (inclusive) to 2 (exclusive) "
+        "Actual: <2>");
+  });
+}
diff --git a/test/operator_matchers_test.dart b/test/operator_matchers_test.dart
new file mode 100644
index 0000000..fd9627a
--- /dev/null
+++ b/test/operator_matchers_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library matcher.operator_matchers_test;
+
+import 'package:matcher/matcher.dart';
+import 'package:unittest/unittest.dart' show test, group;
+
+import 'test_utils.dart';
+
+void main() {
+  initUtils();
+
+  test('anyOf', () {
+    shouldFail(0, anyOf([equals(1), equals(2)]),
+        "Expected: (<1> or <2>) Actual: <0>");
+    shouldPass(1, anyOf([equals(1), equals(2)]));
+  });
+
+  test('allOf', () {
+    shouldPass(1, allOf([lessThan(10), greaterThan(0)]));
+    shouldFail(-1, allOf([lessThan(10), greaterThan(0)]),
+        "Expected: (a value less than <10> and a value greater than <0>) "
+        "Actual: <-1> "
+        "Which: is not a value greater than <0>");
+  });
+}
diff --git a/test/string_matchers_test.dart b/test/string_matchers_test.dart
new file mode 100644
index 0000000..1303641
--- /dev/null
+++ b/test/string_matchers_test.dart
@@ -0,0 +1,94 @@
+// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library matcher.string_matchers_test;
+
+import 'package:matcher/matcher.dart';
+import 'package:unittest/unittest.dart' show test, group;
+
+import 'test_utils.dart';
+
+void main() {
+  initUtils();
+
+  test('collapseWhitespace', () {
+    var source = '\t\r\n hello\t\r\n world\r\t \n';
+    expect(collapseWhitespace(source), 'hello world');
+  });
+
+  test('isEmpty', () {
+    shouldPass('', isEmpty);
+    shouldFail(null, isEmpty, "Expected: empty Actual: <null>");
+    shouldFail(0, isEmpty, "Expected: empty Actual: <0>");
+    shouldFail('a', isEmpty, "Expected: empty Actual: 'a'");
+  });
+
+  test('equalsIgnoringCase', () {
+    shouldPass('hello', equalsIgnoringCase('HELLO'));
+    shouldFail('hi', equalsIgnoringCase('HELLO'),
+        "Expected: 'HELLO' ignoring case Actual: 'hi'");
+  });
+
+  test('equalsIgnoringWhitespace', () {
+    shouldPass(' hello   world  ', equalsIgnoringWhitespace('hello world'));
+    shouldFail(' helloworld  ', equalsIgnoringWhitespace('hello world'),
+        "Expected: 'hello world' ignoring whitespace "
+        "Actual: ' helloworld ' "
+        "Which: is 'helloworld' with whitespace compressed");
+  });
+
+  test('startsWith', () {
+    shouldPass('hello', startsWith(''));
+    shouldPass('hello', startsWith('hell'));
+    shouldPass('hello', startsWith('hello'));
+    shouldFail('hello', startsWith('hello '),
+        "Expected: a string starting with 'hello ' "
+        "Actual: 'hello'");
+  });
+
+  test('endsWith', () {
+    shouldPass('hello', endsWith(''));
+    shouldPass('hello', endsWith('lo'));
+    shouldPass('hello', endsWith('hello'));
+    shouldFail('hello', endsWith(' hello'),
+        "Expected: a string ending with ' hello' "
+        "Actual: 'hello'");
+  });
+
+  test('contains', () {
+    shouldPass('hello', contains(''));
+    shouldPass('hello', contains('h'));
+    shouldPass('hello', contains('o'));
+    shouldPass('hello', contains('hell'));
+    shouldPass('hello', contains('hello'));
+    shouldFail('hello', contains(' '),
+        "Expected: contains ' ' Actual: 'hello'");
+  });
+
+  test('stringContainsInOrder', () {
+    shouldPass('goodbye cruel world', stringContainsInOrder(['']));
+    shouldPass('goodbye cruel world', stringContainsInOrder(['goodbye']));
+    shouldPass('goodbye cruel world', stringContainsInOrder(['cruel']));
+    shouldPass('goodbye cruel world', stringContainsInOrder(['world']));
+    shouldPass('goodbye cruel world',
+               stringContainsInOrder(['good', 'bye', 'world']));
+    shouldPass('goodbye cruel world',
+               stringContainsInOrder(['goodbye', 'cruel']));
+    shouldPass('goodbye cruel world',
+               stringContainsInOrder(['cruel', 'world']));
+    shouldPass('goodbye cruel world',
+      stringContainsInOrder(['goodbye', 'cruel', 'world']));
+    shouldFail('goodbye cruel world',
+      stringContainsInOrder(['goo', 'cruel', 'bye']),
+      "Expected: a string containing 'goo', 'cruel', 'bye' in order "
+      "Actual: 'goodbye cruel world'");
+  });
+
+  test('matches', () {
+    shouldPass('c0d', matches('[a-z][0-9][a-z]'));
+    shouldPass('c0d', matches(new RegExp('[a-z][0-9][a-z]')));
+    shouldFail('cOd', matches('[a-z][0-9][a-z]'),
+        "Expected: match '[a-z][0-9][a-z]' Actual: 'cOd'");
+  });
+}
diff --git a/test/test_common.dart b/test/test_common.dart
index 562786d..93f45f3 100644
--- a/test/test_common.dart
+++ b/test/test_common.dart
@@ -13,13 +13,13 @@
 }
 
 class HasPrice extends CustomMatcher {
-  HasPrice(matcher) :
-    super("Widget with a price that is", "price", matcher);
+  HasPrice(matcher) : super("Widget with a price that is", "price", matcher);
   featureValueOf(actual) => actual.price;
 }
 
-class SimpleIterable extends IterableBase {
-  int count;
+class SimpleIterable extends IterableBase<int> {
+  final int count;
+
   SimpleIterable(this.count);
 
   bool contains(int val) => count < val ? false : true;
@@ -34,15 +34,15 @@
   String toString() => "<[$count]>";
 
   Iterator get iterator {
-    return new SimpleIterator(count);
+    return new _SimpleIterator(count);
   }
 }
 
-class SimpleIterator implements Iterator {
+class _SimpleIterator implements Iterator<int> {
   int _count;
   int _current;
 
-  SimpleIterator(this._count);
+  _SimpleIterator(this._count);
 
   bool moveNext() {
     if (_count > 0) {
@@ -54,6 +54,6 @@
     return false;
   }
 
-  get current => _current;
+  int get current => _current;
 }