Migrate to latest lints, bump min SDK to Dart 3.2 (dart-lang/web_socket_channel#292)

diff --git a/pkgs/web_socket_channel/.github/workflows/test-package.yml b/pkgs/web_socket_channel/.github/workflows/test-package.yml
index d8fd949..bf51a79 100644
--- a/pkgs/web_socket_channel/.github/workflows/test-package.yml
+++ b/pkgs/web_socket_channel/.github/workflows/test-package.yml
@@ -42,7 +42,7 @@
       fail-fast: false
       matrix:
         os: [ubuntu-latest]
-        sdk: [2.15.0, dev]
+        sdk: [3.2.0, dev]
     steps:
       - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
       - uses: dart-lang/setup-dart@b64355ae6ca0b5d484f0106a033dd1388965d06d
diff --git a/pkgs/web_socket_channel/CHANGELOG.md b/pkgs/web_socket_channel/CHANGELOG.md
index de523a5..02e4630 100644
--- a/pkgs/web_socket_channel/CHANGELOG.md
+++ b/pkgs/web_socket_channel/CHANGELOG.md
@@ -1,5 +1,6 @@
 ## 2.4.1-wip
 
+- Bump minimum Dart version to 3.2.0
 - Update the examples to use `WebSocketChannel.ready` and clarify that
   `WebSocketChannel.ready` should be awaited before sending data over the
   `WebSocketChannel`.
diff --git a/pkgs/web_socket_channel/analysis_options.yaml b/pkgs/web_socket_channel/analysis_options.yaml
index 30371c6..b7d68c9 100644
--- a/pkgs/web_socket_channel/analysis_options.yaml
+++ b/pkgs/web_socket_channel/analysis_options.yaml
@@ -1,4 +1,4 @@
-include: package:pedantic/analysis_options.yaml
+include: package:dart_flutter_team_lints/analysis_options.yaml
 
 analyzer:
   language:
@@ -7,70 +7,24 @@
 linter:
   rules:
   - avoid_bool_literals_in_conditional_expressions
-  - avoid_catching_errors
   - avoid_classes_with_only_static_members
-  - avoid_function_literals_in_foreach_calls
   - avoid_private_typedef_functions
   - avoid_redundant_argument_values
-  - avoid_renaming_method_parameters
   - avoid_returning_null
   - avoid_returning_null_for_future
-  - avoid_returning_null_for_void
   - avoid_returning_this
-  - avoid_single_cascade_in_expression_statements
   - avoid_unused_constructor_parameters
   - avoid_void_async
-  - await_only_futures
-  - camel_case_types
   - cancel_subscriptions
-  - comment_references
-  - constant_identifier_names
-  - control_flow_in_finally
-  - directives_ordering
-  - empty_statements
-  - file_names
-  - hash_and_equals
-  - implementation_imports
-  - iterable_contains_unrelated_type
   - join_return_with_assignment
-  - lines_longer_than_80_chars
-  - list_remove_unrelated_type
   - literal_only_boolean_expressions
   - missing_whitespace_between_adjacent_strings
   - no_adjacent_strings_in_list
   - no_runtimeType_toString
-  - non_constant_identifier_names
-  - only_throw_errors
-  - overridden_fields
   - package_api_docs
-  - package_names
-  - package_prefixed_library_names
-  - prefer_asserts_in_initializer_lists
-  - prefer_const_constructors
   - prefer_const_declarations
   - prefer_expression_function_bodies
   - prefer_final_locals
-  - prefer_function_declarations_over_variables
-  - prefer_initializing_formals
-  - prefer_inlined_adds
-  - prefer_interpolation_to_compose_strings
-  - prefer_is_not_operator
-  - prefer_null_aware_operators
-  - prefer_relative_imports
-  - prefer_typing_uninitialized_variables
   - prefer_void_to_null
-  - provide_deprecation_message
-  - sort_pub_dependencies
-  - test_types_in_equals
-  - throw_in_finally
   - unnecessary_await_in_return
-  - unnecessary_brace_in_string_interps
-  - unnecessary_getters_setters
-  - unnecessary_lambdas
-  - unnecessary_null_aware_assignments
-  - unnecessary_overrides
-  - unnecessary_parenthesis
-  - unnecessary_statements
-  - unnecessary_string_interpolations
   - use_string_buffers
-  - void_checks
diff --git a/pkgs/web_socket_channel/lib/html.dart b/pkgs/web_socket_channel/lib/html.dart
index 25b4175..0cb7ffd 100644
--- a/pkgs/web_socket_channel/lib/html.dart
+++ b/pkgs/web_socket_channel/lib/html.dart
@@ -55,7 +55,7 @@
   Stream get stream => _controller.foreign.stream;
 
   final _controller =
-      StreamChannelController(sync: true, allowForeignErrors: false);
+      StreamChannelController<Object?>(sync: true, allowForeignErrors: false);
 
   @override
   late final WebSocketSink sink = _HtmlWebSocketSink(this);
@@ -71,7 +71,7 @@
   /// received by this socket. It defaults to [BinaryType.list], which causes
   /// binary messages to be delivered as [Uint8List]s. If it's
   /// [BinaryType.blob], they're delivered as [Blob]s instead.
-  HtmlWebSocketChannel.connect(url,
+  HtmlWebSocketChannel.connect(Object url,
       {Iterable<String>? protocols, BinaryType? binaryType})
       : this(WebSocket(url.toString(), protocols)
           ..binaryType = (binaryType ?? BinaryType.list).value);
@@ -102,7 +102,9 @@
       // Unfortunately, the underlying WebSocket API doesn't expose any
       // specific information about the error itself.
       final error = WebSocketChannelException('WebSocket connection failed.');
-      _readyCompleter.completeError(error);
+      if (!_readyCompleter.isCompleted) {
+        _readyCompleter.completeError(error);
+      }
       _controller.local.sink.addError(error);
       _controller.local.sink.close();
     });
