mirror of
https://github.com/SpaceManiac/SpacemanDMM.git
synced 2025-12-23 05:36:47 +00:00
Add method matcher for notifications
This commit is contained in:
parent
5b51f84dd4
commit
3a4153ae08
1 changed files with 66 additions and 18 deletions
|
|
@ -16,20 +16,30 @@ mod io;
|
|||
|
||||
use std::io::Write;
|
||||
use jsonrpc::{Request, Call, Response, Output};
|
||||
use langserver::MessageType;
|
||||
|
||||
fn main() {
|
||||
let stdio = io::StdIo;
|
||||
Engine {
|
||||
read: &stdio,
|
||||
write: &stdio,
|
||||
status: InitStatus::Starting,
|
||||
}.run()
|
||||
}
|
||||
|
||||
const VERSION: Option<jsonrpc::Version> = Some(jsonrpc::Version::V2);
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum InitStatus {
|
||||
Starting,
|
||||
Running,
|
||||
ShuttingDown,
|
||||
}
|
||||
|
||||
struct Engine<'a, R: 'a, W: 'a> {
|
||||
read: &'a R,
|
||||
write: &'a W,
|
||||
status: InitStatus,
|
||||
}
|
||||
|
||||
impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
|
||||
|
|
@ -65,16 +75,19 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
|
|||
let request = Request::Single(Call::Notification(jsonrpc::Notification {
|
||||
jsonrpc: VERSION,
|
||||
method: T::METHOD.to_owned(),
|
||||
params: Some(match params {
|
||||
serde_json::Value::Null => jsonrpc::Params::None,
|
||||
serde_json::Value::Array(x) => jsonrpc::Params::Array(x),
|
||||
serde_json::Value::Object(x) => jsonrpc::Params::Map(x),
|
||||
_ => panic!("notification bad value to params conversion")
|
||||
})
|
||||
params: Some(value_to_params(params)),
|
||||
}));
|
||||
self.write.write(serde_json::to_string(&request).expect("notification bad to_string"))
|
||||
}
|
||||
|
||||
fn show_message<S>(&mut self, typ: langserver::MessageType, message: S) where
|
||||
S: Into<String>
|
||||
{
|
||||
self.issue_notification::<langserver::notification::ShowMessage>(
|
||||
langserver::ShowMessageParams { typ, message: message.into() }
|
||||
)
|
||||
}
|
||||
|
||||
fn handle_call(&mut self, call: Call) -> Option<Output> {
|
||||
match call {
|
||||
Call::Invalid(id) => {
|
||||
|
|
@ -84,8 +97,8 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
|
|||
let id = method_call.id.clone();
|
||||
Some(Output::from(self.handle_method_call(method_call), id, VERSION))
|
||||
},
|
||||
Call::Notification(_notification) => {
|
||||
// TODO
|
||||
Call::Notification(notification) => {
|
||||
self.handle_notification(notification);
|
||||
None
|
||||
},
|
||||
}
|
||||
|
|
@ -94,12 +107,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
|
|||
fn handle_method_call(&mut self, call: jsonrpc::MethodCall) -> Result<serde_json::Value, jsonrpc::Error> {
|
||||
use langserver::request::*;
|
||||
|
||||
let params_value = match call.params {
|
||||
Some(jsonrpc::Params::None) |
|
||||
None => serde_json::Value::Null,
|
||||
Some(jsonrpc::Params::Array(x)) => serde_json::Value::Array(x),
|
||||
Some(jsonrpc::Params::Map(x)) => serde_json::Value::Object(x),
|
||||
};
|
||||
let params_value = params_to_value(call.params);
|
||||
|
||||
macro_rules! match_call {
|
||||
($(|$name:ident: $what:ty| $body:block;)*) => (
|
||||
|
|
@ -108,6 +116,7 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
|
|||
let result: <$what as Request>::Result = $body;
|
||||
Ok(serde_json::to_value(result).expect("blah 2"))
|
||||
} else)* {
|
||||
self.show_message(MessageType::Warning, format!("Call NYI: {}", call.method));
|
||||
Err(jsonrpc::Error {
|
||||
code: jsonrpc::ErrorCode::InternalError,
|
||||
message: "Not yet implemented".to_owned(),
|
||||
|
|
@ -119,12 +128,51 @@ impl<'a, R: io::RequestRead, W: io::ResponseWrite> Engine<'a, R, W> {
|
|||
|
||||
match_call! {
|
||||
|_init: Initialize| {
|
||||
self.issue_notification::<langserver::notification::ShowMessage>(langserver::ShowMessageParams {
|
||||
typ: langserver::MessageType::Info,
|
||||
message: "Hello, world!".to_owned(),
|
||||
});
|
||||
self.show_message(MessageType::Info, "Hello, world!");
|
||||
self.status = InitStatus::Running;
|
||||
Default::default()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_notification(&mut self, notification: jsonrpc::Notification) {
|
||||
use langserver::notification::*;
|
||||
|
||||
let params_value = params_to_value(notification.params);
|
||||
|
||||
macro_rules! match_notify {
|
||||
($(|$name:ident: $what:ty| $body:block;)*) => (
|
||||
$(if notification.method == <$what>::METHOD {
|
||||
let $name: <$what as Notification>::Params = serde_json::from_value(params_value).expect("blah");
|
||||
$body
|
||||
} else)* {
|
||||
self.show_message(MessageType::Warning, format!("Notify NYI: {}", notification.method));
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
match_notify! {
|
||||
|_empty: Exit| {
|
||||
std::process::exit(if self.status == InitStatus::ShuttingDown { 0 } else { 1 });
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn params_to_value(params: Option<jsonrpc::Params>) -> serde_json::Value {
|
||||
match params {
|
||||
Some(jsonrpc::Params::None) |
|
||||
None => serde_json::Value::Null,
|
||||
Some(jsonrpc::Params::Array(x)) => serde_json::Value::Array(x),
|
||||
Some(jsonrpc::Params::Map(x)) => serde_json::Value::Object(x),
|
||||
}
|
||||
}
|
||||
|
||||
fn value_to_params(value: serde_json::Value) -> jsonrpc::Params {
|
||||
match value {
|
||||
serde_json::Value::Null => jsonrpc::Params::None,
|
||||
serde_json::Value::Array(x) => jsonrpc::Params::Array(x),
|
||||
serde_json::Value::Object(x) => jsonrpc::Params::Map(x),
|
||||
_ => panic!("bad value to params conversion")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue