Files
sdk/pkg/analysis_server/lib/lsp_protocol/protocol_special.dart
T
Danny Tuppeny f484e1b05e Call canParse() for all LSP requests before passing to handlers
Any requests with params that don't pass canParse() will result in an InvalidParams error being returned without the handler being invoked.

Change-Id: Ic3e84b9259a467179baa2309fb58ee207f1225fa
Reviewed-on: https://dart-review.googlesource.com/c/94298
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Nate Bosch <nbosch@google.com>
Commit-Queue: Danny Tuppeny <dantup@google.com>
2019-02-27 08:12:02 +00:00

208 lines
5.3 KiB
Dart

// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
// 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:analysis_server/lsp_protocol/protocol_generated.dart';
const jsonRpcVersion = '2.0';
Object specToJson(Object obj) {
if (obj is ToJsonable) {
return obj.toJson();
} else {
return obj;
}
}
class Either2<T1, T2> {
final int _which;
final T1 _t1;
final T2 _t2;
Either2.t1(this._t1)
: _t2 = null,
_which = 1;
Either2.t2(this._t2)
: _t1 = null,
_which = 2;
@override
get hashCode => map((t) => t.hashCode, (t) => t.hashCode);
bool operator ==(o) => o is Either2<T1, T2> && o._t1 == _t1 && o._t2 == _t2;
T map<T>(T Function(T1) f1, T Function(T2) f2) {
return _which == 1 ? f1(_t1) : f2(_t2);
}
Object toJson() => map(specToJson, specToJson);
/// Checks whether the value of the union equals the supplied value.
bool valueEquals(o) => map((t) => t == o, (t) => t == o);
}
class Either3<T1, T2, T3> {
final int _which;
final T1 _t1;
final T2 _t2;
final T3 _t3;
Either3.t1(this._t1)
: _t2 = null,
_t3 = null,
_which = 1;
Either3.t2(this._t2)
: _t1 = null,
_t3 = null,
_which = 2;
Either3.t3(this._t3)
: _t1 = null,
_t2 = null,
_which = 3;
@override
get hashCode => map((t) => t.hashCode, (t) => t.hashCode, (t) => t.hashCode);
bool operator ==(o) =>
o is Either3<T1, T2, T3> && o._t1 == _t1 && o._t2 == _t2 && o._t3 == _t3;
T map<T>(T Function(T1) f1, T Function(T2) f2, T Function(T3) f3) {
switch (_which) {
case 1:
return f1(_t1);
case 2:
return f2(_t2);
case 3:
return f3(_t3);
default:
throw 'Invalid state.';
}
}
Object toJson() => map(specToJson, specToJson, specToJson);
/// Checks whether the value of the union equals the supplied value.
bool valueEquals(o) => map((t) => t == o, (t) => t == o, (t) => t == o);
}
class Either4<T1, T2, T3, T4> {
final int _which;
final T1 _t1;
final T2 _t2;
final T3 _t3;
final T4 _t4;
Either4.t1(this._t1)
: _t2 = null,
_t3 = null,
_t4 = null,
_which = 1;
Either4.t2(this._t2)
: _t1 = null,
_t3 = null,
_t4 = null,
_which = 2;
Either4.t3(this._t3)
: _t1 = null,
_t2 = null,
_t4 = null,
_which = 3;
Either4.t4(this._t4)
: _t1 = null,
_t2 = null,
_t3 = null,
_which = 4;
@override
get hashCode => map((t) => t.hashCode, (t) => t.hashCode, (t) => t.hashCode,
(t) => t.hashCode);
bool operator ==(o) =>
o is Either4<T1, T2, T3, T4> &&
o._t1 == _t1 &&
o._t2 == _t2 &&
o._t3 == _t3 &&
o._t4 == _t4;
T map<T>(T Function(T1) f1, T Function(T2) f2, T Function(T3) f3,
T Function(T4) f4) {
switch (_which) {
case 1:
return f1(_t1);
case 2:
return f2(_t2);
case 3:
return f3(_t3);
case 4:
return f4(_t4);
default:
throw 'Invalid state.';
}
}
Object toJson() => map(specToJson, specToJson, specToJson, specToJson);
/// Checks whether the value of the union equals the supplied value.
bool valueEquals(o) =>
map((t) => t == o, (t) => t == o, (t) => t == o, (t) => t == o);
}
class ErrorOr<T> extends Either2<ResponseError, T> {
ErrorOr.error(ResponseError error) : super.t1(error);
ErrorOr.success([T result]) : super.t2(result);
/// Returns the error or throws if object is not an error. Check [isError]
/// before accessing [error].
ResponseError get error {
return _which == 1 ? _t1 : (throw 'Value is not an error');
}
/// Returns true if this object is an error, false if it is a result. Prefer
/// [mapResult] instead of checking this flag if [errors] will simply be
/// propagated as-is.
bool get isError => _which == 1;
/// Returns the result or throws if this object is an error. Check [isError]
/// before accessing [result]. It is valid for this to return null is the
/// object does not represent an error but the resulting value was null.
T get result {
return _which == 2 ? _t2 : (throw 'Value is not a result');
}
/// If this object is a result, maps [result] through [f], otherwise returns
/// a new error object representing [error].
FutureOr<ErrorOr<N>> mapResult<N>(FutureOr<ErrorOr<N>> Function(T) f) {
return isError
// Re-wrap the error using our new type arg
? new ErrorOr<N>.error(error)
// Otherwise call the map function
: f(result);
}
}
/// A base class containing the fields common to RequestMessage and
/// NotificationMessage to simplify handling.
abstract class IncomingMessage {
Method get method;
dynamic get params;
}
/// A helper to allow handlers to declare both a JSON validation function and
/// parse function.
class LspJsonHandler<T> {
final bool Function(Map<String, Object>) validateParams;
final T Function(Map<String, Object>) convertParams;
const LspJsonHandler(this.validateParams, this.convertParams);
}
bool _alwaysTrue(_) => true;
Null _alwaysNull(_) => null;
const NullJsonHandler = const LspJsonHandler<Null>(_alwaysTrue, _alwaysNull);
abstract class ToJsonable {
Object toJson();
}