diff --git a/pkgs/web_socket_channel/lib/io.dart b/pkgs/web_socket_channel/lib/io.dart
index e39bc67..9f71d81 100644
--- a/pkgs/web_socket_channel/lib/io.dart
+++ b/pkgs/web_socket_channel/lib/io.dart
@@ -105,7 +105,7 @@
   IOWebSocketChannel(WebSocket socket)
       : _webSocket = socket,
         stream = socket.handleError(
-            (error) => throw WebSocketChannelException.from(error)),
+            (Object? error) => throw WebSocketChannelException.from(error)),
         sink = _IOWebSocketSink(socket),
         _readyCompleter = Completer()..complete();
 
@@ -116,7 +116,7 @@
   IOWebSocketChannel._withoutSocket(Stream stream, this.sink)
       : _webSocket = null,
         stream = stream.handleError(
-            (error) => throw WebSocketChannelException.from(error)),
+            (Object? error) => throw WebSocketChannelException.from(error)),
         _readyCompleter = Completer();
 }
 
@@ -125,9 +125,7 @@
   /// The underlying socket.
   final WebSocket _webSocket;
 
-  _IOWebSocketSink(WebSocket webSocket)
-      : _webSocket = webSocket,
-        super(webSocket);
+  _IOWebSocketSink(WebSocket super.webSocket) : _webSocket = webSocket;
 
   @override
   Future close([int? closeCode, String? closeReason]) =>
diff --git a/pkgs/web_socket_channel/lib/src/channel.dart b/pkgs/web_socket_channel/lib/src/channel.dart
index 46d16b8..4143128 100644
--- a/pkgs/web_socket_channel/lib/src/channel.dart
+++ b/pkgs/web_socket_channel/lib/src/channel.dart
@@ -11,7 +11,7 @@
 
 import '_connect_api.dart'
     if (dart.library.io) '_connect_io.dart'
-    if (dart.library.html) '_connect_html.dart' as platform;
+    if (dart.library.js_interop) '_connect_html.dart' as platform;
 import 'copy/web_socket_impl.dart';
 import 'exception.dart';
 
@@ -151,9 +151,7 @@
 class WebSocketSink extends DelegatingStreamSink {
   final WebSocketImpl _webSocket;
 
-  WebSocketSink._(WebSocketImpl webSocket)
-      : _webSocket = webSocket,
-        super(webSocket);
+  WebSocketSink._(WebSocketImpl super.webSocket) : _webSocket = webSocket;
 
   /// Closes the web socket connection.
   ///
diff --git a/pkgs/web_socket_channel/lib/src/copy/io_sink.dart b/pkgs/web_socket_channel/lib/src/copy/io_sink.dart
index 2abf999..6dfe7a0 100644
--- a/pkgs/web_socket_channel/lib/src/copy/io_sink.dart
+++ b/pkgs/web_socket_channel/lib/src/copy/io_sink.dart
@@ -36,7 +36,7 @@
   }
 
   @override
