Turn on stricter analyzer options (#17)

(and fix the associated warnings & errors)
diff --git a/.analysis_options b/.analysis_options
index b941521..b0163e6 100644
--- a/.analysis_options
+++ b/.analysis_options
@@ -15,9 +15,9 @@
 
     # === error rules ===
     - avoid_empty_else
-    # TODO - comment_references
+    - comment_references
     - cancel_subscriptions
-    # TODO - close_sinks
+    - close_sinks
     - control_flow_in_finally
     - empty_statements
     - hash_and_equals
@@ -32,14 +32,14 @@
 
     # === style rules ===
     - always_declare_return_types
-    # TODO - always_specify_types
-    # TODO - annotate_overrides
+    - always_specify_types
+    - annotate_overrides
     # TODO - avoid_as
     - avoid_init_to_null
     - avoid_return_types_on_setters
     - await_only_futures
-    # TODO - camel_case_types
-    # TODO - constant_identifier_names
+    - camel_case_types
+    - constant_identifier_names
     - control_flow_in_finally
     - empty_catches
     - empty_constructor_bodies
@@ -53,14 +53,14 @@
     - package_api_docs
     - package_prefixed_library_names
     - prefer_is_not_empty
-    # TODO - public_member_api_docs
+    - public_member_api_docs
     - slash_for_doc_comments
     - sort_constructors_first
-    # TODO - sort_unnamed_constructors_first
+    - sort_unnamed_constructors_first
     - super_goes_last
-    # TODO - type_annotate_public_apis
+    - type_annotate_public_apis
     - type_init_formals
-    # TODO - unawaited_futures
+    - unawaited_futures
     - unnecessary_brace_in_string_interp
     - unnecessary_getters_setters
 
diff --git a/lib/memory.dart b/lib/memory.dart
index c587499..85dfcc6 100644
--- a/lib/memory.dart
+++ b/lib/memory.dart
@@ -2,6 +2,9 @@
 // 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 'src/backends/memory.dart';
+import 'src/interface.dart';
+
 /// An implementation of [FileSystem] that exists entirely in memory with an
 /// internal representation loosely based on the Filesystem Hierarchy Standard.
 /// [MemoryFileSystem] is suitable for mocking and tests, as well as for
diff --git a/lib/src/backends/chroot/chroot_directory.dart b/lib/src/backends/chroot/chroot_directory.dart
index 901506d..d743760 100644
--- a/lib/src/backends/chroot/chroot_directory.dart
+++ b/lib/src/backends/chroot/chroot_directory.dart
@@ -6,6 +6,8 @@
 
 class _ChrootDirectory extends _ChrootFileSystemEntity<Directory, io.Directory>
     with ForwardingDirectory {
+  _ChrootDirectory(ChrootFileSystem fs, String path) : super(fs, path);
+
   factory _ChrootDirectory.wrapped(
     ChrootFileSystem fs,
     Directory delegate, {
@@ -15,8 +17,6 @@
     return new _ChrootDirectory(fs, localPath);
   }
 
-  _ChrootDirectory(ChrootFileSystem fs, String path) : super(fs, path);
-
   @override
   FileSystemEntityType get expectedType => FileSystemEntityType.DIRECTORY;
 
diff --git a/lib/src/backends/chroot/chroot_file.dart b/lib/src/backends/chroot/chroot_file.dart
index 04b4bea..2e556e9 100644
--- a/lib/src/backends/chroot/chroot_file.dart
+++ b/lib/src/backends/chroot/chroot_file.dart
@@ -4,8 +4,12 @@
 
 part of file.src.backends.chroot;
 
+typedef dynamic _SetupCallback();
+
 class _ChrootFile extends _ChrootFileSystemEntity<File, io.File>
     with ForwardingFile {
+  _ChrootFile(ChrootFileSystem fs, String path) : super(fs, path);
+
   factory _ChrootFile.wrapped(
     ChrootFileSystem fs,
     io.File delegate, {
@@ -15,8 +19,6 @@
     return new _ChrootFile(fs, localPath);
   }
 
-  _ChrootFile(ChrootFileSystem fs, String path) : super(fs, path);
-
   @override
   FileSystemEntityType get expectedType => FileSystemEntityType.FILE;
 
@@ -25,7 +27,7 @@
 
   @override
   Future<File> rename(String newPath) async {
-    var setUp = () {};
+    _SetupCallback setUp = () {};
 
     if (await fileSystem.type(newPath, followLinks: false) ==
         FileSystemEntityType.LINK) {
@@ -72,7 +74,7 @@
 
   @override
   File renameSync(String newPath) {
-    var setUp = () {};
+    _SetupCallback setUp = () {};
 
     if (fileSystem.typeSync(newPath, followLinks: false) ==
         FileSystemEntityType.LINK) {
@@ -125,7 +127,7 @@
     String path = fileSystem._resolve(
       this.path,
       followLinks: false,
-      notFound: recursive ? _NotFoundBehavior.MKDIR : _NotFoundBehavior.ALLOW,
+      notFound: recursive ? _NotFoundBehavior.mkdir : _NotFoundBehavior.allow,
     );
 
     String real() => fileSystem._real(path, resolve: false);
@@ -134,7 +136,7 @@
 
     if (await type() == FileSystemEntityType.LINK) {
       path = fileSystem._resolve(p.basename(path),
-          from: p.dirname(path), notFound: _NotFoundBehavior.ALLOW_AT_TAIL);
+          from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail);
       switch (await type()) {
         case FileSystemEntityType.NOT_FOUND:
           await _rawDelegate(real()).create();
@@ -157,7 +159,7 @@
     String path = fileSystem._resolve(
       this.path,
       followLinks: false,
-      notFound: recursive ? _NotFoundBehavior.MKDIR : _NotFoundBehavior.ALLOW,
+      notFound: recursive ? _NotFoundBehavior.mkdir : _NotFoundBehavior.allow,
     );
 
     String real() => fileSystem._real(path, resolve: false);
@@ -166,7 +168,7 @@
 
     if (type() == FileSystemEntityType.LINK) {
       path = fileSystem._resolve(p.basename(path),
-          from: p.dirname(path), notFound: _NotFoundBehavior.ALLOW_AT_TAIL);
+          from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail);
       switch (type()) {
         case FileSystemEntityType.NOT_FOUND:
           _rawDelegate(real()).createSync();
diff --git a/lib/src/backends/chroot/chroot_file_system.dart b/lib/src/backends/chroot/chroot_file_system.dart
index 9ba2b81..bb51210 100644
--- a/lib/src/backends/chroot/chroot_file_system.dart
+++ b/lib/src/backends/chroot/chroot_file_system.dart
@@ -60,13 +60,14 @@
   String get _localRoot => p.rootPrefix(root);
 
   @override
-  Directory directory(path) => new _ChrootDirectory(this, common.getPath(path));
+  Directory directory(dynamic path) =>
+      new _ChrootDirectory(this, common.getPath(path));
 
   @override
-  File file(path) => new _ChrootFile(this, common.getPath(path));
+  File file(dynamic path) => new _ChrootFile(this, common.getPath(path));
 
   @override
-  Link link(path) => new _ChrootLink(this, common.getPath(path));
+  Link link(dynamic path) => new _ChrootLink(this, common.getPath(path));
 
   @override
   p.Context get path =>
@@ -99,7 +100,7 @@
   /// Gets the path context for this file system given the current working dir.
 
   @override
-  set currentDirectory(path) {
+  set currentDirectory(dynamic path) {
     String value;
     if (path is io.Directory) {
       value = path.path;
@@ -109,7 +110,7 @@
       throw new ArgumentError('Invalid type for "path": ${path?.runtimeType}');
     }
 
-    value = _resolve(value, notFound: _NotFoundBehavior.THROW);
+    value = _resolve(value, notFound: _NotFoundBehavior.throwError);
     String realPath = _real(value, resolve: false);
     switch (delegate.typeSync(realPath, followLinks: false)) {
       case FileSystemEntityType.DIRECTORY:
@@ -128,7 +129,7 @@
     try {
       path = _resolve(path);
     } on FileSystemException {
-      return new Future.value(const _NotFoundFileStat());
+      return new Future<FileStat>.value(const _NotFoundFileStat());
     }
     return delegate.stat(_real(path, resolve: false));
   }
@@ -164,7 +165,8 @@
     try {
       realPath = _real(path, followLinks: followLinks);
     } on FileSystemException {
-      return new Future.value(FileSystemEntityType.NOT_FOUND);
+      return new Future<FileSystemEntityType>.value(
+          FileSystemEntityType.NOT_FOUND);
     }
     return delegate.type(realPath, followLinks: false);
   }
@@ -244,14 +246,20 @@
   /// only if [followLinks] is `true`. Symbolic links found in the middle of
   /// the path will always be resolved.
   ///
-  /// If [throwIfNotFound] is `true`, and the path cannot be resolved, a file
-  /// system exception is thrown - otherwise the resolution will halt and the
-  /// partially resolved path will be returned.
+  /// If the path cannot be resolved, and [notFound] is:
+  ///   - [_NotFoundBehavior.throwError]: a [FileSystemException] is thrown.
+  ///   - [_NotFoundBehavior.mkdir]: the path will be created as needed.
+  ///   - [_NotFoundBehavior.allowAtTail]: a [FileSystemException] is thrown,
+  ///     unless only the *tail* path element cannot be resolved, in which case
+  ///     the resolution will halt at the tail element, and the partially
+  ///     resolved path will be returned.
+  ///   - [_NotFoundBehavior.allow] (the default), the resolution will halt and
+  ///     the partially resolved path will be returned.
   String _resolve(
     String path, {
     String from,
     bool followLinks: true,
-    _NotFoundBehavior notFound: _NotFoundBehavior.ALLOW,
+    _NotFoundBehavior notFound: _NotFoundBehavior.allow,
   }) {
     p.Context ctx = _context;
     String root = _localRoot;
@@ -304,19 +312,19 @@
           }
 
           switch (notFound) {
-            case _NotFoundBehavior.MKDIR:
+            case _NotFoundBehavior.mkdir:
               if (parts.isNotEmpty) {
                 delegate.directory(realPath).createSync();
               }
               break;
-            case _NotFoundBehavior.ALLOW:
+            case _NotFoundBehavior.allow:
               return returnEarly();
-            case _NotFoundBehavior.ALLOW_AT_TAIL:
+            case _NotFoundBehavior.allowAtTail:
               if (parts.isEmpty) {
                 return returnEarly();
               }
               throw notFoundException();
-            case _NotFoundBehavior.THROW:
+            case _NotFoundBehavior.throwError:
               throw notFoundException();
           }
           break;
@@ -351,10 +359,10 @@
 
 /// What to do when `NOT_FOUND` paths are encountered while resolving.
 enum _NotFoundBehavior {
-  ALLOW,
-  ALLOW_AT_TAIL,
-  THROW,
-  MKDIR,
+  allow,
+  allowAtTail,
+  throwError,
+  mkdir,
 }
 
 /// A [FileStat] representing a `NOT_FOUND` entity.
diff --git a/lib/src/backends/chroot/chroot_file_system_entity.dart b/lib/src/backends/chroot/chroot_file_system_entity.dart
index 23a6fc5..a7a8388 100644
--- a/lib/src/backends/chroot/chroot_file_system_entity.dart
+++ b/lib/src/backends/chroot/chroot_file_system_entity.dart
@@ -76,7 +76,7 @@
 
   @override
   String resolveSymbolicLinksSync() =>
-      fileSystem._resolve(path, notFound: _NotFoundBehavior.THROW);
+      fileSystem._resolve(path, notFound: _NotFoundBehavior.throwError);
 
   @override
   Future<FileStat> stat() {
@@ -103,7 +103,7 @@
   @override
   Future<T> delete({bool recursive: false}) async {
     String path = fileSystem._resolve(this.path,
-        followLinks: false, notFound: _NotFoundBehavior.THROW);
+        followLinks: false, notFound: _NotFoundBehavior.throwError);
 
     String real(String path) => fileSystem._real(path, resolve: false);
     Future<FileSystemEntityType> type(String path) =>
@@ -114,7 +114,7 @@
         await fileSystem.delegate.link(real(path)).delete();
       } else {
         String resolvedPath = fileSystem._resolve(p.basename(path),
-            from: p.dirname(path), notFound: _NotFoundBehavior.ALLOW_AT_TAIL);
+            from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail);
         if (!recursive && await type(resolvedPath) != expectedType) {
           String msg = expectedType == FileSystemEntityType.FILE
               ? 'Is a directory'
@@ -133,7 +133,7 @@
   @override
   void deleteSync({bool recursive: false}) {
     String path = fileSystem._resolve(this.path,
-        followLinks: false, notFound: _NotFoundBehavior.THROW);
+        followLinks: false, notFound: _NotFoundBehavior.throwError);
 
     String real(String path) => fileSystem._real(path, resolve: false);
     FileSystemEntityType type(String path) =>
@@ -144,7 +144,7 @@
         fileSystem.delegate.link(real(path)).deleteSync();
       } else {
         String resolvedPath = fileSystem._resolve(p.basename(path),
-            from: p.dirname(path), notFound: _NotFoundBehavior.ALLOW_AT_TAIL);
+            from: p.dirname(path), notFound: _NotFoundBehavior.allowAtTail);
         if (!recursive && type(resolvedPath) != expectedType) {
           String msg = expectedType == FileSystemEntityType.FILE
               ? 'Is a directory'
diff --git a/lib/src/backends/chroot/chroot_link.dart b/lib/src/backends/chroot/chroot_link.dart
index ed66ca0..e0ffa17 100644
--- a/lib/src/backends/chroot/chroot_link.dart
+++ b/lib/src/backends/chroot/chroot_link.dart
@@ -6,6 +6,8 @@
 
 class _ChrootLink extends _ChrootFileSystemEntity<Link, io.Link>
     with ForwardingLink {
+  _ChrootLink(ChrootFileSystem fs, String path) : super(fs, path);
+
   factory _ChrootLink.wrapped(
     ChrootFileSystem fs,
     io.Link delegate, {
@@ -15,8 +17,6 @@
     return new _ChrootLink(fs, localPath);
   }
 
-  _ChrootLink(ChrootFileSystem fs, String path) : super(fs, path);
-
   @override
   Future<bool> exists() => delegate.exists();
 
diff --git a/lib/src/backends/local/local_file_system.dart b/lib/src/backends/local/local_file_system.dart
index 7e285a5..0751e79 100644
--- a/lib/src/backends/local/local_file_system.dart
+++ b/lib/src/backends/local/local_file_system.dart
@@ -9,17 +9,18 @@
 /// Since this implementation of the [FileSystem] interface delegates to
 /// `dart:io`, is is not suitable for use in the browser.
 class LocalFileSystem extends FileSystem {
+  /// Creates a new `LocalFileSystem`.
   const LocalFileSystem();
 
   @override
-  Directory directory(path) =>
+  Directory directory(dynamic path) =>
       new _LocalDirectory(this, shim.newDirectory(path));
 
   @override
-  File file(path) => new _LocalFile(this, shim.newFile(path));
+  File file(dynamic path) => new _LocalFile(this, shim.newFile(path));
 
   @override
-  Link link(path) => new _LocalLink(this, shim.newLink(path));
+  Link link(dynamic path) => new _LocalLink(this, shim.newLink(path));
 
   @override
   p.Context get path => new p.Context();
diff --git a/lib/src/backends/memory/memory_directory.dart b/lib/src/backends/memory/memory_directory.dart
index 9be6b39..34793df 100644
--- a/lib/src/backends/memory/memory_directory.dart
+++ b/lib/src/backends/memory/memory_directory.dart
@@ -55,7 +55,7 @@
     _DirectoryNode node = fileSystem._findNode(dirname);
     _checkExists(node, () => dirname);
     _checkIsDir(node, () => dirname);
-    var name = () => '$basename$_tempCounter';
+    String name() => '$basename$_tempCounter';
     while (node.children.containsKey(name())) {
       _tempCounter++;
     }
@@ -90,7 +90,7 @@
     bool recursive: false,
     bool followLinks: true,
   }) =>
-      new Stream.fromIterable(listSync(
+      new Stream<FileSystemEntity>.fromIterable(listSync(
         recursive: recursive,
         followLinks: followLinks,
       ));
diff --git a/lib/src/backends/memory/memory_file.dart b/lib/src/backends/memory/memory_file.dart
index 05e6d09..66e5abc 100644
--- a/lib/src/backends/memory/memory_file.dart
+++ b/lib/src/backends/memory/memory_file.dart
@@ -146,9 +146,9 @@
             ? content.sublist(start)
             : content.sublist(start, min(end, content.length));
       }
-      return new Stream.fromIterable(<List<int>>[content]);
+      return new Stream<List<int>>.fromIterable(<List<int>>[content]);
     } catch (e) {
-      return new Stream.fromFuture(new Future.error(e));
+      return new Stream<List<int>>.fromFuture(new Future<List<int>>.error(e));
     }
   }
 
@@ -262,7 +262,7 @@
     io.FileMode mode,
     Encoding encoding,
   ) {
-    Future<_FileNode> node = new Future.microtask(() {
+    Future<_FileNode> node = new Future<_FileNode>.microtask(() {
       _FileNode node = file._resolvedBackingOrCreate;
       file._truncateIfNecessary(node, mode);
       return node;
@@ -288,7 +288,7 @@
   void write(Object obj) => add(encoding.encode(obj?.toString() ?? 'null'));
 
   @override
-  void writeAll(Iterable objects, [String separator = ""]) {
+  void writeAll(Iterable<dynamic> objects, [String separator = ""]) {
     bool firstIter = true;
     for (dynamic obj in objects) {
       if (!firstIter && separator != null) {
@@ -309,23 +309,24 @@
   void writeCharCode(int charCode) => write(new String.fromCharCode(charCode));
 
   @override
-  void addError(error, [StackTrace stackTrace]) {
+  void addError(dynamic error, [StackTrace stackTrace]) {
     _checkNotStreaming();
     _completer.completeError(error, stackTrace);
   }
 
   @override
-  Future addStream(Stream<List<int>> stream) {
+  Future<Null> addStream(Stream<List<int>> stream) {
     _checkNotStreaming();
     _streamCompleter = new Completer<Null>();
-    var finish = () {
+    void finish() {
       _streamCompleter.complete();
       _streamCompleter = null;
-    };
+    }
+
     stream.listen(
       (List<int> data) => _addData(data),
       cancelOnError: true,
-      onError: (error, StackTrace stackTrace) {
+      onError: (dynamic error, StackTrace stackTrace) {
         _completer.completeError(error, stackTrace);
         finish();
       },
@@ -335,19 +336,20 @@
   }
 
   @override
-  Future flush() {
+  // TODO(tvolkert): Change to Future<Null> once Dart 1.22 is stable
+  Future<dynamic> flush() {
     _checkNotStreaming();
     return _pendingWrites;
   }
 
   @override
-  Future close() {
+  Future<Null> close() {
     _checkNotStreaming();
     if (!_isClosed) {
       _isClosed = true;
       _pendingWrites.then(
         (_) => _completer.complete(),
-        onError: (error, stackTrace) =>
+        onError: (dynamic error, StackTrace stackTrace) =>
             _completer.completeError(error, stackTrace),
       );
     }
@@ -355,7 +357,7 @@
   }
 
   @override
-  Future get done => _completer.future;
+  Future<Null> get done => _completer.future;
 
   void _addData(List<int> data) {
     _pendingWrites = _pendingWrites.then((_FileNode node) {
diff --git a/lib/src/backends/memory/memory_file_stat.dart b/lib/src/backends/memory/memory_file_stat.dart
index 9497dc5..87d8a6d 100644
--- a/lib/src/backends/memory/memory_file_stat.dart
+++ b/lib/src/backends/memory/memory_file_stat.dart
@@ -5,7 +5,8 @@
 part of file.src.backends.memory;
 
 class _MemoryFileStat implements io.FileStat {
-  static const _notFound = const _MemoryFileStat._internalNotFound();
+  static const _MemoryFileStat _notFound =
+      const _MemoryFileStat._internalNotFound();
 
   @override
   final DateTime changed;
@@ -45,7 +46,16 @@
   @override
   String modeString() {
     int permissions = mode & 0xFFF;
-    var codes = const ['---', '--x', '-w-', '-wx', 'r--', 'r-x', 'rw-', 'rwx'];
+    List<String> codes = const <String>[
+      '---',
+      '--x',
+      '-w-',
+      '-wx',
+      'r--',
+      'r-x',
+      'rw-',
+      'rwx',
+    ];
     List<String> result = <String>[];
     result
       ..add(codes[(permissions >> 6) & 0x7])
diff --git a/lib/src/backends/memory/memory_file_system.dart b/lib/src/backends/memory/memory_file_system.dart
index d379186..4fa8578 100644
--- a/lib/src/backends/memory/memory_file_system.dart
+++ b/lib/src/backends/memory/memory_file_system.dart
@@ -8,7 +8,7 @@
 const String _thisDir = '.';
 const String _parentDir = '..';
 
-/// Visitor callback for use with [_findNode].
+/// Visitor callback for use with `_findNode`.
 ///
 /// [parent] is the parent node of the current path segment and is guaranteed
 /// to be non-null.
@@ -22,10 +22,10 @@
 /// do things like recursively create or delete folders.
 ///
 /// [currentSegment] is the index of the current segment within the overall
-/// path that's being walked by [_findNode].
+/// path that's being walked by `_findNode`.
 ///
 /// [finalSegment] is the index of the final segment that will be walked by
-/// [_findNode].
+/// `_findNode`.
 typedef _Node _SegmentVisitor(
   _DirectoryNode parent,
   String childName,
@@ -51,18 +51,23 @@
   String _systemTemp;
   String _cwd = _separator;
 
+  /// Creates a new `MemoryFileSystem`.
+  ///
+  /// The file system will be empty, and the current directory will be the
+  /// root directory.
   MemoryFileSystem() {
     _root = new _RootNode(this);
   }
 
   @override
-  Directory directory(path) => new _MemoryDirectory(this, common.getPath(path));
+  Directory directory(dynamic path) =>
+      new _MemoryDirectory(this, common.getPath(path));
 
   @override
-  File file(path) => new _MemoryFile(this, common.getPath(path));
+  File file(dynamic path) => new _MemoryFile(this, common.getPath(path));
 
   @override
-  Link link(path) => new _MemoryLink(this, common.getPath(path));
+  Link link(dynamic path) => new _MemoryLink(this, common.getPath(path));
 
   @override
   p.Context get path => new p.Context(style: p.Style.posix, current: _cwd);
diff --git a/lib/src/backends/memory/memory_file_system_entity.dart b/lib/src/backends/memory/memory_file_system_entity.dart
index c8df73e..b5fdcee 100644
--- a/lib/src/backends/memory/memory_file_system_entity.dart
+++ b/lib/src/backends/memory/memory_file_system_entity.dart
@@ -4,7 +4,7 @@
 
 part of file.src.backends.memory;
 
-/// Validator function for use with [_renameSync]. This will be invoked if the
+/// Validator function for use with `_renameSync`. This will be invoked if the
 /// rename would overwrite an existing entity at the new path. If this operation
 /// should not be allowed, this function is expected to throw a
 /// [io.FileSystemException]. The lack of such an exception will be interpreted
@@ -53,7 +53,7 @@
 
   /// Gets the node that backs this file system entity, or if that node is
   /// a symbolic link, the target node. This also will check that the type of
-  /// the node (aftere symlink resolution) matches [expectedType]. If the type
+  /// the node (after symlink resolution) matches [expectedType]. If the type
   /// doesn't match, this will throw a [io.FileSystemException].
   _Node get _resolvedBacking {
     _Node node = _backing;
@@ -67,8 +67,8 @@
   /// match. Note that since this checks the node's `stat` type, symbolic links
   /// will be resolved to their target type for the purpose of this validation.
   ///
-  /// Protected methods that accept a [checkType] argument will default to this
-  /// method if the [checkType] argument is unspecified.
+  /// Protected methods that accept a `checkType` argument will default to this
+  /// method if the `checkType` argument is unspecified.
   void _defaultCheckType(_Node node) {
     _checkType(expectedType, node.stat.type, () => path);
   }
@@ -140,9 +140,9 @@
   /// calling [createChild] for each segment whose child does not already exist.
   ///
   /// When [createChild] is invoked:
-  /// - [parent] will be the parent node for the current segment and is
+  /// - `parent` will be the parent node for the current segment and is
   ///   guaranteed to be non-null.
-  /// - [isFinalSegment] will indicate whether the current segment is the tail
+  /// - `isFinalSegment` will indicate whether the current segment is the tail
   ///   segment, which in turn indicates that this is the segment into which to
   ///   create the node for this entity.
   ///
diff --git a/lib/src/backends/record_replay/encoding.dart b/lib/src/backends/record_replay/encoding.dart
index f71dec2..74d075b 100644
--- a/lib/src/backends/record_replay/encoding.dart
+++ b/lib/src/backends/record_replay/encoding.dart
@@ -5,6 +5,7 @@
 import 'dart:convert';
 
 import 'package:file/file.dart';
+import 'package:file/src/io.dart' as io;
 import 'package:path/path.dart' as p;
 
 import 'common.dart';
@@ -35,19 +36,20 @@
 /// When encoding an object, we will walk this map in iteration order looking
 /// for a matching encoder. Thus, when there are two encoders that match an
 //  object, the first one will win.
-const Map<_TypeMatcher, _Encoder> _kEncoders = const <_TypeMatcher, _Encoder>{
+const Map<_TypeMatcher<dynamic>, _Encoder> _kEncoders =
+    const <_TypeMatcher<dynamic>, _Encoder>{
   const _TypeMatcher<num>(): _encodeRaw,
   const _TypeMatcher<bool>(): _encodeRaw,
   const _TypeMatcher<String>(): _encodeRaw,
   const _TypeMatcher<Null>(): _encodeRaw,
-  const _TypeMatcher<List>(): _encodeRaw,
-  const _TypeMatcher<Map>(): _encodeMap,
-  const _TypeMatcher<Iterable>(): _encodeIterable,
+  const _TypeMatcher<List<dynamic>>(): _encodeRaw,
+  const _TypeMatcher<Map<dynamic, dynamic>>(): _encodeMap,
+  const _TypeMatcher<Iterable<dynamic>>(): _encodeIterable,
   const _TypeMatcher<Symbol>(): getSymbolName,
   const _TypeMatcher<DateTime>(): _encodeDateTime,
   const _TypeMatcher<Uri>(): _encodeUri,
   const _TypeMatcher<p.Context>(): _encodePathContext,
-  const _TypeMatcher<EventImpl>(): _encodeEvent,
+  const _TypeMatcher<EventImpl<dynamic>>(): _encodeEvent,
   const _TypeMatcher<FileSystem>(): _encodeFileSystem,
   const _TypeMatcher<RecordingDirectory>(): _encodeFileSystemEntity,
   const _TypeMatcher<RecordingFile>(): _encodeFileSystemEntity,
@@ -70,7 +72,7 @@
 ///   - [JsonEncoder.withIndent]
 dynamic encode(dynamic object) {
   _Encoder encoder = _encodeDefault;
-  for (_TypeMatcher matcher in _kEncoders.keys) {
+  for (_TypeMatcher<dynamic> matcher in _kEncoders.keys) {
     if (matcher.check(object)) {
       encoder = _kEncoders[matcher];
       break;
@@ -112,14 +114,15 @@
       'cwd': context.current,
     };
 
-Map<String, dynamic> _encodeEvent(EventImpl event) => event.encode();
+Map<String, dynamic> _encodeEvent(EventImpl<dynamic> event) => event.encode();
 
 String _encodeFileSystem(FileSystem fs) => kFileSystemEncodedValue;
 
 /// Encodes a file system entity by using its `uid` as a reference identifier.
 /// During replay, this allows us to tie the return value of of one event to
 /// the object of another.
-String _encodeFileSystemEntity(RecordingFileSystemEntity entity) {
+String _encodeFileSystemEntity(
+    RecordingFileSystemEntity<FileSystemEntity, io.FileSystemEntity> entity) {
   return '${entity.runtimeType}@${entity.uid}';
 }
 
diff --git a/lib/src/backends/record_replay/events.dart b/lib/src/backends/record_replay/events.dart
index a0802ea..bbb1526 100644
--- a/lib/src/backends/record_replay/events.dart
+++ b/lib/src/backends/record_replay/events.dart
@@ -53,7 +53,9 @@
   Map<Symbol, dynamic> get namedArguments;
 }
 
+/// Non-exported implementation of [InvocationEvent].
 abstract class EventImpl<T> implements InvocationEvent<T> {
+  /// Creates a new `EventImpl`.
   EventImpl(this.object, this.result, this.timestamp);
 
   @override
@@ -76,8 +78,10 @@
   String toString() => encode().toString();
 }
 
+/// Non-exported implementation of [PropertyGetEvent].
 class PropertyGetEventImpl<T> extends EventImpl<T>
     implements PropertyGetEvent<T> {
+  /// Create a new `PropertyGetEventImpl`.
   PropertyGetEventImpl(Object object, this.property, T result, int timestamp)
       : super(object, result, timestamp);
 
@@ -91,8 +95,10 @@
       }..addAll(super.encode());
 }
 
+/// Non-exported implementation of [PropertySetEvent].
 class PropertySetEventImpl<T> extends EventImpl<Null>
     implements PropertySetEvent<T> {
+  /// Create a new `PropertySetEventImpl`.
   PropertySetEventImpl(Object object, this.property, this.value, int timestamp)
       : super(object, null, timestamp);
 
@@ -110,11 +116,21 @@
       }..addAll(super.encode());
 }
 
+/// Non-exported implementation of [MethodEvent].
 class MethodEventImpl<T> extends EventImpl<T> implements MethodEvent<T> {
-  MethodEventImpl(Object object, this.method, List<dynamic> positionalArguments,
-      Map<Symbol, dynamic> namedArguments, T result, int timestamp)
-      : this.positionalArguments = new List.unmodifiable(positionalArguments),
-        this.namedArguments = new Map.unmodifiable(namedArguments),
+  /// Create a new `MethodEventImpl`.
+  MethodEventImpl(
+    Object object,
+    this.method,
+    List<dynamic> positionalArguments,
+    Map<Symbol, dynamic> namedArguments,
+    T result,
+    int timestamp,
+  )
+      : this.positionalArguments =
+            new List<dynamic>.unmodifiable(positionalArguments),
+        this.namedArguments =
+            new Map<Symbol, dynamic>.unmodifiable(namedArguments),
         super(object, result, timestamp);
 
   @override
diff --git a/lib/src/backends/record_replay/mutable_recording.dart b/lib/src/backends/record_replay/mutable_recording.dart
index 98a9baf..d75f91a 100644
--- a/lib/src/backends/record_replay/mutable_recording.dart
+++ b/lib/src/backends/record_replay/mutable_recording.dart
@@ -24,7 +24,8 @@
   final Directory destination;
 
   @override
-  List<InvocationEvent<dynamic>> get events => new List.unmodifiable(_events);
+  List<InvocationEvent<dynamic>> get events =>
+      new List<InvocationEvent<dynamic>>.unmodifiable(_events);
 
   // TODO(tvolkert): Add ability to wait for all Future and Stream results
   @override
diff --git a/lib/src/backends/record_replay/recording.dart b/lib/src/backends/record_replay/recording.dart
index 75462c2..a3e5836 100644
--- a/lib/src/backends/record_replay/recording.dart
+++ b/lib/src/backends/record_replay/recording.dart
@@ -20,9 +20,10 @@
 }
 
 /// An [Recording] in progress that can be serialized to disk for later use
-/// in [ReplayFileSystem].
+/// in `ReplayFileSystem`.
 ///
 /// Live recordings exist only in memory until [flush] is called.
+// TODO(tvolkert): Link to ReplayFileSystem in docs once it's implemented
 abstract class LiveRecording extends Recording {
   /// The directory in which recording files will be stored.
   ///
diff --git a/lib/src/backends/record_replay/recording_directory.dart b/lib/src/backends/record_replay/recording_directory.dart
index db74661..0686141 100644
--- a/lib/src/backends/record_replay/recording_directory.dart
+++ b/lib/src/backends/record_replay/recording_directory.dart
@@ -10,9 +10,12 @@
 import 'recording_file_system.dart';
 import 'recording_file_system_entity.dart';
 
+/// [Directory] implementation that records all invocation activity to its file
+/// system's recording.
 class RecordingDirectory
     extends RecordingFileSystemEntity<Directory, io.Directory>
     implements Directory {
+  /// Creates a new `RecordingDirectory`.
   RecordingDirectory(RecordingFileSystem fileSystem, io.Directory delegate)
       : super(fileSystem, delegate) {
     methods.addAll(<Symbol, Function>{
diff --git a/lib/src/backends/record_replay/recording_file.dart b/lib/src/backends/record_replay/recording_file.dart
index a6bd2c4..5365614 100644
--- a/lib/src/backends/record_replay/recording_file.dart
+++ b/lib/src/backends/record_replay/recording_file.dart
@@ -13,8 +13,11 @@
 import 'recording_io_sink.dart';
 import 'recording_random_access_file.dart';
 
+/// [File] implementation that records all invocation activity to its file
+/// system's recording.
 class RecordingFile extends RecordingFileSystemEntity<File, io.File>
     implements File {
+  /// Creates a new `RecordingFile`.
   RecordingFile(RecordingFileSystem fileSystem, io.File delegate)
       : super(fileSystem, delegate) {
     methods.addAll(<Symbol, Function>{
@@ -63,12 +66,17 @@
       _wrapRandomAccessFile(delegate.openSync(mode: mode));
 
   IOSink _openWrite({FileMode mode: FileMode.WRITE, Encoding encoding: UTF8}) {
-    IOSink sink = delegate.openWrite(mode: mode, encoding: encoding);
-    return new RecordingIOSink(fileSystem, sink);
+    return new RecordingIOSink(
+      fileSystem,
+      delegate.openWrite(mode: mode, encoding: encoding),
+    );
   }
 
-  Future<File> _writeAsBytes(List<int> bytes,
-          {FileMode mode: FileMode.WRITE, bool flush: false}) =>
+  Future<File> _writeAsBytes(
+    List<int> bytes, {
+    FileMode mode: FileMode.WRITE,
+    bool flush: false,
+  }) =>
       delegate.writeAsBytes(bytes, mode: mode, flush: flush).then(wrap);
 
   Future<File> _writeAsString(
diff --git a/lib/src/backends/record_replay/recording_file_system.dart b/lib/src/backends/record_replay/recording_file_system.dart
index be99963..aad9c45 100644
--- a/lib/src/backends/record_replay/recording_file_system.dart
+++ b/lib/src/backends/record_replay/recording_file_system.dart
@@ -16,7 +16,7 @@
 ///
 /// This will record all invocations (methods, property getters, and property
 /// setters) that occur on it, in an opaque format that can later be used in
-/// [ReplayFileSystem]. All activity in the [File], [Directory], [Link],
+/// `ReplayFileSystem`. All activity in the [File], [Directory], [Link],
 /// [IOSink], and [RandomAccessFile] instances returned from this API will also
 /// be recorded.
 ///
@@ -35,7 +35,8 @@
 ///     order.
 ///
 /// See also:
-///   - [ReplayFileSystem]
+///   - `ReplayFileSystem`
+// TODO(tvolkert): Link to ReplayFileSystem in docs once it's implemented
 abstract class RecordingFileSystem extends FileSystem {
   /// Creates a new `RecordingFileSystem`.
   ///
@@ -73,9 +74,11 @@
   Stopwatch get stopwatch;
 }
 
+/// Non-exported implementation class for `RecordingFileSystem`.
 class RecordingFileSystemImpl extends FileSystem
     with RecordingProxyMixin
     implements RecordingFileSystem {
+  /// Creates a new `RecordingFileSystemImpl`.
   RecordingFileSystemImpl(
       this.delegate, Directory destination, Stopwatch recordingStopwatch)
       : recording = new MutableRecording(destination),
diff --git a/lib/src/backends/record_replay/recording_file_system_entity.dart b/lib/src/backends/record_replay/recording_file_system_entity.dart
index 097ba0b..e1f695b 100644
--- a/lib/src/backends/record_replay/recording_file_system_entity.dart
+++ b/lib/src/backends/record_replay/recording_file_system_entity.dart
@@ -16,10 +16,13 @@
 import 'recording_link.dart';
 import 'recording_proxy_mixin.dart';
 
+/// [FileSystemEntity] implementation that records all invocation activity to
+/// its file system's recording.
 abstract class RecordingFileSystemEntity<T extends FileSystemEntity,
         D extends io.FileSystemEntity> extends Object
     with RecordingProxyMixin
     implements FileSystemEntity {
+  /// Creates a new `RecordingFileSystemEntity`.
   RecordingFileSystemEntity(this.fileSystem, this.delegate) {
     methods.addAll(<Symbol, Function>{
       #exists: delegate.exists,
@@ -56,28 +59,36 @@
   @override
   Stopwatch get stopwatch => fileSystem.stopwatch;
 
+  /// The entity to which this entity delegates its functionality while
+  /// recording.
   @protected
   final D delegate;
 
   /// Returns an entity with the same file system and same type as this
   /// entity but backed by the specified delegate.
   ///
-  /// If the specified delegate is the same as this entity's delegate, this
-  /// will return this entity.
-  ///
-  /// Subclasses should override this method to instantiate the correct wrapped
-  /// type if this super implementation returns `null`.
+  /// This base implementation checks to see if the specified delegate is the
+  /// same as this entity's delegate, and if so, it returns this entity.
+  /// Otherwise it returns `null`. Subclasses should override this method to
+  /// instantiate the correct wrapped type only if this super implementation
+  /// returns `null`.
   @protected
   @mustCallSuper
   T wrap(D delegate) => delegate == this.delegate ? this as T : null;
 
+  /// Returns a directory with the same file system as this entity but backed
+  /// by the specified delegate directory.
   @protected
   Directory wrapDirectory(io.Directory delegate) =>
       new RecordingDirectory(fileSystem, delegate);
 
+  /// Returns a file with the same file system as this entity but backed
+  /// by the specified delegate file.
   @protected
   File wrapFile(io.File delegate) => new RecordingFile(fileSystem, delegate);
 
+  /// Returns a link with the same file system as this entity but backed
+  /// by the specified delegate link.
   @protected
   Link wrapLink(io.Link delegate) => new RecordingLink(fileSystem, delegate);
 
diff --git a/lib/src/backends/record_replay/recording_io_sink.dart b/lib/src/backends/record_replay/recording_io_sink.dart
index 8cff748..ea20004 100644
--- a/lib/src/backends/record_replay/recording_io_sink.dart
+++ b/lib/src/backends/record_replay/recording_io_sink.dart
@@ -11,12 +11,18 @@
 import 'recording_file_system.dart';
 import 'recording_proxy_mixin.dart';
 
+/// [IOSink] implementation that records all invocation activity to its file
+/// system's recording.
 class RecordingIOSink extends Object
     with RecordingProxyMixin
     implements IOSink {
+  /// The file system that owns this sink.
   final RecordingFileSystem fileSystem;
+
+  /// The sink to which this sink delegates its functionality while recording.
   final IOSink delegate;
 
+  /// Creates a new `RecordingIOSink`.
   RecordingIOSink(this.fileSystem, this.delegate) {
     methods.addAll(<Symbol, Function>{
       #add: delegate.add,
diff --git a/lib/src/backends/record_replay/recording_link.dart b/lib/src/backends/record_replay/recording_link.dart
index 2154551..0114499 100644
--- a/lib/src/backends/record_replay/recording_link.dart
+++ b/lib/src/backends/record_replay/recording_link.dart
@@ -10,8 +10,11 @@
 import 'recording_file_system.dart';
 import 'recording_file_system_entity.dart';
 
+/// [Link] implementation that records all invocation activity to its file
+/// system's recording.
 class RecordingLink extends RecordingFileSystemEntity<Link, io.Link>
     implements Link {
+  /// Creates a new `RecordingLink`.
   RecordingLink(RecordingFileSystem fileSystem, io.Link delegate)
       : super(fileSystem, delegate) {
     methods.addAll(<Symbol, Function>{
diff --git a/lib/src/backends/record_replay/recording_proxy_mixin.dart b/lib/src/backends/record_replay/recording_proxy_mixin.dart
index 77e6490..bf69f74 100644
--- a/lib/src/backends/record_replay/recording_proxy_mixin.dart
+++ b/lib/src/backends/record_replay/recording_proxy_mixin.dart
@@ -113,13 +113,15 @@
     T recordEvent<T>(T value) {
       InvocationEvent<T> event;
       if (invocation.isGetter) {
-        event = new PropertyGetEventImpl(this, name, value, time);
+        event = new PropertyGetEventImpl<T>(this, name, value, time);
       } else if (invocation.isSetter) {
         // TODO(tvolkert): Remove indirection once SDK 1.22 is in stable branch
-        dynamic temp = new PropertySetEventImpl(this, name, args[0], time);
+        dynamic temp =
+            new PropertySetEventImpl<dynamic>(this, name, args[0], time);
         event = temp;
       } else {
-        event = new MethodEventImpl(this, name, args, namedArgs, value, time);
+        event =
+            new MethodEventImpl<T>(this, name, args, namedArgs, value, time);
       }
       recording.add(event);
       return value;
diff --git a/lib/src/backends/record_replay/recording_random_access_file.dart b/lib/src/backends/record_replay/recording_random_access_file.dart
index 2b1d911..e0bf90d 100644
--- a/lib/src/backends/record_replay/recording_random_access_file.dart
+++ b/lib/src/backends/record_replay/recording_random_access_file.dart
@@ -12,12 +12,19 @@
 import 'recording_file_system.dart';
 import 'recording_proxy_mixin.dart';
 
+/// [RandomAccessFile] implementation that records all invocation activity to
+/// its file system's recording.
 class RecordingRandomAccessFile extends Object
     with RecordingProxyMixin
     implements RandomAccessFile {
+  /// The file system that owns this random access file.
   final RecordingFileSystem fileSystem;
+
+  /// The random access file to which this random access file delegates its
+  /// functionality while recording.
   final RandomAccessFile delegate;
 
+  /// Creates a new `RecordingRandomAccessFile`.
   RecordingRandomAccessFile(this.fileSystem, this.delegate) {
     methods.addAll(<Symbol, Function>{
       #close: _close,
diff --git a/lib/src/common.dart b/lib/src/common.dart
index 27ab4fa..24dc7be 100644
--- a/lib/src/common.dart
+++ b/lib/src/common.dart
@@ -4,7 +4,8 @@
 
 import 'package:file/src/io.dart' as io;
 
-String getPath(path) {
+/// Gets the string path represented by the specified generic [path].
+String getPath(dynamic path) {
   if (path is io.FileSystemEntity) {
     return path.path;
   } else if (path is String) {
diff --git a/lib/src/forwarding/forwarding_file_system.dart b/lib/src/forwarding/forwarding_file_system.dart
index ec5efda..f6c62dc 100644
--- a/lib/src/forwarding/forwarding_file_system.dart
+++ b/lib/src/forwarding/forwarding_file_system.dart
@@ -15,13 +15,13 @@
   ForwardingFileSystem(this.delegate);
 
   @override
-  Directory directory(path) => delegate.directory(path);
+  Directory directory(dynamic path) => delegate.directory(path);
 
   @override
-  File file(path) => delegate.file(path);
+  File file(dynamic path) => delegate.file(path);
 
   @override
-  Link link(path) => delegate.link(path);
+  Link link(dynamic path) => delegate.link(path);
 
   @override
   p.Context get path => delegate.path;
diff --git a/lib/src/interface/file_system.dart b/lib/src/interface/file_system.dart
index 56cc004..abd954e 100644
--- a/lib/src/interface/file_system.dart
+++ b/lib/src/interface/file_system.dart
@@ -11,22 +11,23 @@
 /// dependence on the library (and the associated implications of using that
 /// implementation in the browser).
 abstract class FileSystem {
+  /// Creates a new `FileSystem`.
   const FileSystem();
 
   /// Returns a reference to a [Directory] at [path].
   ///
   /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`].
-  Directory directory(path);
+  Directory directory(dynamic path);
 
   /// Returns a reference to a [File] at [path].
   ///
   /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`].
-  File file(path);
+  File file(dynamic path);
 
   /// Returns a reference to a [Link] at [path].
   ///
   /// [path] can be either a [`String`], a [`Uri`], or a [`FileSystemEntity`].
-  Link link(path);
+  Link link(dynamic path);
 
   /// An object for manipulating paths in this file system.
   path.Context get path;
@@ -47,7 +48,7 @@
   /// Relative paths will be resolved by the underlying file system
   /// implementation (meaning it is up to the underlying implementation to
   /// decide whether to support relative paths).
-  set currentDirectory(path);
+  set currentDirectory(dynamic path);
 
   /// Asynchronously calls the operating system's stat() function on [path].
   /// Returns a Future which completes with a [FileStat] object containing
@@ -86,27 +87,27 @@
   /// exist.
   bool identicalSync(String path1, String path2);
 
-  /// Tests if [watch] is supported on the current system.
+  /// Tests if [FileSystemEntity.watch] is supported on the current system.
   bool get isWatchSupported;
 
   /// Finds the type of file system object that a [path] points to. Returns
   /// a Future<FileSystemEntityType> that completes with the result.
   ///
-  /// [FileSystemEntityType.LINK] will only be returned if [followLinks] is
+  /// [io.FileSystemEntityType.LINK] will only be returned if [followLinks] is
   /// `false`, and [path] points to a link
   ///
   /// If the [path] does not point to a file system object or an error occurs
-  /// then [FileSystemEntityType.NOT_FOUND] is returned.
+  /// then [io.FileSystemEntityType.NOT_FOUND] is returned.
   Future<io.FileSystemEntityType> type(String path, {bool followLinks: true});
 
   /// Syncronously finds the type of file system object that a [path] points
   /// to. Returns a [FileSystemEntityType].
   ///
-  /// [FileSystemEntityType.LINK] will only be returned if [followLinks] is
+  /// [io.FileSystemEntityType.LINK] will only be returned if [followLinks] is
   /// `false`, and [path] points to a link
   ///
   /// If the [path] does not point to a file system object or an error occurs
-  /// then [FileSystemEntityType.NOT_FOUND] is returned.
+  /// then [io.FileSystemEntityType.NOT_FOUND] is returned.
   io.FileSystemEntityType typeSync(String path, {bool followLinks: true});
 
   /// Checks if [`type(path)`](type) returns [io.FileSystemEntityType.FILE].
diff --git a/lib/src/io/interface.dart b/lib/src/io/interface.dart
index b2aa6bb..46777aa 100644
--- a/lib/src/io/interface.dart
+++ b/lib/src/io/interface.dart
@@ -5,139 +5,307 @@
 import 'dart:async';
 import 'dart:convert';
 
+// ignore: public_member_api_docs
 abstract class Directory implements FileSystemEntity {
-  String get path;
-  Uri get uri;
+  // ignore: public_member_api_docs
   Future<Directory> create({bool recursive: false});
+
+  // ignore: public_member_api_docs
   void createSync({bool recursive: false});
+
+  // ignore: public_member_api_docs
   Future<Directory> createTemp([String prefix]);
+
+  // ignore: public_member_api_docs
   Directory createTempSync([String prefix]);
-  Future<String> resolveSymbolicLinks();
-  String resolveSymbolicLinksSync();
+
+  @override
   Future<Directory> rename(String newPath);
+
+  @override
   Directory renameSync(String newPath);
+
+  @override
   Directory get absolute;
+
+  // ignore: public_member_api_docs
   Stream<FileSystemEntity> list(
       {bool recursive: false, bool followLinks: true});
+
+  // ignore: public_member_api_docs
   List<FileSystemEntity> listSync(
       {bool recursive: false, bool followLinks: true});
 }
 
+// ignore: public_member_api_docs
 abstract class File implements FileSystemEntity {
-  String get path;
+  // ignore: public_member_api_docs
   Future<File> create({bool recursive: false});
+
+  // ignore: public_member_api_docs
   void createSync({bool recursive: false});
+
+  @override
   Future<File> rename(String newPath);
+
+  @override
   File renameSync(String newPath);
+
+  // ignore: public_member_api_docs
   Future<File> copy(String newPath);
+
+  // ignore: public_member_api_docs
   File copySync(String newPath);
+
+  // ignore: public_member_api_docs
   Future<int> length();
+
+  // ignore: public_member_api_docs
   int lengthSync();
+
+  @override
   File get absolute;
+
+  // ignore: public_member_api_docs
   Future<DateTime> lastModified();
+
+  // ignore: public_member_api_docs
   DateTime lastModifiedSync();
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> open({FileMode mode: FileMode.READ});
+
+  // ignore: public_member_api_docs
   RandomAccessFile openSync({FileMode mode: FileMode.READ});
+
+  // ignore: public_member_api_docs
   Stream<List<int>> openRead([int start, int end]);
+
+  // ignore: public_member_api_docs
   IOSink openWrite({FileMode mode: FileMode.WRITE, Encoding encoding: UTF8});
+
+  // ignore: public_member_api_docs
   Future<List<int>> readAsBytes();
+
+  // ignore: public_member_api_docs
   List<int> readAsBytesSync();
+
+  // ignore: public_member_api_docs
   Future<String> readAsString({Encoding encoding: UTF8});
+
+  // ignore: public_member_api_docs
   String readAsStringSync({Encoding encoding: UTF8});
+
+  // ignore: public_member_api_docs
   Future<List<String>> readAsLines({Encoding encoding: UTF8});
+
+  // ignore: public_member_api_docs
   List<String> readAsLinesSync({Encoding encoding: UTF8});
+
+  // ignore: public_member_api_docs
   Future<File> writeAsBytes(List<int> bytes,
       {FileMode mode: FileMode.WRITE, bool flush: false});
+
+  // ignore: public_member_api_docs
   void writeAsBytesSync(List<int> bytes,
       {FileMode mode: FileMode.WRITE, bool flush: false});
+
+  // ignore: public_member_api_docs
   Future<File> writeAsString(String contents,
       {FileMode mode: FileMode.WRITE,
       Encoding encoding: UTF8,
       bool flush: false});
+
+  // ignore: public_member_api_docs
   void writeAsStringSync(String contents,
       {FileMode mode: FileMode.WRITE,
       Encoding encoding: UTF8,
       bool flush: false});
 }
 
+// ignore: public_member_api_docs
 enum FileLock {
+  // ignore: constant_identifier_names, public_member_api_docs
   SHARED,
+
+  // ignore: constant_identifier_names, public_member_api_docs
   EXCLUSIVE,
+
+  // ignore: constant_identifier_names, public_member_api_docs
   BLOCKING_SHARED,
+
+  // ignore: constant_identifier_names, public_member_api_docs
   BLOCKING_EXCLUSIVE,
 }
 
+// ignore: public_member_api_docs
 class FileMode {
-  static const READ = const FileMode._internal(0);
-  static const WRITE = const FileMode._internal(1);
-  static const APPEND = const FileMode._internal(2);
-  static const WRITE_ONLY = const FileMode._internal(3);
-  static const WRITE_ONLY_APPEND = const FileMode._internal(4);
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileMode READ = const FileMode._internal(0);
+
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileMode WRITE = const FileMode._internal(1);
+
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileMode APPEND = const FileMode._internal(2);
+
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileMode WRITE_ONLY = const FileMode._internal(3);
+
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileMode WRITE_ONLY_APPEND = const FileMode._internal(4);
+
   final int _mode; // ignore: unused_field
+
   const FileMode._internal(this._mode);
 }
 
+// ignore: public_member_api_docs
 abstract class FileStat {
+  // ignore: public_member_api_docs
   DateTime get changed;
+
+  // ignore: public_member_api_docs
   DateTime get modified;
+
+  // ignore: public_member_api_docs
   DateTime get accessed;
+
+  // ignore: public_member_api_docs
   FileSystemEntityType get type;
+
+  // ignore: public_member_api_docs
   int get mode;
+
+  // ignore: public_member_api_docs
   int get size;
+
+  // ignore: public_member_api_docs
   String modeString();
 }
 
+// ignore: public_member_api_docs
 abstract class FileSystemEntity {
+  // ignore: public_member_api_docs
   String get path;
+
+  // ignore: public_member_api_docs
   Uri get uri;
+
+  // ignore: public_member_api_docs
   Future<bool> exists();
+
+  // ignore: public_member_api_docs
   bool existsSync();
+
+  // ignore: public_member_api_docs
   Future<FileSystemEntity> rename(String newPath);
+
+  // ignore: public_member_api_docs
   FileSystemEntity renameSync(String newPath);
+
+  // ignore: public_member_api_docs
   Future<String> resolveSymbolicLinks();
+
+  // ignore: public_member_api_docs
   String resolveSymbolicLinksSync();
+
+  // ignore: public_member_api_docs
   Future<FileStat> stat();
+
+  // ignore: public_member_api_docs
   FileStat statSync();
+
+  // ignore: public_member_api_docs
   Future<FileSystemEntity> delete({bool recursive: false});
+
+  // ignore: public_member_api_docs
   void deleteSync({bool recursive: false});
+
+  // ignore: public_member_api_docs
   Stream<FileSystemEvent> watch(
       {int events: FileSystemEvent.ALL, bool recursive: false});
+
+  // ignore: public_member_api_docs
   bool get isAbsolute;
+
+  // ignore: public_member_api_docs
   FileSystemEntity get absolute;
+
+  // ignore: public_member_api_docs
   Directory get parent;
 }
 
+// ignore: public_member_api_docs
 class FileSystemEntityType {
-  static const FILE = const FileSystemEntityType._internal(0);
-  static const DIRECTORY = const FileSystemEntityType._internal(1);
-  static const LINK = const FileSystemEntityType._internal(2);
-  static const NOT_FOUND = const FileSystemEntityType._internal(3);
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileSystemEntityType FILE =
+      const FileSystemEntityType._internal(0);
+
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileSystemEntityType DIRECTORY =
+      const FileSystemEntityType._internal(1);
+
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileSystemEntityType LINK =
+      const FileSystemEntityType._internal(2);
+
+  // ignore: constant_identifier_names, public_member_api_docs
+  static const FileSystemEntityType NOT_FOUND =
+      const FileSystemEntityType._internal(3);
 
   final int _type;
   const FileSystemEntityType._internal(this._type);
 
-  String toString() => const ['FILE', 'DIRECTORY', 'LINK', 'NOT_FOUND'][_type];
+  // ignore: public_member_api_docs
+  @override
+  String toString() =>
+      const <String>['FILE', 'DIRECTORY', 'LINK', 'NOT_FOUND'][_type];
 }
 
+// ignore: public_member_api_docs
 abstract class FileSystemEvent {
+  // ignore: constant_identifier_names, public_member_api_docs
   static const int CREATE = 1 << 0;
+
+  // ignore: constant_identifier_names, public_member_api_docs
   static const int MODIFY = 1 << 1;
+
+  // ignore: constant_identifier_names, public_member_api_docs
   static const int DELETE = 1 << 2;
+
+  // ignore: constant_identifier_names, public_member_api_docs
   static const int MOVE = 1 << 3;
+
+  // ignore: constant_identifier_names, public_member_api_docs
   static const int ALL = CREATE | MODIFY | DELETE | MOVE;
 
+  // ignore: public_member_api_docs
   int get type;
+
+  // ignore: public_member_api_docs
   String get path;
+
+  // ignore: public_member_api_docs
   bool get isDirectory;
 }
 
+// ignore: public_member_api_docs
 class FileSystemException implements IOException {
-  final String message;
-  final String path;
-  final OSError osError;
-
+  // ignore: public_member_api_docs
   const FileSystemException([this.message = "", this.path = "", this.osError]);
 
+  // ignore: public_member_api_docs
+  final String message;
+
+  // ignore: public_member_api_docs
+  final String path;
+
+  // ignore: public_member_api_docs
+  final OSError osError;
+
+  // ignore: public_member_api_docs
+  @override
   String toString() {
     StringBuffer sb = new StringBuffer();
     sb.write("FileSystemException");
@@ -161,44 +329,101 @@
   }
 }
 
+// ignore: public_member_api_docs
 abstract class IOException implements Exception {}
 
+// ignore: public_member_api_docs
 abstract class IOSink implements StreamSink<List<int>>, StringSink {
+  // ignore: public_member_api_docs
   Encoding encoding;
+
+  // ignore: public_member_api_docs
+  @override
   void add(List<int> data);
+
+  // ignore: public_member_api_docs
+  @override
   void write(Object obj);
-  void writeAll(Iterable objects, [String separator = ""]);
+
+  // ignore: public_member_api_docs
+  @override
+  void writeAll(Iterable<dynamic> objects, [String separator = ""]);
+
+  // ignore: public_member_api_docs
+  @override
   void writeln([Object obj = ""]);
+
+  // ignore: public_member_api_docs
+  @override
   void writeCharCode(int charCode);
-  void addError(error, [StackTrace stackTrace]);
-  Future addStream(Stream<List<int>> stream);
-  Future flush();
-  Future close();
-  Future get done;
+
+  // ignore: public_member_api_docs
+  @override
+  void addError(dynamic error, [StackTrace stackTrace]);
+
+  // ignore: public_member_api_docs
+  @override
+  Future<dynamic> addStream(Stream<List<int>> stream);
+
+  // ignore: public_member_api_docs
+  Future<dynamic> flush();
+
+  // ignore: public_member_api_docs
+  @override
+  Future<dynamic> close();
+
+  // ignore: public_member_api_docs
+  @override
+  Future<dynamic> get done;
 }
 
+// ignore: public_member_api_docs
 abstract class Link implements FileSystemEntity {
+  // ignore: public_member_api_docs
   Future<Link> create(String target, {bool recursive: false});
+
+  // ignore: public_member_api_docs
   void createSync(String target, {bool recursive: false});
+
+  // ignore: public_member_api_docs
   void updateSync(String target);
+
+  // ignore: public_member_api_docs
   Future<Link> update(String target);
-  Future<String> resolveSymbolicLinks();
-  String resolveSymbolicLinksSync();
+
+  // ignore: public_member_api_docs
+  @override
   Future<Link> rename(String newPath);
+
+  // ignore: public_member_api_docs
+  @override
   Link renameSync(String newPath);
+
+  // ignore: public_member_api_docs
+  @override
   Link get absolute;
+
+  // ignore: public_member_api_docs
   Future<String> target();
+
+  // ignore: public_member_api_docs
   String targetSync();
 }
 
+// ignore: public_member_api_docs
 class OSError {
+  // ignore: public_member_api_docs
   static const int noErrorCode = -1;
 
-  final String message;
-  final int errorCode;
-
+  // ignore: public_member_api_docs
   const OSError([this.message = "", this.errorCode = noErrorCode]);
 
+  // ignore: public_member_api_docs
+  final String message;
+
+  // ignore: public_member_api_docs
+  final int errorCode;
+
   @override
   String toString() {
     StringBuffer sb = new StringBuffer();
@@ -215,38 +440,96 @@
   }
 }
 
+// ignore: public_member_api_docs
 abstract class RandomAccessFile {
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> close();
+
+  // ignore: public_member_api_docs
   void closeSync();
+
+  // ignore: public_member_api_docs
   Future<int> readByte();
+
+  // ignore: public_member_api_docs
   int readByteSync();
+
+  // ignore: public_member_api_docs
   Future<List<int>> read(int bytes);
+
+  // ignore: public_member_api_docs
   List<int> readSync(int bytes);
+
+  // ignore: public_member_api_docs
   Future<int> readInto(List<int> buffer, [int start = 0, int end]);
+
+  // ignore: public_member_api_docs
   int readIntoSync(List<int> buffer, [int start = 0, int end]);
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> writeByte(int value);
+
+  // ignore: public_member_api_docs
   int writeByteSync(int value);
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> writeFrom(List<int> buffer,
       [int start = 0, int end]);
+
+  // ignore: public_member_api_docs
   void writeFromSync(List<int> buffer, [int start = 0, int end]);
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> writeString(String string,
       {Encoding encoding: UTF8});
+
+  // ignore: public_member_api_docs
   void writeStringSync(String string, {Encoding encoding: UTF8});
+
+  // ignore: public_member_api_docs
   Future<int> position();
+
+  // ignore: public_member_api_docs
   int positionSync();
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> setPosition(int position);
+
+  // ignore: public_member_api_docs
   void setPositionSync(int position);
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> truncate(int length);
+
+  // ignore: public_member_api_docs
   void truncateSync(int length);
+
+  // ignore: public_member_api_docs
   Future<int> length();
+
+  // ignore: public_member_api_docs
   int lengthSync();
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> flush();
+
+  // ignore: public_member_api_docs
   void flushSync();
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> lock(
       [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]);
+
+  // ignore: public_member_api_docs
   void lockSync(
       [FileLock mode = FileLock.EXCLUSIVE, int start = 0, int end = -1]);
+
+  // ignore: public_member_api_docs
   Future<RandomAccessFile> unlock([int start = 0, int end = -1]);
+
+  // ignore: public_member_api_docs
   void unlockSync([int start = 0, int end = -1]);
+
+  // ignore: public_member_api_docs
   String get path;
 }
diff --git a/lib/src/io/shim_dart_io.dart b/lib/src/io/shim_dart_io.dart
index 73cbdec..18744f0 100644
--- a/lib/src/io/shim_dart_io.dart
+++ b/lib/src/io/shim_dart_io.dart
@@ -8,20 +8,46 @@
 
 import 'package:file/src/common.dart' as common;
 
-io.Directory newDirectory(path) => new io.Directory(common.getPath(path));
-io.File newFile(path) => new io.File(common.getPath(path));
-io.Link newLink(path) => new io.Link(common.getPath(path));
+/// Creates a new [io.Directory] with the specified [path].
+io.Directory newDirectory(dynamic path) =>
+    new io.Directory(common.getPath(path));
+
+/// Creates a new [io.File] with the specified [path].
+io.File newFile(dynamic path) => new io.File(common.getPath(path));
+
+/// Creates a new [io.Link] with the specified [path].
+io.Link newLink(dynamic path) => new io.Link(common.getPath(path));
+
+/// Wraps [io.Directory.systemTemp].
 io.Directory systemTemp() => io.Directory.systemTemp;
+
+/// Wraps [io.Directory.current].
 io.Directory get currentDirectory => io.Directory.current;
+
+/// Wraps [io.Directory.current=].
 set currentDirectory(dynamic path) => io.Directory.current = path;
+
+/// Wraps [io.FileStat.stat].
 Future<io.FileStat> stat(String path) => io.FileStat.stat(path);
+
+/// Wraps [io.FileStat.statSync].
 io.FileStat statSync(String path) => io.FileStat.statSync(path);
+
+/// Wraps [io.FileSystemEntity.identical].
 Future<bool> identical(String path1, String path2) =>
     io.FileSystemEntity.identical(path1, path2);
+
+/// Wraps [io.FileSystemEntity.identicalSync].
 bool identicalSync(String path1, String path2) =>
     io.FileSystemEntity.identicalSync(path1, path2);
+
+/// Wraps [io.FileSystemEntity.isWatchSupported].
 bool get isWatchSupported => io.FileSystemEntity.isWatchSupported;
+
+/// Wraps [io.FileSystemEntity.type].
 Future<io.FileSystemEntityType> type(String path, bool followLinks) =>
     io.FileSystemEntity.type(path, followLinks: followLinks);
+
+/// Wraps [io.FileSystemEntity.typeSync].
 io.FileSystemEntityType typeSync(String path, bool followLinks) =>
     io.FileSystemEntity.typeSync(path, followLinks: followLinks);
diff --git a/lib/src/io/shim_internal.dart b/lib/src/io/shim_internal.dart
index c4b72e8..920c7c7 100644
--- a/lib/src/io/shim_internal.dart
+++ b/lib/src/io/shim_internal.dart
@@ -9,16 +9,41 @@
 const String _requiresIOMsg = 'This operation requires the use of dart:io';
 dynamic _requiresIO() => throw new UnsupportedError(_requiresIOMsg);
 
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 io.Directory newDirectory(_) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 io.File newFile(_) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 io.Link newLink(_) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 io.Directory systemTemp() => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 io.Directory get currentDirectory => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 set currentDirectory(dynamic _) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 Future<io.FileStat> stat(String _) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 io.FileStat statSync(String _) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 Future<bool> identical(String _, String __) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 bool identicalSync(String _, String __) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 bool get isWatchSupported => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 Future<io.FileSystemEntityType> type(String _, bool __) => _requiresIO();
+
+/// Throws [UnsupportedError]; browsers cannot use the `local` library.
 io.FileSystemEntityType typeSync(String _, bool __) => _requiresIO();
diff --git a/lib/src/testing/core_matchers.dart b/lib/src/testing/core_matchers.dart
index d631c2f..a16977a 100644
--- a/lib/src/testing/core_matchers.dart
+++ b/lib/src/testing/core_matchers.dart
@@ -51,6 +51,12 @@
 Matcher throwsFileSystemException([dynamic message]) =>
     new Throws(isFileSystemException(message));
 
+/// Expects the specified [callback] to throw a [FileSystemException] with the
+/// specified [message].
+void expectFileSystemException(dynamic message, void callback()) {
+  expect(callback, throwsFileSystemException(message));
+}
+
 class _FileSystemException extends Matcher {
   final Matcher _matcher;
 
@@ -91,7 +97,11 @@
 
   @override
   Description describeMismatch(
-      item, Description desc, Map matchState, bool verbose) {
+    dynamic item,
+    Description desc,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
     desc.add('has path: \'${item.path}\'').add('\n   Which: ');
     Description pathDesc = new StringDescription();
     _matcher.describeMismatch(item.path, pathDesc, matchState, verbose);
diff --git a/lib/src/testing/record_replay_matchers.dart b/lib/src/testing/record_replay_matchers.dart
index 25cc13e..1475ba4 100644
--- a/lib/src/testing/record_replay_matchers.dart
+++ b/lib/src/testing/record_replay_matchers.dart
@@ -88,14 +88,15 @@
   }
 
   /// @nodoc
+  @override
   bool matches(dynamic item, Map<dynamic, dynamic> matchState) {
     if (!_typeMatcher.matches(item, matchState)) {
-      addStateInfo(matchState, {'matcher': _typeMatcher});
+      addStateInfo(matchState, <String, Matcher>{'matcher': _typeMatcher});
       return false;
     }
     for (Matcher matcher in _fieldMatchers) {
       if (!matcher.matches(item, matchState)) {
-        addStateInfo(matchState, {'matcher': matcher});
+        addStateInfo(matchState, <String, Matcher>{'matcher': matcher});
         return false;
       }
     }
@@ -103,15 +104,20 @@
   }
 
   /// @nodoc
-  Description describeMismatch(dynamic item, Description mismatchDescription,
-      Map matchState, bool verbose) {
+  @override
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
     Matcher matcher = matchState['matcher'];
-    matcher.describeMismatch(
-        item, mismatchDescription, matchState['state'], verbose);
-    return mismatchDescription;
+    matcher.describeMismatch(item, description, matchState['state'], verbose);
+    return description;
   }
 
   /// @nodoc
+  @override
   Description describe(Description description) {
     String divider = '\n  - ';
     return _typeMatcher
@@ -208,17 +214,22 @@
 
   @override
   Description describeMismatch(
-      dynamic item, Description desc, Map matchState, bool verbose) {
-    desc.add('was invoked on: ${item.object}').add('\n   Which: ');
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
+    description.add('was invoked on: ${item.object}').add('\n   Which: ');
     Description matcherDesc = new StringDescription();
     _matcher.describeMismatch(item.object, matcherDesc, matchState, verbose);
-    desc.add(matcherDesc.toString());
-    return desc;
+    description.add(matcherDesc.toString());
+    return description;
   }
 
-  Description describe(Description description) {
-    description.add('on object: ');
-    return _matcher.describe(description);
+  @override
+  Description describe(Description desc) {
+    desc.add('on object: ');
+    return _matcher.describe(desc);
   }
 }
 
@@ -232,18 +243,23 @@
       _matcher.matches(item.result, matchState);
 
   @override
-  Description describeMismatch(dynamic item, Description mismatchDescription,
-      Map matchState, bool verbose) {
-    mismatchDescription.add('returned: ${item.result}').add('\n   Which: ');
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
+    description.add('returned: ${item.result}').add('\n   Which: ');
     Description matcherDesc = new StringDescription();
     _matcher.describeMismatch(item.result, matcherDesc, matchState, verbose);
-    mismatchDescription.add(matcherDesc.toString());
-    return mismatchDescription;
+    description.add(matcherDesc.toString());
+    return description;
   }
 
-  Description describe(Description description) {
-    description.add('with result: ');
-    return _matcher.describe(description);
+  @override
+  Description describe(Description desc) {
+    desc.add('with result: ');
+    return _matcher.describe(desc);
   }
 }
 
@@ -257,8 +273,12 @@
       _kTypeMatchers[type].matches(item, matchState);
 
   @override
-  Description describeMismatch(dynamic item, Description desc,
-      Map<dynamic, dynamic> matchState, bool verbose) {
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
     Type type;
     for (Type matchType in _kTypeMatchers.keys) {
       Matcher matcher = _kTypeMatchers[matchType];
@@ -268,11 +288,11 @@
       }
     }
     if (type != null) {
-      desc.add('is ').add(_kTypeDescriptions[type]);
+      description.add('is ').add(_kTypeDescriptions[type]);
     } else {
-      desc.add('is a ${item.runtimeType}');
+      description.add('is a ${item.runtimeType}');
     }
-    return desc;
+    return description;
   }
 
   @override
@@ -289,21 +309,24 @@
       _matcher.matches(getSymbolName(item.method), matchState);
 
   @override
-  Description describeMismatch(dynamic item, Description mismatchDescription,
-      Map matchState, bool verbose) {
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
     String methodName = getSymbolName(item.method);
-    mismatchDescription
-        .add('invoked method: \'$methodName\'')
-        .add('\n   Which: ');
+    description.add('invoked method: \'$methodName\'').add('\n   Which: ');
     Description matcherDesc = new StringDescription();
     _matcher.describeMismatch(methodName, matcherDesc, matchState, verbose);
-    mismatchDescription.add(matcherDesc.toString());
-    return mismatchDescription;
+    description.add(matcherDesc.toString());
+    return description;
   }
 
-  Description describe(Description description) {
-    description.add('method: ');
-    return _matcher.describe(description);
+  @override
+  Description describe(Description desc) {
+    desc.add('method: ');
+    return _matcher.describe(desc);
   }
 }
 
@@ -317,15 +340,20 @@
       _matcher.matches(item.positionalArguments, matchState);
 
   @override
-  Description describeMismatch(dynamic item, Description desc,
-      Map<dynamic, dynamic> matchState, bool verbose) {
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
     return _matcher.describeMismatch(
-        item.positionalArguments, desc, matchState, verbose);
+        item.positionalArguments, description, matchState, verbose);
   }
 
-  Description describe(Description description) {
-    description.add('with positional arguments: ');
-    return _matcher.describe(description);
+  @override
+  Description describe(Description desc) {
+    desc.add('with positional arguments: ');
+    return _matcher.describe(desc);
   }
 }
 
@@ -343,12 +371,17 @@
       _matcher.matches(item.namedArguments, matchState);
 
   @override
-  Description describeMismatch(dynamic item, Description desc,
-      Map<dynamic, dynamic> matchState, bool verbose) {
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
     return _matcher.describeMismatch(
-        item.namedArguments, desc, matchState, verbose);
+        item.namedArguments, description, matchState, verbose);
   }
 
+  @override
   Description describe(Description description) =>
       description.add('with named argument "$name" = $value');
 }
@@ -363,18 +396,21 @@
       _matcher.matches(getSymbolName(item.property), matchState);
 
   @override
-  Description describeMismatch(dynamic item, Description mismatchDescription,
-      Map matchState, bool verbose) {
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
     String propertyName = getSymbolName(item.property);
-    mismatchDescription
-        .add('got property: \'$propertyName\'')
-        .add('\n   Which: ');
+    description.add('got property: \'$propertyName\'').add('\n   Which: ');
     Description matcherDesc = new StringDescription();
     _matcher.describeMismatch(propertyName, matcherDesc, matchState, verbose);
-    mismatchDescription.add(matcherDesc.toString());
-    return mismatchDescription;
+    description.add(matcherDesc.toString());
+    return description;
   }
 
+  @override
   Description describe(Description description) {
     description.add('gets property: ');
     return _matcher.describe(description);
@@ -398,18 +434,21 @@
   }
 
   @override
-  Description describeMismatch(dynamic item, Description mismatchDescription,
-      Map matchState, bool verbose) {
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
     String propertyName = _getPropertyName(item);
-    mismatchDescription
-        .add('set property: \'$propertyName\'')
-        .add('\n   Which: ');
+    description.add('set property: \'$propertyName\'').add('\n   Which: ');
     Description matcherDesc = new StringDescription();
     _matcher.describeMismatch(propertyName, matcherDesc, matchState, verbose);
-    mismatchDescription.add(matcherDesc.toString());
-    return mismatchDescription;
+    description.add(matcherDesc.toString());
+    return description;
   }
 
+  @override
   Description describe(Description description) {
     description.add('of property: ');
     return _matcher.describe(description);
@@ -426,15 +465,20 @@
       _matcher.matches(item.value, matchState);
 
   @override
-  Description describeMismatch(dynamic item, Description mismatchDescription,
-      Map matchState, bool verbose) {
-    mismatchDescription.add('set value: ${item.value}').add('\n   Which: ');
+  Description describeMismatch(
+    dynamic item,
+    Description description,
+    Map<dynamic, dynamic> matchState,
+    bool verbose,
+  ) {
+    description.add('set value: ${item.value}').add('\n   Which: ');
     Description matcherDesc = new StringDescription();
     _matcher.describeMismatch(item.value, matcherDesc, matchState, verbose);
-    mismatchDescription.add(matcherDesc.toString());
-    return mismatchDescription;
+    description.add(matcherDesc.toString());
+    return description;
   }
 
+  @override
   Description describe(Description description) {
     description.add('to value: ');
     return _matcher.describe(description);
diff --git a/test/chroot_test.dart b/test/chroot_test.dart
index 898a48b..995d08b 100644
--- a/test/chroot_test.dart
+++ b/test/chroot_test.dart
@@ -9,6 +9,7 @@
 import 'package:file/file.dart';
 import 'package:file/local.dart';
 import 'package:file/memory.dart';
+import 'package:file/testing.dart';
 import 'package:test/test.dart';
 
 import 'common_tests.dart';
diff --git a/test/common_tests.dart b/test/common_tests.dart
index 940b06e..c3c2abf 100644
--- a/test/common_tests.dart
+++ b/test/common_tests.dart
@@ -12,9 +12,9 @@
 import 'package:test/test.dart';
 import 'package:test/test.dart' as testpkg show group, test;
 
-void expectFileSystemException(dynamic msg, void callback()) {
-  expect(callback, throwsFileSystemException(msg));
-}
+/// Callback used in [runCommonTests] to produce the root folder in which all
+/// file system entities will be created.
+typedef String RootPathGenerator();
 
 /// Runs a suite of tests common to all file system implementations. All file
 /// system implementations should run *at least* these tests to ensure
@@ -31,10 +31,10 @@
 /// Entries may use regular expression syntax.
 void runCommonTests(
   FileSystem createFileSystem(), {
-  String root(),
+  RootPathGenerator root,
   List<String> skip: const <String>[],
 }) {
-  var rootfn = root;
+  RootPathGenerator rootfn = root;
 
   group('common', () {
     FileSystem fs;
@@ -42,7 +42,7 @@
 
     List<String> stack = <String>[];
 
-    void skipIfNecessary(description, callback()) {
+    void skipIfNecessary(String description, callback()) {
       stack.add(description);
       bool matchesCurrentFrame(String input) =>
           new RegExp('^$input\$').hasMatch(stack.join(' > '));
@@ -52,10 +52,10 @@
       stack.removeLast();
     }
 
-    void group(description, body()) =>
+    void group(String description, body()) =>
         skipIfNecessary(description, () => testpkg.group(description, body));
 
-    void test(description, body()) =>
+    void test(String description, body()) =>
         skipIfNecessary(description, () => testpkg.test(description, body));
 
     /// Returns [path] prefixed by the [root] namespace.
@@ -141,7 +141,7 @@
 
       group('systemTempDirectory', () {
         test('existsAsDirectory', () {
-          var tmp = fs.systemTempDirectory;
+          Directory tmp = fs.systemTempDirectory;
           expect(tmp, isDirectory);
           expect(tmp.existsSync(), isTrue);
         });
@@ -270,20 +270,20 @@
 
         test('isDirectoryForDirectory', () {
           fs.directory(ns('/foo')).createSync();
-          var stat = fs.statSync(ns('/foo'));
+          FileStat stat = fs.statSync(ns('/foo'));
           expect(stat.type, FileSystemEntityType.DIRECTORY);
         });
 
         test('isFileForFile', () {
           fs.file(ns('/foo')).createSync();
-          var stat = fs.statSync(ns('/foo'));
+          FileStat stat = fs.statSync(ns('/foo'));
           expect(stat.type, FileSystemEntityType.FILE);
         });
 
         test('isFileForLinkToFile', () {
           fs.file(ns('/foo')).createSync();
           fs.link(ns('/bar')).createSync(ns('/foo'));
-          var stat = fs.statSync(ns('/bar'));
+          FileStat stat = fs.statSync(ns('/bar'));
           expect(stat.type, FileSystemEntityType.FILE);
         });
 
@@ -291,7 +291,7 @@
           fs.link(ns('/foo')).createSync(ns('/bar'));
           fs.link(ns('/bar')).createSync(ns('/baz'));
           fs.link(ns('/baz')).createSync(ns('/foo'));
-          var stat = fs.statSync(ns('/foo'));
+          FileStat stat = fs.statSync(ns('/foo'));
           expect(stat.type, FileSystemEntityType.NOT_FOUND);
         });
       });
@@ -337,32 +337,33 @@
       group('type', () {
         test('isFileForFile', () {
           fs.file(ns('/foo')).createSync();
-          var type = fs.typeSync(ns('/foo'));
+          FileSystemEntityType type = fs.typeSync(ns('/foo'));
           expect(type, FileSystemEntityType.FILE);
         });
 
         test('isDirectoryForDirectory', () {
           fs.directory(ns('/foo')).createSync();
-          var type = fs.typeSync(ns('/foo'));
+          FileSystemEntityType type = fs.typeSync(ns('/foo'));
           expect(type, FileSystemEntityType.DIRECTORY);
         });
 
         test('isDirectoryForAncestorOfRoot', () {
-          var type = fs.typeSync('../../../../../../../..');
+          FileSystemEntityType type = fs.typeSync('../../../../../../../..');
           expect(type, FileSystemEntityType.DIRECTORY);
         });
 
         test('isFileForLinkToFileAndFollowLinksTrue', () {
           fs.file(ns('/foo')).createSync();
           fs.link(ns('/bar')).createSync(ns('/foo'));
-          var type = fs.typeSync(ns('/bar'));
+          FileSystemEntityType type = fs.typeSync(ns('/bar'));
           expect(type, FileSystemEntityType.FILE);
         });
 
         test('isLinkForLinkToFileAndFollowLinksFalse', () {
           fs.file(ns('/foo')).createSync();
           fs.link(ns('/bar')).createSync(ns('/foo'));
-          var type = fs.typeSync(ns('/bar'), followLinks: false);
+          FileSystemEntityType type =
+              fs.typeSync(ns('/bar'), followLinks: false);
           expect(type, FileSystemEntityType.LINK);
         });
 
@@ -370,17 +371,17 @@
           fs.link(ns('/foo')).createSync(ns('/bar'));
           fs.link(ns('/bar')).createSync(ns('/baz'));
           fs.link(ns('/baz')).createSync(ns('/foo'));
-          var type = fs.typeSync(ns('/foo'));
+          FileSystemEntityType type = fs.typeSync(ns('/foo'));
           expect(type, FileSystemEntityType.NOT_FOUND);
         });
 
         test('isNotFoundForNoEntityAtTail', () {
-          var type = fs.typeSync(ns('/foo'));
+          FileSystemEntityType type = fs.typeSync(ns('/foo'));
           expect(type, FileSystemEntityType.NOT_FOUND);
         });
 
         test('isNotFoundForNoDirectoryInTraversal', () {
-          var type = fs.typeSync(ns('/foo/bar/baz'));
+          FileSystemEntityType type = fs.typeSync(ns('/foo/bar/baz'));
           expect(type, FileSystemEntityType.NOT_FOUND);
         });
       });
@@ -519,30 +520,30 @@
         });
 
         test('succeedsIfDestinationDoesntExist', () {
-          var src = fs.directory(ns('/foo'))..createSync();
-          var dest = src.renameSync(ns('/bar'));
+          Directory src = fs.directory(ns('/foo'))..createSync();
+          Directory dest = src.renameSync(ns('/bar'));
           expect(dest.path, ns('/bar'));
           expect(dest.existsSync(), true);
         });
 
         test('succeedsIfDestinationIsEmptyDirectory', () {
           fs.directory(ns('/bar')).createSync();
-          var src = fs.directory(ns('/foo'))..createSync();
-          var dest = src.renameSync(ns('/bar'));
+          Directory src = fs.directory(ns('/foo'))..createSync();
+          Directory dest = src.renameSync(ns('/bar'));
           expect(src.existsSync(), false);
           expect(dest.existsSync(), true);
         });
 
         test('throwsIfDestinationIsFile', () {
           fs.file(ns('/bar')).createSync();
-          var src = fs.directory(ns('/foo'))..createSync();
+          Directory src = fs.directory(ns('/foo'))..createSync();
           expectFileSystemException('Not a directory', () {
             src.renameSync(ns('/bar'));
           });
         });
 
         test('throwsIfDestinationParentFolderDoesntExist', () {
-          var src = fs.directory(ns('/foo'))..createSync();
+          Directory src = fs.directory(ns('/foo'))..createSync();
           expectFileSystemException('No such file or directory', () {
             src.renameSync(ns('/bar/baz'));
           });
@@ -550,7 +551,7 @@
 
         test('throwsIfDestinationIsNonEmptyDirectory', () {
           fs.file(ns('/bar/baz')).createSync(recursive: true);
-          var src = fs.directory(ns('/foo'))..createSync();
+          Directory src = fs.directory(ns('/foo'))..createSync();
           // The error will be 'Directory not empty' on OS X, but it will be
           // 'File exists' on Linux, so we just ignore it here in the test.
           expectFileSystemException(null, () {
@@ -596,7 +597,7 @@
         });
 
         test('throwsIfDestinationIsLinkToEmptyDirectory', () {
-          var src = fs.directory(ns('/foo'))..createSync();
+          Directory src = fs.directory(ns('/foo'))..createSync();
           fs.directory(ns('/bar')).createSync();
           fs.link(ns('/baz')).createSync(ns('/bar'));
           expectFileSystemException('Not a directory', () {
@@ -605,7 +606,7 @@
         });
 
         test('succeedsIfDestinationIsInDifferentDirectory', () {
-          var src = fs.directory(ns('/foo'))..createSync();
+          Directory src = fs.directory(ns('/foo'))..createSync();
           fs.directory(ns('/bar')).createSync();
           src.renameSync(ns('/bar/baz'));
           expect(fs.typeSync(ns('/foo')), FileSystemEntityType.NOT_FOUND);
@@ -634,19 +635,19 @@
         });
 
         test('succeedsIfEmptyDirectoryExistsAndRecursiveFalse', () {
-          var dir = fs.directory(ns('/foo'))..createSync();
+          Directory dir = fs.directory(ns('/foo'))..createSync();
           dir.deleteSync();
           expect(dir.existsSync(), false);
         });
 
         test('succeedsIfEmptyDirectoryExistsAndRecursiveTrue', () {
-          var dir = fs.directory(ns('/foo'))..createSync();
+          Directory dir = fs.directory(ns('/foo'))..createSync();
           dir.deleteSync(recursive: true);
           expect(dir.existsSync(), false);
         });
 
         test('throwsIfNonEmptyDirectoryExistsAndRecursiveFalse', () {
-          var dir = fs.directory(ns('/foo'))..createSync();
+          Directory dir = fs.directory(ns('/foo'))..createSync();
           fs.file(ns('/foo/bar')).createSync();
           expectFileSystemException('Directory not empty', () {
             dir.deleteSync();
@@ -654,7 +655,7 @@
         });
 
         test('succeedsIfNonEmptyDirectoryExistsAndRecursiveTrue', () {
-          var dir = fs.directory(ns('/foo'))..createSync();
+          Directory dir = fs.directory(ns('/foo'))..createSync();
           fs.file(ns('/foo/bar')).createSync();
           dir.deleteSync(recursive: true);
           expect(fs.directory(ns('/foo')).existsSync(), false);
@@ -823,7 +824,7 @@
         test('handlesParentAndThisFolderReferences', () {
           fs.directory(ns('/foo/bar/baz')).createSync(recursive: true);
           fs.link(ns('/foo/bar/baz/qux')).createSync('../..');
-          var resolved = fs
+          String resolved = fs
               .directory(ns('/foo/./bar/baz/../baz/qux/bar'))
               .resolveSymbolicLinksSync();
           expect(resolved, ns('/foo/bar'));
@@ -839,7 +840,7 @@
           fs.link(ns('/foo/bar/baz')).createSync('../../qux', recursive: true);
           fs.link(ns('/qux')).createSync('quux');
           fs.link(ns('/quux/quuz')).createSync(ns('/foo'), recursive: true);
-          var resolved = fs
+          String resolved = fs
               .directory(ns('/foo//bar/./baz/quuz/bar/..///bar/baz/'))
               .resolveSymbolicLinksSync();
           expect(resolved, ns('/quux'));
@@ -887,29 +888,29 @@
 
         test('resolvesNameCollisions', () {
           fs.directory(ns('/foo/bar')).createSync(recursive: true);
-          var tmp = fs.directory(ns('/foo')).createTempSync('bar');
+          Directory tmp = fs.directory(ns('/foo')).createTempSync('bar');
           expect(tmp.path,
               allOf(isNot(ns('/foo/bar')), startsWith(ns('/foo/bar'))));
         });
 
         test('succeedsWithoutPrefix', () {
-          var dir = fs.directory(ns('/foo'))..createSync();
+          Directory dir = fs.directory(ns('/foo'))..createSync();
           expect(dir.createTempSync().path, startsWith(ns('/foo/')));
         });
 
         test('succeedsWithPrefix', () {
-          var dir = fs.directory(ns('/foo'))..createSync();
+          Directory dir = fs.directory(ns('/foo'))..createSync();
           expect(dir.createTempSync('bar').path, startsWith(ns('/foo/bar')));
         });
 
         test('succeedsWithNestedPathPrefixThatExists', () {
           fs.directory(ns('/foo/bar')).createSync(recursive: true);
-          var tmp = fs.directory(ns('/foo')).createTempSync('bar/baz');
+          Directory tmp = fs.directory(ns('/foo')).createTempSync('bar/baz');
           expect(tmp.path, startsWith(ns('/foo/bar/baz')));
         });
 
         test('throwsWithNestedPathPrefixThatDoesntExist', () {
-          var dir = fs.directory(ns('/foo'))..createSync();
+          Directory dir = fs.directory(ns('/foo'))..createSync();
           expectFileSystemException('No such file or directory', () {
             dir.createTempSync('bar/baz');
           });
@@ -930,7 +931,7 @@
         });
 
         test('returnsCovariantType', () async {
-          void expectIsFileSystemEntity(entity) {
+          void expectIsFileSystemEntity(dynamic entity) {
             expect(entity, isFileSystemEntity);
           }
 
@@ -939,7 +940,7 @@
         });
 
         test('returnsEmptyListForEmptyDirectory', () {
-          var empty = fs.directory(ns('/bar'))..createSync();
+          Directory empty = fs.directory(ns('/bar'))..createSync();
           expect(empty.listSync(), isEmpty);
         });
 
@@ -950,7 +951,7 @@
         });
 
         test('returnsLinkObjectsIfFollowLinksFalse', () {
-          var list = dir.listSync(followLinks: false);
+          List<FileSystemEntity> list = dir.listSync(followLinks: false);
           expect(list, hasLength(3));
           expect(list, contains(allOf(isFile, hasPath(ns('/foo/bar')))));
           expect(list, contains(allOf(isDirectory, hasPath(ns('/foo/baz')))));
@@ -958,7 +959,7 @@
         });
 
         test('followsLinksIfFollowLinksTrue', () {
-          var list = dir.listSync();
+          List<FileSystemEntity> list = dir.listSync();
           expect(list, hasLength(3));
           expect(list, contains(allOf(isFile, hasPath(ns('/foo/bar')))));
           expect(list, contains(allOf(isDirectory, hasPath(ns('/foo/baz')))));
@@ -1005,7 +1006,8 @@
         test('childEntriesNotNormalized', () {
           dir = fs.directory(ns('/bar/baz'))..createSync(recursive: true);
           fs.file(ns('/bar/baz/qux')).createSync();
-          var list = fs.directory(ns('/bar//../bar/./baz')).listSync();
+          List<FileSystemEntity> list =
+              fs.directory(ns('/bar//../bar/./baz')).listSync();
           expect(list, hasLength(1));
           expect(list[0], allOf(isFile, hasPath(ns('/bar//../bar/./baz/qux'))));
         });
@@ -1013,8 +1015,9 @@
         test('symlinksToNotFoundAlwaysReturnedAsLinks', () {
           dir = fs.directory(ns('/bar'))..createSync();
           fs.link(ns('/bar/baz')).createSync('qux');
-          for (bool followLinks in [true, false]) {
-            var list = dir.listSync(followLinks: followLinks);
+          for (bool followLinks in const <bool>[true, false]) {
+            List<FileSystemEntity> list =
+                dir.listSync(followLinks: followLinks);
             expect(list, hasLength(1));
             expect(list[0], allOf(isLink, hasPath(ns('/bar/baz'))));
           }
@@ -1459,7 +1462,7 @@
             });
           } else {
             test('createsFileIfDoesntExistAtTail', () {
-              var raf = fs.file(ns('/bar')).openSync(mode: mode);
+              RandomAccessFile raf = fs.file(ns('/bar')).openSync(mode: mode);
               raf.closeSync();
               expect(fs.file(ns('/bar')).existsSync(), true);
             });
@@ -1833,8 +1836,8 @@
         test('succeedsIfExistsAsFile', () async {
           File f = fs.file(ns('/foo'))..createSync();
           f.writeAsStringSync('Hello world', flush: true);
-          var stream = f.openRead();
-          var data = await stream.toList();
+          Stream<List<int>> stream = f.openRead();
+          List<List<int>> data = await stream.toList();
           expect(data, hasLength(1));
           expect(UTF8.decode(data[0]), 'Hello world');
         });
@@ -1849,8 +1852,8 @@
           File f = fs.file(ns('/foo'))..createSync();
           fs.link(ns('/bar')).createSync(ns('/foo'));
           f.writeAsStringSync('Hello world', flush: true);
-          var stream = fs.file(ns('/bar')).openRead();
-          var data = await stream.toList();
+          Stream<List<int>> stream = fs.file(ns('/bar')).openRead();
+          List<List<int>> data = await stream.toList();
           expect(data, hasLength(1));
           expect(UTF8.decode(data[0]), 'Hello world');
         });
@@ -1858,8 +1861,8 @@
         test('respectsStartAndEndParameters', () async {
           File f = fs.file(ns('/foo'))..createSync();
           f.writeAsStringSync('Hello world', flush: true);
-          var stream = f.openRead(2);
-          var data = await stream.toList();
+          Stream<List<int>> stream = f.openRead(2);
+          List<List<int>> data = await stream.toList();
           expect(data, hasLength(1));
           expect(UTF8.decode(data[0]), 'llo world');
           stream = f.openRead(2, 5);
@@ -1870,15 +1873,15 @@
 
         test('throwsIfStartParameterIsNegative', () async {
           File f = fs.file(ns('/foo'))..createSync();
-          var stream = f.openRead(-2);
+          Stream<List<int>> stream = f.openRead(-2);
           expect(stream.drain(), throwsRangeError);
         });
 
         test('stopsAtEndOfFileIfEndParameterIsPastEndOfFile', () async {
           File f = fs.file(ns('/foo'))..createSync();
           f.writeAsStringSync('Hello world', flush: true);
-          var stream = f.openRead(2, 1024);
-          var data = await stream.toList();
+          Stream<List<int>> stream = f.openRead(2, 1024);
+          List<List<int>> data = await stream.toList();
           expect(data, hasLength(1));
           expect(UTF8.decode(data[0]), 'llo world');
         });
@@ -1886,7 +1889,7 @@
         test('providesSingleSubscriptionStream', () async {
           File f = fs.file(ns('/foo'))..createSync();
           f.writeAsStringSync('Hello world', flush: true);
-          var stream = f.openRead();
+          Stream<List<int>> stream = f.openRead();
           expect(stream.isBroadcast, isFalse);
           await stream.drain();
         });
@@ -1961,7 +1964,7 @@
           bool isSinkClosed = false;
 
           Future<dynamic> closeSink() {
-            var future = sink.close();
+            Future<dynamic> future = sink.close();
             isSinkClosed = true;
             return future;
           }
@@ -2036,14 +2039,14 @@
 
           test('ignoresCloseAfterAlreadyClosed', () async {
             sink.write('Hello world');
-            Future f1 = closeSink();
-            Future f2 = closeSink();
-            await Future.wait([f1, f2]);
+            Future<dynamic> f1 = closeSink();
+            Future<dynamic> f2 = closeSink();
+            await Future.wait(<Future<dynamic>>[f1, f2]);
           });
 
           test('returnsAccurateDoneFuture', () async {
             bool done = false;
-            sink.done.then((_) => done = true);
+            sink.done.then((_) => done = true); // ignore: unawaited_futures
             expect(done, isFalse);
             sink.write('foo');
             expect(done, isFalse);
@@ -2056,7 +2059,7 @@
             bool isControllerClosed = false;
 
             Future<dynamic> closeController() {
-              var future = controller.close();
+              Future<dynamic> future = controller.close();
               isControllerClosed = true;
               return future;
             }
diff --git a/test/recording_test.dart b/test/recording_test.dart
index ec0e52b..e9c5118 100644
--- a/test/recording_test.dart
+++ b/test/recording_test.dart
@@ -37,7 +37,7 @@
       test('supportsMultipleActions', () {
         fs.directory('/foo').createSync();
         fs.file('/foo/bar').writeAsStringSync('BAR');
-        var events = recording.events;
+        List<InvocationEvent<dynamic>> events = recording.events;
         expect(events, hasLength(4));
         expect(events[0], invokesMethod('directory'));
         expect(events[1], invokesMethod('createSync'));
@@ -50,51 +50,54 @@
       group('FileSystem', () {
         test('directory', () {
           fs.directory('/foo');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
-              events[0],
-              invokesMethod('directory')
-                  .on(fs)
-                  .withPositionalArguments(['/foo']).withResult(isDirectory));
+            events[0],
+            invokesMethod('directory').on(fs).withPositionalArguments(
+                <String>['/foo']).withResult(isDirectory),
+          );
         });
 
         test('file', () {
           fs.file('/foo');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
-              events[0],
-              invokesMethod('file')
-                  .on(fs)
-                  .withPositionalArguments(['/foo']).withResult(isFile));
+            events[0],
+            invokesMethod('file')
+                .on(fs)
+                .withPositionalArguments(<String>['/foo']).withResult(isFile),
+          );
         });
 
         test('link', () {
           fs.link('/foo');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
-              events[0],
-              invokesMethod('link')
-                  .on(fs)
-                  .withPositionalArguments(['/foo']).withResult(isLink));
+            events[0],
+            invokesMethod('link')
+                .on(fs)
+                .withPositionalArguments(<String>['/foo']).withResult(isLink),
+          );
         });
 
         test('path', () {
           fs.path;
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
-              events[0],
-              getsProperty('path')
-                  .on(fs)
-                  .withResult(const isInstanceOf<p.Context>()));
+            events[0],
+            getsProperty('path')
+                .on(fs)
+                .withResult(const isInstanceOf<p.Context>()),
+          );
         });
 
         test('systemTempDirectory', () {
           fs.systemTempDirectory;
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
               events[0],
@@ -106,7 +109,7 @@
         group('currentDirectory', () {
           test('get', () {
             fs.currentDirectory;
-            var events = recording.events;
+            List<InvocationEvent<dynamic>> events = recording.events;
             expect(events, hasLength(1));
             expect(
                 events[0],
@@ -118,7 +121,7 @@
           test('setToString', () {
             delegate.directory('/foo').createSync();
             fs.currentDirectory = '/foo';
-            var events = recording.events;
+            List<InvocationEvent<dynamic>> events = recording.events;
             expect(events, hasLength(1));
             expect(events[0],
                 setsProperty('currentDirectory').on(fs).toValue('/foo'));
@@ -127,7 +130,7 @@
           test('setToRecordingDirectory', () {
             delegate.directory('/foo').createSync();
             fs.currentDirectory = fs.directory('/foo');
-            var events = recording.events;
+            List<InvocationEvent<dynamic>> events = recording.events;
             expect(events.length, greaterThanOrEqualTo(2));
             expect(events[0], invokesMethod().withResult(isDirectory));
             Directory directory = events[0].result;
@@ -142,7 +145,7 @@
             Directory dir = delegate.directory('/foo');
             dir.createSync();
             fs.currentDirectory = dir;
-            var events = recording.events;
+            List<InvocationEvent<dynamic>> events = recording.events;
             expect(events, hasLength(1));
             expect(events[0],
                 setsProperty('currentDirectory').on(fs).toValue(isDirectory));
@@ -152,26 +155,24 @@
         test('stat', () async {
           delegate.file('/foo').createSync();
           await fs.stat('/foo');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
             events[0],
-            invokesMethod('stat')
-                .on(fs)
-                .withPositionalArguments(['/foo']).withResult(isFileStat),
+            invokesMethod('stat').on(fs).withPositionalArguments(
+                <String>['/foo']).withResult(isFileStat),
           );
         });
 
         test('statSync', () {
           delegate.file('/foo').createSync();
           fs.statSync('/foo');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
             events[0],
-            invokesMethod('statSync')
-                .on(fs)
-                .withPositionalArguments(['/foo']).withResult(isFileStat),
+            invokesMethod('statSync').on(fs).withPositionalArguments(
+                <String>['/foo']).withResult(isFileStat),
           );
         });
 
@@ -179,29 +180,29 @@
           delegate.file('/foo').createSync();
           delegate.file('/bar').createSync();
           await fs.identical('/foo', '/bar');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
               events[0],
               invokesMethod('identical').on(fs).withPositionalArguments(
-                  ['/foo', '/bar']).withResult(isFalse));
+                  <String>['/foo', '/bar']).withResult(isFalse));
         });
 
         test('identicalSync', () {
           delegate.file('/foo').createSync();
           delegate.file('/bar').createSync();
           fs.identicalSync('/foo', '/bar');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
               events[0],
               invokesMethod('identicalSync').on(fs).withPositionalArguments(
-                  ['/foo', '/bar']).withResult(isFalse));
+                  <String>['/foo', '/bar']).withResult(isFalse));
         });
 
         test('isWatchSupported', () {
           fs.isWatchSupported;
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(events[0],
               getsProperty('isWatchSupported').on(fs).withResult(isFalse));
@@ -210,23 +211,23 @@
         test('type', () async {
           delegate.file('/foo').createSync();
           await fs.type('/foo');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
               events[0],
               invokesMethod('type').on(fs).withPositionalArguments(
-                  ['/foo']).withResult(FileSystemEntityType.FILE));
+                  <String>['/foo']).withResult(FileSystemEntityType.FILE));
         });
 
         test('typeSync', () {
           delegate.file('/foo').createSync();
           fs.typeSync('/foo');
-          var events = recording.events;
+          List<InvocationEvent<dynamic>> events = recording.events;
           expect(events, hasLength(1));
           expect(
               events[0],
               invokesMethod('typeSync').on(fs).withPositionalArguments(
-                  ['/foo']).withResult(FileSystemEntityType.FILE));
+                  <String>['/foo']).withResult(FileSystemEntityType.FILE));
         });
       });