aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/gen_lsp_server/Cargo.toml4
-rw-r--r--crates/gen_lsp_server/src/lib.rs85
-rw-r--r--crates/ra_lsp_server/src/main.rs4
-rw-r--r--crates/ra_lsp_server/src/main_loop/mod.rs12
4 files changed, 88 insertions, 17 deletions
diff --git a/crates/gen_lsp_server/Cargo.toml b/crates/gen_lsp_server/Cargo.toml
index 6580ba6e4..cf5c34a88 100644
--- a/crates/gen_lsp_server/Cargo.toml
+++ b/crates/gen_lsp_server/Cargo.toml
@@ -2,11 +2,13 @@
2name = "gen_lsp_server" 2name = "gen_lsp_server"
3version = "0.1.0" 3version = "0.1.0"
4authors = ["Aleksey Kladov <[email protected]>"] 4authors = ["Aleksey Kladov <[email protected]>"]
5repository = "https://github.com/rust-analyzer/rust-analyzer"
6license = "MIT OR Apache-2.0"
7description = "Generic LSP server scaffold."
5 8
6[dependencies] 9[dependencies]
7languageserver-types = "0.51.0" 10languageserver-types = "0.51.0"
8log = "0.4.3" 11log = "0.4.3"
9
10failure = "0.1.2" 12failure = "0.1.2"
11serde_json = "1.0.24" 13serde_json = "1.0.24"
12serde = "1.0.71" 14serde = "1.0.71"
diff --git a/crates/gen_lsp_server/src/lib.rs b/crates/gen_lsp_server/src/lib.rs
index baca921df..645728a57 100644
--- a/crates/gen_lsp_server/src/lib.rs
+++ b/crates/gen_lsp_server/src/lib.rs
@@ -1,3 +1,65 @@
1//! A language server scaffold, exposing synchroneous crossbeam-channel based API.
2//! This crate handles protocol handshaking and parsing messages, while you
3//! control the message dispatch loop yourself.
4//!
5//! Run with `RUST_LOG=sync_lsp_server=debug` to see all the messages.
6//!
7//! ```no_run
8//! extern crate gen_lsp_server;
9//! extern crate languageserver_types;
10//! extern crate failure;
11//! extern crate crossbeam_channel;
12//!
13//! use crossbeam_channel::{Sender, Receiver};
14//! use languageserver_types::{ServerCapabilities, InitializeParams, request::{GotoDefinition, GotoDefinitionResponse}};
15//! use gen_lsp_server::{run_server, stdio_transport, handle_shutdown, RawMessage, RawResponse};
16//!
17//! fn main() -> Result<(), failure::Error> {
18//! let (receiver, sender, io_threads) = stdio_transport();
19//! gen_lsp_server::run_server(
20//! ServerCapabilities::default(),
21//! receiver,
22//! sender,
23//! main_loop,
24//! )?;
25//! io_threads.join()?;
26//! Ok(())
27//! }
28//!
29//! fn main_loop(
30//! _params: InitializeParams,
31//! receiver: &Receiver<RawMessage>,
32//! sender: &Sender<RawMessage>,
33//! ) -> Result<(), failure::Error> {
34//! for msg in receiver {
35//! match msg {
36//! RawMessage::Request(req) => {
37//! let req = match handle_shutdown(req, sender) {
38//! None => return Ok(()),
39//! Some(req) => req,
40//! };
41//! let req = match req.cast::<GotoDefinition>() {
42//! Ok((id, _params)) => {
43//! let resp = RawResponse::ok::<GotoDefinition>(
44//! id,
45//! &Some(GotoDefinitionResponse::Array(Vec::new())),
46//! );
47//! sender.send(RawMessage::Response(resp));
48//! continue;
49//! },
50//! Err(req) => req,
51//! };
52//! // ...
53//! }
54//! RawMessage::Response(_resp) => (),
55//! RawMessage::Notification(_not) => (),
56//! }
57//! }
58//! Ok(())
59//! }
60//! ```
61
62
1#[macro_use] 63#[macro_use]
2extern crate failure; 64extern crate failure;
3#[macro_use] 65#[macro_use]
@@ -25,20 +87,26 @@ pub use {
25 stdio::{stdio_transport, Threads}, 87 stdio::{stdio_transport, Threads},
26}; 88};
27 89
90/// Main entry point: runs the server from initialization to shutdown.
91/// To attach server to standard input/output streams, use `stdio_transport`
92/// function to create corresponding `sender` and `receiver` pair.
93///
94///`server` should use `handle_shutdown` function to handle the `Shutdown`
95/// request.
28pub fn run_server( 96pub fn run_server(
29 caps: ServerCapabilities, 97 caps: ServerCapabilities,
98 receiver: Receiver<RawMessage>,
99 sender: Sender<RawMessage>,
30 server: impl FnOnce( 100 server: impl FnOnce(
31 InitializeParams, 101 InitializeParams,
32 &mut Receiver<RawMessage>, 102 &Receiver<RawMessage>,
33 &mut Sender<RawMessage>, 103 &Sender<RawMessage>,
34 ) -> Result<()>, 104 ) -> Result<()>,
35 mut receiver: Receiver<RawMessage>,
36 mut sender: Sender<RawMessage>,
37) -> Result<()> { 105) -> Result<()> {
38 info!("lsp server initializes"); 106 info!("lsp server initializes");
39 let params = initialize(&mut receiver, &mut sender, caps)?; 107 let params = initialize(&receiver, &sender, caps)?;
40 info!("lsp server initialized, serving requests"); 108 info!("lsp server initialized, serving requests");
41 server(params, &mut receiver, &mut sender)?; 109 server(params, &receiver, &sender)?;
42 info!("lsp server waiting for exit notification"); 110 info!("lsp server waiting for exit notification");
43 match receiver.recv() { 111 match receiver.recv() {
44 Some(RawMessage::Notification(n)) => { 112 Some(RawMessage::Notification(n)) => {
@@ -52,6 +120,7 @@ pub fn run_server(
52 Ok(()) 120 Ok(())
53} 121}
54 122
123/// if `req` is `Shutdown`, respond to it and return `None`, otherwise return `Some(req)`
55pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> { 124pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> {
56 match req.cast::<Shutdown>() { 125 match req.cast::<Shutdown>() {
57 Ok((id, ())) => { 126 Ok((id, ())) => {
@@ -64,8 +133,8 @@ pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<R
64} 133}
65 134
66fn initialize( 135fn initialize(
67 receiver: &mut Receiver<RawMessage>, 136 receiver: &Receiver<RawMessage>,
68 sender: &mut Sender<RawMessage>, 137 sender: &Sender<RawMessage>,
69 caps: ServerCapabilities, 138 caps: ServerCapabilities,
70) -> Result<InitializeParams> { 139) -> Result<InitializeParams> {
71 let (id, params) = match receiver.recv() { 140 let (id, params) = match receiver.recv() {
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index c547764f6..e5d1792b7 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -35,14 +35,14 @@ fn main_inner() -> Result<()> {
35 let cwd = ::std::env::current_dir()?; 35 let cwd = ::std::env::current_dir()?;
36 run_server( 36 run_server(
37 ra_lsp_server::server_capabilities(), 37 ra_lsp_server::server_capabilities(),
38 receiver,
39 sender,
38 |params, r, s| { 40 |params, r, s| {
39 let root = params.root_uri 41 let root = params.root_uri
40 .and_then(|it| it.to_file_path().ok()) 42 .and_then(|it| it.to_file_path().ok())
41 .unwrap_or(cwd); 43 .unwrap_or(cwd);
42 ra_lsp_server::main_loop(false, root, r, s) 44 ra_lsp_server::main_loop(false, root, r, s)
43 }, 45 },
44 receiver,
45 sender,
46 )?; 46 )?;
47 info!("shutting down IO..."); 47 info!("shutting down IO...");
48 threads.join()?; 48 threads.join()?;
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs
index abc58b70e..47a9b202e 100644
--- a/crates/ra_lsp_server/src/main_loop/mod.rs
+++ b/crates/ra_lsp_server/src/main_loop/mod.rs
@@ -35,8 +35,8 @@ enum Task {
35pub fn main_loop( 35pub fn main_loop(
36 internal_mode: bool, 36 internal_mode: bool,
37 root: PathBuf, 37 root: PathBuf,
38 msg_receriver: &mut Receiver<RawMessage>, 38 msg_receriver: &Receiver<RawMessage>,
39 msg_sender: &mut Sender<RawMessage>, 39 msg_sender: &Sender<RawMessage>,
40) -> Result<()> { 40) -> Result<()> {
41 let pool = rayon::ThreadPoolBuilder::new() 41 let pool = rayon::ThreadPoolBuilder::new()
42 .num_threads(4) 42 .num_threads(4)
@@ -88,8 +88,8 @@ fn main_loop_inner(
88 internal_mode: bool, 88 internal_mode: bool,
89 ws_root: PathBuf, 89 ws_root: PathBuf,
90 pool: &ThreadPool, 90 pool: &ThreadPool,
91 msg_sender: &mut Sender<RawMessage>, 91 msg_sender: &Sender<RawMessage>,
92 msg_receiver: &mut Receiver<RawMessage>, 92 msg_receiver: &Receiver<RawMessage>,
93 task_sender: Sender<Task>, 93 task_sender: Sender<Task>,
94 task_receiver: Receiver<Task>, 94 task_receiver: Receiver<Task>,
95 fs_worker: Worker<PathBuf, (PathBuf, Vec<FileEvent>)>, 95 fs_worker: Worker<PathBuf, (PathBuf, Vec<FileEvent>)>,
@@ -212,7 +212,7 @@ fn main_loop_inner(
212 212
213fn on_task( 213fn on_task(
214 task: Task, 214 task: Task,
215 msg_sender: &mut Sender<RawMessage>, 215 msg_sender: &Sender<RawMessage>,
216 pending_requests: &mut HashMap<u64, JobHandle>, 216 pending_requests: &mut HashMap<u64, JobHandle>,
217) { 217) {
218 match task { 218 match task {
@@ -266,7 +266,7 @@ fn on_request(
266} 266}
267 267
268fn on_notification( 268fn on_notification(
269 msg_sender: &mut Sender<RawMessage>, 269 msg_sender: &Sender<RawMessage>,
270 state: &mut ServerWorldState, 270 state: &mut ServerWorldState,
271 pending_requests: &mut HashMap<u64, JobHandle>, 271 pending_requests: &mut HashMap<u64, JobHandle>,
272 subs: &mut Subscriptions, 272 subs: &mut Subscriptions,