-  void addError(error, [StackTrace? stackTrace]) {
+  void addError(Object error, [StackTrace? stackTrace]) {
     if (_isClosed) {
       return;
     }
@@ -101,7 +101,7 @@
   @override
   Future get done => _doneCompleter.future;
 
-  void _completeDoneValue(value) {
+  void _completeDoneValue(Object? value) {
     if (!_doneCompleter.isCompleted) {
       _doneCompleter.complete(value);
     }
diff --git a/pkgs/web_socket_channel/lib/src/copy/web_socket_impl.dart b/pkgs/web_socket_channel/lib/src/copy/web_socket_impl.dart
index 7c35134..0616caa 100644
--- a/pkgs/web_socket_channel/lib/src/copy/web_socket_impl.dart
+++ b/pkgs/web_socket_channel/lib/src/copy/web_socket_impl.dart
@@ -408,7 +408,7 @@
       });
 
   @override
-  void add(message) {
+  void add(Object? message) {
     if (message is _WebSocketPong) {
       addFrame(_WebSocketOpcode.PONG, message.payload);
       return;
@@ -619,7 +619,7 @@
     sink.addStream(stream).then((_) {
       _done();
       _closeCompleter.complete(webSocket);
-    }, onError: (error, StackTrace stackTrace) {
+    }, onError: (Object error, StackTrace stackTrace) {
       _closed = true;
       _cancel();
       if (error is ArgumentError) {
@@ -645,7 +645,7 @@
   }
 
   @override
-  Future addStream(var stream) {
+  Future addStream(Stream stream) {
     if (_closed) {
       stream.listen(null).cancel();
       return Future.value(webSocket);
@@ -672,7 +672,7 @@
     return _closeCompleter.future.then((_) => closeSocket());
   }
 
-  void add(data) {
+  void add(Object? data) {
     if (_closed) return;
     _ensureController();
     _controller!.add(data);
@@ -729,7 +729,7 @@
       } else {
         _controller.add(data);
       }
-    }, onError: (error, stackTrace) {
+    }, onError: (Object error) {
       if (_closeTimer != null) _closeTimer!.cancel();
       if (error is FormatException) {
         _close(WebSocketStatus.INVALID_FRAME_PAYLOAD_DATA);
@@ -804,7 +804,7 @@
   String? get closeReason => _closeReason;
 
   @override
-  void add(data) {
+  void add(Object? data) {
     _sink.add(data);
   }
 
@@ -835,7 +835,7 @@
       //   2) set a timer terminate the connection if a close frame is
       //      not received.
       if (!_controller.hasListener && _subscription != null) {
-        _controller.stream.drain().catchError((_) => {});
+        _controller.stream.drain<void>().catchError((_) => <String, dynamic>{});
       }
       // When closing the web-socket, we no longer accept data.
       _closeTimer ??= Timer(const Duration(seconds: 5), () {
@@ -881,7 +881,7 @@
 int _nextServiceId = 1;
 
 // TODO(ajohnsen): Use other way of getting a uniq id.
-abstract class _ServiceObject {
+mixin class _ServiceObject {
   int __serviceId = 0;
 
   int get _serviceId {
diff --git a/pkgs/web_socket_channel/lib/src/sink_completer.dart b/pkgs/web_socket_channel/lib/src/sink_completer.dart
index 9012d68..cea8c17 100644
--- a/pkgs/web_socket_channel/lib/src/sink_completer.dart
+++ b/pkgs/web_socket_channel/lib/src/sink_completer.dart
@@ -83,7 +83,7 @@
   }
 
   @override
-  void add(event) {
+  void add(Object? event) {
     if (_canSendDirectly) {
       _destinationSink!.add(event);
     } else {
diff --git a/pkgs/web_socket_channel/pubspec.yaml b/pkgs/web_socket_channel/pubspec.yaml
index 1403492..c772f4d 100644
--- a/pkgs/web_socket_channel/pubspec.yaml
+++ b/pkgs/web_socket_channel/pubspec.yaml
@@ -8,7 +8,7 @@
 repository: https://github.com/dart-lang/web_socket_channel
 
 environment:
-  sdk: ">=2.15.0 <3.0.0"
+  sdk: ^3.2.0
 
 dependencies:
   async: ^2.5.0
@@ -16,5 +16,5 @@
   stream_channel: ^2.1.0
 
 dev_dependencies:
-  pedantic: ^1.10.0
+  dart_flutter_team_lints: ^2.0.0
   test: ^1.16.0
diff --git a/pkgs/web_socket_channel/test/html_test.dart b/pkgs/web_socket_channel/test/html_test.dart
index 54b34d7..d444d7c 100644
--- a/pkgs/web_socket_channel/test/html_test.dart
+++ b/pkgs/web_socket_channel/test/html_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('browser')
+library;
+
 import 'dart:async';
 import 'dart:html';
 import 'dart:typed_data';
@@ -87,7 +89,14 @@
     webSocket.close();
 
     final channel = HtmlWebSocketChannel(webSocket);
-    expect(channel.ready, throwsA(isA<WebSocketChannelException>()));
+    await expectLater(
+      channel.ready,
+      throwsA(
+        isA<WebSocketChannelException>()
+            .having((p0) => p0.message, 'message', 'WebSocket state error: 2')
+            .having((p0) => p0.inner, 'inner', isNull),
+      ),
+    );
   });
 
   test('.connect defaults to binary lists', () async {
diff --git a/pkgs/web_socket_channel/test/io_test.dart b/pkgs/web_socket_channel/test/io_test.dart
index fde1a9f..b2b7cbf 100644
--- a/pkgs/web_socket_channel/test/io_test.dart
+++ b/pkgs/web_socket_channel/test/io_test.dart
@@ -3,6 +3,8 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
+
 import 'dart:async';
 import 'dart:io';
 
@@ -106,7 +108,7 @@
     server.transform(WebSocketTransformer()).listen((WebSocket webSocket) {
       expect(() async {
         final channel = IOWebSocketChannel(webSocket);
-        await channel.stream.drain();
+        await channel.stream.drain<void>();
         expect(channel.closeCode, equals(5678));
         expect(channel.closeReason, equals('raisin'));
       }(), completes);
@@ -130,7 +132,8 @@
 
     final channel = IOWebSocketChannel.connect('ws://localhost:${server.port}');
     expect(channel.ready, throwsA(isA<WebSocketException>()));
-    expect(channel.stream.drain(), throwsA(isA<WebSocketChannelException>()));
+    expect(channel.stream.drain<void>(),
+        throwsA(isA<WebSocketChannelException>()));
   });
 
   test('.protocols fail', () async {
@@ -153,7 +156,7 @@
     );
     expect(channel.ready, throwsA(isA<WebSocketException>()));
     expect(
-      channel.stream.drain(),
+      channel.stream.drain<void>(),
       throwsA(isA<WebSocketChannelException>()),
     );
   });
@@ -178,7 +181,7 @@
 
     expect(channel.ready, completes);
 
-    await channel.stream.drain();
+    await channel.stream.drain<void>();
     expect(channel.protocol, passedProtocol);
   });
 
@@ -188,7 +191,7 @@
     server.transform(WebSocketTransformer()).listen((webSocket) {
       expect(() async {
         final channel = IOWebSocketChannel(webSocket);
-        await channel.stream.drain();
+        await channel.stream.drain<void>();
         expect(channel.closeCode, equals(5678));
         expect(channel.closeReason, equals('raisin'));
       }(), completes);
@@ -218,7 +221,7 @@
         .transform(WebSocketTransformer())
         .listen((webSocket) {
           final channel = IOWebSocketChannel(webSocket);
-          channel.stream.drain();
+          channel.stream.drain<void>();
         });
 
     final channel = IOWebSocketChannel.connect(
@@ -227,7 +230,8 @@
     );
 
     expect(channel.ready, throwsA(isA<TimeoutException>()));
-    expect(channel.stream.drain(), throwsA(isA<WebSocketChannelException>()));
+    expect(channel.stream.drain<void>(),
+        throwsA(isA<WebSocketChannelException>()));
   });
 
   test('.custom client is passed through', () async {
diff --git a/pkgs/web_socket_channel/test/web_socket_test.dart b/pkgs/web_socket_channel/test/web_socket_test.dart
index 441c628..7aaabc7 100644
--- a/pkgs/web_socket_channel/test/web_socket_test.dart
+++ b/pkgs/web_socket_channel/test/web_socket_test.dart
@@ -3,12 +3,12 @@
 // BSD-style license that can be found in the LICENSE file.
 
 @TestOn('vm')
+library;
 
 import 'dart:io';
 
 import 'package:stream_channel/stream_channel.dart';
 import 'package:test/test.dart';
-
 import 'package:web_socket_channel/web_socket_channel.dart';
 
 void main() {
@@ -51,7 +51,7 @@
           fail('Only expected two messages.');
         }
         n++;
-      }).asFuture();
+      }).asFuture<void>();
     });
 
     test('a server can communicate with a WebSocket client', () async {
@@ -94,7 +94,7 @@
           fail('Only expected two messages.');
         }
         n++;
-      }).asFuture();
+      }).asFuture<void>();
     });
   });
 }