Fix strong mode errors, warnings, and hints. (#14)
diff --git a/lib/src/client.dart b/lib/src/client.dart
index 82baa6a..0568da0 100644
--- a/lib/src/client.dart
+++ b/lib/src/client.dart
@@ -49,9 +49,8 @@
/// Note that the client won't begin listening to [responses] until
/// [Client.listen] is called.
Client(StreamChannel<String> channel)
- : this.withoutJson(channel
- .transform(jsonDocument)
- .transformStream(ignoreFormatExceptions));
+ : this.withoutJson(
+ jsonDocument.bind(channel).transformStream(ignoreFormatExceptions));
/// Creates a [Client] that communicates using decoded messages over
/// [channel].
diff --git a/lib/src/peer.dart b/lib/src/peer.dart
index 810d173..c663da2 100644
--- a/lib/src/peer.dart
+++ b/lib/src/peer.dart
@@ -44,9 +44,8 @@
/// Note that the peer won't begin listening to [channel] until [Peer.listen]
/// is called.
Peer(StreamChannel<String> channel)
- : this.withoutJson(channel
- .transform(jsonDocument)
- .transform(respondToFormatExceptions));
+ : this.withoutJson(
+ jsonDocument.bind(channel).transform(respondToFormatExceptions));
/// Creates a [Peer] that communicates using decoded messages over [channel].
///
diff --git a/lib/src/server.dart b/lib/src/server.dart
index 3ef59ed..b85a46f 100644
--- a/lib/src/server.dart
+++ b/lib/src/server.dart
@@ -56,9 +56,8 @@
/// Note that the server won't begin listening to [requests] until
/// [Server.listen] is called.
Server(StreamChannel<String> channel)
- : this.withoutJson(channel
- .transform(jsonDocument)
- .transform(respondToFormatExceptions));
+ : this.withoutJson(
+ jsonDocument.bind(channel).transform(respondToFormatExceptions));
/// Creates a [Server] that communicates using decoded messages over
/// [channel].
@@ -126,41 +125,45 @@
/// errors by throwing an [RpcException].
Future _handleRequest(request) async {
var response;
- if (request is! List) {
+ if (request is List) {
+ if (request.isEmpty) {
+ response = new RpcException(error_code.INVALID_REQUEST,
+ 'A batch must contain at least one request.')
+ .serialize(request);
+ } else {
+ var results = await Future.wait(request.map(_handleSingleRequest));
+ var nonNull = results.where((result) => result != null);
+ if (nonNull.isEmpty) return;
+ response = nonNull.toList();
+ }
+ } else {
response = await _handleSingleRequest(request);
if (response == null) return;
- } else if (request.isEmpty) {
- response = new RpcException(
- error_code.INVALID_REQUEST,
- 'A batch must contain at least one request.')
- .serialize(request);
- } else {
- var results = await Future.wait(request.map(_handleSingleRequest));
- var nonNull = results.where((result) => result != null);
- if (nonNull.isEmpty) return;
- response = nonNull.toList();
}
if (!isClosed) _manager.add(response);
}
/// Handles an individual parsed request.
- Future _handleSingleRequest(request) {
- return syncFuture(() {
+ Future _handleSingleRequest(request) async {
+ try {
_validateRequest(request);
var name = request['method'];
var method = _methods[name];
if (method == null) method = _tryFallbacks;
+ Object result;
if (method is ZeroArgumentFunction) {
- if (!request.containsKey('params')) return method();
- throw new RpcException.invalidParams('No parameters are allowed for '
- 'method "$name".');
+ if (request.containsKey('params')) {
+ throw new RpcException.invalidParams('No parameters are allowed for '
+ 'method "$name".');
+ }
+ result = await method();
+ } else {
+ result = await method(new Parameters(name, request['params']));
}
- return method(new Parameters(name, request['params']));
- }).then((result) {
// A request without an id is a notification, which should not be sent a
// response, even if one is generated on the server.
if (!request.containsKey('id')) return null;
@@ -170,22 +173,24 @@
'result': result,
'id': request['id']
};
- }).catchError((error, stackTrace) {
- if (error is! RpcException) {
- error = new RpcException(
- error_code.SERVER_ERROR, getErrorMessage(error), data: {
- 'full': error.toString(),
- 'stack': new Chain.forTrace(stackTrace).toString()
- });
- }
-
- if (error.code != error_code.INVALID_REQUEST &&
- !request.containsKey('id')) {
+ } catch (error, stackTrace) {
+ if (error is RpcException) {
+ if (error.code == error_code.INVALID_REQUEST ||
+ request.containsKey('id')) {
+ return error.serialize(request);
+ } else {
+ return null;
+ }
+ } else if (!request.containsKey('id')) {
return null;
- } else {
- return error.serialize(request);
}
- });
+ final chain = new Chain.forTrace(stackTrace);
+ return new RpcException(error_code.SERVER_ERROR, getErrorMessage(error),
+ data: {
+ 'full': '$error',
+ 'stack': '$chain',
+ }).serialize(request);
+ }
}
/// Validates that [request] matches the JSON-RPC spec.
@@ -233,18 +238,18 @@
Future _tryFallbacks(Parameters params) {
var iterator = _fallbacks.toList().iterator;
- _tryNext() {
+ _tryNext() async {
if (!iterator.moveNext()) {
- return new Future.error(
- new RpcException.methodNotFound(params.method),
- new Chain.current());
+ throw new RpcException.methodNotFound(params.method);
}
- return syncFuture(() => iterator.current(params)).catchError((error) {
+ try {
+ return iterator.current(params);
+ } on RpcException catch (error) {
if (error is! RpcException) throw error;
if (error.code != error_code.METHOD_NOT_FOUND) throw error;
return _tryNext();
- });
+ }
}
return _tryNext();
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 8871b56..1e2d6b1 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -4,7 +4,6 @@
import 'dart:async';
-import 'package:stack_trace/stack_trace.dart';
import 'package:stream_channel/stream_channel.dart';
import '../error_code.dart' as error_code;
@@ -12,10 +11,6 @@
typedef ZeroArgumentFunction();
-/// Like [new Future.sync], but automatically wraps the future in a
-/// [Chain.track] call.
-Future syncFuture(callback()) => Chain.track(new Future.sync(callback));
-
/// Returns a sentence fragment listing the elements of [iter].
///
/// This converts each element of [iter] to a string and separates them with
@@ -69,8 +64,9 @@
}
/// A transformer that silently drops [FormatException]s.
-final ignoreFormatExceptions = new StreamTransformer.fromHandlers(
- handleError: (error, stackTrace, sink) {
+final ignoreFormatExceptions =
+ new StreamTransformer<Object, Object>.fromHandlers(
+ handleError: (error, stackTrace, sink) {
if (error is FormatException) return;
sink.addError(error, stackTrace);
});
diff --git a/test/client/utils.dart b/test/client/utils.dart
index 09a200c..9b4dd79 100644
--- a/test/client/utils.dart
+++ b/test/client/utils.dart
@@ -45,10 +45,14 @@
}
/// Sends [response], a decoded response, to [client].
- Future sendResponse(response) => sendJsonResponse(JSON.encode(response));
+ void sendResponse(response) {
+ sendJsonResponse(JSON.encode(response));
+ }
/// Sends [response], a JSON-encoded response, to [client].
- Future sendJsonResponse(String request) => _responseController.add(request);
+ void sendJsonResponse(String request) {
+ _responseController.add(request);
+ }
}
/// Returns a [Future] that completes after pumping the event queue [times]
diff --git a/test/peer_test.dart b/test/peer_test.dart
index ad7ad22..5241e15 100644
--- a/test/peer_test.dart
+++ b/test/peer_test.dart
@@ -164,8 +164,8 @@
});
test("returns a response for malformed JSON", () {
- var incomingController = new StreamController();
- var outgoingController = new StreamController();
+ var incomingController = new StreamController<String>();
+ var outgoingController = new StreamController<String>();
var jsonPeer = new json_rpc.Peer(
new StreamChannel(incomingController.stream, outgoingController));