Enable and fix a number of lints (#19)

diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..749f62a
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1,11 @@
+include: package:pedantic/analysis_options.yaml
+analyzer:
+  strong-mode:
+    implicit-casts: false
+linter:
+  rules:
+    - await_only_futures
+    - implementation_imports
+    - prefer_typing_uninitialized_variables
+    - unnecessary_const
+    - unnecessary_new
diff --git a/lib/pool.dart b/lib/pool.dart
index ea3d2f0..416b14b 100644
--- a/lib/pool.dart
+++ b/lib/pool.dart
@@ -21,20 +21,20 @@
   ///
   /// When an item is released, the next element of [_requestedResources] will
   /// be completed.
-  final _requestedResources = new Queue<Completer<PoolResource>>();
+  final _requestedResources = Queue<Completer<PoolResource>>();
 
   /// Callbacks that must be called before additional resources can be
   /// allocated.
   ///
   /// See [PoolResource.allowRelease].
-  final _onReleaseCallbacks = new Queue<Function>();
+  final _onReleaseCallbacks = Queue<void Function()>();
 
   /// Completers that will be completed once `onRelease` callbacks are done
   /// running.
   ///
   /// These are kept in a queue to ensure that the earliest request completes
   /// first regardless of what order the `onRelease` callbacks complete in.
-  final _onReleaseCompleters = new Queue<Completer<PoolResource>>();
+  final _onReleaseCompleters = Queue<Completer<PoolResource>>();
 
   /// The maximum number of resources that may be allocated at once.
   final int _maxAllocatedResources;
@@ -82,7 +82,7 @@
     if (timeout != null) {
       // Start the timer canceled since we only want to start counting down once
       // we've run out of available resources.
-      _timer = new RestartableTimer(timeout, _onTimeout)..cancel();
+      _timer = RestartableTimer(timeout, _onTimeout)..cancel();
     }
   }
 
@@ -92,16 +92,16 @@
   /// until one of them is released.
   Future<PoolResource> request() {
     if (isClosed) {
-      throw new StateError("request() may not be called on a closed Pool.");
+      throw StateError("request() may not be called on a closed Pool.");
     }
 
     if (_allocatedResources < _maxAllocatedResources) {
       _allocatedResources++;
-      return new Future.value(new PoolResource._(this));
+      return Future.value(PoolResource._(this));
     } else if (_onReleaseCallbacks.isNotEmpty) {
       return _runOnRelease(_onReleaseCallbacks.removeFirst());
     } else {
-      var completer = new Completer<PoolResource>();
+      var completer = Completer<PoolResource>();
       _requestedResources.add(completer);
       _resetTimer();
       return completer.future;
@@ -114,8 +114,7 @@
   /// The return value of [callback] is piped to the returned Future.
   Future<T> withResource<T>(FutureOr<T> callback()) {
     if (isClosed) {
-      throw new StateError(
-          "withResource() may not be called on a closed Pool.");
+      throw StateError("withResource() may not be called on a closed Pool.");
     }
 
     // We can't use async/await here because we need to start the request
@@ -123,7 +122,7 @@
     // functions have an asynchronous gap between calling and running the body,
     // and [close] could be called during that gap. See #3.
     return request().then((resource) {
-      return new Future<T>.sync(callback).whenComplete(resource.release);
+      return Future<T>.sync(callback).whenComplete(resource.release);
     });
   }
 
@@ -143,9 +142,9 @@
 
         _resetTimer();
 
-        _closeGroup = new FutureGroup();
+        _closeGroup = FutureGroup();
         for (var callback in _onReleaseCallbacks) {
-          _closeGroup.add(new Future.sync(callback));
+          _closeGroup.add(Future.sync(callback));
         }
 
         _allocatedResources -= _onReleaseCallbacks.length;
@@ -154,7 +153,7 @@
         if (_allocatedResources == 0) _closeGroup.close();
         return _closeGroup.future;
       });
