cleanup: enable and fix a number of lints (#85)

diff --git a/analysis_options.yaml b/analysis_options.yaml
index a10d4c5..a7a7298 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,2 +1,78 @@
 analyzer:
   strong-mode: true
+  errors:
+    dead_code: error
+    override_on_non_overriding_method: error
+    unused_element: error
+    unused_import: error
+    unused_local_variable: error
+linter:
+  rules:
+    - always_declare_return_types
+    #- annotate_overrides
+    - avoid_empty_else
+    - avoid_function_literals_in_foreach_calls
+    - avoid_init_to_null
+    - avoid_null_checks_in_equality_operators
+    - avoid_renaming_method_parameters
+    - avoid_return_types_on_setters
+    - avoid_returning_null
+    - avoid_types_as_parameter_names
+    - avoid_unused_constructor_parameters
+    - await_only_futures
+    - camel_case_types
+    - cancel_subscriptions
+    #- cascade_invocations
+    - comment_references
+    - constant_identifier_names
+    - control_flow_in_finally
+    - directives_ordering
+    - empty_catches
+    - empty_constructor_bodies
+    - empty_statements
+    - hash_and_equals
+    - implementation_imports
+    - invariant_booleans
+    - iterable_contains_unrelated_type
+    - library_names
+    - library_prefixes
+    - list_remove_unrelated_type
+    - literal_only_boolean_expressions
+    - no_adjacent_strings_in_list
+    - no_duplicate_case_values
+    - non_constant_identifier_names
+    - omit_local_variable_types
+    - only_throw_errors
+    - overridden_fields
+    #- package_api_docs
+    - package_names
+    - package_prefixed_library_names
+    - prefer_adjacent_string_concatenation
+    - prefer_collection_literals
+    - prefer_conditional_assignment
+    - prefer_const_constructors
+    - prefer_contains
+    - prefer_equal_for_default_values
+    - prefer_final_fields
+    - prefer_initializing_formals
+    #- prefer_interpolation_to_compose_strings
+    - prefer_is_empty
+    - prefer_is_not_empty
+    #- prefer_single_quotes
+    - prefer_typing_uninitialized_variables
+    - recursive_getters
+    - slash_for_doc_comments
+    - super_goes_last
+    - test_types_in_equals
+    - throw_in_finally
+    - type_init_formals
+    - unawaited_futures
+    - unnecessary_brace_in_string_interps
+    - unnecessary_getters_setters
+    - unnecessary_lambdas
+    - unnecessary_null_aware_assignments
+    - unnecessary_statements
+    - unnecessary_this
+    - unrelated_type_equality_checks
+    - use_rethrow_when_possible
+    - valid_regexps
diff --git a/lib/mirror_matchers.dart b/lib/mirror_matchers.dart
index 0ce90da..eb2225a 100644
--- a/lib/mirror_matchers.dart
+++ b/lib/mirror_matchers.dart
@@ -29,8 +29,8 @@
       addStateInfo(matchState, {'reason': 'has no property named "$_name"'});
       return false;
     }
