Enable and fix standard lints, test on oldest supported SDK (#20)

diff --git a/.travis.yml b/.travis.yml
index 0e7bde8..e8ffe6d 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -2,16 +2,15 @@
 
 dart:
   - dev
-  - stable
+  - 2.0.0
 
 dart_task:
   - test: --platform vm
   - test: --platform chrome
-  - dartanalyzer
-  - dartfmt
+  - dartanalyzer: --fatal-warnings --fatal-infos .
 
 matrix:
-  exclude:
+  include:
     - dart: dev
       dart_task: dartfmt
 
diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..0711aca
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,43 @@
+include: package:pedantic/analysis_options.yaml
+analyzer:
+  strong-mode:
+    implicit-casts: false
+linter:
+  rules:
+    - avoid_empty_else
+    - avoid_init_to_null
+    - avoid_null_checks_in_equality_operators
+    - avoid_unused_constructor_parameters
+    - await_only_futures
+    - camel_case_types
+    - cancel_subscriptions
+    - constant_identifier_names
+    - control_flow_in_finally
+    - directives_ordering
+    - empty_catches
+    - empty_constructor_bodies
+    - empty_statements
+    - hash_and_equals
+    - implementation_imports
+    - iterable_contains_unrelated_type
+    - library_names
+    - library_prefixes
+    - list_remove_unrelated_type
+    - non_constant_identifier_names
+    - overridden_fields
+    - package_api_docs
+    - package_names
+    - package_prefixed_library_names
+    - prefer_equal_for_default_values
+    - prefer_final_fields
+    - prefer_generic_function_type_aliases
+    - prefer_is_not_empty
+    - slash_for_doc_comments
+    - test_types_in_equals
+    - throw_in_finally
+    - type_init_formals
+    - unnecessary_brace_in_string_interps
+    - unnecessary_const
+    - unnecessary_new
+    - unrelated_type_equality_checks
+    - valid_regexps
diff --git a/codereview.settings b/codereview.settings
deleted file mode 100644
index 8237636..0000000
--- a/codereview.settings
+++ /dev/null
@@ -1,3 +0,0 @@
-CODE_REVIEW_SERVER: http://codereview.chromium.org/
-VIEW_VC: https://github.com/dart-lang/convert/commit/
-CC_LIST: reviews@dartlang.org
\ No newline at end of file
diff --git a/lib/src/accumulator_sink.dart b/lib/src/accumulator_sink.dart
index ca35f7a..d92b4a8 100644
--- a/lib/src/accumulator_sink.dart
+++ b/lib/src/accumulator_sink.dart
@@ -9,7 +9,7 @@
 /// See also [ChunkedConversionSink.withCallback].
 class AccumulatorSink<T> implements Sink<T> {
   /// An unmodifiable list of events passed to this sink so far.
-  List<T> get events => new UnmodifiableListView(_events);
+  List<T> get events => UnmodifiableListView(_events);
   final _events = <T>[];
 
   /// Whether [close] has been called.
@@ -25,7 +25,7 @@
 
   void add(T event) {
     if (_isClosed) {
-      throw new StateError("Can't add to a closed sink.");
+      throw StateError("Can't add to a closed sink.");
     }
 
     _events.add(event);
diff --git a/lib/src/byte_accumulator_sink.dart b/lib/src/byte_accumulator_sink.dart
index 10bd8ee..d1fab06 100644
--- a/lib/src/byte_accumulator_sink.dart
+++ b/lib/src/byte_accumulator_sink.dart
@@ -15,9 +15,9 @@
   ///
   /// The returned [Uint8List] is viewing a shared buffer, so it should not be
   /// changed and any bytes outside the view should not be accessed.
-  Uint8List get bytes => new Uint8List.view(_buffer.buffer, 0, _buffer.length);
+  Uint8List get bytes => Uint8List.view(_buffer.buffer, 0, _buffer.length);
 
-  final _buffer = new Uint8Buffer();
+  final _buffer = Uint8Buffer();
 
   /// Whether [close] has been called.
   bool get isClosed => _isClosed;
@@ -32,7 +32,7 @@
 
   void add(List<int> bytes) {
     if (_isClosed) {
-      throw new StateError("Can't add to a closed sink.");
+      throw StateError("Can't add to a closed sink.");
     }
 
     _buffer.addAll(bytes);
@@ -40,7 +40,7 @@
 
   void addSlice(List<int> chunk, int start, int end, bool isLast) {
     if (_isClosed) {
-      throw new StateError("Can't add to a closed sink.");
+      throw StateError("Can't add to a closed sink.");
     }
 
     _buffer.addAll(chunk, start, end);
diff --git a/lib/src/hex.dart b/lib/src/hex.dart
index ec4451e..28e9203 100644
--- a/lib/src/hex.dart
+++ b/lib/src/hex.dart
@@ -6,14 +6,14 @@
 
 import 'dart:convert';
 
-import 'hex/encoder.dart';
 import 'hex/decoder.dart';
+import 'hex/encoder.dart';
 
-export 'hex/encoder.dart' hide hexEncoder;
 export 'hex/decoder.dart' hide hexDecoder;
+export 'hex/encoder.dart' hide hexEncoder;
 
 /// The canonical instance of [HexCodec].
-const hex = const HexCodec._();
+const hex = HexCodec._();
 
 /// A codec that converts byte arrays to and from hexadecimal strings, following
 /// [the Base16 spec][rfc].
diff --git a/lib/src/hex/decoder.dart b/lib/src/hex/decoder.dart
index c1c8feb..e37d5c9 100644
--- a/lib/src/hex/decoder.dart
+++ b/lib/src/hex/decoder.dart
@@ -10,7 +10,7 @@
 import '../utils.dart';
 
 /// The canonical instance of [HexDecoder].
-const hexDecoder = const HexDecoder._();
+const hexDecoder = HexDecoder._();
 
 /// A converter that decodes hexadecimal strings into byte arrays.
 ///
@@ -22,17 +22,17 @@
 
   List<int> convert(String string) {
     if (!string.length.isEven) {
-      throw new FormatException(
+      throw FormatException(
           "Invalid input length, must be even.", string, string.length);
     }
 
-    var bytes = new Uint8List(string.length ~/ 2);
+    var bytes = Uint8List(string.length ~/ 2);
     _decode(string.codeUnits, 0, string.length, bytes, 0);
     return bytes;
   }
 
   StringConversionSink startChunkedConversion(Sink<List<int>> sink) =>
-      new _HexDecoderSink(sink);
+      _HexDecoderSink(sink);
 }
 
 /// A conversion sink for chunked hexadecimal decoding.
@@ -61,11 +61,11 @@
     Uint8List bytes;
     int bytesStart;
     if (_lastDigit == null) {
-      bytes = new Uint8List((end - start) ~/ 2);
+      bytes = Uint8List((end - start) ~/ 2);
       bytesStart = 0;
     } else {
       var hexPairs = (end - start - 1) ~/ 2;
-      bytes = new Uint8List(1 + hexPairs);
+      bytes = Uint8List(1 + hexPairs);
       bytes[0] = _lastDigit + digitForCodeUnit(codeUnits, start);
       start++;
       bytesStart = 1;
@@ -78,7 +78,7 @@
   }
 
   ByteConversionSink asUtf8Sink(bool allowMalformed) =>
-      new _HexDecoderByteSink(_sink);
+      _HexDecoderByteSink(_sink);
 
   void close() => _close();
 
@@ -86,7 +86,7 @@
   /// if one is thrown.
   void _close([String string, int index]) {
     if (_lastDigit != null) {
-      throw new FormatException(
+      throw FormatException(
           "Input ended with incomplete encoded byte.", string, index);
     }
 
@@ -121,11 +121,11 @@
     Uint8List bytes;
     int bytesStart;
     if (_lastDigit == null) {
-      bytes = new Uint8List((end - start) ~/ 2);
+      bytes = Uint8List((end - start) ~/ 2);
       bytesStart = 0;
     } else {
       var hexPairs = (end - start - 1) ~/ 2;
-      bytes = new Uint8List(1 + hexPairs);
+      bytes = Uint8List(1 + hexPairs);
       bytes[0] = _lastDigit + digitForCodeUnit(chunk, start);
       start++;
       bytesStart = 1;
@@ -143,7 +143,7 @@
   /// if one is thrown.
   void _close([List<int> chunk, int index]) {
     if (_lastDigit != null) {
-      throw new FormatException(
+      throw FormatException(
           "Input ended with incomplete encoded byte.", chunk, index);
     }
 
diff --git a/lib/src/hex/encoder.dart b/lib/src/hex/encoder.dart
index 9339cda..3ed85c7 100644
--- a/lib/src/hex/encoder.dart
+++ b/lib/src/hex/encoder.dart
@@ -10,7 +10,7 @@
 import 'package:charcode/ascii.dart';
 
 /// The canonical instance of [HexEncoder].
-const hexEncoder = const HexEncoder._();
+const hexEncoder = HexEncoder._();
 
 /// A converter that encodes byte arrays into hexadecimal strings.
 ///
@@ -22,7 +22,7 @@
   String convert(List<int> bytes) => _convert(bytes, 0, bytes.length);
 
   ByteConversionSink startChunkedConversion(Sink<String> sink) =>
-      new _HexEncoderSink(sink);
+      _HexEncoderSink(sink);
 }
 
 /// A conversion sink for chunked hexadecimal encoding.
@@ -51,7 +51,7 @@
   // A Uint8List is more efficient than a StringBuffer given that we know that
   // we're only emitting ASCII-compatible characters, and that we know the
   // length ahead of time.
-  var buffer = new Uint8List((end - start) * 2);
+  var buffer = Uint8List((end - start) * 2);
   var bufferIndex = 0;
 
   // A bitwise OR of all bytes in [bytes]. This allows us to check for
@@ -69,13 +69,13 @@
     buffer[bufferIndex++] = _codeUnitForDigit(byte & 0x0F);
   }
 
-  if (byteOr >= 0 && byteOr <= 255) return new String.fromCharCodes(buffer);
+  if (byteOr >= 0 && byteOr <= 255) return String.fromCharCodes(buffer);
 
   // If there was an invalid byte, find it and throw an exception.
   for (var i = start; i < end; i++) {
     var byte = bytes[i];
     if (byte >= 0 && byte <= 0xff) continue;
-    throw new FormatException(
+    throw FormatException(
         "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.",
         bytes,
         i);
diff --git a/lib/src/identity_codec.dart b/lib/src/identity_codec.dart
index 3a2d028..9da7bca 100644
--- a/lib/src/identity_codec.dart
+++ b/lib/src/identity_codec.dart
@@ -17,8 +17,8 @@
 class IdentityCodec<T> extends Codec<T, T> {
   const IdentityCodec();
 
-  Converter<T, T> get decoder => new _IdentityConverter<T>();
-  Converter<T, T> get encoder => new _IdentityConverter<T>();
+  Converter<T, T> get decoder => _IdentityConverter<T>();
+  Converter<T, T> get encoder => _IdentityConverter<T>();
 
   /// Fuse with an other codec.
   ///
diff --git a/lib/src/percent.dart b/lib/src/percent.dart
index 3bb3da1..b06d08f 100644
--- a/lib/src/percent.dart
+++ b/lib/src/percent.dart
@@ -6,14 +6,14 @@
 
 import 'dart:convert';
 
-import 'percent/encoder.dart';
 import 'percent/decoder.dart';
+import 'percent/encoder.dart';
 
-export 'percent/encoder.dart' hide percentEncoder;
 export 'percent/decoder.dart' hide percentDecoder;
+export 'percent/encoder.dart' hide percentEncoder;
 
 /// The canonical instance of [PercentCodec].
-const percent = const PercentCodec._();
+const percent = PercentCodec._();
 
 // TODO(nweiz): Add flags to support generating and interpreting "+" as a space
 // character. Also add an option for custom sets of unreserved characters.
diff --git a/lib/src/percent/decoder.dart b/lib/src/percent/decoder.dart
index 334e754..cc403ff 100644
--- a/lib/src/percent/decoder.dart
+++ b/lib/src/percent/decoder.dart
@@ -12,7 +12,7 @@
 import '../utils.dart';
 
 /// The canonical instance of [PercentDecoder].
-const percentDecoder = const PercentDecoder._();
+const percentDecoder = PercentDecoder._();
 
 const _lastPercent = -1;
 
@@ -29,11 +29,11 @@
   const PercentDecoder._();
 
   List<int> convert(String string) {
-    var buffer = new Uint8Buffer();
+    var buffer = Uint8Buffer();
     var lastDigit = _decode(string.codeUnits, 0, string.length, buffer);
 
     if (lastDigit != null) {
-      throw new FormatException(
+      throw FormatException(
           "Input ended with incomplete encoded byte.", string, string.length);
     }
 
@@ -41,7 +41,7 @@
   }
 
   StringConversionSink startChunkedConversion(Sink<List<int>> sink) =>
-      new _PercentDecoderSink(sink);
+      _PercentDecoderSink(sink);
 }
 
 /// A conversion sink for chunked percent-encoded decoding.
@@ -68,7 +68,7 @@
       return;
     }
 
-    var buffer = new Uint8Buffer();
+    var buffer = Uint8Buffer();
     var codeUnits = string.codeUnits;
     if (_lastDigit == _lastPercent) {
       _lastDigit = 16 * digitForCodeUnit(codeUnits, start);
@@ -92,7 +92,7 @@
   }
 
   ByteConversionSink asUtf8Sink(bool allowMalformed) =>
-      new _PercentDecoderByteSink(_sink);
+      _PercentDecoderByteSink(_sink);
 
   void close() => _close();
 
@@ -100,7 +100,7 @@
   /// if one is thrown.
   void _close([String string, int index]) {
     if (_lastDigit != null) {
-      throw new FormatException(
+      throw FormatException(
           "Input ended with incomplete encoded byte.", string, index);
     }
 
@@ -134,7 +134,7 @@
       return;
     }
 
-    var buffer = new Uint8Buffer();
+    var buffer = Uint8Buffer();
     if (_lastDigit == _lastPercent) {
       _lastDigit = 16 * digitForCodeUnit(chunk, start);
       start++;
@@ -162,7 +162,7 @@
   /// if one is thrown.
   void _close([List<int> chunk, int index]) {
     if (_lastDigit != null) {
-      throw new FormatException(
+      throw FormatException(
           "Input ended with incomplete encoded byte.", chunk, index);
     }
 
@@ -235,7 +235,7 @@
   for (var i = start; i < end; i++) {
     var codeUnit = codeUnits[i];
     if (codeUnit >= 0 && codeUnit <= 0x7f) continue;
-    throw new FormatException(
+    throw FormatException(
         "Non-ASCII code unit "
         "U+${codeUnit.toRadixString(16).padLeft(4, '0')}",
         codeUnits,
diff --git a/lib/src/percent/encoder.dart b/lib/src/percent/encoder.dart
index d4419a9..390316f 100644
--- a/lib/src/percent/encoder.dart
+++ b/lib/src/percent/encoder.dart
@@ -9,7 +9,7 @@
 import 'package:charcode/ascii.dart';
 
 /// The canonical instance of [PercentEncoder].
-const percentEncoder = const PercentEncoder._();
+const percentEncoder = PercentEncoder._();
 
 /// A converter that encodes byte arrays into percent-encoded strings.
 ///
@@ -25,7 +25,7 @@
   String convert(List<int> bytes) => _convert(bytes, 0, bytes.length);
 
   ByteConversionSink startChunkedConversion(Sink<String> sink) =>
-      new _PercentEncoderSink(sink);
+      _PercentEncoderSink(sink);
 }
 
 /// A conversion sink for chunked percentadecimal encoding.
@@ -51,7 +51,7 @@
 }
 
 String _convert(List<int> bytes, int start, int end) {
-  var buffer = new StringBuffer();
+  var buffer = StringBuffer();
 
   // A bitwise OR of all bytes in [bytes]. This allows us to check for
   // out-of-range bytes without adding more branches than necessary to the
@@ -92,7 +92,7 @@
   for (var i = start; i < end; i++) {
     var byte = bytes[i];
     if (byte >= 0 && byte <= 0xff) continue;
-    throw new FormatException(
+    throw FormatException(
         "Invalid byte ${byte < 0 ? "-" : ""}0x${byte.abs().toRadixString(16)}.",
         bytes,
         i);
diff --git a/lib/src/string_accumulator_sink.dart b/lib/src/string_accumulator_sink.dart
index 95e2248..c8bdf75 100644
--- a/lib/src/string_accumulator_sink.dart
+++ b/lib/src/string_accumulator_sink.dart
@@ -10,7 +10,7 @@
 class StringAccumulatorSink extends StringConversionSinkBase {
   /// The string accumulated so far.
   String get string => _buffer.toString();
-  final _buffer = new StringBuffer();
+  final _buffer = StringBuffer();
 
   /// Whether [close] has been called.
   bool get isClosed => _isClosed;
@@ -25,7 +25,7 @@
 
   void add(String chunk) {
     if (_isClosed) {
-      throw new StateError("Can't add to a closed sink.");
+      throw StateError("Can't add to a closed sink.");
     }
 
     _buffer.write(chunk);
@@ -33,7 +33,7 @@
 
   void addSlice(String chunk, int start, int end, bool isLast) {
     if (_isClosed) {
-      throw new StateError("Can't add to a closed sink.");
+      throw StateError("Can't add to a closed sink.");
     }
 
     _buffer.write(chunk.substring(start, end));
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 7990779..4001e3e 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -31,7 +31,7 @@
     if ($a <= letter && letter <= $f) return letter - $a + 10;
   }
 
-  throw new FormatException(
+  throw FormatException(
       "Invalid hexadecimal code unit "
       "U+${codeUnit.toRadixString(16).padLeft(4, '0')}.",
       codeUnits,
diff --git a/pubspec.yaml b/pubspec.yaml
index e788c48..8002b7c 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,15 +1,16 @@
 name: convert
-version: 2.1.1
+version: 2.1.2-dev
 description: Utilities for converting between data representations.
 author: Dart Team <misc@dartlang.org>
 homepage: https://github.com/dart-lang/convert
 
 environment:
-  sdk: '>=1.17.0 <3.0.0'
+  sdk: '>=2.0.0 <3.0.0'
 
 dependencies:
   charcode: ^1.1.0
   typed_data: ^1.1.0
 
 dev_dependencies:
-  test: '>=0.12.0 <2.0.0'
+  pedantic: ^1.0.0
+  test: ^1.0.0
\ No newline at end of file
diff --git a/test/accumulator_sink_test.dart b/test/accumulator_sink_test.dart
index 81fe1db..2c280e1 100644
--- a/test/accumulator_sink_test.dart
+++ b/test/accumulator_sink_test.dart
@@ -8,7 +8,7 @@
 void main() {
   var sink;
   setUp(() {
-    sink = new AccumulatorSink<int>();
+    sink = AccumulatorSink<int>();
   });
 
   test("provides access to events as they're added", () {
diff --git a/test/byte_accumulator_sink_test.dart b/test/byte_accumulator_sink_test.dart
index 332e71c..31ea03a 100644
--- a/test/byte_accumulator_sink_test.dart
+++ b/test/byte_accumulator_sink_test.dart
@@ -8,7 +8,7 @@
 void main() {
   ByteAccumulatorSink sink;
   setUp(() {
-    sink = new ByteAccumulatorSink();
+    sink = ByteAccumulatorSink();
   });
 
   test("provides access to the concatenated bytes", () {
diff --git a/test/hex_test.dart b/test/hex_test.dart
index 95f0e90..78db5fd 100644
--- a/test/hex_test.dart
+++ b/test/hex_test.dart
@@ -17,7 +17,7 @@
     group("with chunked conversion", () {
       test("converts byte arrays to hex", () {
         var results = <String>[];
-        var controller = new StreamController<String>(sync: true);
+        var controller = StreamController<String>(sync: true);
         controller.stream.listen(results.add);
         var sink = hex.encoder.startChunkedConversion(controller.sink);
 
@@ -30,7 +30,7 @@
 
       test("handles empty and single-byte lists", () {
         var results = <String>[];
-        var controller = new StreamController<String>(sync: true);
+        var controller = StreamController<String>(sync: true);
         controller.stream.listen(results.add);
         var sink = hex.encoder.startChunkedConversion(controller.sink);
 
@@ -49,7 +49,7 @@
       expect(() => hex.encode([0x100]), throwsFormatException);
 
       var sink =
-          hex.encoder.startChunkedConversion(new StreamController(sync: true));
+          hex.encoder.startChunkedConversion(StreamController(sync: true));
       expect(() => sink.add([0x100]), throwsFormatException);
     });
   });
@@ -83,7 +83,7 @@
       var sink;
       setUp(() {
         results = [];
-        var controller = new StreamController<List<int>>(sync: true);
+        var controller = StreamController<List<int>>(sync: true);
         controller.stream.listen(results.add);
         sink = hex.decoder.startChunkedConversion(controller.sink);
       });
@@ -207,8 +207,8 @@
           expect(() => hex.decode("a$char"), throwsFormatException);
           expect(() => hex.decode("${char}a"), throwsFormatException);
 
-          var sink = hex.decoder
-              .startChunkedConversion(new StreamController(sync: true));
+          var sink =
+              hex.decoder.startChunkedConversion(StreamController(sync: true));
           expect(() => sink.add(char), throwsFormatException);
         });
       }
diff --git a/test/percent_test.dart b/test/percent_test.dart
index c2f0a3c..d50ef32 100644
--- a/test/percent_test.dart
+++ b/test/percent_test.dart
@@ -115,7 +115,7 @@
     group("with chunked conversion", () {
       test("percent-encodes byte arrays", () {
         var results = <String>[];
-        var controller = new StreamController<String>(sync: true);
+        var controller = StreamController<String>(sync: true);
         controller.stream.listen(results.add);
         var sink = percent.encoder.startChunkedConversion(controller.sink);
 
@@ -128,7 +128,7 @@
 
       test("handles empty and single-byte lists", () {
         var results = <String>[];
-        var controller = new StreamController<String>(sync: true);
+        var controller = StreamController<String>(sync: true);
         controller.stream.listen(results.add);
         var sink = percent.encoder.startChunkedConversion(controller.sink);
 
@@ -146,8 +146,8 @@
     test("rejects non-bytes", () {
       expect(() => percent.encode([0x100]), throwsFormatException);
 
-      var sink = percent.encoder
-          .startChunkedConversion(new StreamController(sync: true));
+      var sink =
+          percent.encoder.startChunkedConversion(StreamController(sync: true));
       expect(() => sink.add([0x100]), throwsFormatException);
     });
   });
@@ -190,7 +190,7 @@
       var sink;
       setUp(() {
         results = [];
-        var controller = new StreamController<List<int>>(sync: true);
+        var controller = StreamController<List<int>>(sync: true);
         controller.stream.listen(results.add);
         sink = percent.decoder.startChunkedConversion(controller.sink);
       });
@@ -320,7 +320,7 @@
           expect(() => percent.decode("${char}a"), throwsFormatException);
 
           var sink = percent.decoder
-              .startChunkedConversion(new StreamController(sync: true));
+              .startChunkedConversion(StreamController(sync: true));
           expect(() => sink.add(char), throwsFormatException);
         });
       }
diff --git a/test/string_accumulator_sink_test.dart b/test/string_accumulator_sink_test.dart
index 914dd93..2bef19b 100644
--- a/test/string_accumulator_sink_test.dart
+++ b/test/string_accumulator_sink_test.dart
@@ -8,7 +8,7 @@
 void main() {
   var sink;
   setUp(() {
-    sink = new StringAccumulatorSink();
+    sink = StringAccumulatorSink();
   });
 
   test("provides access to the concatenated string", () {