-  final _closeMemo = new AsyncMemoizer();
+  final _closeMemo = AsyncMemoizer();
 
   /// If there are any pending requests, this will fire the oldest one.
   void _onResourceReleased() {
@@ -162,7 +161,7 @@
 
     if (_requestedResources.isNotEmpty) {
       var pending = _requestedResources.removeFirst();
-      pending.complete(new PoolResource._(this));
+      pending.complete(PoolResource._(this));
     } else {
       _allocatedResources--;
       if (isClosed && _allocatedResources == 0) _closeGroup.close();
@@ -178,7 +177,7 @@
       var pending = _requestedResources.removeFirst();
       pending.complete(_runOnRelease(onRelease));
     } else if (isClosed) {
-      _closeGroup.add(new Future.sync(onRelease));
+      _closeGroup.add(Future.sync(onRelease));
       _allocatedResources--;
       if (_allocatedResources == 0) _closeGroup.close();
     } else {
@@ -194,13 +193,13 @@
   /// Futures returned by [_runOnRelease] always complete in the order they were
   /// created, even if earlier [onRelease] callbacks take longer to run.
   Future<PoolResource> _runOnRelease(onRelease()) {
-    new Future.sync(onRelease).then((value) {
-      _onReleaseCompleters.removeFirst().complete(new PoolResource._(this));
-    }).catchError((error, stackTrace) {
+    Future.sync(onRelease).then((value) {
+      _onReleaseCompleters.removeFirst().complete(PoolResource._(this));
+    }).catchError((error, StackTrace stackTrace) {
       _onReleaseCompleters.removeFirst().completeError(error, stackTrace);
     });
 
-    var completer = new Completer<PoolResource>.sync();
+    var completer = Completer<PoolResource>.sync();
     _onReleaseCompleters.add(completer);
     return completer.future;
   }
@@ -221,11 +220,11 @@
   void _onTimeout() {
     for (var completer in _requestedResources) {
       completer.completeError(
-          new TimeoutException(
+          TimeoutException(
               "Pool deadlock: all resources have been "
               "allocated for too long.",
               _timeout),
-          new Chain.current());
+          Chain.current());
     }
     _requestedResources.clear();
     _timer = null;
@@ -248,7 +247,7 @@
   /// no longer allocated, and that a new [PoolResource] may be allocated.
   void release() {
     if (_released) {
-      throw new StateError("A PoolResource may only be released once.");
+      throw StateError("A PoolResource may only be released once.");
     }
     _released = true;
     _pool._onResourceReleased();
@@ -268,7 +267,7 @@
   /// may be complete, but it could still emit asynchronous errors.
   void allowRelease(onRelease()) {
     if (_released) {
-      throw new StateError("A PoolResource may only be released once.");
+      throw StateError("A PoolResource may only be released once.");
     }
     _released = true;
     _pool._onResourceReleaseAllowed(onRelease);
diff --git a/pubspec.yaml b/pubspec.yaml
index 84b97b2..a709842 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: pool
-version: 1.3.6
+version: 1.3.7-dev
 
 description: A class for managing a finite pool of resources.
 author: Dart Team <misc@dartlang.org>
@@ -14,4 +14,5 @@
 
 dev_dependencies:
   fake_async: ^1.0.0
+  pedantic: ^1.4.0
   test: ^1.0.0
diff --git a/test/pool_test.dart b/test/pool_test.dart
index cb0dd30..a156c52 100644
--- a/test/pool_test.dart
+++ b/test/pool_test.dart
@@ -5,6 +5,7 @@
 import 'dart:async';
 
 import 'package:fake_async/fake_async.dart';
+import 'package:pedantic/pedantic.dart';
 import 'package:pool/pool.dart';
 import 'package:stack_trace/stack_trace.dart';
 import 'package:test/test.dart';
@@ -12,27 +13,27 @@
 void main() {
   group("request()", () {
     test("resources can be requested freely up to the limit", () {
-      var pool = new Pool(50);
+      var pool = Pool(50);
       for (var i = 0; i < 50; i++) {
         expect(pool.request(), completes);
       }
     });
 
     test("resources block past the limit", () {
-      new FakeAsync().run((async) {
-        var pool = new Pool(50);
+      FakeAsync().run((async) {
+        var pool = Pool(50);
         for (var i = 0; i < 50; i++) {
           expect(pool.request(), completes);
         }
         expect(pool.request(), doesNotComplete);
 
-        async.elapse(new Duration(seconds: 1));
+        async.elapse(Duration(seconds: 1));
       });
     });
 
     test("a blocked resource is allocated when another is released", () {
-      new FakeAsync().run((async) {
-        var pool = new Pool(50);
+      FakeAsync().run((async) {
+        var pool = Pool(50);
         for (var i = 0; i < 49; i++) {
           expect(pool.request(), completes);
         }
@@ -41,85 +42,85 @@
           // This will only complete once [lastAllocatedResource] is released.
           expect(pool.request(), completes);
 
-          new Future.delayed(new Duration(microseconds: 1)).then((_) {
+          Future.delayed(Duration(microseconds: 1)).then((_) {
             lastAllocatedResource.release();
           });
         });
 
-        async.elapse(new Duration(seconds: 1));
+        async.elapse(Duration(seconds: 1));
       });
     });
   });
 
   group("withResource()", () {
     test("can be called freely up to the limit", () {
-      var pool = new Pool(50);
+      var pool = Pool(50);
       for (var i = 0; i < 50; i++) {
-        pool.withResource(expectAsync0(() => new Completer().future));
+        pool.withResource(expectAsync0(() => Completer().future));
       }
     });
 
     test("blocks the callback past the limit", () {
-      new FakeAsync().run((async) {
-        var pool = new Pool(50);
+      FakeAsync().run((async) {
+        var pool = Pool(50);
         for (var i = 0; i < 50; i++) {
-          pool.withResource(expectAsync0(() => new Completer().future));
+          pool.withResource(expectAsync0(() => Completer().future));
         }
         pool.withResource(expectNoAsync());
 
-        async.elapse(new Duration(seconds: 1));
+        async.elapse(Duration(seconds: 1));
       });
     });
 
     test("a blocked resource is allocated when another is released", () {
-      new FakeAsync().run((async) {
-        var pool = new Pool(50);
+      FakeAsync().run((async) {
+        var pool = Pool(50);
         for (var i = 0; i < 49; i++) {
-          pool.withResource(expectAsync0(() => new Completer().future));
+          pool.withResource(expectAsync0(() => Completer().future));
         }
 
-        var completer = new Completer();
+        var completer = Completer();
         pool.withResource(() => completer.future);
         var blockedResourceAllocated = false;
         pool.withResource(() {
           blockedResourceAllocated = true;
         });
 
-        new Future.delayed(new Duration(microseconds: 1)).then((_) {
+        Future.delayed(Duration(microseconds: 1)).then((_) {
           expect(blockedResourceAllocated, isFalse);
           completer.complete();
-          return new Future.delayed(new Duration(microseconds: 1));
+          return Future.delayed(Duration(microseconds: 1));
         }).then((_) {
           expect(blockedResourceAllocated, isTrue);
         });
 
-        async.elapse(new Duration(seconds: 1));
+        async.elapse(Duration(seconds: 1));
       });
     });
 
     // Regression test for #3.
     test("can be called immediately before close()", () async {
-      var pool = new Pool(1);
-      pool.withResource(expectAsync0(() {}));
+      var pool = Pool(1);
+      unawaited(pool.withResource(expectAsync0(() {})));
       await pool.close();
     });
   });
 
   group("with a timeout", () {
     test("doesn't time out if there are no pending requests", () {
-      new FakeAsync().run((async) {
-        var pool = new Pool(50, timeout: new Duration(seconds: 5));
+      FakeAsync().run((async) {
+        var pool = Pool(50, timeout: Duration(seconds: 5));
         for (var i = 0; i < 50; i++) {
           expect(pool.request(), completes);
         }
 
-        async.elapse(new Duration(seconds: 6));
+        async.elapse(Duration(seconds: 6));
       });
     });
 
     test("resets the timer if a resource is returned", () {
-      new FakeAsync().run((async) {
-        var pool = new Pool(50, timeout: new Duration(seconds: 5));
+      FakeAsync().run((async) {
+        var pool = Pool(50, timeout: Duration(seconds: 5));
         for (var i = 0; i < 49; i++) {
           expect(pool.request(), completes);
         }
@@ -128,48 +129,48 @@
           // This will only complete once [lastAllocatedResource] is released.
           expect(pool.request(), completes);
 
-          new Future.delayed(new Duration(seconds: 3)).then((_) {
+          Future.delayed(Duration(seconds: 3)).then((_) {
             lastAllocatedResource.release();
             expect(pool.request(), doesNotComplete);
           });
         });
 
-        async.elapse(new Duration(seconds: 6));
+        async.elapse(Duration(seconds: 6));
       });
     });
 
     test("resets the timer if a resource is requested", () {
-      new FakeAsync().run((async) {
-        var pool = new Pool(50, timeout: new Duration(seconds: 5));
+      FakeAsync().run((async) {
+        var pool = Pool(50, timeout: Duration(seconds: 5));
         for (var i = 0; i < 50; i++) {
           expect(pool.request(), completes);
         }
         expect(pool.request(), doesNotComplete);
 
-        new Future.delayed(new Duration(seconds: 3)).then((_) {
+        Future.delayed(Duration(seconds: 3)).then((_) {
           expect(pool.request(), doesNotComplete);
         });
 
-        async.elapse(new Duration(seconds: 6));
+        async.elapse(Duration(seconds: 6));
       });
     });
 
     test("times out if nothing happens", () {
-      new FakeAsync().run((async) {
-        var pool = new Pool(50, timeout: new Duration(seconds: 5));
+      FakeAsync().run((async) {
+        var pool = Pool(50, timeout: Duration(seconds: 5));
         for (var i = 0; i < 50; i++) {
           expect(pool.request(), completes);
         }
-        expect(pool.request(), throwsA(new TypeMatcher<TimeoutException>()));
+        expect(pool.request(), throwsA(TypeMatcher<TimeoutException>()));
 
-        async.elapse(new Duration(seconds: 6));
+        async.elapse(Duration(seconds: 6));
       });
     });
   });
 
   group("allowRelease()", () {
     test("runs the callback once the resource limit is exceeded", () async {
-      var pool = new Pool(50);
+      var pool = Pool(50);
       for (var i = 0; i < 49; i++) {
         expect(pool.request(), completes);
       }
@@ -177,17 +178,17 @@
       var resource = await pool.request();
       var onReleaseCalled = false;
       resource.allowRelease(() => onReleaseCalled = true);
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(onReleaseCalled, isFalse);
 
       expect(pool.request(), completes);
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(onReleaseCalled, isTrue);
     });
 
     test("runs the callback immediately if there are blocked requests",
         () async {
-      var pool = new Pool(1);
+      var pool = Pool(1);
       var resource = await pool.request();
 
       // This will be blocked until [resource.allowRelease] is called.
@@ -195,54 +196,54 @@
 
       var onReleaseCalled = false;
       resource.allowRelease(() => onReleaseCalled = true);
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(onReleaseCalled, isTrue);
     });
 
     test("blocks the request until the callback completes", () async {
-      var pool = new Pool(1);
+      var pool = Pool(1);
       var resource = await pool.request();
 
       var requestComplete = false;
-      pool.request().then((_) => requestComplete = true);
+      unawaited(pool.request().then((_) => requestComplete = true));
 
-      var completer = new Completer();
+      var completer = Completer();
       resource.allowRelease(() => completer.future);
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(requestComplete, isFalse);
 
       completer.complete();
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(requestComplete, isTrue);
     });
 
     test("completes requests in request order regardless of callback order",
         () async {
-      var pool = new Pool(2);
+      var pool = Pool(2);
       var resource1 = await pool.request();
       var resource2 = await pool.request();
 
       var request1Complete = false;
-      pool.request().then((_) => request1Complete = true);
+      unawaited(pool.request().then((_) => request1Complete = true));
       var request2Complete = false;
-      pool.request().then((_) => request2Complete = true);
+      unawaited(pool.request().then((_) => request2Complete = true));
 
       var onRelease1Called = false;
-      var completer1 = new Completer();
+      var completer1 = Completer();
       resource1.allowRelease(() {
         onRelease1Called = true;
         return completer1.future;
       });
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(onRelease1Called, isTrue);
 
       var onRelease2Called = false;
-      var completer2 = new Completer();
+      var completer2 = Completer();
       resource2.allowRelease(() {
         onRelease2Called = true;
         return completer2.future;
       });
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(onRelease2Called, isTrue);
       expect(request1Complete, isFalse);
       expect(request2Complete, isFalse);
@@ -251,18 +252,18 @@
       // was triggered by the second blocking request, it should complete the
       // first one to preserve ordering.
       completer2.complete();
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(request1Complete, isTrue);
       expect(request2Complete, isFalse);
 
       completer1.complete();
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       expect(request1Complete, isTrue);
       expect(request2Complete, isTrue);
     });
 
     test("runs onRequest in the zone it was created", () async {
-      var pool = new Pool(1);
+      var pool = Pool(1);
       var resource = await pool.request();
 
       var outerZone = Zone.current;
@@ -275,29 +276,29 @@
         }));
       });
 
-      pool.request();
+      await pool.request();
     });
   });
 
   test("done doesn't complete without close", () async {
-    var pool = new Pool(1);
-    pool.done.then(expectAsync1((_) {}, count: 0));
+    var pool = Pool(1);
+    unawaited(pool.done.then(expectAsync1((_) {}, count: 0)));
 
     var resource = await pool.request();
     resource.release();
 
-    await new Future.delayed(Duration.zero);
+    await Future.delayed(Duration.zero);
   });
 
   group("close()", () {
     test("disallows request() and withResource()", () {
-      var pool = new Pool(1)..close();
+      var pool = Pool(1)..close();
       expect(pool.request, throwsStateError);
       expect(() => pool.withResource(() {}), throwsStateError);
     });
 
     test("pending requests are fulfilled", () async {
-      var pool = new Pool(1);
+      var pool = Pool(1);
       var resource1 = await pool.request();
       expect(
           pool.request().then((resource2) {
@@ -310,10 +311,10 @@
     });
 
     test("pending requests are fulfilled with allowRelease", () async {
-      var pool = new Pool(1);
+      var pool = Pool(1);
       var resource1 = await pool.request();
 
-      var completer = new Completer();
+      var completer = Completer();
       expect(
           pool.request().then((resource2) {
             expect(completer.isCompleted, isTrue);
@@ -323,13 +324,13 @@
       expect(pool.close(), completes);
 
       resource1.allowRelease(() => completer.future);
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
 
       completer.complete();
     });
 
     test("doesn't complete until all resources are released", () async {
-      var pool = new Pool(2);
+      var pool = Pool(2);
       var resource1 = await pool.request();
       var resource2 = await pool.request();
       var resource3Future = pool.request();
@@ -347,11 +348,11 @@
 
       resource1Released = true;
       resource1.release();
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
 
       resource2Released = true;
       resource2.release();
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
 
       var resource3 = await resource3Future;
       resource3Released = true;
@@ -359,12 +360,12 @@
     });
 
     test("active onReleases complete as usual", () async {
-      var pool = new Pool(1);
+      var pool = Pool(1);
       var resource = await pool.request();
 
       // Set up an onRelease callback whose completion is controlled by
       // [completer].
-      var completer = new Completer();
+      var completer = Completer();
       resource.allowRelease(() => completer.future);
       expect(
           pool.request().then((_) {
@@ -372,21 +373,21 @@
           }),
           completes);
 
-      await new Future.delayed(Duration.zero);
-      pool.close();
+      await Future.delayed(Duration.zero);
+      unawaited(pool.close());
 
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       completer.complete();
     });
 
     test("inactive onReleases fire", () async {
-      var pool = new Pool(2);
+      var pool = Pool(2);
       var resource1 = await pool.request();
       var resource2 = await pool.request();
 
-      var completer1 = new Completer();
+      var completer1 = Completer();
       resource1.allowRelease(() => completer1.future);
-      var completer2 = new Completer();
+      var completer2 = Completer();
       resource2.allowRelease(() => completer2.future);
 
       expect(
@@ -396,42 +397,42 @@
           }),
           completes);
 
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       completer1.complete();
 
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       completer2.complete();
     });
 
     test("new allowReleases fire immediately", () async {
-      var pool = new Pool(1);
+      var pool = Pool(1);
       var resource = await pool.request();
 
-      var completer = new Completer();
+      var completer = Completer();
       expect(
           pool.close().then((_) {
             expect(completer.isCompleted, isTrue);
           }),
           completes);
 
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       resource.allowRelease(() => completer.future);
 
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       completer.complete();
     });
 
     test("an onRelease error is piped to the return value", () async {
-      var pool = new Pool(1);
+      var pool = Pool(1);
       var resource = await pool.request();
 
-      var completer = new Completer();
+      var completer = Completer();
       resource.allowRelease(() => completer.future);
 
       expect(pool.done, throwsA("oh no!"));
       expect(pool.close(), throwsA("oh no!"));
 
-      await new Future.delayed(Duration.zero);
+      await Future.delayed(Duration.zero);
       completer.completeError("oh no!");
     });
   });
@@ -440,20 +441,20 @@
 /// Returns a function that will cause the test to fail if it's called.
 ///
 /// This should only be called within a [FakeAsync.run] zone.
-Function expectNoAsync() {
-  var stack = new Trace.current(1);
+void Function() expectNoAsync() {
+  var stack = Trace.current(1);
   return () => registerException(
-      new TestFailure("Expected function not to be called."), stack);
+      TestFailure("Expected function not to be called."), stack);
 }
 
 /// A matcher for Futures that asserts that they don't complete.
 ///
 /// This should only be called within a [FakeAsync.run] zone.
 Matcher get doesNotComplete => predicate((future) {
-      expect(future, new TypeMatcher<Future>());
+      expect(future, TypeMatcher<Future>());
 
-      var stack = new Trace.current(1);
+      var stack = Trace.current(1);
       future.then((_) => registerException(
-          new TestFailure("Expected future not to complete."), stack));
+          TestFailure("Expected future not to complete."), stack));
       return true;
     });