aboutsummaryrefslogtreecommitdiff
path: root/crates/server/src/main.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-12 19:34:17 +0100
committerAleksey Kladov <[email protected]>2018-08-12 19:34:17 +0100
commit8dad14b5cd63203d7ad9d86686b3c654ff353c83 (patch)
treef823b1423a9735bf4c776d750a25e7a02d136e0a /crates/server/src/main.rs
parent23c06db9c236db0f9c8ef5117fb1adefd6616c43 (diff)
Convert Thunk to Task
Diffstat (limited to 'crates/server/src/main.rs')
-rw-r--r--crates/server/src/main.rs75
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;
32use libanalysis::{WorldState, World}; 32use libanalysis::{WorldState, World};
33 33
34use ::{ 34use ::{
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
41pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 41pub 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
109type Thunk = Box<for<'a> FnBox<&'a mut Io, Result<()>>>; 109
110enum Task {
111 Respond(RawResponse),
112 Notify(RawNotification),
113 Die(::failure::Error),
114}
110 115
111fn initialized(io: &mut Io) -> Result<()> { 116fn 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>(
267fn update_file_notifications_on_threadpool( 286fn 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 });