Fix newly enforce package:pedantic lints (#91)

- always_declare_return_types
- annotate_overrides
- omit_local_variable_types
- prefer_collection_literals
- prefer_conditional_assignment
- prefer_single_quotes
- use_function_type_syntax_for_parameters
diff --git a/example/example.dart b/example/example.dart
index b641fd0..af7bd4d 100644
--- a/example/example.dart
+++ b/example/example.dart
@@ -6,10 +6,10 @@
 import 'package:web_socket_channel/status.dart' as status;
 
 void main() async {
-  final channel = await IOWebSocketChannel.connect("ws://localhost:1234");
+  final channel = await IOWebSocketChannel.connect('ws://localhost:1234');
 
   channel.stream.listen((message) {
-    channel.sink.add("received!");
+    channel.sink.add('received!');
     channel.sink.close(status.goingAway);
   });
 }
diff --git a/lib/html.dart b/lib/html.dart
index e2dc145..db42d5d 100644
--- a/lib/html.dart
+++ b/lib/html.dart
@@ -20,11 +20,14 @@
   /// The underlying `dart:html` [WebSocket].
   final WebSocket _webSocket;
 
+  @override
   String get protocol => _webSocket.protocol;
 
+  @override
   int get closeCode => _closeCode;
   int _closeCode;
 
+  @override
   String get closeReason => _closeReason;
   String _closeReason;
 
@@ -44,10 +47,12 @@
   /// [_controller.local.stream].
   String _localCloseReason;
 
+  @override
   Stream get stream => _controller.foreign.stream;
   final _controller =
       StreamChannelController(sync: true, allowForeignErrors: false);
 
+  @override
   WebSocketSink get sink => _sink;
   WebSocketSink _sink;
 
@@ -85,7 +90,7 @@
     // and that once it is no open or message events will be emitted.
     _webSocket.onError.first.then((_) {
       _controller.local.sink
-          .addError(WebSocketChannelException("WebSocket connection failed."));
+          .addError(WebSocketChannelException('WebSocket connection failed.'));
       _controller.local.sink.close();
     });
 
@@ -131,6 +136,7 @@
       : _channel = channel,
         super(channel._controller.foreign.sink);
 
+  @override
   Future close([int closeCode, String closeReason]) {
     _channel._localCloseCode = closeCode;
     _channel._localCloseReason = closeReason;
@@ -142,10 +148,10 @@
 /// messages.
 class BinaryType {
   /// Tells the channel to emit binary messages as [Blob]s.
-  static const blob = BinaryType._("blob", "blob");
+  static const blob = BinaryType._('blob', 'blob');
 
   /// Tells the channel to emit binary messages as [Uint8List]s.
-  static const list = BinaryType._("list", "arraybuffer");
+  static const list = BinaryType._('list', 'arraybuffer');
 
   /// The name of the binary type, which matches its variable name.
   final String name;
@@ -155,5 +161,6 @@
 
   const BinaryType._(this.name, this.value);
 
+  @override
   String toString() => name;
 }
diff --git a/lib/io.dart b/lib/io.dart
index 861b79f..e2a7ce4 100644
--- a/lib/io.dart
+++ b/lib/io.dart
@@ -23,11 +23,16 @@
   /// `null` until the [WebSocket.connect] future completes.
   WebSocket _webSocket;
 
+  @override
   String get protocol => _webSocket?.protocol;
+  @override
   int get closeCode => _webSocket?.closeCode;
+  @override
   String get closeReason => _webSocket?.closeReason;
 
+  @override
   final Stream stream;
+  @override
   final WebSocketSink sink;
 
   // TODO(nweiz): Add a compression parameter after the initial release.
@@ -93,6 +98,7 @@
       : _webSocket = webSocket,
         super(webSocket);
 
+  @override
   Future close([int closeCode, String closeReason]) =>
       _webSocket.close(closeCode, closeReason);
 }
diff --git a/lib/src/channel.dart b/lib/src/channel.dart
index cee27f2..8fcee55 100644
--- a/lib/src/channel.dart
+++ b/lib/src/channel.dart
@@ -51,12 +51,14 @@
   /// Before the connection has been closed, this will be `null`.
   String get closeReason => _webSocket.closeReason;
 
+  @override
   Stream get stream => StreamView(_webSocket);
 
   /// The sink for sending values to the other endpoint.
   ///
   /// This supports additional arguments to [WebSocketSink.close] that provide
   /// the remote endpoint reasons for closing the connection.
+  @override
   WebSocketSink get sink => WebSocketSink._(_webSocket);
 
   /// Signs a `Sec-WebSocket-Key` header sent by a WebSocket client as part of
@@ -125,6 +127,7 @@
   ///
   /// [close code]: https://tools.ietf.org/html/rfc6455#section-7.1.5
   /// [reason]: https://tools.ietf.org/html/rfc6455#section-7.1.6
+  @override
   Future close([int closeCode, String closeReason]) =>
       _webSocket.close(closeCode, closeReason);
 }
diff --git a/lib/src/copy/bytes_builder.dart b/lib/src/copy/bytes_builder.dart
index f34df48..4cbd6d7 100644
--- a/lib/src/copy/bytes_builder.dart
+++ b/lib/src/copy/bytes_builder.dart
@@ -81,10 +81,11 @@
             ? _emptyList
             : Uint8List(_pow2roundup(initialCapacity));
 