-    bool isInstanceField = candidate is VariableMirror && !candidate.isStatic;
-    bool isInstanceGetter =
+    var isInstanceField = candidate is VariableMirror && !candidate.isStatic;
+    var isInstanceGetter =
         candidate is MethodMirror && candidate.isGetter && !candidate.isStatic;
     if (!(isInstanceField || isInstanceGetter)) {
       addStateInfo(matchState, {
@@ -60,14 +60,14 @@
       item, Description mismatchDescription, Map matchState, bool verbose) {
     var reason = matchState == null ? null : matchState['reason'];
     if (reason != null) {
-      mismatchDescription.add(reason);
+      mismatchDescription.add(reason as String);
     } else {
       mismatchDescription
           .add('has property "$_name" with value ')
           .addDescriptionOf(matchState['value']);
       var innerDescription = new StringDescription();
-      _matcher.describeMismatch(
-          matchState['value'], innerDescription, matchState['state'], verbose);
+      _matcher.describeMismatch(matchState['value'], innerDescription,
+          matchState['state'] as Map, verbose);
       if (innerDescription.length > 0) {
         mismatchDescription.add(' which ').add(innerDescription.toString());
       }
diff --git a/lib/src/core_matchers.dart b/lib/src/core_matchers.dart
index 6ab3f62..681f206 100644
--- a/lib/src/core_matchers.dart
+++ b/lib/src/core_matchers.dart
@@ -86,7 +86,7 @@
 Matcher same(expected) => new _IsSameAs(expected);
 
 class _IsSameAs extends Matcher {
-  final _expected;
+  final Object _expected;
   const _IsSameAs(this._expected);
   bool matches(item, Map matchState) => identical(item, _expected);
   // If all types were hashable we could show a hash here.
@@ -113,10 +113,11 @@
 /// 'Foo', we would write:
 ///
 ///     expect(bar, new isInstanceOf<Foo>());
+// ignore: camel_case_types
 class isInstanceOf<T> extends Matcher {
   const isInstanceOf();
 
-  bool matches(obj, Map matchState) => obj is T;
+  bool matches(item, Map matchState) => item is T;
 
   Description describe(Description description) =>
       description.add('an instance of $T');
@@ -195,7 +196,7 @@
 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;
 }
 
@@ -205,7 +206,7 @@
 
 class _HasLength extends Matcher {
   final Matcher _matcher;
-  const _HasLength([Matcher matcher = null]) : this._matcher = matcher;
+  const _HasLength([Matcher matcher]) : this._matcher = matcher;
 
   bool matches(item, Map matchState) {
     try {
@@ -214,8 +215,10 @@
       if (item.length * item.length >= 0) {
         return _matcher.matches(item.length, matchState);
       }
-    } catch (e) {}
-    return false;
+    } catch (e) {
+      return false;
+    }
+    throw new UnsupportedError('Should never get here');
   }
 
   Description describe(Description description) =>
@@ -231,8 +234,10 @@
             .add('has length of ')
             .addDescriptionOf(item.length);
       }
-    } catch (e) {}
-    return mismatchDescription.add('has no length property');
+    } catch (e) {
+      return mismatchDescription.add('has no length property');
+    }
+    throw new UnsupportedError('Should never get here');
   }
 }
 
