diff options
Diffstat (limited to 'crates/server/src/main.rs')
-rw-r--r-- | crates/server/src/main.rs | 75 |
1 files changed, 46 insertions, 29 deletions
diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 3ff300e3d..be63fea93 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs | |||
@@ -32,10 +32,10 @@ use languageserver_types::Url; | |||
32 | use libanalysis::{WorldState, World}; | 32 | use libanalysis::{WorldState, World}; |
33 | 33 | ||
34 | use ::{ | 34 | use ::{ |
35 | io::{Io, RawMsg, RawRequest}, | 35 | io::{Io, RawMsg, RawRequest, RawResponse, RawNotification}, |
36 | handlers::{handle_syntax_tree, handle_extend_selection, publish_diagnostics, publish_decorations, | 36 | handlers::{handle_syntax_tree, handle_extend_selection, publish_diagnostics, publish_decorations, |
37 | handle_document_symbol, handle_code_action}, | 37 | handle_document_symbol, handle_code_action}, |
38 | util::{FilePath, FnBox} | 38 | util::FilePath, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; | 41 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; |
@@ -80,9 +80,9 @@ fn initialize(io: &mut Io) -> Result<()> { | |||
80 | match io.recv()? { | 80 | match io.recv()? { |
81 | RawMsg::Request(req) => { | 81 | RawMsg::Request(req) => { |
82 | if let Some((_params, resp)) = dispatch::expect_request::<req::Initialize>(io, req)? { | 82 | if let Some((_params, resp)) = dispatch::expect_request::<req::Initialize>(io, req)? { |
83 | resp.result(io, req::InitializeResult { | 83 | let res = req::InitializeResult { capabilities: caps::SERVER_CAPABILITIES }; |
84 | capabilities: caps::SERVER_CAPABILITIES | 84 | let resp = resp.into_response(Ok(res))?; |
85 | })?; | 85 | io.send(RawMsg::Response(resp)); |
86 | match io.recv()? { | 86 | match io.recv()? { |
87 | RawMsg::Notification(n) => { | 87 | RawMsg::Notification(n) => { |
88 | if n.method != "initialized" { | 88 | if n.method != "initialized" { |
@@ -106,13 +106,18 @@ fn initialize(io: &mut Io) -> Result<()> { | |||
106 | } | 106 | } |
107 | } | 107 | } |
108 | 108 | ||
109 | type Thunk = Box<for<'a> FnBox<&'a mut Io, Result<()>>>; | 109 | |
110 | enum Task { | ||
111 | Respond(RawResponse), | ||
112 | Notify(RawNotification), | ||
113 | Die(::failure::Error), | ||
114 | } | ||
110 | 115 | ||
111 | fn initialized(io: &mut Io) -> Result<()> { | 116 | fn initialized(io: &mut Io) -> Result<()> { |
112 | { | 117 | { |
113 | let mut world = WorldState::new(); | 118 | let mut world = WorldState::new(); |
114 | let mut pool = ThreadPool::new(4); | 119 | let mut pool = ThreadPool::new(4); |
115 | let (sender, receiver) = bounded::<Thunk>(16); | 120 | let (sender, receiver) = bounded::<Task>(16); |
116 | info!("lifecycle: handshake finished, server ready to serve requests"); | 121 | info!("lifecycle: handshake finished, server ready to serve requests"); |
117 | let res = main_loop(io, &mut world, &mut pool, sender, receiver.clone()); | 122 | let res = main_loop(io, &mut world, &mut pool, sender, receiver.clone()); |
118 | info!("waiting for background jobs to finish..."); | 123 | info!("waiting for background jobs to finish..."); |
@@ -140,14 +145,14 @@ fn main_loop( | |||
140 | io: &mut Io, | 145 | io: &mut Io, |
141 | world: &mut WorldState, | 146 | world: &mut WorldState, |
142 | pool: &mut ThreadPool, | 147 | pool: &mut ThreadPool, |
143 | sender: Sender<Thunk>, | 148 | sender: Sender<Task>, |
144 | receiver: Receiver<Thunk>, | 149 | receiver: Receiver<Task>, |
145 | ) -> Result<()> { | 150 | ) -> Result<()> { |
146 | info!("server initialized, serving requests"); | 151 | info!("server initialized, serving requests"); |
147 | loop { | 152 | loop { |
148 | enum Event { | 153 | enum Event { |
149 | Msg(RawMsg), | 154 | Msg(RawMsg), |
150 | Thunk(Thunk), | 155 | Task(Task), |
151 | ReceiverDead, | 156 | ReceiverDead, |
152 | } | 157 | } |
153 | 158 | ||
@@ -156,7 +161,7 @@ fn main_loop( | |||
156 | Some(msg) => Event::Msg(msg), | 161 | Some(msg) => Event::Msg(msg), |
157 | None => Event::ReceiverDead, | 162 | None => Event::ReceiverDead, |
158 | }, | 163 | }, |
159 | recv(receiver, thunk) => Event::Thunk(thunk.unwrap()), | 164 | recv(receiver, task) => Event::Task(task.unwrap()), |
160 | }; | 165 | }; |
161 | 166 | ||
162 | let msg = match event { | 167 | let msg = match event { |
@@ -164,8 +169,15 @@ fn main_loop( | |||
164 | io.cleanup_receiver()?; | 169 | io.cleanup_receiver()?; |
165 | unreachable!(); | 170 | unreachable!(); |
166 | } | 171 | } |
167 | Event::Thunk(thunk) => { | 172 | Event::Task(task) => { |
168 | thunk.call_box(io)?; | 173 | match task { |
174 | Task::Respond(response) => | ||
175 | io.send(RawMsg::Response(response)), | ||
176 | Task::Notify(n) => | ||
177 | io.send(RawMsg::Notification(n)), | ||
178 | Task::Die(error) => | ||
179 | return Err(error), | ||
180 | } | ||
169 | continue; | 181 | continue; |
170 | } | 182 | } |
171 | Event::Msg(msg) => msg, | 183 | Event::Msg(msg) => msg, |
@@ -175,21 +187,22 @@ fn main_loop( | |||
175 | RawMsg::Request(req) => { | 187 | RawMsg::Request(req) => { |
176 | let mut req = Some(req); | 188 | let mut req = Some(req); |
177 | handle_request_on_threadpool::<req::SyntaxTree>( | 189 | handle_request_on_threadpool::<req::SyntaxTree>( |
178 | &mut req, pool, world, &sender, handle_syntax_tree | 190 | &mut req, pool, world, &sender, handle_syntax_tree, |
179 | )?; | 191 | )?; |
180 | handle_request_on_threadpool::<req::ExtendSelection>( | 192 | handle_request_on_threadpool::<req::ExtendSelection>( |
181 | &mut req, pool, world, &sender, handle_extend_selection | 193 | &mut req, pool, world, &sender, handle_extend_selection, |
182 | )?; | 194 | )?; |
183 | handle_request_on_threadpool::<req::DocumentSymbolRequest>( | 195 | handle_request_on_threadpool::<req::DocumentSymbolRequest>( |
184 | &mut req, pool, world, &sender, handle_document_symbol | 196 | &mut req, pool, world, &sender, handle_document_symbol, |
185 | )?; | 197 | )?; |
186 | handle_request_on_threadpool::<req::CodeActionRequest>( | 198 | handle_request_on_threadpool::<req::CodeActionRequest>( |
187 | &mut req, pool, world, &sender, handle_code_action | 199 | &mut req, pool, world, &sender, handle_code_action, |
188 | )?; | 200 | )?; |
189 | 201 | ||
190 | let mut shutdown = false; | 202 | let mut shutdown = false; |
191 | dispatch::handle_request::<req::Shutdown, _>(&mut req, |(), resp| { | 203 | dispatch::handle_request::<req::Shutdown, _>(&mut req, |(), resp| { |
192 | resp.result(io, ())?; | 204 | let resp = resp.into_response(Ok(()))?; |
205 | io.send(RawMsg::Response(resp)); | ||
193 | shutdown = true; | 206 | shutdown = true; |
194 | Ok(()) | 207 | Ok(()) |
195 | })?; | 208 | })?; |
@@ -227,10 +240,12 @@ fn main_loop( | |||
227 | dispatch::handle_notification::<req::DidCloseTextDocument, _>(&mut not, |params| { | 240 | dispatch::handle_notification::<req::DidCloseTextDocument, _>(&mut not, |params| { |
228 | let path = params.text_document.file_path()?; | 241 | let path = params.text_document.file_path()?; |
229 | world.change_overlay(path, None); | 242 | world.change_overlay(path, None); |
230 | dispatch::send_notification::<req::PublishDiagnostics>(io, req::PublishDiagnosticsParams { | 243 | let not = req::PublishDiagnosticsParams { |
231 | uri: params.text_document.uri, | 244 | uri: params.text_document.uri, |
232 | diagnostics: Vec::new(), | 245 | diagnostics: Vec::new(), |
233 | })?; | 246 | }; |
247 | let not = dispatch::send_notification::<req::PublishDiagnostics>(not); | ||
248 | io.send(RawMsg::Notification(not)); | ||
234 | Ok(()) | 249 | Ok(()) |
235 | })?; | 250 | })?; |
236 | 251 | ||
@@ -249,7 +264,7 @@ fn handle_request_on_threadpool<R: req::ClientRequest>( | |||
249 | req: &mut Option<RawRequest>, | 264 | req: &mut Option<RawRequest>, |
250 | pool: &ThreadPool, | 265 | pool: &ThreadPool, |
251 | world: &WorldState, | 266 | world: &WorldState, |
252 | sender: &Sender<Thunk>, | 267 | sender: &Sender<Task>, |
253 | f: fn(World, R::Params) -> Result<R::Result>, | 268 | f: fn(World, R::Params) -> Result<R::Result>, |
254 | ) -> Result<()> | 269 | ) -> Result<()> |
255 | { | 270 | { |
@@ -258,7 +273,11 @@ fn handle_request_on_threadpool<R: req::ClientRequest>( | |||
258 | let sender = sender.clone(); | 273 | let sender = sender.clone(); |
259 | pool.execute(move || { | 274 | pool.execute(move || { |
260 | let res = f(world, params); | 275 | let res = f(world, params); |
261 | sender.send(Box::new(|io: &mut Io| resp.response(io, res))) | 276 | let task = match resp.into_response(res) { |
277 | Ok(resp) => Task::Respond(resp), | ||
278 | Err(e) => Task::Die(e), | ||
279 | }; | ||
280 | sender.send(task); | ||
262 | }); | 281 | }); |
263 | Ok(()) | 282 | Ok(()) |
264 | }) | 283 | }) |
@@ -267,7 +286,7 @@ fn handle_request_on_threadpool<R: req::ClientRequest>( | |||
267 | fn update_file_notifications_on_threadpool( | 286 | fn update_file_notifications_on_threadpool( |
268 | pool: &ThreadPool, | 287 | pool: &ThreadPool, |
269 | world: World, | 288 | world: World, |
270 | sender: Sender<Thunk>, | 289 | sender: Sender<Task>, |
271 | uri: Url, | 290 | uri: Url, |
272 | ) { | 291 | ) { |
273 | pool.execute(move || { | 292 | pool.execute(move || { |
@@ -276,9 +295,8 @@ fn update_file_notifications_on_threadpool( | |||
276 | error!("failed to compute diagnostics: {:?}", e) | 295 | error!("failed to compute diagnostics: {:?}", e) |
277 | } | 296 | } |
278 | Ok(params) => { | 297 | Ok(params) => { |
279 | sender.send(Box::new(|io: &mut Io| { | 298 | let not = dispatch::send_notification::<req::PublishDiagnostics>(params); |
280 | dispatch::send_notification::<req::PublishDiagnostics>(io, params) | 299 | sender.send(Task::Notify(not)); |
281 | })) | ||
282 | } | 300 | } |
283 | } | 301 | } |
284 | match publish_decorations(world, uri) { | 302 | match publish_decorations(world, uri) { |
@@ -286,9 +304,8 @@ fn update_file_notifications_on_threadpool( | |||
286 | error!("failed to compute decortions: {:?}", e) | 304 | error!("failed to compute decortions: {:?}", e) |
287 | } | 305 | } |
288 | Ok(params) => { | 306 | Ok(params) => { |
289 | sender.send(Box::new(|io: &mut Io| { | 307 | let not = dispatch::send_notification::<req::PublishDecorations>(params); |
290 | dispatch::send_notification::<req::PublishDecorations>(io, params) | 308 | sender.send(Task::Notify(not)) |
291 | })) | ||
292 | } | 309 | } |
293 | } | 310 | } |
294 | }); | 311 | }); |