Update with implementation from 'analyzer'.

R=brianwilkerson@google.com
BUG=

Review URL: https://codereview.chromium.org/2300503003 .
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a2d63c..da6f2f7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # Changelog
 
+## 0.0.4
+
+- Added @failingTest, @assertFailingTest and @soloTest annotations.
+
 ## 0.0.1
 
 - Initial version
diff --git a/codereview.settings b/codereview.settings
new file mode 100644
index 0000000..3ba713c
--- /dev/null
+++ b/codereview.settings
@@ -0,0 +1,4 @@
+# This file is used by gcl to get repository specific information.
+CODE_REVIEW_SERVER: http://codereview.chromium.org
+VIEW_VC: https://github.com/dart-lang/test_reflective_loader/commit/
+CC_LIST: reviews@dartlang.org
diff --git a/lib/test_reflective_loader.dart b/lib/test_reflective_loader.dart
index f8387e3..6e3c945 100644
--- a/lib/test_reflective_loader.dart
+++ b/lib/test_reflective_loader.dart
@@ -4,14 +4,50 @@
 
 library test_reflective_loader;
 
+import 'dart:async';
 @MirrorsUsed(metaTargets: 'ReflectiveTest')
 import 'dart:mirrors';
-import 'dart:async';
 
 import 'package:unittest/unittest.dart';
 
 /**
- * Define tests using methods existing in the given [type].
+ * A marker annotation used to annotate overridden test methods (so we cannot
+ * rename them to `fail_`) which are expected to fail at `assert` in the
+ * checked mode.
+ */
+const _AssertFailingTest assertFailingTest = const _AssertFailingTest();
+
+/**
+ * A marker annotation used to annotate overridden test methods (so we cannot
+ * rename them to `fail_`) which are expected to fail.
+ */
+const _FailingTest failingTest = const _FailingTest();
+
+/**
+ * A marker annotation used to instruct dart2js to keep reflection information
+ * for the annotated classes.
+ */
+const ReflectiveTest reflectiveTest = const ReflectiveTest();
+
+/**
+ * Test classes annotated with this annotation are run using [solo_group].
+ */
+const _SoloTest soloTest = const _SoloTest();
+
+/**
+ * Is `true` the application is running in the checked mode.
+ */
+final bool _isCheckedMode = () {
+  try {
+    assert(false);
+    return false;
+  } catch (_) {
+    return true;
+  }
+}();
+
+/**
+ * Runs test methods existing in the given [type].
  *
  * Methods with names starting with `test` are run using [test] function.
  * Methods with names starting with `solo_test` are run using [solo_test] function.
@@ -23,20 +59,20 @@
  * method invocation.
  *
  * If [type] declares method `tearDown`, it will be invoked after any test
- * method invocation. If method returns [Future] to test some asyncronous
+ * method invocation. If method returns [Future] to test some asynchronous
  * behavior, then `tearDown` will be invoked in `Future.complete`.
  */
 void defineReflectiveTests(Type type) {
   ClassMirror classMirror = reflectClass(type);
   if (!classMirror.metadata.any((InstanceMirror annotation) =>
-      annotation.type.reflectedType == ReflectiveTest)) {
+  annotation.type.reflectedType == ReflectiveTest)) {
     String name = MirrorSystem.getName(classMirror.qualifiedName);
     throw new Exception('Class $name must have annotation "@reflectiveTest" '
         'in order to be run by runReflectiveTests.');
   }
-  String className = MirrorSystem.getName(classMirror.simpleName);
-  group(className, () {
-    classMirror.instanceMembers.forEach((symbol, memberMirror) {
+  void runMembers() {
+    classMirror.instanceMembers
+        .forEach((Symbol symbol, MethodMirror memberMirror) {
       // we need only methods
       if (memberMirror is! MethodMirror || !memberMirror.isRegularMethod) {
         return;
@@ -45,7 +81,12 @@
       // test_
       if (memberName.startsWith('test_')) {
         test(memberName, () {
-          return _runTest(classMirror, symbol);
+          if (_hasFailingTestAnnotation(memberMirror) ||
+              _isCheckedMode && _hasAssertFailingTestAnnotation(memberMirror)) {
+            return _runFailingTest(classMirror, symbol);
+          } else {
+            return _runTest(classMirror, symbol);
+          }
         });
         return;
       }
@@ -68,19 +109,36 @@
         });
       }
     });
-  });
+  }
+  String className = MirrorSystem.getName(classMirror.simpleName);
+  if (_hasAnnotationInstance(classMirror, soloTest)) {
+    solo_group(className, runMembers);
+  } else {
+    group(className, runMembers);
+  }
 }
 
+bool _hasAnnotationInstance(DeclarationMirror declaration, instance) =>
+    declaration.metadata.any((InstanceMirror annotation) =>
+        identical(annotation.reflectee, instance));
+
+bool _hasAssertFailingTestAnnotation(MethodMirror method) =>
+    _hasAnnotationInstance(method, assertFailingTest);
+
+bool _hasFailingTestAnnotation(MethodMirror method) =>
+    _hasAnnotationInstance(method, failingTest);
+
 Future _invokeSymbolIfExists(InstanceMirror instanceMirror, Symbol symbol) {
   var invocationResult = null;
+  InstanceMirror closure;
   try {
-    invocationResult = instanceMirror.invoke(symbol, []).reflectee;
+    closure = instanceMirror.getField(symbol);
   } on NoSuchMethodError {}
-  if (invocationResult is Future) {
-    return invocationResult;
-  } else {
-    return new Future.value(invocationResult);
+
+  if (closure is ClosureMirror) {
+    invocationResult = closure.apply([]).reflectee;
   }
+  return new Future.value(invocationResult);
 }
 
 /**
@@ -115,7 +173,26 @@
 }
 
 /**
- * A marker annotation used to instruct dart2js to keep reflection information
- * for the annotated classes.
+ * A marker annotation used to annotate overridden test methods (so we cannot
+ * rename them to `fail_`) which are expected to fail at `assert` in the
+ * checked mode.
  */
-const ReflectiveTest reflectiveTest = const ReflectiveTest();
+class _AssertFailingTest {
+  const _AssertFailingTest();
+}
+
+/**
+ * A marker annotation used to annotate overridden test methods (so we cannot
+ * rename them to `fail_`) which are expected to fail.
+ */
+class _FailingTest {
+  const _FailingTest();
+}
+
+/**
+ * A marker annotation used to annotate a test class to run it using
+ * [solo_group].
+ */
+class _SoloTest {
+  const _SoloTest();
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 60d4ec8..8b93c1e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: test_reflective_loader
-version: 0.0.3
+version: 0.0.4
 description: Support for discovering tests and test suites using reflection.
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/test_reflective_loader