@@ -246,16 +251,16 @@
 Matcher contains(expected) => new _Contains(expected);
 
 class _Contains extends Matcher {
-  final _expected;
+  final Object _expected;
 
   const _Contains(this._expected);
 
   bool matches(item, Map matchState) {
     if (item is String) {
-      return item.indexOf(_expected) >= 0;
+      return item.contains((_expected as Pattern));
     } else if (item is Iterable) {
       if (_expected is Matcher) {
-        return item.any((e) => _expected.matches(e, matchState));
+        return item.any((e) => (_expected as Matcher).matches(e, matchState));
       } else {
         return item.contains(_expected);
       }
@@ -284,17 +289,18 @@
 Matcher isIn(expected) => new _In(expected);
 
 class _In extends Matcher {
-  final _expected;
+  final Object _expected;
 
   const _In(this._expected);
 
   bool matches(item, Map matchState) {
-    if (_expected is String) {
-      return _expected.indexOf(item) >= 0;
-    } else if (_expected is Iterable) {
-      return _expected.any((e) => e == item);
-    } else if (_expected is Map) {
-      return _expected.containsKey(item);
+    var expected = _expected;
+    if (expected is String) {
+      return expected.contains(item as Pattern);
+    } else if (expected is Iterable) {
+      return expected.contains(item);
+    } else if (expected is Map) {
+      return expected.containsKey(item);
     }
     return false;
   }
diff --git a/lib/src/custom_matcher.dart b/lib/src/custom_matcher.dart
index 82b0e01..862d133 100644
--- a/lib/src/custom_matcher.dart
+++ b/lib/src/custom_matcher.dart
@@ -39,7 +39,7 @@
       : this._matcher = wrapMatcher(matcher);
 
   /// Override this to extract the interesting feature.
-  featureValueOf(actual) => actual;
+  Object featureValueOf(actual) => actual;
 
   bool matches(item, Map matchState) {
     try {
@@ -84,7 +84,7 @@
     var innerDescription = new StringDescription();
 
     _matcher.describeMismatch(matchState['custom.feature'], innerDescription,
-        matchState['state'], verbose);
+        matchState['state'] as Map, verbose);
 
     if (innerDescription.length > 0) {
       mismatchDescription.add(' which ').add(innerDescription.toString());
diff --git a/lib/src/equals_matcher.dart b/lib/src/equals_matcher.dart
index 255141b..28aee51 100644
--- a/lib/src/equals_matcher.dart
+++ b/lib/src/equals_matcher.dart
@@ -16,7 +16,7 @@
 /// handle cyclic structures a recursion depth [limit] can be provided. The
 /// default limit is 100. [Set]s will be compared order-independently.
 Matcher equals(expected, [int limit = 100]) => expected is String
-    ? new _StringEqualsMatcher(expected)
+    ? new _StringEqualsMatcher(expected) as Matcher
     : new _DeepMatcher(expected, limit);
 
 typedef _RecursiveMatcher = List<String> Function(
@@ -44,7 +44,7 @@
       buff.write('is different.');
       var escapedItem = escape(item);
       var escapedValue = escape(_value);
-      int minLength = escapedItem.length < escapedValue.length
+      var minLength = escapedItem.length < escapedValue.length
           ? escapedItem.length
           : escapedValue.length;
       var start = 0;
@@ -71,7 +71,7 @@
         _writeLeading(buff, escapedItem, start);
         _writeTrailing(buff, escapedItem, start);
         buff.write('\n          ');
-        for (int i = (start > 10 ? 14 : start); i > 0; i--) buff.write(' ');
+        for (var i = (start > 10 ? 14 : start); i > 0; i--) buff.write(' ');
         buff.write('^\n Differ at offset $start');
       }
 
@@ -99,7 +99,7 @@
 }
 
 class _DeepMatcher extends Matcher {
-  final _expected;
+  final Object _expected;
   final int _limit;
 
   _DeepMatcher(this._expected, [int limit = 1000]) : this._limit = limit;
@@ -136,7 +136,7 @@
   List<String> _compareSets(Set expected, Object actual,
       _RecursiveMatcher matcher, int depth, String location) {
     if (actual is Iterable) {
-      Set other = actual.toSet();
+      var other = actual.toSet();
 
       for (var expectedElement in expected) {
         if (other.every((actualElement) =>
@@ -235,8 +235,8 @@
     var rp = _recursiveMatch(expected, actual, '', 0);
     if (rp == null) return null;
     String reason;
-    if (rp[0].length > 0) {
-      if (rp[1].length > 0) {
+    if (rp[0].isNotEmpty) {
+      if (rp[1].isNotEmpty) {
         reason = "${rp[0]} at location ${rp[1]}";
       } else {
         reason = rp[0];
@@ -257,12 +257,12 @@
 
   Description describeMismatch(
       item, Description mismatchDescription, Map matchState, bool verbose) {
-    var reason = matchState['reason'] ?? '';
+    var reason = matchState['reason'] as String ?? '';
     // If we didn't get a good reason, that would normally be a
     // simple 'is <value>' message. We only add that if the mismatch
     // description is non empty (so we are supplementing the mismatch
     // description).
-    if (reason.length == 0 && mismatchDescription.length > 0) {
+    if (reason.isEmpty && mismatchDescription.length > 0) {
       mismatchDescription.add('is ').addDescriptionOf(item);
     } else {
       mismatchDescription.add(reason);
diff --git a/lib/src/interfaces.dart b/lib/src/interfaces.dart
index 6ab0f14..0ef8248 100644
--- a/lib/src/interfaces.dart
+++ b/lib/src/interfaces.dart
@@ -27,8 +27,6 @@
   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])
diff --git a/lib/src/iterable_matchers.dart b/lib/src/iterable_matchers.dart
index 8d57e5c..f13525d 100644
--- a/lib/src/iterable_matchers.dart
+++ b/lib/src/iterable_matchers.dart
@@ -2,8 +2,8 @@
 // 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.
 
-import 'equals_matcher.dart';
 import 'description.dart';
+import 'equals_matcher.dart';
 import 'interfaces.dart';
 import 'util.dart';
 
@@ -45,7 +45,7 @@
           .add(' which ');
       var subDescription = new StringDescription();
       _matcher.describeMismatch(
-          element, subDescription, matchState['state'], verbose);
+          element, subDescription, matchState['state'] as Map, verbose);
       if (subDescription.length > 0) {
         mismatchDescription.add(subDescription.toString());
       } else {
@@ -159,10 +159,13 @@
         _allowUnmatchedValues = allowUnmatchedValues ?? false;
 
   String _test(item) {
-    if (item is! Iterable) return 'not iterable';
+    if (item is Iterable) {
+      return _testCore(item.toList());
+    }
+    return 'not iterable';
+  }
 
-    var values = item.toList();
-
+  String _testCore(List values) {
     // Check the lengths are the same.
     if (_expected.length > values.length) {
       return 'has too few elements (${values.length} < ${_expected.length})';
@@ -172,8 +175,8 @@
 
     var edges =
         new List.generate(values.length, (_) => <int>[], growable: false);
-    for (int v = 0; v < values.length; v++) {
-      for (int m = 0; m < _expected.length; m++) {
+    for (var v = 0; v < values.length; v++) {
+      for (var m = 0; m < _expected.length; m++) {
         if (_expected[m].matches(values[v], {})) {
           edges[v].add(m);
         }
@@ -182,10 +185,10 @@
     // The index into `values` matched with each matcher or `null` if no value
     // has been matched yet.
     var matched = new List<int>(_expected.length);
-    for (int valueIndex = 0; valueIndex < values.length; valueIndex++) {
+    for (var valueIndex = 0; valueIndex < values.length; valueIndex++) {
       _findPairing(edges, valueIndex, matched);
     }
-    for (int matcherIndex = 0;
+    for (var matcherIndex = 0;
         matcherIndex < _expected.length;
         matcherIndex++) {
       if (matched[matcherIndex] == null) {
@@ -216,10 +219,10 @@
           Map matchState, bool verbose) =>
       mismatchDescription.add(_test(item));
 
-  /// Returns [true] if the value at [valueIndex] can be paired with some
+  /// Returns `true` if the value at [valueIndex] can be paired with some
   /// unmatched matcher and updates the state of [matched].
   ///
-  /// If there is a conflic where multiple values may match the same matcher
+  /// If there is a conflict where multiple values may match the same matcher
   /// recursively looks for a new place to match the old value. [reserved]
   /// tracks the matchers that have been used _during_ this search.
   bool _findPairing(List<List<int>> edges, int valueIndex, List<int> matched,
diff --git a/lib/src/map_matchers.dart b/lib/src/map_matchers.dart
index 47cddef..9825c9b 100644
--- a/lib/src/map_matchers.dart
+++ b/lib/src/map_matchers.dart
@@ -9,7 +9,7 @@
 Matcher containsValue(value) => new _ContainsValue(value);
 
 class _ContainsValue extends Matcher {
-  final _value;
+  final Object _value;
 
   const _ContainsValue(this._value);
 
@@ -24,7 +24,7 @@
     new _ContainsMapping(key, wrapMatcher(value));
 
 class _ContainsMapping extends Matcher {
-  final _key;
+  final Object _key;
   final Matcher _valueMatcher;
 
   const _ContainsMapping(this._key, this._valueMatcher);
diff --git a/lib/src/operator_matchers.dart b/lib/src/operator_matchers.dart
index 5d6baed..827fbf1 100644
--- a/lib/src/operator_matchers.dart
+++ b/lib/src/operator_matchers.dart
@@ -106,5 +106,5 @@
     args = [arg0, arg1, arg2, arg3, arg4, arg5, arg6].where((e) => e != null);
   }
 
-  return args.map((e) => wrapMatcher(e)).toList();
+  return args.map(wrapMatcher).toList();
 }
diff --git a/lib/src/order_matchers.dart b/lib/src/order_matchers.dart
index b6079e9..829aadb 100644
--- a/lib/src/order_matchers.dart
+++ b/lib/src/order_matchers.dart
@@ -52,7 +52,7 @@
 // `==` and `<` operators to evaluate the match. Or change the matcher.
 class _OrderingMatcher extends Matcher {
   /// Expected value.
-  final _value;
+  final Object _value;
 
   /// What to return if actual == expected
   final bool _equalValue;
diff --git a/lib/src/string_matchers.dart b/lib/src/string_matchers.dart
index 14e6fbb..d82e830 100644
--- a/lib/src/string_matchers.dart
+++ b/lib/src/string_matchers.dart
@@ -119,10 +119,10 @@
 
   bool matches(item, Map matchState) {
     if (item is String) {
-      var from_index = 0;
+      var fromIndex = 0;
       for (var s in _substrings) {
-        from_index = item.indexOf(s, from_index);
-        if (from_index < 0) return false;
+        fromIndex = item.indexOf(s, fromIndex);
+        if (fromIndex < 0) return false;
       }
       return true;
     } else {
diff --git a/lib/src/util.dart b/lib/src/util.dart
index 38e6b73..1df39ef 100644
--- a/lib/src/util.dart
+++ b/lib/src/util.dart
@@ -45,6 +45,7 @@
   } else if (x is _Predicate<Null>) {
     // x is a unary predicate, but expects a specific type
     // so wrap it.
+    // ignore: unnecessary_lambdas
     return predicate((a) => (x as dynamic)(a));
   } else {
     return equals(x);
@@ -66,6 +67,6 @@
 
 /// Given single-character string, return the hex-escaped equivalent.
 String _getHexLiteral(String input) {
-  int rune = input.runes.single;
+  var rune = input.runes.single;
   return r'\x' + rune.toRadixString(16).toUpperCase().padLeft(2, '0');
 }
diff --git a/test/core_matchers_test.dart b/test/core_matchers_test.dart
index 15723ec..033002f 100644
--- a/test/core_matchers_test.dart
+++ b/test/core_matchers_test.dart
@@ -40,15 +40,15 @@
   });
 
   test('same', () {
-    var a = new Map();
-    var b = new Map();
+    var a = {};
+    var b = {};
     shouldPass(a, same(a));
     shouldFail(b, same(a), "Expected: same instance as {} Actual: {}");
   });
 
   test('equals', () {
-    var a = new Map();
-    var b = new Map();
+    var a = {};
+    var b = {};
     shouldPass(a, equals(a));
     shouldPass(a, equals(b));
   });
@@ -76,7 +76,7 @@
   });
 
   test('anything', () {
-    var a = new Map();
+    var a = {};
     shouldPass(0, anything);
     shouldPass(null, anything);
     shouldPass(a, anything);
@@ -90,12 +90,12 @@
         returnsNormally,
         matches(r"Expected: return normally"
             r"  Actual: <Closure.*>"
-            r"   Which: threw 'X'"));
+            r"   Which: threw StateError:<Bad state: X>"));
   });
 
   test('hasLength', () {
-    var a = new Map();
-    var b = new List();
+    var a = {};
+    var b = [];
     shouldPass(a, hasLength(0));
     shouldPass(b, hasLength(0));
     shouldPass('a', hasLength(1));
@@ -210,9 +210,9 @@
   });
 
   test('isInstanceOf', () {
-    shouldFail(0, new isInstanceOf<String>(),
+    shouldFail(0, const isInstanceOf<String>(),
         "Expected: an instance of String Actual: <0>");
-    shouldPass('cow', new isInstanceOf<String>());
+    shouldPass('cow', const isInstanceOf<String>());
   });
 
   group('Predicate Matchers', () {
diff --git a/test/custom_matcher_test.dart b/test/custom_matcher_test.dart
index 3ff4813..53f035b 100644
--- a/test/custom_matcher_test.dart
+++ b/test/custom_matcher_test.dart
@@ -9,12 +9,12 @@
 
 class _BadCustomMatcher extends CustomMatcher {
   _BadCustomMatcher() : super("feature", "description", {1: "a"});
-  featureValueOf(actual) => throw new Exception("bang");
+  Object featureValueOf(actual) => throw new Exception("bang");
 }
 
 class _HasPrice extends CustomMatcher {
   _HasPrice(matcher) : super("Widget with a price that is", "price", matcher);
-  featureValueOf(actual) => actual.price;
+  Object featureValueOf(actual) => actual.price;
 }
 
 void main() {
diff --git a/test/iterable_matchers_test.dart b/test/iterable_matchers_test.dart
index e8a8df8..dcd4049 100644
--- a/test/iterable_matchers_test.dart
+++ b/test/iterable_matchers_test.dart
@@ -266,20 +266,21 @@
     var e = [1, 4, 9];
     shouldFail(
         'x',
-        pairwiseCompare(e, (e, a) => a <= e, "less than or equal"),
+        pairwiseCompare(e, (int e, int 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"),
+        pairwiseCompare(e, (int e, int 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"));
+    shouldPass(
+        d, pairwiseCompare(e, (int e, int a) => a <= e, "less than or equal"));
     shouldFail(
         d,
-        pairwiseCompare(e, (e, a) => a < e, "less than"),
+        pairwiseCompare(e, (int e, int 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");
diff --git a/test/mirror_matchers_test.dart b/test/mirror_matchers_test.dart
index bbd80a1..e9f88b4 100644
--- a/test/mirror_matchers_test.dart
+++ b/test/mirror_matchers_test.dart
@@ -11,9 +11,9 @@
 
 class C {
   var instanceField = 1;
-  get instanceGetter => 2;
+  int get instanceGetter => 2;
   static var staticField = 3;
-  static get staticGetter => 4;
+  static int get staticGetter => 4;
 }
 
 void main() {
diff --git a/test/test_utils.dart b/test/test_utils.dart
index 574d257..ab52cd2 100644
--- a/test/test_utils.dart
+++ b/test/test_utils.dart
@@ -27,9 +27,9 @@
   expect(value, matcher);
 }
 
-doesNotThrow() {}
-doesThrow() {
-  throw 'X';
+void doesNotThrow() {}
+void doesThrow() {
+  throw new StateError('X');
 }
 
 class Widget {