Merge pull request #83 from dart-lang/prep_publish

prep for publishing 3.0.2
diff --git a/.github/workflows/test-package.yml b/.github/workflows/test-package.yml
index e47bf66..9e0fcc4 100644
--- a/.github/workflows/test-package.yml
+++ b/.github/workflows/test-package.yml
@@ -47,7 +47,7 @@
       matrix:
         # Add macos-latest and/or windows-latest if relevant for this package.
         os: [ubuntu-latest]
-        sdk: [2.12.0, dev]
+        sdk: [2.15.0, dev]
     steps:
       - uses: actions/checkout@v2
       - uses: dart-lang/setup-dart@v1.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e64acb6..cd42d75 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,6 @@
-## 3.0.2-dev
+## 3.0.2
 
+* Switch to using `package:lints`.
 * Address a few analysis hint violations.
 * Populate the pubspec `repository` field.
 
diff --git a/README.md b/README.md
index fef7008..2564d8a 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,7 @@
+[![Dart CI](https://github.com/dart-lang/json_rpc_2/actions/workflows/test-package.yml/badge.svg)](https://github.com/dart-lang/json_rpc_2/actions/workflows/test-package.yml)
+[![pub package](https://img.shields.io/pub/v/json_rpc_2.svg)](https://pub.dev/packages/json_rpc_2)
+[![package publisher](https://img.shields.io/pub/publisher/json_rpc_2.svg)](https://pub.dev/packages/json_rpc_2/publisher)
+
 A library that implements the [JSON-RPC 2.0 spec][spec].
 
 [spec]: https://www.jsonrpc.org/specification
diff --git a/analysis_options.yaml b/analysis_options.yaml
index bff1a74..9ec6408 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,5 +1,15 @@
-# Defines a default set of lint rules enforced for
-# projects at Google. For details and rationale,
-# see https://github.com/dart-lang/pedantic#enabled-lints.
-include: package:pedantic/analysis_options.yaml
+include: package:lints/recommended.yaml
 
+linter:
+  rules:
+    - always_declare_return_types
+    # - avoid_dynamic_calls
+    - avoid_unused_constructor_parameters
+    - cancel_subscriptions
+    - directives_ordering
+    - omit_local_variable_types
+    - package_api_docs
+    - prefer_single_quotes
+    - test_types_in_equals
+    - throw_in_finally
+    - unawaited_futures
diff --git a/example/client.dart b/example/client.dart
index 243b83e..d23be94 100644
--- a/example/client.dart
+++ b/example/client.dart
@@ -2,8 +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 'dart:async';
+
 import 'package:json_rpc_2/json_rpc_2.dart';
-import 'package:pedantic/pedantic.dart';
 import 'package:web_socket_channel/web_socket_channel.dart';
 
 void main() async {
diff --git a/lib/error_code.dart b/lib/error_code.dart
index f4ca462..14e0543 100644
--- a/lib/error_code.dart
+++ b/lib/error_code.dart
@@ -2,6 +2,8 @@
 // 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.
 
+// ignore_for_file: constant_identifier_names
+
 /// Error codes defined in the [JSON-RPC 2.0 specificiation][spec].
 ///
 /// These codes are generally used for protocol-level communication. Most of
diff --git a/lib/src/client.dart b/lib/src/client.dart
index 7e040cc..cc1ca59 100644
--- a/lib/src/client.dart
+++ b/lib/src/client.dart
@@ -173,7 +173,10 @@
   /// invokes [callback] without creating another batch. This means that
   /// responses are batched until the first batch ends.
   void withBatch(Function() callback) {
-    if (_batch != null) return callback();
+    if (_batch != null) {
+      callback();
+      return;
+    }
 
     _batch = [];
     return tryFinally(callback, () {
diff --git a/lib/src/exception.dart b/lib/src/exception.dart
index 64c97d0..ad39ff2 100644
--- a/lib/src/exception.dart
+++ b/lib/src/exception.dart
@@ -24,7 +24,7 @@
   /// This must be a JSON-serializable object. If it's a [Map] without a
   /// `"request"` key, a copy of the request that caused the error will
   /// automatically be injected.
-  final data;
+  final Object? data;
 
   RpcException(this.code, this.message, {this.data});
 
@@ -44,9 +44,9 @@
   /// Converts this exception into a JSON-serializable object that's a valid
   /// JSON-RPC 2.0 error response.
   Map<String, dynamic> serialize(request) {
-    var modifiedData;
-    if (data is Map && !data.containsKey('request')) {
-      modifiedData = Map.from(data);
+    dynamic modifiedData;
+    if (data is Map && !(data as Map).containsKey('request')) {
+      modifiedData = Map.from(data as Map);
       modifiedData['request'] = request;
     } else if (data == null) {
       modifiedData = {'request': request};
diff --git a/lib/src/parameters.dart b/lib/src/parameters.dart
index 665765b..7cf3f2f 100644
--- a/lib/src/parameters.dart
+++ b/lib/src/parameters.dart
@@ -27,7 +27,7 @@
   /// If this is accessed for a [Parameter] that was not passed, the request
   /// will be automatically rejected. To avoid this, use [Parameter.valueOr].
   dynamic get value => _value;
-  final _value;
+  final dynamic _value;
 
   Parameters(this.method, this._value);
 
@@ -111,7 +111,7 @@
   final Parameters _parent;
 
   /// The key used to access [this], used to construct [_path].
-  final _key;
+  final dynamic _key;
 
   /// A human-readable representation of the path of getters used to get this.
   ///
diff --git a/lib/src/server.dart b/lib/src/server.dart
index afcc4ca..5cb2937 100644
--- a/lib/src/server.dart
+++ b/lib/src/server.dart
@@ -172,7 +172,7 @@
   /// if no response should be sent. [callback] may send custom
   /// errors by throwing an [RpcException].
   Future _handleRequest(request) async {
-    var response;
+    dynamic response;
     if (request is List) {
       if (request.isEmpty) {
         response = RpcException(error_code.INVALID_REQUEST,
@@ -301,7 +301,7 @@
   Future _tryFallbacks(Parameters params) {
     var iterator = _fallbacks.toList().iterator;
 
-    Future _tryNext() async {
+    Future tryNext() async {
       if (!iterator.moveNext()) {
         throw RpcException.methodNotFound(params.method);
       }
@@ -310,10 +310,10 @@
         return await iterator.current(params);
       } on RpcException catch (error) {
         if (error.code != error_code.METHOD_NOT_FOUND) rethrow;
-        return _tryNext();
+        return tryNext();
       }
     }
 
-    return _tryNext();
+    return tryNext();
   }
 }
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 37523f0..305945c 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -28,7 +28,7 @@
 /// This is synchronicity-agnostic relative to [body]. If [body] returns a
 /// [Future], this wil run asynchronously; otherwise it will run synchronously.
 void tryFinally(Function() body, Function() whenComplete) {
-  var result;
+  dynamic result;
   try {
     result = body();
   } catch (_) {
@@ -38,7 +38,6 @@
 
   if (result is! Future) {
     whenComplete();
-    return result;
   } else {
     result.whenComplete(whenComplete);
   }
diff --git a/pubspec.yaml b/pubspec.yaml
index 48bc0b6..7d4897e 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: json_rpc_2
-version: 3.0.2-dev
+version: 3.0.2
 description: >-
   Utilities to write a client or server using the JSON-RPC 2.0 spec.
 repository: https://github.com/dart-lang/json_rpc_2
@@ -12,6 +12,6 @@
   stream_channel: ^2.1.0
 
 dev_dependencies:
-  pedantic: ^1.11.0
+  lints: '>=1.0.0 < 3.0.0'
   test: ^1.16.0
   web_socket_channel: ^2.0.0
diff --git a/test/client/client_test.dart b/test/client/client_test.dart
index 1c9ce10..df9c033 100644
--- a/test/client/client_test.dart
+++ b/test/client/client_test.dart
@@ -2,14 +2,15 @@
 // 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 'package:test/test.dart';
 import 'package:json_rpc_2/error_code.dart' as error_code;
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:test/test.dart';
 
 import 'utils.dart';
 
 void main() {
-  var controller;
+  late ClientController controller;
+
   setUp(() => controller = ClientController());
 
   test('sends a message and returns the response', () {
diff --git a/test/client/stream_test.dart b/test/client/stream_test.dart
index 4080064..b33778e 100644
--- a/test/client/stream_test.dart
+++ b/test/client/stream_test.dart
@@ -4,15 +4,15 @@
 
 import 'dart:async';
 
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 import 'package:stream_channel/stream_channel.dart';
 import 'package:test/test.dart';
 
-import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-
 void main() {
-  var responseController;
-  var requestController;
-  var client;
+  late StreamController responseController;
+  late StreamController requestController;
+  late json_rpc.Client client;
+
   setUp(() {
     responseController = StreamController();
     requestController = StreamController();
diff --git a/test/client/utils.dart b/test/client/utils.dart
index 398c558..45342cf 100644
--- a/test/client/utils.dart
+++ b/test/client/utils.dart
@@ -5,11 +5,10 @@
 import 'dart:async';
 import 'dart:convert';
 
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 import 'package:stream_channel/stream_channel.dart';
 import 'package:test/test.dart';
 
-import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-
 /// A controller used to test a [json_rpc.Client].
 class ClientController {
   /// The controller for the client's response stream.
diff --git a/test/peer_test.dart b/test/peer_test.dart
index e209763..4b4c44a 100644
--- a/test/peer_test.dart
+++ b/test/peer_test.dart
@@ -5,17 +5,16 @@
 import 'dart:async';
 import 'dart:convert';
 
-import 'package:pedantic/pedantic.dart';
+import 'package:json_rpc_2/error_code.dart' as error_code;
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 import 'package:stream_channel/stream_channel.dart';
 import 'package:test/test.dart';
 
-import 'package:json_rpc_2/error_code.dart' as error_code;
-import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-
 void main() {
-  var incoming;
-  var outgoing;
-  var peer;
+  late StreamSink incoming;
+  late Stream outgoing;
+  late json_rpc.Peer peer;
+
   setUp(() {
     var incomingController = StreamController();
     incoming = incomingController.sink;
@@ -240,6 +239,7 @@
     );
     peer
       ..registerMethod('foo', () => throw exception)
+      // ignore: unawaited_futures
       ..listen();
 
     incomingController.add({'jsonrpc': '2.0', 'method': 'foo'});
diff --git a/test/server/batch_test.dart b/test/server/batch_test.dart
index c9411b3..b8b8fea 100644
--- a/test/server/batch_test.dart
+++ b/test/server/batch_test.dart
@@ -2,13 +2,14 @@
 // 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 'package:test/test.dart';
 import 'package:json_rpc_2/error_code.dart' as error_code;
+import 'package:test/test.dart';
 
 import 'utils.dart';
 
 void main() {
-  var controller;
+  late ServerController controller;
+
   setUp(() {
     controller = ServerController();
     controller.server
diff --git a/test/server/invalid_request_test.dart b/test/server/invalid_request_test.dart
index a67afec..4fa4de1 100644
--- a/test/server/invalid_request_test.dart
+++ b/test/server/invalid_request_test.dart
@@ -2,13 +2,13 @@
 // 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 'package:test/test.dart';
 import 'package:json_rpc_2/error_code.dart' as error_code;
+import 'package:test/test.dart';
 
 import 'utils.dart';
 
 void main() {
-  var controller;
+  late ServerController controller;
   setUp(() => controller = ServerController());
 
   test('a non-Array/Object request is invalid', () {
diff --git a/test/server/parameters_test.dart b/test/server/parameters_test.dart
index 069daf3..9ecfb1f 100644
--- a/test/server/parameters_test.dart
+++ b/test/server/parameters_test.dart
@@ -2,14 +2,14 @@
 // 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 'package:test/test.dart';
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:test/test.dart';
 
 import 'utils.dart';
 
 void main() {
   group('with named parameters', () {
-    var parameters;
+    late json_rpc.Parameters parameters;
     setUp(() {
       parameters = json_rpc.Parameters('foo', {
         'num': 1.5,
@@ -277,7 +277,7 @@
     });
 
     group('with a nested parameter map', () {
-      var nested;
+      late json_rpc.Parameter nested;
       setUp(() => nested = parameters['map']);
 
       test('[int] fails with a type error', () {
@@ -312,7 +312,8 @@
     });
 
     group('with a nested parameter list', () {
-      var nested;
+      late json_rpc.Parameter nested;
+
       setUp(() => nested = parameters['list']);
 
       test('[string] fails with a type error', () {
@@ -348,7 +349,7 @@
   });
 
   group('with positional parameters', () {
-    var parameters;
+    late json_rpc.Parameters parameters;
     setUp(() => parameters = json_rpc.Parameters('foo', [1, 2, 3, 4, 5]));
 
     test('value returns the wrapped value', () {
diff --git a/test/server/server_test.dart b/test/server/server_test.dart
index 8213ee7..10f2678 100644
--- a/test/server/server_test.dart
+++ b/test/server/server_test.dart
@@ -4,14 +4,15 @@
 
 import 'dart:convert';
 
-import 'package:test/test.dart';
 import 'package:json_rpc_2/error_code.dart' as error_code;
 import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
+import 'package:test/test.dart';
 
 import 'utils.dart';
 
 void main() {
-  var controller;
+  late ServerController controller;
+
   setUp(() => controller = ServerController());
 
   test('calls a registered method with the given name', () {
diff --git a/test/server/stream_test.dart b/test/server/stream_test.dart
index 7105cd6..2f95150 100644
--- a/test/server/stream_test.dart
+++ b/test/server/stream_test.dart
@@ -4,15 +4,15 @@
 
 import 'dart:async';
 
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 import 'package:stream_channel/stream_channel.dart';
 import 'package:test/test.dart';
 
-import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-
 void main() {
-  var requestController;
-  var responseController;
-  var server;
+  late StreamController requestController;
+  late StreamController responseController;
+  late json_rpc.Server server;
+
   setUp(() {
     requestController = StreamController();
     responseController = StreamController();
diff --git a/test/server/utils.dart b/test/server/utils.dart
index 92f1d32..481d342 100644
--- a/test/server/utils.dart
+++ b/test/server/utils.dart
@@ -5,12 +5,11 @@
 import 'dart:async';
 import 'dart:convert';
 
+import 'package:json_rpc_2/error_code.dart' as error_code;
+import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
 import 'package:stream_channel/stream_channel.dart';
 import 'package:test/test.dart';
 
-import 'package:json_rpc_2/json_rpc_2.dart' as json_rpc;
-import 'package:json_rpc_2/error_code.dart' as error_code;
-
 /// A controller used to test a [json_rpc.Server].
 class ServerController {
   /// The controller for the server's request stream.
@@ -50,7 +49,7 @@
 void expectErrorResponse(
     ServerController controller, request, int errorCode, String message,
     {data}) {
-  var id;
+  dynamic id;
   if (request is Map) id = request['id'];
   data ??= {'request': request};