Add isNotEmpty to core_matchers.

BUG=https://code.google.com/p/dart/issues/detail?id=21562
R=nweiz@google.com

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

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart/pkg/matcher@42119 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8e7bd6f..4689c31 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 0.11.2
+
+* Add an `isNotEmpty` matcher.
+
 ## 0.11.1+1
 
 * Refactored libraries and tests.
diff --git a/lib/src/core_matchers.dart b/lib/src/core_matchers.dart
index c3c996d..c2c1e84 100644
--- a/lib/src/core_matchers.dart
+++ b/lib/src/core_matchers.dart
@@ -9,23 +9,32 @@
 import 'util.dart';
 
 /// Returns a matcher that matches empty strings, maps or iterables
-/// (including collections).
+/// (including collections) using the isEmpty property.
 const Matcher isEmpty = const _Empty();
 
 class _Empty extends Matcher {
   const _Empty();
   bool matches(item, Map matchState) {
-    if (item is Map || item is Iterable) {
-      return item.isEmpty;
-    } else if (item is String) {
-      return item.length == 0;
-    } else {
-      return false;
-    }
+    return (item is Map || item is Iterable || item is String) && item.isEmpty;
   }
   Description describe(Description description) => description.add('empty');
 }
 
+/// Returns a matcher that matches non-empty strings, maps or iterables
+/// (including collections) using the isNotEmpty property.
+const Matcher isNotEmpty = const _NotEmpty();
+
+class _NotEmpty extends Matcher {
+  const _NotEmpty();
+
+  bool matches(item, Map matchState) {
+    return (item is Map || item is Iterable || item is String) &&
+      item.isNotEmpty;
+  }
+
+  Description describe(Description description) => description.add('non-empty');
+}
+
 /// A matcher that matches any null value.
 const Matcher isNull = const _IsNull();
 
diff --git a/pubspec.yaml b/pubspec.yaml
index c6cb49d..230ddc3 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: matcher
-version: 0.11.1+1
+version: 0.11.2
 author: Dart Team <misc@dartlang.org>
 description: Support for specifying test expectations
 homepage: https://pub.dartlang.org/packages/matcher
diff --git a/test/core_matchers_test.dart b/test/core_matchers_test.dart
index 99d10ac..be9758e 100644
--- a/test/core_matchers_test.dart
+++ b/test/core_matchers_test.dart
@@ -93,7 +93,6 @@
             r"   Which: threw 'X'"));
   });
 
-
   test('hasLength', () {
     var a = new Map();
     var b = new List();
diff --git a/test/iterable_matchers_test.dart b/test/iterable_matchers_test.dart
index 4570d52..91d5335 100644
--- a/test/iterable_matchers_test.dart
+++ b/test/iterable_matchers_test.dart
@@ -17,6 +17,11 @@
     shouldFail([1], isEmpty, "Expected: empty Actual: [1]");
   });
 
+  test('isNotEmpty', () {
+    shouldFail([], isNotEmpty, "Expected: non-empty Actual: []");
+    shouldPass([1], isNotEmpty);
+  });
+
   test('contains', () {
     var d = [1, 2];
     shouldPass(d, contains(1));
diff --git a/test/matchers_minified_test.dart b/test/matchers_minified_test.dart
index 65a35ac..4b39d42 100644
--- a/test/matchers_minified_test.dart
+++ b/test/matchers_minified_test.dart
@@ -109,6 +109,14 @@
           matches(r"Expected: empty +Actual: " + _MINIFIED_NAME + r":\[1\]"));
     });
 
+    test('isNotEmpty', () {
+      var d = new SimpleIterable(0);
+      var e = new SimpleIterable(1);
+      shouldPass(e, isNotEmpty);
+      shouldFail(d, isNotEmpty,
+          matches(r"Expected: non-empty +Actual: " + _MINIFIED_NAME + r":\[\]"));
+    });
+
     test('contains', () {
       var d = new SimpleIterable(3);
       shouldPass(d, contains(2));
diff --git a/test/matchers_unminified_test.dart b/test/matchers_unminified_test.dart
index 28d97ab..6947884 100644
--- a/test/matchers_unminified_test.dart
+++ b/test/matchers_unminified_test.dart
@@ -108,6 +108,15 @@
           "Actual: SimpleIterable:[1]");
     });
 
+    test('isNotEmpty', () {
+      var d = new SimpleIterable(0);
+      var e = new SimpleIterable(1);
+      shouldPass(e, isNotEmpty);
+      shouldFail(d, isNotEmpty, "Expected: non-empty "
+          "Actual: SimpleIterable:[]");
+    });
+
+
     test('contains', () {
       var d = new SimpleIterable(3);
       shouldPass(d, contains(2));
diff --git a/test/string_matchers_test.dart b/test/string_matchers_test.dart
index 1303641..ba96713 100644
--- a/test/string_matchers_test.dart
+++ b/test/string_matchers_test.dart
@@ -24,6 +24,13 @@
     shouldFail('a', isEmpty, "Expected: empty Actual: 'a'");
   });
 
+  test('isNotEmpty', () {
+    shouldFail('', isNotEmpty, "Expected: non-empty Actual: ''");
+    shouldFail(null, isNotEmpty, "Expected: non-empty Actual: <null>");
+    shouldFail(0, isNotEmpty, "Expected: non-empty Actual: <0>");
+    shouldPass('a', isNotEmpty);
+  });
+
   test('equalsIgnoringCase', () {
     shouldPass('hello', equalsIgnoringCase('HELLO'));
     shouldFail('hi', equalsIgnoringCase('HELLO'),