+  @override
   void add(List<int> bytes) {
-    int bytesLength = bytes.length;
+    var bytesLength = bytes.length;
     if (bytesLength == 0) return;
-    int required = _length + bytesLength;
+    var required = _length + bytesLength;
     if (_buffer.length < required) {
       _grow(required);
     }
@@ -92,13 +93,14 @@
     if (bytes is Uint8List) {
       _buffer.setRange(_length, required, bytes);
     } else {
-      for (int i = 0; i < bytesLength; i++) {
+      for (var i = 0; i < bytesLength; i++) {
         _buffer[_length + i] = bytes[i];
       }
     }
     _length = required;
   }
 
+  @override
   void addByte(int byte) {
     if (_buffer.length == _length) {
       // The grow algorithm always at least doubles.
@@ -113,7 +115,7 @@
   void _grow(int required) {
     // We will create a list in the range of 2-4 times larger than
     // required.
-    int newSize = required * 2;
+    var newSize = required * 2;
     if (newSize < _INIT_SIZE) {
       newSize = _INIT_SIZE;
     } else {
@@ -124,6 +126,7 @@
     _buffer = newBuffer;
   }
 
+  @override
   Uint8List takeBytes() {
     if (_length == 0) return _emptyList;
     var buffer = Uint8List.view(_buffer.buffer, 0, _length);
@@ -131,17 +134,22 @@
     return buffer;
   }
 
+  @override
   Uint8List toBytes() {
     if (_length == 0) return _emptyList;
     return Uint8List.fromList(Uint8List.view(_buffer.buffer, 0, _length));
   }
 
+  @override
   int get length => _length;
 
+  @override
   bool get isEmpty => _length == 0;
 
+  @override
   bool get isNotEmpty => _length != 0;
 
+  @override
   void clear() {
     _length = 0;
     _buffer = _emptyList;
@@ -163,6 +171,7 @@
   int _length = 0;
   final List<Uint8List> _chunks = [];
 
+  @override
   void add(List<int> bytes) {
     Uint8List typedBytes;
     if (bytes is Uint8List) {
@@ -174,11 +183,13 @@
     _length += typedBytes.length;
   }
 
+  @override
   void addByte(int byte) {
     _chunks.add(Uint8List(1)..[0] = byte);
     _length++;
   }
 
+  @override
   Uint8List takeBytes() {
     if (_length == 0) return _CopyingBytesBuilder._emptyList;
     if (_chunks.length == 1) {
@@ -187,7 +198,7 @@
       return buffer;
     }
     var buffer = Uint8List(_length);
-    int offset = 0;
+    var offset = 0;
     for (var chunk in _chunks) {
       buffer.setRange(offset, offset + chunk.length, chunk);
       offset += chunk.length;
@@ -196,10 +207,11 @@
     return buffer;
   }
 
+  @override
   Uint8List toBytes() {
     if (_length == 0) return _CopyingBytesBuilder._emptyList;
     var buffer = Uint8List(_length);
-    int offset = 0;
+    var offset = 0;
     for (var chunk in _chunks) {
       buffer.setRange(offset, offset + chunk.length, chunk);
       offset += chunk.length;
@@ -207,12 +219,16 @@
     return buffer;
   }
 
+  @override
   int get length => _length;
 
+  @override
   bool get isEmpty => _length == 0;
 
+  @override
   bool get isNotEmpty => _length != 0;
 
+  @override
   void clear() {
     _length = 0;
     _chunks.clear();
diff --git a/lib/src/copy/io_sink.dart b/lib/src/copy/io_sink.dart
index 9e9b7b9..8da7f12 100644
--- a/lib/src/copy/io_sink.dart
+++ b/lib/src/copy/io_sink.dart
@@ -27,6 +27,7 @@
   // The _reportClosedSink method has been deleted for web_socket_channel. This
   // method did nothing but print to stderr, which is unavailable here.
 
+  @override
   void add(T data) {
     if (_isClosed) {
       return;
@@ -34,6 +35,7 @@
     _controller.add(data);
   }
 
+  @override
   void addError(error, [StackTrace stackTrace]) {
     if (_isClosed) {
       return;
@@ -41,9 +43,10 @@
     _controller.addError(error, stackTrace);
   }
 
+  @override
   Future addStream(Stream<T> stream) {
     if (_isBound) {
-      throw StateError("StreamSink is already bound to a stream");
+      throw StateError('StreamSink is already bound to a stream');
     }
     if (_hasError) return done;
 
@@ -62,7 +65,7 @@
 
   Future flush() {
     if (_isBound) {
-      throw StateError("StreamSink is bound to a stream");
+      throw StateError('StreamSink is bound to a stream');
     }
     if (_controllerInstance == null) return Future.value(this);
     // Adding an empty stream-controller will return a future that will complete
@@ -75,9 +78,10 @@
     });
   }
 
+  @override
   Future close() {
     if (_isBound) {
-      throw StateError("StreamSink is bound to a stream");
+      throw StateError('StreamSink is bound to a stream');
     }
     if (!_isClosed) {
       _isClosed = true;
@@ -94,6 +98,7 @@
     _target.close().then(_completeDoneValue, onError: _completeDoneError);
   }
 
+  @override
   Future get done => _doneCompleter.future;
 
   void _completeDoneValue(value) {
@@ -111,10 +116,10 @@
 
   StreamController<T> get _controller {
     if (_isBound) {
-      throw StateError("StreamSink is bound to a stream");
+      throw StateError('StreamSink is bound to a stream');
     }
     if (_isClosed) {
-      throw StateError("StreamSink is closed");
+      throw StateError('StreamSink is closed');
     }
     if (_controllerInstance == null) {
       _controllerInstance = StreamController<T>(sync: true);
diff --git a/lib/src/copy/web_socket_impl.dart b/lib/src/copy/web_socket_impl.dart
index 552b3e4..21464a2 100644
--- a/lib/src/copy/web_socket_impl.dart
+++ b/lib/src/copy/web_socket_impl.dart
@@ -22,7 +22,7 @@
 import 'io_sink.dart';
 import 'web_socket.dart';
 
-const String webSocketGUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+const String webSocketGUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
 
 final _random = Random();
 
@@ -86,7 +86,7 @@
   int _unmaskingIndex = 0;
   int _currentMessageType = _WebSocketMessageType.NONE;
   int closeCode = WebSocketStatus.NO_STATUS_RECEIVED;
-  String closeReason = "";
+  String closeReason = '';
 
   EventSink<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > _eventSink;
 
@@ -96,45 +96,49 @@
 
   _WebSocketProtocolTransformer([this._serverSide = false]);
 
+  @override
   Stream<dynamic /*List<int>|_WebSocketPing|_WebSocketPong*/ > bind(
       Stream<List<int>> stream) {
     return Stream.eventTransformed(stream, (EventSink eventSink) {
       if (_eventSink != null) {
-        throw StateError("WebSocket transformer already used.");
+        throw StateError('WebSocket transformer already used.');
       }
       _eventSink = eventSink;
       return this;
     });
   }
 
+  @override
   void addError(Object error, [StackTrace stackTrace]) {
     _eventSink.addError(error, stackTrace);
   }
 
+  @override
   void close() {
     _eventSink.close();
   }
 
   /// Process data received from the underlying communication channel.
+  @override
   void add(List<int> bytes) {
     var buffer = bytes is Uint8List ? bytes : Uint8List.fromList(bytes);
-    int index = 0;
-    int lastIndex = buffer.length;
+    var index = 0;
+    var lastIndex = buffer.length;
     if (_state == CLOSED) {
-      throw WebSocketChannelException("Data on closed connection");
+      throw WebSocketChannelException('Data on closed connection');
     }
     if (_state == FAILURE) {
-      throw WebSocketChannelException("Data on failed connection");
+      throw WebSocketChannelException('Data on failed connection');
     }
     while ((index < lastIndex) && _state != CLOSED && _state != FAILURE) {
-      int byte = buffer[index];
+      var byte = buffer[index];
       if (_state <= LEN_REST) {
         if (_state == START) {
           _fin = (byte & FIN) != 0;
 
           if ((byte & (RSV2 | RSV3)) != 0) {
             // The RSV2, RSV3 bits must both be zero.
-            throw WebSocketChannelException("Protocol error");
+            throw WebSocketChannelException('Protocol error');
           }
 
           _opcode = (byte & OPCODE);
@@ -142,29 +146,29 @@
           if (_opcode <= _WebSocketOpcode.BINARY) {
             if (_opcode == _WebSocketOpcode.CONTINUATION) {
               if (_currentMessageType == _WebSocketMessageType.NONE) {
-                throw WebSocketChannelException("Protocol error");
+                throw WebSocketChannelException('Protocol error');
               }
             } else {
               assert(_opcode == _WebSocketOpcode.TEXT ||
                   _opcode == _WebSocketOpcode.BINARY);
               if (_currentMessageType != _WebSocketMessageType.NONE) {
-                throw WebSocketChannelException("Protocol error");
+                throw WebSocketChannelException('Protocol error');
               }
               _currentMessageType = _opcode;
             }
           } else if (_opcode >= _WebSocketOpcode.CLOSE &&
               _opcode <= _WebSocketOpcode.PONG) {
             // Control frames cannot be fragmented.
-            if (!_fin) throw WebSocketChannelException("Protocol error");
+            if (!_fin) throw WebSocketChannelException('Protocol error');
           } else {
-            throw WebSocketChannelException("Protocol error");
+            throw WebSocketChannelException('Protocol error');
           }
           _state = LEN_FIRST;
         } else if (_state == LEN_FIRST) {
           _masked = (byte & 0x80) != 0;
           _len = byte & 0x7F;
           if (_isControlFrame() && _len > 125) {
-            throw WebSocketChannelException("Protocol error");
+            throw WebSocketChannelException('Protocol error');
           }
           if (_len == 126) {
             _len = 0;
@@ -195,7 +199,7 @@
         } else {
           assert(_state == PAYLOAD);
           // The payload is not handled one byte at a time but in blocks.
-          int payloadLength = min(lastIndex - index, _remainingPayloadBytes);
+          var payloadLength = min(lastIndex - index, _remainingPayloadBytes);
           _remainingPayloadBytes -= payloadLength;
           // Unmask payload if masked.
           if (_masked) {
@@ -209,7 +213,7 @@
           } else {
             if (_currentMessageType != _WebSocketMessageType.TEXT &&
                 _currentMessageType != _WebSocketMessageType.BINARY) {
-              throw WebSocketChannelException("Protocol error");
+              throw WebSocketChannelException('Protocol error');
             }
             if (_remainingPayloadBytes == 0) _messageFrameEnd();
           }
@@ -225,38 +229,37 @@
   }
 
   void _unmask(int index, int length, Uint8List buffer) {
-    const int BLOCK_SIZE = 16;
+    const BLOCK_SIZE = 16;
     // Skip Int32x4-version if message is small.
     if (length >= BLOCK_SIZE) {
       // Start by aligning to 16 bytes.
-      final int startOffset = BLOCK_SIZE - (index & 15);
-      final int end = index + startOffset;
-      for (int i = index; i < end; i++) {
+      final startOffset = BLOCK_SIZE - (index & 15);
+      final end = index + startOffset;
+      for (var i = index; i < end; i++) {
         buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
       }
       index += startOffset;
       length -= startOffset;
-      final int blockCount = length ~/ BLOCK_SIZE;
+      final blockCount = length ~/ BLOCK_SIZE;
       if (blockCount > 0) {
         // Create mask block.
-        int mask = 0;
-        for (int i = 3; i >= 0; i--) {
+        var mask = 0;
+        for (var i = 3; i >= 0; i--) {
           mask = (mask << 8) | _maskingBytes[(_unmaskingIndex + i) & 3];
         }
-        Int32x4 blockMask = Int32x4(mask, mask, mask, mask);
-        Int32x4List blockBuffer =
-            Int32x4List.view(buffer.buffer, index, blockCount);
-        for (int i = 0; i < blockBuffer.length; i++) {
+        var blockMask = Int32x4(mask, mask, mask, mask);
+        var blockBuffer = Int32x4List.view(buffer.buffer, index, blockCount);
+        for (var i = 0; i < blockBuffer.length; i++) {
           blockBuffer[i] ^= blockMask;
         }
-        final int bytes = blockCount * BLOCK_SIZE;
+        final bytes = blockCount * BLOCK_SIZE;
         index += bytes;
         length -= bytes;
       }
     }
     // Handle end.
-    final int end = index + length;
-    for (int i = index; i < end; i++) {
+    final end = index + length;
+    for (var i = index; i < end; i++) {
       buffer[i] ^= _maskingBytes[_unmaskingIndex++ & 3];
     }
   }
@@ -264,12 +267,12 @@
   void _lengthDone() {
     if (_masked) {
       if (!_serverSide) {
-        throw WebSocketChannelException("Received masked frame from server");
+        throw WebSocketChannelException('Received masked frame from server');
       }
       _state = MASK;
     } else {
       if (_serverSide) {
-        throw WebSocketChannelException("Received unmasked frame from client");
+        throw WebSocketChannelException('Received unmasked frame from client');
       }
       _remainingPayloadBytes = _len;
       _startPayload();
@@ -331,11 +334,11 @@
         var payload = _payload.takeBytes();
         if (payload.isNotEmpty) {
           if (payload.length == 1) {
-            throw WebSocketChannelException("Protocol error");
+            throw WebSocketChannelException('Protocol error');
           }
           closeCode = payload[0] << 8 | payload[1];
           if (closeCode == WebSocketStatus.NO_STATUS_RECEIVED) {
-            throw WebSocketChannelException("Protocol error");
+            throw WebSocketChannelException('Protocol error');
           }
           if (payload.length > 2) {
             closeReason = utf8.decode(payload.sublist(2));
@@ -392,17 +395,19 @@
 
   _WebSocketOutgoingTransformer(this.webSocket);
 
+  @override
   Stream<List<int>> bind(Stream stream) {
     return Stream<List<int>>.eventTransformed(stream,
         (EventSink<List<int>> eventSink) {
       if (_eventSink != null) {
-        throw StateError("WebSocket transformer already used");
+        throw StateError('WebSocket transformer already used');
       }
       _eventSink = eventSink;
       return this;
     });
   }
 
+  @override
   void add(message) {
     if (message is _WebSocketPong) {
       addFrame(_WebSocketOpcode.PONG, message.payload);
@@ -430,16 +435,18 @@
     addFrame(opcode, data);
   }
 
+  @override
   void addError(Object error, [StackTrace stackTrace]) {
     _eventSink.addError(error, stackTrace);
   }
 
+  @override
   void close() {
-    int code = webSocket._outCloseCode;
-    String reason = webSocket._outCloseReason;
+    var code = webSocket._outCloseCode;
+    var reason = webSocket._outCloseReason;
     List<int> data;
     if (code != null) {
-      data = List<int>();
+      data = <int>[];
       data.add((code >> 8) & 0xFF);
       data.add(code & 0xFF);
       if (reason != null) {
@@ -465,17 +472,17 @@
 
   static Iterable<List<int>> createFrame(
       int opcode, List<int> data, bool serverSide, bool compressed) {
-    bool mask = !serverSide; // Masking not implemented for server.
-    int dataLength = data == null ? 0 : data.length;
+    var mask = !serverSide; // Masking not implemented for server.
+    var dataLength = data == null ? 0 : data.length;
     // Determine the header size.
-    int headerSize = (mask) ? 6 : 2;
+    var headerSize = (mask) ? 6 : 2;
     if (dataLength > 65535) {
       headerSize += 8;
     } else if (dataLength > 125) {
       headerSize += 2;
     }
-    Uint8List header = Uint8List(headerSize);
-    int index = 0;
+    var header = Uint8List(headerSize);
+    var index = 0;
 
     // Set FIN and opcode.
     var hoc = _WebSocketProtocolTransformer.FIN |
@@ -484,7 +491,7 @@
 
     header[index++] = hoc;
     // Determine size and position of length field.
-    int lengthBytes = 1;
+    var lengthBytes = 1;
     if (dataLength > 65535) {
       header[index++] = 127;
       lengthBytes = 8;
@@ -493,7 +500,7 @@
       lengthBytes = 2;
     }
     // Write the length in network byte order into the header.
-    for (int i = 0; i < lengthBytes; i++) {
+    for (var i = 0; i < lengthBytes; i++) {
       header[index++] = dataLength >> (((lengthBytes - 1) - i) * 8) & 0xFF;
     }
     if (mask) {
@@ -517,32 +524,31 @@
             list = Uint8List.fromList(data);
           } else {
             list = Uint8List(data.length);
-            for (int i = 0; i < data.length; i++) {
+            for (var i = 0; i < data.length; i++) {
               if (data[i] < 0 || 255 < data[i]) {
-                throw ArgumentError("List element is not a byte value "
-                    "(value ${data[i]} at index $i)");
+                throw ArgumentError('List element is not a byte value '
+                    '(value ${data[i]} at index $i)');
               }
               list[i] = data[i];
             }
           }
         }
-        const int BLOCK_SIZE = 16;
-        int blockCount = list.length ~/ BLOCK_SIZE;
+        const BLOCK_SIZE = 16;
+        var blockCount = list.length ~/ BLOCK_SIZE;
         if (blockCount > 0) {
           // Create mask block.
-          int mask = 0;
-          for (int i = 3; i >= 0; i--) {
+          var mask = 0;
+          for (var i = 3; i >= 0; i--) {
             mask = (mask << 8) | maskBytes[i];
           }
-          Int32x4 blockMask = Int32x4(mask, mask, mask, mask);
-          Int32x4List blockBuffer =
-              Int32x4List.view(list.buffer, 0, blockCount);
-          for (int i = 0; i < blockBuffer.length; i++) {
+          var blockMask = Int32x4(mask, mask, mask, mask);
+          var blockBuffer = Int32x4List.view(list.buffer, 0, blockCount);
+          for (var i = 0; i < blockBuffer.length; i++) {
             blockBuffer[i] ^= blockMask;
           }
         }
         // Handle end.
-        for (int i = blockCount * BLOCK_SIZE; i < list.length; i++) {
+        for (var i = blockCount * BLOCK_SIZE; i < list.length; i++) {
           list[i] ^= maskBytes[i & 3];
         }
         data = list;
@@ -599,7 +605,7 @@
     }
   }
 
-  _ensureController() {
+  void _ensureController() {
     if (_controller != null) return;
     _controller = StreamController(
         sync: true,
@@ -636,6 +642,7 @@
     return true;
   }
 
+  @override
   Future addStream(var stream) {
     if (_closed) {
       stream.listen(null).cancel();
@@ -653,6 +660,7 @@
     return _completer.future;
   }
 
+  @override
   Future close() {
     _ensureController();
     Future closeSocket() {
@@ -678,9 +686,9 @@
 
 class WebSocketImpl extends Stream with _ServiceObject implements StreamSink {
   // Use default Map so we keep order.
-  static final Map<int, WebSocketImpl> _webSockets = Map<int, WebSocketImpl>();
+  static final Map<int, WebSocketImpl> _webSockets = <int, WebSocketImpl>{};
   static const int DEFAULT_WINDOW_BITS = 15;
-  static const String PER_MESSAGE_DEFLATE = "permessage-deflate";
+  static const String PER_MESSAGE_DEFLATE = 'permessage-deflate';
 
   final String protocol;
 
@@ -759,8 +767,9 @@
     _webSockets[_serviceId] = this;
   }
 
-  StreamSubscription listen(void onData(message),
-      {Function onError, void onDone(), bool cancelOnError}) {
+  @override
+  StreamSubscription listen(void Function(dynamic) onData,
+      {Function onError, void Function() onDone, bool cancelOnError}) {
     return _controller.stream.listen(onData,
         onError: onError, onDone: onDone, cancelOnError: cancelOnError);
   }
@@ -790,20 +799,25 @@
   int get closeCode => _closeCode;
   String get closeReason => _closeReason;
 
+  @override
   void add(data) {
     _sink.add(data);
   }
 
+  @override
   void addError(error, [StackTrace stackTrace]) {
     _sink.addError(error, stackTrace);
   }
 
+  @override
   Future addStream(Stream stream) => _sink.addStream(stream);
+  @override
   Future get done => _sink.done;
 
+  @override
   Future close([int code, String reason]) {
     if (_isReservedStatusCode(code)) {
-      throw WebSocketChannelException("Reserved status code $code");
+      throw WebSocketChannelException('Reserved status code $code');
     }
     if (_outCloseCode == null) {
       _outCloseCode = code;
@@ -818,17 +832,15 @@
       if (!_controller.hasListener && _subscription != null) {
         _controller.stream.drain().catchError((_) => {});
       }
-      if (_closeTimer == null) {
-        // When closing the web-socket, we no longer accept data.
-        _closeTimer = Timer(const Duration(seconds: 5), () {
-          // Reuse code and reason from the local close.
-          _closeCode = _outCloseCode;
-          _closeReason = _outCloseReason;
-          if (_subscription != null) _subscription.cancel();
-          _controller.close();
-          _webSockets.remove(_serviceId);
-        });
-      }
+      // When closing the web-socket, we no longer accept data.
+      _closeTimer ??= Timer(const Duration(seconds: 5), () {
+        // Reuse code and reason from the local close.
+        _closeCode = _outCloseCode;
+        _closeReason = _outCloseReason;
+        if (_subscription != null) _subscription.cancel();
+        _controller.close();
+        _webSockets.remove(_serviceId);
+      });
     }
     return _sink.close();
   }
diff --git a/lib/src/exception.dart b/lib/src/exception.dart
index 6cb8836..d166e6a 100644
--- a/lib/src/exception.dart
+++ b/lib/src/exception.dart
@@ -17,7 +17,8 @@
       : message = inner.toString(),
         inner = inner;
 
+  @override
   String toString() => message == null
-      ? "WebSocketChannelException"
-      : "WebSocketChannelException: $message";
+      ? 'WebSocketChannelException'
+      : 'WebSocketChannelException: $message';
 }
diff --git a/lib/src/sink_completer.dart b/lib/src/sink_completer.dart
index ae6e64e..c6204d6 100644
--- a/lib/src/sink_completer.dart
+++ b/lib/src/sink_completer.dart
@@ -37,7 +37,7 @@
   /// A destination sink may be set at most once.
   void setDestinationSink(WebSocketSink destinationSink) {
     if (_sink._destinationSink != null) {
-      throw StateError("Destination sink already set");
+      throw StateError('Destination sink already set');
     }
     _sink._setDestinationSink(destinationSink);
   }
@@ -72,6 +72,7 @@
   /// to going through [_controller].
   bool get _canSendDirectly => _controller == null && _destinationSink != null;
 
+  @override
   Future get done {
     if (_doneCompleter != null) return _doneCompleter.future;
     if (_destinationSink == null) {
@@ -81,6 +82,7 @@
     return _destinationSink.done;
   }
 
+  @override
   void add(event) {
     if (_canSendDirectly) {
       _destinationSink.add(event);
@@ -90,6 +92,7 @@
     }
   }
 
+  @override
   void addError(error, [StackTrace stackTrace]) {
     if (_canSendDirectly) {
       _destinationSink.addError(error, stackTrace);
@@ -99,6 +102,7 @@
     }
   }
 
+  @override
   Future addStream(Stream stream) {
     if (_canSendDirectly) return _destinationSink.addStream(stream);
 
@@ -106,6 +110,7 @@
     return _controller.addStream(stream, cancelOnError: false);
   }
 
+  @override
   Future close([int closeCode, String closeReason]) {
     if (_canSendDirectly) {
       _destinationSink.close(closeCode, closeReason);
@@ -120,7 +125,7 @@
 
   /// Create [_controller] if it doesn't yet exist.
   void _ensureController() {
-    if (_controller == null) _controller = StreamController(sync: true);
+    _controller ??= StreamController(sync: true);
   }
 
   /// Sets the destination sink to which events from this sink will be provided.
diff --git a/pubspec.yaml b/pubspec.yaml
index e5a2b35..8b79da0 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: web_socket_channel
-version: 1.1.0
+version: 1.1.1-dev
 
 description: >-
   StreamChannel wrappers for WebSockets. Provides a cross-platform
diff --git a/test/html_test.dart b/test/html_test.dart
index b05c8ec..54df7cb 100644
--- a/test/html_test.dart
+++ b/test/html_test.dart
@@ -17,7 +17,7 @@
 void main() {
   int port;
   setUpAll(() async {
-    var channel = spawnHybridCode(r"""
+    var channel = spawnHybridCode(r'''
       import 'dart:io';
 
       import 'package:stream_channel/stream_channel.dart';
@@ -31,7 +31,7 @@
         });
         channel.sink.add(server.port);
       }
-    """, stayAlive: true);
+    ''', stayAlive: true);
 
     port = await channel.stream.first;
   });
@@ -41,72 +41,72 @@
     if (channel != null) channel.sink.close();
   });
 
-  test("communicates using an existing WebSocket", () async {
-    var webSocket = WebSocket("ws://localhost:$port");
+  test('communicates using an existing WebSocket', () async {
+    var webSocket = WebSocket('ws://localhost:$port');
     channel = HtmlWebSocketChannel(webSocket);
 
     var queue = StreamQueue(channel.stream);
-    channel.sink.add("foo");
-    expect(await queue.next, equals("foo"));
+    channel.sink.add('foo');
+    expect(await queue.next, equals('foo'));
 
     channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
     expect(await _decodeBlob(await queue.next), equals([1, 2, 3, 4, 5]));
 
-    webSocket.binaryType = "arraybuffer";
+    webSocket.binaryType = 'arraybuffer';
     channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
     expect(await queue.next, equals([1, 2, 3, 4, 5]));
   });
 
-  test("communicates using an existing open WebSocket", () async {
-    var webSocket = WebSocket("ws://localhost:$port");
+  test('communicates using an existing open WebSocket', () async {
+    var webSocket = WebSocket('ws://localhost:$port');
     await webSocket.onOpen.first;
 
     channel = HtmlWebSocketChannel(webSocket);
 
     var queue = StreamQueue(channel.stream);
-    channel.sink.add("foo");
-    expect(await queue.next, equals("foo"));
+    channel.sink.add('foo');
+    expect(await queue.next, equals('foo'));
   });
 
-  test(".connect defaults to binary lists", () async {
-    channel = HtmlWebSocketChannel.connect("ws://localhost:$port");
+  test('.connect defaults to binary lists', () async {
+    channel = HtmlWebSocketChannel.connect('ws://localhost:$port');
 
     var queue = StreamQueue(channel.stream);
-    channel.sink.add("foo");
-    expect(await queue.next, equals("foo"));
+    channel.sink.add('foo');
+    expect(await queue.next, equals('foo'));
 
     channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
     expect(await queue.next, equals([1, 2, 3, 4, 5]));
   });
 
-  test(".connect defaults to binary lists using platform independent api",
+  test('.connect defaults to binary lists using platform independent api',
       () async {
-    channel = WebSocketChannel.connect(Uri.parse("ws://localhost:$port"));
+    channel = WebSocketChannel.connect(Uri.parse('ws://localhost:$port'));
 
     var queue = StreamQueue(channel.stream);
-    channel.sink.add("foo");
-    expect(await queue.next, equals("foo"));
+    channel.sink.add('foo');
+    expect(await queue.next, equals('foo'));
 
     channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
     expect(await queue.next, equals([1, 2, 3, 4, 5]));
   });
 
-  test(".connect can use blobs", () async {
-    channel = HtmlWebSocketChannel.connect("ws://localhost:$port",
+  test('.connect can use blobs', () async {
+    channel = HtmlWebSocketChannel.connect('ws://localhost:$port',
         binaryType: BinaryType.blob);
 
     var queue = StreamQueue(channel.stream);
-    channel.sink.add("foo");
-    expect(await queue.next, equals("foo"));
+    channel.sink.add('foo');
+    expect(await queue.next, equals('foo'));
 
     channel.sink.add(Uint8List.fromList([1, 2, 3, 4, 5]));
     expect(await _decodeBlob(await queue.next), equals([1, 2, 3, 4, 5]));
   });
 
-  test(".connect wraps a connection error in WebSocketChannelException",
+  test('.connect wraps a connection error in WebSocketChannelException',
       () async {
     // Spawn a server that will immediately reject the connection.
-    var serverChannel = spawnHybridCode(r"""
+    var serverChannel = spawnHybridCode(r'''
       import 'dart:io';
 
       import 'package:stream_channel/stream_channel.dart';
@@ -118,12 +118,12 @@
         });
         channel.sink.add(server.port);
       }
-    """);
+    ''');
 
     // TODO(nweiz): Make this channel use a port number that's guaranteed to be
     // invalid.
     var channel = HtmlWebSocketChannel.connect(
-        "ws://localhost:${await serverChannel.stream.first}");
+        'ws://localhost:${await serverChannel.stream.first}');
     expect(channel.stream.toList(),
         throwsA(TypeMatcher<WebSocketChannelException>()));
   });
diff --git a/test/io_test.dart b/test/io_test.dart
index 4d4b1a9..7d87c3f 100644
--- a/test/io_test.dart
+++ b/test/io_test.dart
@@ -17,111 +17,111 @@
     if (server != null) await server.close();
   });
 
-  test("communicates using existing WebSockets", () async {
-    server = await HttpServer.bind("localhost", 0);
+  test('communicates using existing WebSockets', () async {
+    server = await HttpServer.bind('localhost', 0);
     server.transform(WebSocketTransformer()).listen((webSocket) {
       var channel = IOWebSocketChannel(webSocket);
-      channel.sink.add("hello!");
+      channel.sink.add('hello!');
       channel.stream.listen((request) {
-        expect(request, equals("ping"));
-        channel.sink.add("pong");
-        channel.sink.close(5678, "raisin");
+        expect(request, equals('ping'));
+        channel.sink.add('pong');
+        channel.sink.close(5678, 'raisin');
       });
     });
 
-    var webSocket = await WebSocket.connect("ws://localhost:${server.port}");
+    var webSocket = await WebSocket.connect('ws://localhost:${server.port}');
     var channel = IOWebSocketChannel(webSocket);
 
     var n = 0;
     channel.stream.listen((message) {
       if (n == 0) {
-        expect(message, equals("hello!"));
-        channel.sink.add("ping");
+        expect(message, equals('hello!'));
+        channel.sink.add('ping');
       } else if (n == 1) {
-        expect(message, equals("pong"));
+        expect(message, equals('pong'));
       } else {
-        fail("Only expected two messages.");
+        fail('Only expected two messages.');
       }
       n++;
     }, onDone: expectAsync0(() {
       expect(channel.closeCode, equals(5678));
-      expect(channel.closeReason, equals("raisin"));
+      expect(channel.closeReason, equals('raisin'));
     }));
   });
 
-  test(".connect communicates immediately", () async {
-    server = await HttpServer.bind("localhost", 0);
+  test('.connect communicates immediately', () async {
+    server = await HttpServer.bind('localhost', 0);
     server.transform(WebSocketTransformer()).listen((webSocket) {
       var channel = IOWebSocketChannel(webSocket);
       channel.stream.listen((request) {
-        expect(request, equals("ping"));
-        channel.sink.add("pong");
+        expect(request, equals('ping'));
+        channel.sink.add('pong');
       });
     });
 
-    var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}");
-    channel.sink.add("ping");
+    var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}');
+    channel.sink.add('ping');
 
     channel.stream.listen(
         expectAsync1((message) {
-          expect(message, equals("pong"));
-          channel.sink.close(5678, "raisin");
+          expect(message, equals('pong'));
+          channel.sink.close(5678, 'raisin');
         }, count: 1),
         onDone: expectAsync0(() {}));
   });
 
-  test(".connect communicates immediately using platform independent api",
+  test('.connect communicates immediately using platform independent api',
       () async {
-    server = await HttpServer.bind("localhost", 0);
+    server = await HttpServer.bind('localhost', 0);
     server.transform(WebSocketTransformer()).listen((webSocket) {
       var channel = IOWebSocketChannel(webSocket);
       channel.stream.listen((request) {
-        expect(request, equals("ping"));
-        channel.sink.add("pong");
+        expect(request, equals('ping'));
+        channel.sink.add('pong');
       });
     });
 
     var channel =
-        WebSocketChannel.connect(Uri.parse("ws://localhost:${server.port}"));
-    channel.sink.add("ping");
+        WebSocketChannel.connect(Uri.parse('ws://localhost:${server.port}'));
+    channel.sink.add('ping');
 
     channel.stream.listen(
         expectAsync1((message) {
-          expect(message, equals("pong"));
-          channel.sink.close(5678, "raisin");
+          expect(message, equals('pong'));
+          channel.sink.close(5678, 'raisin');
         }, count: 1),
         onDone: expectAsync0(() {}));
   });
 
-  test(".connect with an immediate call to close", () async {
-    server = await HttpServer.bind("localhost", 0);
+  test('.connect with an immediate call to close', () async {
+    server = await HttpServer.bind('localhost', 0);
     server.transform(WebSocketTransformer()).listen((webSocket) {
       expect(() async {
         var channel = IOWebSocketChannel(webSocket);
         await channel.stream.drain();
         expect(channel.closeCode, equals(5678));
-        expect(channel.closeReason, equals("raisin"));
+        expect(channel.closeReason, equals('raisin'));
       }(), completes);
     });
 
-    var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}");
-    await channel.sink.close(5678, "raisin");
+    var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}');
+    await channel.sink.close(5678, 'raisin');
   });
 
-  test(".connect wraps a connection error in WebSocketChannelException",
+  test('.connect wraps a connection error in WebSocketChannelException',
       () async {
-    server = await HttpServer.bind("localhost", 0);
+    server = await HttpServer.bind('localhost', 0);
     server.listen((request) {
       request.response.statusCode = 404;
       request.response.close();
     });
 
-    var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}");
+    var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}');
     expect(channel.stream.drain(),
         throwsA(TypeMatcher<WebSocketChannelException>()));
   });
 
-  test(".protocols fail", () async {
+  test('.protocols fail', () async {
     var passedProtocol = 'passed-protocol';
     var failedProtocol = 'failed-protocol';
     var selector = (List<String> receivedProtocols) => passedProtocol;
@@ -132,13 +132,13 @@
           throwsException);
     });
 
-    var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}",
+    var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}',
         protocols: [failedProtocol]);
     expect(channel.stream.drain(),
         throwsA(TypeMatcher<WebSocketChannelException>()));
   });
 
-  test(".protocols pass", () async {
+  test('.protocols pass', () async {
     var passedProtocol = 'passed-protocol';
     var selector = (List<String> receivedProtocols) => passedProtocol;
 
@@ -150,7 +150,7 @@
       await webSocket.close();
     });
 
-    var channel = IOWebSocketChannel.connect("ws://localhost:${server.port}",
+    var channel = IOWebSocketChannel.connect('ws://localhost:${server.port}',
         protocols: [passedProtocol]);
     await channel.stream.drain();
     expect(channel.protocol, passedProtocol);
diff --git a/test/web_socket_test.dart b/test/web_socket_test.dart
index 0d63323..be22850 100644
--- a/test/web_socket_test.dart
+++ b/test/web_socket_test.dart
@@ -12,26 +12,26 @@
 import 'package:web_socket_channel/web_socket_channel.dart';
 
 void main() {
-  group("using WebSocketChannel", () {
-    test("a client can communicate with a WebSocket server", () async {
-      var server = await HttpServer.bind("localhost", 0);
+  group('using WebSocketChannel', () {
+    test('a client can communicate with a WebSocket server', () async {
+      var server = await HttpServer.bind('localhost', 0);
       server.transform(WebSocketTransformer()).listen((webSocket) {
-        webSocket.add("hello!");
+        webSocket.add('hello!');
         webSocket.listen((request) {
-          expect(request, equals("ping"));
-          webSocket.add("pong");
+          expect(request, equals('ping'));
+          webSocket.add('pong');
           webSocket.close();
         });
       });
 
       var client = HttpClient();
       var request = await client.openUrl(
-          "GET", Uri.parse("http://localhost:${server.port}"));
+          'GET', Uri.parse('http://localhost:${server.port}'));
       request.headers
-        ..set("Connection", "Upgrade")
-        ..set("Upgrade", "websocket")
-        ..set("Sec-WebSocket-Key", "x3JJHMbDL1EzLkh9GBhXDw==")
-        ..set("Sec-WebSocket-Version", "13");
+        ..set('Connection', 'Upgrade')
+        ..set('Upgrade', 'websocket')
+        ..set('Sec-WebSocket-Key', 'x3JJHMbDL1EzLkh9GBhXDw==')
+        ..set('Sec-WebSocket-Version', '13');
 
       var response = await request.close();
       var socket = await response.detachSocket();
@@ -41,29 +41,29 @@
       var n = 0;
       await webSocket.stream.listen((message) {
         if (n == 0) {
-          expect(message, equals("hello!"));
-          webSocket.sink.add("ping");
+          expect(message, equals('hello!'));
+          webSocket.sink.add('ping');
         } else if (n == 1) {
-          expect(message, equals("pong"));
+          expect(message, equals('pong'));
           webSocket.sink.close();
           server.close();
         } else {
-          fail("Only expected two messages.");
+          fail('Only expected two messages.');
         }
         n++;
       }).asFuture();
     });
 
-    test("a server can communicate with a WebSocket client", () async {
-      var server = await HttpServer.bind("localhost", 0);
+    test('a server can communicate with a WebSocket client', () async {
+      var server = await HttpServer.bind('localhost', 0);
       server.listen((request) async {
         var response = request.response;
         response.statusCode = 101;
         response.headers
-          ..set("Connection", "Upgrade")
-          ..set("Upgrade", "websocket")
+          ..set('Connection', 'Upgrade')
+          ..set('Upgrade', 'websocket')
           ..set(
-              "Sec-WebSocket-Accept",
+              'Sec-WebSocket-Accept',
               WebSocketChannel.signKey(
                   request.headers.value('Sec-WebSocket-Key')));
         response.contentLength = 0;
@@ -71,11 +71,11 @@
         var socket = await response.detachSocket();
         var innerChannel = StreamChannel<List<int>>(socket, socket);
         var webSocket = WebSocketChannel(innerChannel);
-        webSocket.sink.add("hello!");
+        webSocket.sink.add('hello!');
 
         var message = await webSocket.stream.first;
-        expect(message, equals("ping"));
-        webSocket.sink.add("pong");
+        expect(message, equals('ping'));
+        webSocket.sink.add('pong');
         await webSocket.sink.close();
       });
 
@@ -83,14 +83,14 @@
       var n = 0;
       await webSocket.listen((message) {
         if (n == 0) {
-          expect(message, equals("hello!"));
-          webSocket.add("ping");
+          expect(message, equals('hello!'));
+          webSocket.add('ping');
         } else if (n == 1) {
-          expect(message, equals("pong"));
+          expect(message, equals('pong'));
           webSocket.close();
           server.close();
         } else {
-          fail("Only expected two messages.");
+          fail('Only expected two messages.');
         }
         n++;
       }).asFuture();