diff options
Diffstat (limited to 'crates/ra_lsp_server/src/main_loop')
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/handlers.rs | 87 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/mod.rs | 31 |
2 files changed, 58 insertions, 60 deletions
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs index 20cb5f772..c853ff653 100644 --- a/crates/ra_lsp_server/src/main_loop/handlers.rs +++ b/crates/ra_lsp_server/src/main_loop/handlers.rs | |||
@@ -1,15 +1,16 @@ | |||
1 | use std::collections::HashMap; | 1 | use std::collections::HashMap; |
2 | 2 | ||
3 | use rustc_hash::FxHashMap; | 3 | use gen_lsp_server::ErrorCode; |
4 | use languageserver_types::{ | 4 | use languageserver_types::{ |
5 | CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, | 5 | CodeActionResponse, Command, CompletionItem, CompletionItemKind, Diagnostic, |
6 | DiagnosticSeverity, DocumentSymbol, FoldingRange, FoldingRangeKind, FoldingRangeParams, | 6 | DiagnosticSeverity, DocumentSymbol, Documentation, FoldingRange, FoldingRangeKind, |
7 | InsertTextFormat, Location, Position, SymbolInformation, TextDocumentIdentifier, TextEdit, | 7 | FoldingRangeParams, InsertTextFormat, Location, MarkupContent, MarkupKind, Position, |
8 | RenameParams, WorkspaceEdit, PrepareRenameResponse, Documentation, MarkupContent, MarkupKind | 8 | PrepareRenameResponse, RenameParams, SymbolInformation, TextDocumentIdentifier, TextEdit, |
9 | WorkspaceEdit, | ||
9 | }; | 10 | }; |
10 | use gen_lsp_server::ErrorCode; | ||
11 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind}; | 11 | use ra_analysis::{FileId, FoldKind, Query, RunnableKind}; |
12 | use ra_syntax::text_utils::contains_offset_nonstrict; | 12 | use ra_syntax::text_utils::contains_offset_nonstrict; |
13 | use rustc_hash::FxHashMap; | ||
13 | use serde_json::to_value; | 14 | use serde_json::to_value; |
14 | 15 | ||
15 | use crate::{ | 16 | use crate::{ |
@@ -17,13 +18,10 @@ use crate::{ | |||
17 | project_model::TargetKind, | 18 | project_model::TargetKind, |
18 | req::{self, Decoration}, | 19 | req::{self, Decoration}, |
19 | server_world::ServerWorld, | 20 | server_world::ServerWorld, |
20 | Result, LspError | 21 | LspError, Result, |
21 | }; | 22 | }; |
22 | 23 | ||
23 | pub fn handle_syntax_tree( | 24 | pub fn handle_syntax_tree(world: ServerWorld, params: req::SyntaxTreeParams) -> Result<String> { |
24 | world: ServerWorld, | ||
25 | params: req::SyntaxTreeParams, | ||
26 | ) -> Result<String> { | ||
27 | let id = params.text_document.try_conv_with(&world)?; | 25 | let id = params.text_document.try_conv_with(&world)?; |
28 | let res = world.analysis().syntax_tree(id); | 26 | let res = world.analysis().syntax_tree(id); |
29 | Ok(res) | 27 | Ok(res) |
@@ -182,10 +180,7 @@ pub fn handle_workspace_symbol( | |||
182 | 180 | ||
183 | return Ok(Some(res)); | 181 | return Ok(Some(res)); |
184 | 182 | ||
185 | fn exec_query( | 183 | fn exec_query(world: &ServerWorld, query: Query) -> Result<Vec<SymbolInformation>> { |
186 | world: &ServerWorld, | ||
187 | query: Query, | ||
188 | ) -> Result<Vec<SymbolInformation>> { | ||
189 | let mut res = Vec::new(); | 184 | let mut res = Vec::new(); |
190 | for (file_id, symbol) in world.analysis().symbol_search(query)? { | 185 | for (file_id, symbol) in world.analysis().symbol_search(query)? { |
191 | let line_index = world.analysis().file_line_index(file_id); | 186 | let line_index = world.analysis().file_line_index(file_id); |
@@ -290,7 +285,11 @@ pub fn handle_runnables( | |||
290 | }); | 285 | }); |
291 | return Ok(res); | 286 | return Ok(res); |
292 | 287 | ||
293 | fn runnable_args(world: &ServerWorld, file_id: FileId, kind: &RunnableKind) -> Result<Vec<String>> { | 288 | fn runnable_args( |
289 | world: &ServerWorld, | ||
290 | file_id: FileId, | ||
291 | kind: &RunnableKind, | ||
292 | ) -> Result<Vec<String>> { | ||
294 | let spec = CargoTargetSpec::for_file(world, file_id)?; | 293 | let spec = CargoTargetSpec::for_file(world, file_id)?; |
295 | let mut res = Vec::new(); | 294 | let mut res = Vec::new(); |
296 | match kind { | 295 | match kind { |
@@ -327,18 +326,15 @@ pub fn handle_runnables( | |||
327 | }; | 326 | }; |
328 | let file_id = world.analysis().crate_root(crate_id)?; | 327 | let file_id = world.analysis().crate_root(crate_id)?; |
329 | let path = world.path_map.get_path(file_id); | 328 | let path = world.path_map.get_path(file_id); |
330 | let res = world | 329 | let res = world.workspaces.iter().find_map(|ws| { |
331 | .workspaces | 330 | let tgt = ws.target_by_root(path)?; |
332 | .iter() | 331 | let res = CargoTargetSpec { |
333 | .find_map(|ws| { | 332 | package: tgt.package(ws).name(ws).to_string(), |
334 | let tgt = ws.target_by_root(path)?; | 333 | target: tgt.name(ws).to_string(), |
335 | let res = CargoTargetSpec { | 334 | target_kind: tgt.kind(ws), |
336 | package: tgt.package(ws).name(ws).to_string(), | 335 | }; |
337 | target: tgt.name(ws).to_string(), | 336 | Some(res) |
338 | target_kind: tgt.kind(ws), | 337 | }); |
339 | }; | ||
340 | Some(res) | ||
341 | }); | ||
342 | Ok(res) | 338 | Ok(res) |
343 | } | 339 | } |
344 | 340 | ||
@@ -367,7 +363,6 @@ pub fn handle_runnables( | |||
367 | } | 363 | } |
368 | TargetKind::Other => (), | 364 | TargetKind::Other => (), |
369 | } | 365 | } |
370 | |||
371 | } | 366 | } |
372 | } | 367 | } |
373 | } | 368 | } |
@@ -453,9 +448,7 @@ pub fn handle_signature_help( | |||
453 | let line_index = world.analysis().file_line_index(file_id); | 448 | let line_index = world.analysis().file_line_index(file_id); |
454 | let offset = params.position.conv_with(&line_index); | 449 | let offset = params.position.conv_with(&line_index); |
455 | 450 | ||
456 | if let Some((descriptor, active_param)) = | 451 | if let Some((descriptor, active_param)) = world.analysis().resolve_callable(file_id, offset)? { |
457 | world.analysis().resolve_callable(file_id, offset)? | ||
458 | { | ||
459 | let parameters: Vec<ParameterInformation> = descriptor | 452 | let parameters: Vec<ParameterInformation> = descriptor |
460 | .params | 453 | .params |
461 | .iter() | 454 | .iter() |
@@ -468,7 +461,7 @@ pub fn handle_signature_help( | |||
468 | let documentation = if let Some(doc) = descriptor.doc { | 461 | let documentation = if let Some(doc) = descriptor.doc { |
469 | Some(Documentation::MarkupContent(MarkupContent { | 462 | Some(Documentation::MarkupContent(MarkupContent { |
470 | kind: MarkupKind::Markdown, | 463 | kind: MarkupKind::Markdown, |
471 | value: doc | 464 | value: doc, |
472 | })) | 465 | })) |
473 | } else { | 466 | } else { |
474 | None | 467 | None |
@@ -511,16 +504,17 @@ pub fn handle_prepare_rename( | |||
511 | Ok(Some(PrepareRenameResponse::Range(loc.range))) | 504 | Ok(Some(PrepareRenameResponse::Range(loc.range))) |
512 | } | 505 | } |
513 | 506 | ||
514 | pub fn handle_rename( | 507 | pub fn handle_rename(world: ServerWorld, params: RenameParams) -> Result<Option<WorkspaceEdit>> { |
515 | world: ServerWorld, | ||
516 | params: RenameParams, | ||
517 | ) -> Result<Option<WorkspaceEdit>> { | ||
518 | let file_id = params.text_document.try_conv_with(&world)?; | 508 | let file_id = params.text_document.try_conv_with(&world)?; |
519 | let line_index = world.analysis().file_line_index(file_id); | 509 | let line_index = world.analysis().file_line_index(file_id); |
520 | let offset = params.position.conv_with(&line_index); | 510 | let offset = params.position.conv_with(&line_index); |
521 | 511 | ||
522 | if params.new_name.is_empty() { | 512 | if params.new_name.is_empty() { |
523 | return Err(LspError::new(ErrorCode::InvalidParams as i32, "New Name cannot be empty".into()).into()); | 513 | return Err(LspError::new( |
514 | ErrorCode::InvalidParams as i32, | ||
515 | "New Name cannot be empty".into(), | ||
516 | ) | ||
517 | .into()); | ||
524 | } | 518 | } |
525 | 519 | ||
526 | let refs = world.analysis().find_all_refs(file_id, offset)?; | 520 | let refs = world.analysis().find_all_refs(file_id, offset)?; |
@@ -531,11 +525,10 @@ pub fn handle_rename( | |||
531 | let mut changes = HashMap::new(); | 525 | let mut changes = HashMap::new(); |
532 | for r in refs { | 526 | for r in refs { |
533 | if let Ok(loc) = to_location(r.0, r.1, &world, &line_index) { | 527 | if let Ok(loc) = to_location(r.0, r.1, &world, &line_index) { |
534 | changes.entry(loc.uri).or_insert(Vec::new()).push( | 528 | changes.entry(loc.uri).or_insert(Vec::new()).push(TextEdit { |
535 | TextEdit { | 529 | range: loc.range, |
536 | range: loc.range, | 530 | new_text: params.new_name.clone(), |
537 | new_text: params.new_name.clone() | 531 | }); |
538 | }); | ||
539 | } | 532 | } |
540 | } | 533 | } |
541 | 534 | ||
@@ -543,7 +536,7 @@ pub fn handle_rename( | |||
543 | changes: Some(changes), | 536 | changes: Some(changes), |
544 | 537 | ||
545 | // TODO: return this instead if client/server support it. See #144 | 538 | // TODO: return this instead if client/server support it. See #144 |
546 | document_changes : None, | 539 | document_changes: None, |
547 | })) | 540 | })) |
548 | } | 541 | } |
549 | 542 | ||
@@ -557,9 +550,11 @@ pub fn handle_references( | |||
557 | 550 | ||
558 | let refs = world.analysis().find_all_refs(file_id, offset)?; | 551 | let refs = world.analysis().find_all_refs(file_id, offset)?; |
559 | 552 | ||
560 | Ok(Some(refs.into_iter() | 553 | Ok(Some( |
561 | .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok()) | 554 | refs.into_iter() |
562 | .collect())) | 555 | .filter_map(|r| to_location(r.0, r.1, &world, &line_index).ok()) |
556 | .collect(), | ||
557 | )) | ||
563 | } | 558 | } |
564 | 559 | ||
565 | pub fn handle_code_action( | 560 | pub fn handle_code_action( |
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index 9ddc3fd0b..c568706bd 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs | |||
@@ -24,7 +24,10 @@ use crate::{ | |||
24 | }; | 24 | }; |
25 | 25 | ||
26 | #[derive(Debug, Fail)] | 26 | #[derive(Debug, Fail)] |
27 | #[fail(display = "Language Server request failed with {}. ({})", code, message)] | 27 | #[fail( |
28 | display = "Language Server request failed with {}. ({})", | ||
29 | code, message | ||
30 | )] | ||
28 | pub struct LspError { | 31 | pub struct LspError { |
29 | pub code: i32, | 32 | pub code: i32, |
30 | pub message: String, | 33 | pub message: String, |
@@ -32,7 +35,7 @@ pub struct LspError { | |||
32 | 35 | ||
33 | impl LspError { | 36 | impl LspError { |
34 | pub fn new(code: i32, message: String) -> LspError { | 37 | pub fn new(code: i32, message: String) -> LspError { |
35 | LspError {code, message} | 38 | LspError { code, message } |
36 | } | 39 | } |
37 | } | 40 | } |
38 | 41 | ||
@@ -214,11 +217,7 @@ fn main_loop_inner( | |||
214 | } | 217 | } |
215 | } | 218 | } |
216 | 219 | ||
217 | fn on_task( | 220 | fn on_task(task: Task, msg_sender: &Sender<RawMessage>, pending_requests: &mut FxHashSet<u64>) { |
218 | task: Task, | ||
219 | msg_sender: &Sender<RawMessage>, | ||
220 | pending_requests: &mut FxHashSet<u64>, | ||
221 | ) { | ||
222 | match task { | 221 | match task { |
223 | Task::Respond(response) => { | 222 | Task::Respond(response) => { |
224 | if pending_requests.remove(&response.id) { | 223 | if pending_requests.remove(&response.id) { |
@@ -373,12 +372,16 @@ impl<'a> PoolDispatcher<'a> { | |||
373 | self.pool.spawn(move || { | 372 | self.pool.spawn(move || { |
374 | let resp = match f(world, params) { | 373 | let resp = match f(world, params) { |
375 | Ok(resp) => RawResponse::ok::<R>(id, &resp), | 374 | Ok(resp) => RawResponse::ok::<R>(id, &resp), |
376 | Err(e) => { | 375 | Err(e) => match e.downcast::<LspError>() { |
377 | match e.downcast::<LspError>() { | 376 | Ok(lsp_error) => { |
378 | Ok(lsp_error) => RawResponse::err(id, lsp_error.code, lsp_error.message), | 377 | RawResponse::err(id, lsp_error.code, lsp_error.message) |
379 | Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, format!("{}\n{}", e, e.backtrace())) | ||
380 | } | 378 | } |
381 | } | 379 | Err(e) => RawResponse::err( |
380 | id, | ||
381 | ErrorCode::InternalError as i32, | ||
382 | format!("{}\n{}", e, e.backtrace()), | ||
383 | ), | ||
384 | }, | ||
382 | }; | 385 | }; |
383 | let task = Task::Respond(resp); | 386 | let task = Task::Respond(resp); |
384 | sender.send(task); | 387 | sender.send(task); |
@@ -412,7 +415,7 @@ fn update_file_notifications_on_threadpool( | |||
412 | if !is_canceled(&e) { | 415 | if !is_canceled(&e) { |
413 | error!("failed to compute diagnostics: {:?}", e); | 416 | error!("failed to compute diagnostics: {:?}", e); |
414 | } | 417 | } |
415 | }, | 418 | } |
416 | Ok(params) => { | 419 | Ok(params) => { |
417 | let not = RawNotification::new::<req::PublishDiagnostics>(¶ms); | 420 | let not = RawNotification::new::<req::PublishDiagnostics>(¶ms); |
418 | sender.send(Task::Notify(not)); | 421 | sender.send(Task::Notify(not)); |
@@ -423,7 +426,7 @@ fn update_file_notifications_on_threadpool( | |||
423 | if !is_canceled(&e) { | 426 | if !is_canceled(&e) { |
424 | error!("failed to compute decorations: {:?}", e); | 427 | error!("failed to compute decorations: {:?}", e); |
425 | } | 428 | } |
426 | }, | 429 | } |
427 | Ok(params) => { | 430 | Ok(params) => { |
428 | let not = RawNotification::new::<req::PublishDecorations>(¶ms); | 431 | let not = RawNotification::new::<req::PublishDecorations>(¶ms); |
429 | sender.send(Task::Notify(not)) | 432 | sender.send(Task::Notify(not)) |