diff options
-rw-r--r-- | crates/gen_lsp_server/Cargo.toml | 4 | ||||
-rw-r--r-- | crates/gen_lsp_server/src/lib.rs | 85 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 4 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/mod.rs | 12 |
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 @@ | |||
2 | name = "gen_lsp_server" | 2 | name = "gen_lsp_server" |
3 | version = "0.1.0" | 3 | version = "0.1.0" |
4 | authors = ["Aleksey Kladov <[email protected]>"] | 4 | authors = ["Aleksey Kladov <[email protected]>"] |
5 | repository = "https://github.com/rust-analyzer/rust-analyzer" | ||
6 | license = "MIT OR Apache-2.0" | ||
7 | description = "Generic LSP server scaffold." | ||
5 | 8 | ||
6 | [dependencies] | 9 | [dependencies] |
7 | languageserver-types = "0.51.0" | 10 | languageserver-types = "0.51.0" |
8 | log = "0.4.3" | 11 | log = "0.4.3" |
9 | |||
10 | failure = "0.1.2" | 12 | failure = "0.1.2" |
11 | serde_json = "1.0.24" | 13 | serde_json = "1.0.24" |
12 | serde = "1.0.71" | 14 | serde = "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] |
2 | extern crate failure; | 64 | extern 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. | ||
28 | pub fn run_server( | 96 | pub 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)` | ||
55 | pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> { | 124 | pub 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 | ||
66 | fn initialize( | 135 | fn 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 { | |||
35 | pub fn main_loop( | 35 | pub 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 | ||
213 | fn on_task( | 213 | fn 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 | ||
268 | fn on_notification( | 268 | fn 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, |