Skip to content
This repository has been archived by the owner on Oct 28, 2024. It is now read-only.

Fix strong mode errors, warnings, and hints. #14

Merged
merged 14 commits into from
Oct 28, 2016
18 changes: 7 additions & 11 deletions lib/src/client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,8 @@ class Client {
/// 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].
Expand Down Expand Up @@ -121,10 +120,7 @@ class Client {
'parameters, was "$parameters".');
}

var message = <String, dynamic>{
"jsonrpc": "2.0",
"method": method
};
var message = <String, dynamic>{"jsonrpc": "2.0", "method": method};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove these incidental reformattings. This package doesn't use dartfmt, and they make it harder to see the real changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

if (id != null) message["id"] = id;
if (parameters != null) message["params"] = parameters;

Expand Down Expand Up @@ -174,10 +170,10 @@ class Client {
if (response.containsKey("result")) {
request.completer.complete(response["result"]);
} else {
request.completer.completeError(new RpcException(
response["error"]["code"],
response["error"]["message"],
data: response["error"]["data"]),
request.completer.completeError(
new RpcException(
response["error"]["code"], response["error"]["message"],
data: response["error"]["data"]),
request.chain);
}
}
Expand Down
18 changes: 9 additions & 9 deletions lib/src/peer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ class Peer implements Client, Server {
/// 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].
///
Expand All @@ -57,10 +56,10 @@ class Peer implements Client, Server {
/// [Peer.listen] is called.
Peer.withoutJson(StreamChannel channel)
: _manager = new ChannelManager("Peer", channel) {
_server = new Server.withoutJson(new StreamChannel(
_serverIncomingForwarder.stream, channel.sink));
_client = new Client.withoutJson(new StreamChannel(
_clientIncomingForwarder.stream, channel.sink));
_server = new Server.withoutJson(
new StreamChannel(_serverIncomingForwarder.stream, channel.sink));
_client = new Client.withoutJson(
new StreamChannel(_clientIncomingForwarder.stream, channel.sink));
}

// Client methods.
Expand Down Expand Up @@ -93,8 +92,9 @@ class Peer implements Client, Server {
} else {
_serverIncomingForwarder.add(message);
}
} else if (message is List && message.isNotEmpty &&
message.first is Map) {
} else if (message is List &&
message.isNotEmpty &&
message.first is Map) {
if (message.first.containsKey('result') ||
message.first.containsKey('error')) {
_clientIncomingForwarder.add(message);
Expand Down
70 changes: 40 additions & 30 deletions lib/src/server.dart
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,8 @@ class Server {
/// 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].
Expand Down Expand Up @@ -126,27 +125,28 @@ class Server {
/// 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(() {
return new Future.sync(() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just change this method to use async/await.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

_validateRequest(request);

var name = request['method'];
Expand All @@ -165,11 +165,7 @@ class Server {
// response, even if one is generated on the server.
if (!request.containsKey('id')) return null;

return {
'jsonrpc': '2.0',
'result': result,
'id': request['id']
};
return {'jsonrpc': '2.0', 'result': result, 'id': request['id']};
}).catchError((error, stackTrace) {
if (error is! RpcException) {
error = new RpcException(
Expand All @@ -191,40 +187,54 @@ class Server {
/// Validates that [request] matches the JSON-RPC spec.
void _validateRequest(request) {
if (request is! Map) {
throw new RpcException(error_code.INVALID_REQUEST, 'Request must be '
throw new RpcException(
error_code.INVALID_REQUEST,
'Request must be '
'an Array or an Object.');
}

if (!request.containsKey('jsonrpc')) {
throw new RpcException(error_code.INVALID_REQUEST, 'Request must '
throw new RpcException(
error_code.INVALID_REQUEST,
'Request must '
'contain a "jsonrpc" key.');
}

if (request['jsonrpc'] != '2.0') {
throw new RpcException(error_code.INVALID_REQUEST, 'Invalid JSON-RPC '
throw new RpcException(
error_code.INVALID_REQUEST,
'Invalid JSON-RPC '
'version ${JSON.encode(request['jsonrpc'])}, expected "2.0".');
}

if (!request.containsKey('method')) {
throw new RpcException(error_code.INVALID_REQUEST, 'Request must '
throw new RpcException(
error_code.INVALID_REQUEST,
'Request must '
'contain a "method" key.');
}

var method = request['method'];
if (request['method'] is! String) {
throw new RpcException(error_code.INVALID_REQUEST, 'Request method must '
throw new RpcException(
error_code.INVALID_REQUEST,
'Request method must '
'be a string, but was ${JSON.encode(method)}.');
}

var params = request['params'];
if (request.containsKey('params') && params is! List && params is! Map) {
throw new RpcException(error_code.INVALID_REQUEST, 'Request params must '
throw new RpcException(
error_code.INVALID_REQUEST,
'Request params must '
'be an Array or an Object, but was ${JSON.encode(params)}.');
}

var id = request['id'];
if (id != null && id is! String && id is! num) {
throw new RpcException(error_code.INVALID_REQUEST, 'Request id must be a '
throw new RpcException(
error_code.INVALID_REQUEST,
'Request id must be a '
'string, number, or null, but was ${JSON.encode(id)}.');
}
}
Expand All @@ -235,12 +245,12 @@ class Server {

_tryNext() {
if (!iterator.moveNext()) {
return new Future.error(
new RpcException.methodNotFound(params.method),
return new Future.error(new RpcException.methodNotFound(params.method),
new Chain.current());
}

return syncFuture(() => iterator.current(params)).catchError((error) {
return new Future.sync(() => iterator.current(params))
.catchError((error) {
if (error is! RpcException) throw error;
if (error.code != error_code.METHOD_NOT_FOUND) throw error;
return _tryNext();
Expand Down
10 changes: 3 additions & 7 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,13 @@

import 'dart:async';

import 'package:stack_trace/stack_trace.dart';
import 'package:stream_channel/stream_channel.dart';

import '../error_code.dart' as error_code;
import 'exception.dart';

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
Expand Down Expand Up @@ -69,8 +64,9 @@ tryFinally(body(), whenComplete()) {
}

/// 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);
});
Expand Down
27 changes: 16 additions & 11 deletions test/client/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -35,20 +34,26 @@ class ClientController {
/// null, no response is sent. Otherwise, the return value is encoded and sent
/// as the response.
void expectRequest(callback(request)) {
expect(_requestController.stream.first.then((request) {
return callback(JSON.decode(request));
}).then((response) {
if (response == null) return;
if (response is! String) response = JSON.encode(response);
_responseController.add(response);
}), completes);
expect(
_requestController.stream.first.then((request) {
return callback(JSON.decode(request));
}).then((response) {
if (response == null) return;
if (response is! String) response = JSON.encode(response);
_responseController.add(response);
}),
completes);
}

/// 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]
Expand Down
Loading