aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r--crates/ra_lsp_server/src/conv.rs14
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs70
-rw-r--r--crates/ra_lsp_server/src/req.rs4
-rw-r--r--crates/ra_lsp_server/src/world.rs7
4 files changed, 58 insertions, 37 deletions
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 82c7e757f..6b3be444f 100644
--- a/crates/ra_lsp_server/src/conv.rs
+++ b/crates/ra_lsp_server/src/conv.rs
@@ -272,7 +272,7 @@ impl<'a> TryConvWith for &'a TextDocumentPositionParams {
272 type Output = FilePosition; 272 type Output = FilePosition;
273 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FilePosition> { 273 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FilePosition> {
274 let file_id = self.text_document.try_conv_with(world)?; 274 let file_id = self.text_document.try_conv_with(world)?;
275 let line_index = world.analysis().file_line_index(file_id); 275 let line_index = world.analysis().file_line_index(file_id)?;
276 let offset = self.position.conv_with(&line_index); 276 let offset = self.position.conv_with(&line_index);
277 Ok(FilePosition { file_id, offset }) 277 Ok(FilePosition { file_id, offset })
278 } 278 }
@@ -283,7 +283,7 @@ impl<'a> TryConvWith for (&'a TextDocumentIdentifier, Range) {
283 type Output = FileRange; 283 type Output = FileRange;
284 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileRange> { 284 fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileRange> {
285 let file_id = self.0.try_conv_with(world)?; 285 let file_id = self.0.try_conv_with(world)?;
286 let line_index = world.analysis().file_line_index(file_id); 286 let line_index = world.analysis().file_line_index(file_id)?;
287 let range = self.1.conv_with(&line_index); 287 let range = self.1.conv_with(&line_index);
288 Ok(FileRange { file_id, range }) 288 Ok(FileRange { file_id, range })
289 } 289 }
@@ -308,7 +308,7 @@ impl TryConvWith for SourceChange {
308 let cursor_position = match self.cursor_position { 308 let cursor_position = match self.cursor_position {
309 None => None, 309 None => None,
310 Some(pos) => { 310 Some(pos) => {
311 let line_index = world.analysis().file_line_index(pos.file_id); 311 let line_index = world.analysis().file_line_index(pos.file_id)?;
312 let edit = self 312 let edit = self
313 .source_file_edits 313 .source_file_edits
314 .iter() 314 .iter()
@@ -349,7 +349,7 @@ impl TryConvWith for SourceFileEdit {
349 uri: self.file_id.try_conv_with(world)?, 349 uri: self.file_id.try_conv_with(world)?,
350 version: None, 350 version: None,
351 }; 351 };
352 let line_index = world.analysis().file_line_index(self.file_id); 352 let line_index = world.analysis().file_line_index(self.file_id)?;
353 let edits = self.edit.as_atoms().iter().map_conv_with(&line_index).collect(); 353 let edits = self.edit.as_atoms().iter().map_conv_with(&line_index).collect();
354 Ok(TextDocumentEdit { text_document, edits }) 354 Ok(TextDocumentEdit { text_document, edits })
355 } 355 }
@@ -378,7 +378,7 @@ impl TryConvWith for &NavigationTarget {
378 type Ctx = WorldSnapshot; 378 type Ctx = WorldSnapshot;
379 type Output = Location; 379 type Output = Location;
380 fn try_conv_with(self, world: &WorldSnapshot) -> Result<Location> { 380 fn try_conv_with(self, world: &WorldSnapshot) -> Result<Location> {
381 let line_index = world.analysis().file_line_index(self.file_id()); 381 let line_index = world.analysis().file_line_index(self.file_id())?;
382 let range = self.range(); 382 let range = self.range();
383 to_location(self.file_id(), range, &world, &line_index) 383 to_location(self.file_id(), range, &world, &line_index)
384 } 384 }
@@ -391,8 +391,8 @@ impl TryConvWith for (FileId, RangeInfo<NavigationTarget>) {
391 let (src_file_id, target) = self; 391 let (src_file_id, target) = self;
392 392
393 let target_uri = target.info.file_id().try_conv_with(world)?; 393 let target_uri = target.info.file_id().try_conv_with(world)?;
394 let src_line_index = world.analysis().file_line_index(src_file_id); 394 let src_line_index = world.analysis().file_line_index(src_file_id)?;
395 let tgt_line_index = world.analysis().file_line_index(target.info.file_id()); 395 let tgt_line_index = world.analysis().file_line_index(target.info.file_id())?;
396 396
397 let target_range = target.info.full_range().conv_with(&tgt_line_index); 397 let target_range = target.info.full_range().conv_with(&tgt_line_index);
398 398
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 5bf950a53..9006aa316 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -39,9 +39,9 @@ pub fn handle_analyzer_status(world: WorldSnapshot, _: ()) -> Result<String> {
39 39
40pub fn handle_syntax_tree(world: WorldSnapshot, params: req::SyntaxTreeParams) -> Result<String> { 40pub fn handle_syntax_tree(world: WorldSnapshot, params: req::SyntaxTreeParams) -> Result<String> {
41 let id = params.text_document.try_conv_with(&world)?; 41 let id = params.text_document.try_conv_with(&world)?;
42 let line_index = world.analysis().file_line_index(id); 42 let line_index = world.analysis().file_line_index(id)?;
43 let text_range = params.range.map(|p| p.conv_with(&line_index)); 43 let text_range = params.range.map(|p| p.conv_with(&line_index));
44 let res = world.analysis().syntax_tree(id, text_range); 44 let res = world.analysis().syntax_tree(id, text_range)?;
45 Ok(res) 45 Ok(res)
46} 46}
47 47
@@ -55,7 +55,7 @@ pub fn handle_extend_selection(
55 use the new selection range API in LSP", 55 use the new selection range API in LSP",
56 ); 56 );
57 let file_id = params.text_document.try_conv_with(&world)?; 57 let file_id = params.text_document.try_conv_with(&world)?;
58 let line_index = world.analysis().file_line_index(file_id); 58 let line_index = world.analysis().file_line_index(file_id)?;
59 let selections = params 59 let selections = params
60 .selections 60 .selections
61 .into_iter() 61 .into_iter()
@@ -72,7 +72,7 @@ pub fn handle_selection_range(
72) -> Result<Vec<req::SelectionRange>> { 72) -> Result<Vec<req::SelectionRange>> {
73 let _p = profile("handle_selection_range"); 73 let _p = profile("handle_selection_range");
74 let file_id = params.text_document.try_conv_with(&world)?; 74 let file_id = params.text_document.try_conv_with(&world)?;
75 let line_index = world.analysis().file_line_index(file_id); 75 let line_index = world.analysis().file_line_index(file_id)?;
76 params 76 params
77 .positions 77 .positions
78 .into_iter() 78 .into_iter()
@@ -113,13 +113,19 @@ pub fn handle_find_matching_brace(
113) -> Result<Vec<Position>> { 113) -> Result<Vec<Position>> {
114 let _p = profile("handle_find_matching_brace"); 114 let _p = profile("handle_find_matching_brace");
115 let file_id = params.text_document.try_conv_with(&world)?; 115 let file_id = params.text_document.try_conv_with(&world)?;
116 let line_index = world.analysis().file_line_index(file_id); 116 let line_index = world.analysis().file_line_index(file_id)?;
117 let res = params 117 let res = params
118 .offsets 118 .offsets
119 .into_iter() 119 .into_iter()
120 .map_conv_with(&line_index) 120 .map_conv_with(&line_index)
121 .map(|offset| { 121 .map(|offset| {
122 world.analysis().matching_brace(FilePosition { file_id, offset }).unwrap_or(offset) 122 if let Ok(Some(matching_brace_offset)) =
123 world.analysis().matching_brace(FilePosition { file_id, offset })
124 {
125 matching_brace_offset
126 } else {
127 offset
128 }
123 }) 129 })
124 .map_conv_with(&line_index) 130 .map_conv_with(&line_index)
125 .collect(); 131 .collect();
@@ -132,7 +138,7 @@ pub fn handle_join_lines(
132) -> Result<req::SourceChange> { 138) -> Result<req::SourceChange> {
133 let _p = profile("handle_join_lines"); 139 let _p = profile("handle_join_lines");
134 let frange = (&params.text_document, params.range).try_conv_with(&world)?; 140 let frange = (&params.text_document, params.range).try_conv_with(&world)?;
135 world.analysis().join_lines(frange).try_conv_with(&world) 141 world.analysis().join_lines(frange)?.try_conv_with(&world)
136} 142}
137 143
138pub fn handle_on_enter( 144pub fn handle_on_enter(
@@ -141,7 +147,7 @@ pub fn handle_on_enter(
141) -> Result<Option<req::SourceChange>> { 147) -> Result<Option<req::SourceChange>> {
142 let _p = profile("handle_on_enter"); 148 let _p = profile("handle_on_enter");
143 let position = params.try_conv_with(&world)?; 149 let position = params.try_conv_with(&world)?;
144 match world.analysis().on_enter(position) { 150 match world.analysis().on_enter(position)? {
145 None => Ok(None), 151 None => Ok(None),
146 Some(edit) => Ok(Some(edit.try_conv_with(&world)?)), 152 Some(edit) => Ok(Some(edit.try_conv_with(&world)?)),
147 } 153 }
@@ -153,7 +159,7 @@ pub fn handle_on_type_formatting(
153) -> Result<Option<Vec<TextEdit>>> { 159) -> Result<Option<Vec<TextEdit>>> {
154 let _p = profile("handle_on_type_formatting"); 160 let _p = profile("handle_on_type_formatting");
155 let mut position = params.text_document_position.try_conv_with(&world)?; 161 let mut position = params.text_document_position.try_conv_with(&world)?;
156 let line_index = world.analysis().file_line_index(position.file_id); 162 let line_index = world.analysis().file_line_index(position.file_id)?;
157 163
158 // in `ra_ide_api`, the `on_type` invariant is that 164 // in `ra_ide_api`, the `on_type` invariant is that
159 // `text.char_at(position) == typed_char`. 165 // `text.char_at(position) == typed_char`.
@@ -163,7 +169,7 @@ pub fn handle_on_type_formatting(
163 "=" => world.analysis().on_eq_typed(position), 169 "=" => world.analysis().on_eq_typed(position),
164 "." => world.analysis().on_dot_typed(position), 170 "." => world.analysis().on_dot_typed(position),
165 _ => return Ok(None), 171 _ => return Ok(None),
166 }; 172 }?;
167 let mut edit = match edit { 173 let mut edit = match edit {
168 Some(it) => it, 174 Some(it) => it,
169 None => return Ok(None), 175 None => return Ok(None),
@@ -181,11 +187,11 @@ pub fn handle_document_symbol(
181 params: req::DocumentSymbolParams, 187 params: req::DocumentSymbolParams,
182) -> Result<Option<req::DocumentSymbolResponse>> { 188) -> Result<Option<req::DocumentSymbolResponse>> {
183 let file_id = params.text_document.try_conv_with(&world)?; 189 let file_id = params.text_document.try_conv_with(&world)?;
184 let line_index = world.analysis().file_line_index(file_id); 190 let line_index = world.analysis().file_line_index(file_id)?;
185 191
186 let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new(); 192 let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new();
187 193
188 for symbol in world.analysis().file_structure(file_id) { 194 for symbol in world.analysis().file_structure(file_id)? {
189 let doc_symbol = DocumentSymbol { 195 let doc_symbol = DocumentSymbol {
190 name: symbol.label, 196 name: symbol.label,
191 detail: symbol.detail, 197 detail: symbol.detail,
@@ -309,7 +315,7 @@ pub fn handle_runnables(
309 params: req::RunnablesParams, 315 params: req::RunnablesParams,
310) -> Result<Vec<req::Runnable>> { 316) -> Result<Vec<req::Runnable>> {
311 let file_id = params.text_document.try_conv_with(&world)?; 317 let file_id = params.text_document.try_conv_with(&world)?;
312 let line_index = world.analysis().file_line_index(file_id); 318 let line_index = world.analysis().file_line_index(file_id)?;
313 let offset = params.position.map(|it| it.conv_with(&line_index)); 319 let offset = params.position.map(|it| it.conv_with(&line_index));
314 let mut res = Vec::new(); 320 let mut res = Vec::new();
315 let workspace_root = world.workspace_root_for(file_id); 321 let workspace_root = world.workspace_root_for(file_id);
@@ -383,7 +389,7 @@ pub fn handle_completion(
383 let mut res = false; 389 let mut res = false;
384 if let Some(ctx) = params.context { 390 if let Some(ctx) = params.context {
385 if ctx.trigger_character.unwrap_or_default() == ":" { 391 if ctx.trigger_character.unwrap_or_default() == ":" {
386 let source_file = world.analysis().parse(position.file_id); 392 let source_file = world.analysis().parse(position.file_id)?;
387 let syntax = source_file.syntax(); 393 let syntax = source_file.syntax();
388 let text = syntax.text(); 394 let text = syntax.text();
389 if let Some(next_char) = text.char_at(position.offset) { 395 if let Some(next_char) = text.char_at(position.offset) {
@@ -405,7 +411,7 @@ pub fn handle_completion(
405 None => return Ok(None), 411 None => return Ok(None),
406 Some(items) => items, 412 Some(items) => items,
407 }; 413 };
408 let line_index = world.analysis().file_line_index(position.file_id); 414 let line_index = world.analysis().file_line_index(position.file_id)?;
409 let items: Vec<CompletionItem> = 415 let items: Vec<CompletionItem> =
410 items.into_iter().map(|item| item.conv_with(&line_index)).collect(); 416 items.into_iter().map(|item| item.conv_with(&line_index)).collect();
411 417
@@ -417,12 +423,12 @@ pub fn handle_folding_range(
417 params: FoldingRangeParams, 423 params: FoldingRangeParams,
418) -> Result<Option<Vec<FoldingRange>>> { 424) -> Result<Option<Vec<FoldingRange>>> {
419 let file_id = params.text_document.try_conv_with(&world)?; 425 let file_id = params.text_document.try_conv_with(&world)?;
420 let line_index = world.analysis().file_line_index(file_id); 426 let line_index = world.analysis().file_line_index(file_id)?;
421 427
422 let res = Some( 428 let res = Some(
423 world 429 world
424 .analysis() 430 .analysis()
425 .folding_ranges(file_id) 431 .folding_ranges(file_id)?
426 .into_iter() 432 .into_iter()
427 .map(|fold| { 433 .map(|fold| {
428 let kind = match fold.kind { 434 let kind = match fold.kind {
@@ -474,7 +480,7 @@ pub fn handle_hover(
474 None => return Ok(None), 480 None => return Ok(None),
475 Some(info) => info, 481 Some(info) => info,
476 }; 482 };
477 let line_index = world.analysis.file_line_index(position.file_id); 483 let line_index = world.analysis.file_line_index(position.file_id)?;
478 let range = info.range.conv_with(&line_index); 484 let range = info.range.conv_with(&line_index);
479 let res = Hover { 485 let res = Hover {
480 contents: HoverContents::Markup(MarkupContent { 486 contents: HoverContents::Markup(MarkupContent {
@@ -503,7 +509,7 @@ pub fn handle_prepare_rename(
503 // Refs should always have a declaration 509 // Refs should always have a declaration
504 let r = refs.declaration(); 510 let r = refs.declaration();
505 let file_id = params.text_document.try_conv_with(&world)?; 511 let file_id = params.text_document.try_conv_with(&world)?;
506 let line_index = world.analysis().file_line_index(file_id); 512 let line_index = world.analysis().file_line_index(file_id)?;
507 let loc = to_location(r.file_id(), r.range(), &world, &line_index)?; 513 let loc = to_location(r.file_id(), r.range(), &world, &line_index)?;
508 514
509 Ok(Some(PrepareRenameResponse::Range(loc.range))) 515 Ok(Some(PrepareRenameResponse::Range(loc.range)))
@@ -536,7 +542,7 @@ pub fn handle_references(
536 params: req::ReferenceParams, 542 params: req::ReferenceParams,
537) -> Result<Option<Vec<Location>>> { 543) -> Result<Option<Vec<Location>>> {
538 let position = params.text_document_position.try_conv_with(&world)?; 544 let position = params.text_document_position.try_conv_with(&world)?;
539 let line_index = world.analysis().file_line_index(position.file_id); 545 let line_index = world.analysis().file_line_index(position.file_id)?;
540 546
541 let refs = match world.analysis().find_all_refs(position)? { 547 let refs = match world.analysis().find_all_refs(position)? {
542 None => return Ok(None), 548 None => return Ok(None),
@@ -563,9 +569,9 @@ pub fn handle_formatting(
563 params: DocumentFormattingParams, 569 params: DocumentFormattingParams,
564) -> Result<Option<Vec<TextEdit>>> { 570) -> Result<Option<Vec<TextEdit>>> {
565 let file_id = params.text_document.try_conv_with(&world)?; 571 let file_id = params.text_document.try_conv_with(&world)?;
566 let file = world.analysis().file_text(file_id); 572 let file = world.analysis().file_text(file_id)?;
567 573
568 let file_line_index = world.analysis().file_line_index(file_id); 574 let file_line_index = world.analysis().file_line_index(file_id)?;
569 let end_position = TextUnit::of_str(&file).conv_with(&file_line_index); 575 let end_position = TextUnit::of_str(&file).conv_with(&file_line_index);
570 576
571 use std::process; 577 use std::process;
@@ -623,7 +629,7 @@ pub fn handle_code_action(
623) -> Result<Option<CodeActionResponse>> { 629) -> Result<Option<CodeActionResponse>> {
624 let _p = profile("handle_code_action"); 630 let _p = profile("handle_code_action");
625 let file_id = params.text_document.try_conv_with(&world)?; 631 let file_id = params.text_document.try_conv_with(&world)?;
626 let line_index = world.analysis().file_line_index(file_id); 632 let line_index = world.analysis().file_line_index(file_id)?;
627 let range = params.range.conv_with(&line_index); 633 let range = params.range.conv_with(&line_index);
628 634
629 let assists = world.analysis().assists(FileRange { file_id, range })?.into_iter(); 635 let assists = world.analysis().assists(FileRange { file_id, range })?.into_iter();
@@ -685,7 +691,7 @@ pub fn handle_code_lens(
685 params: req::CodeLensParams, 691 params: req::CodeLensParams,
686) -> Result<Option<Vec<CodeLens>>> { 692) -> Result<Option<Vec<CodeLens>>> {
687 let file_id = params.text_document.try_conv_with(&world)?; 693 let file_id = params.text_document.try_conv_with(&world)?;
688 let line_index = world.analysis().file_line_index(file_id); 694 let line_index = world.analysis().file_line_index(file_id)?;
689 695
690 let mut lenses: Vec<CodeLens> = Default::default(); 696 let mut lenses: Vec<CodeLens> = Default::default();
691 let workspace_root = world.workspace_root_for(file_id); 697 let workspace_root = world.workspace_root_for(file_id);
@@ -730,7 +736,7 @@ pub fn handle_code_lens(
730 lenses.extend( 736 lenses.extend(
731 world 737 world
732 .analysis() 738 .analysis()
733 .file_structure(file_id) 739 .file_structure(file_id)?
734 .into_iter() 740 .into_iter()
735 .filter(|it| match it.kind { 741 .filter(|it| match it.kind {
736 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true, 742 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true,
@@ -807,7 +813,7 @@ pub fn handle_document_highlight(
807 params: req::TextDocumentPositionParams, 813 params: req::TextDocumentPositionParams,
808) -> Result<Option<Vec<DocumentHighlight>>> { 814) -> Result<Option<Vec<DocumentHighlight>>> {
809 let file_id = params.text_document.try_conv_with(&world)?; 815 let file_id = params.text_document.try_conv_with(&world)?;
810 let line_index = world.analysis().file_line_index(file_id); 816 let line_index = world.analysis().file_line_index(file_id)?;
811 817
812 let refs = match world.analysis().find_all_refs(params.try_conv_with(&world)?)? { 818 let refs = match world.analysis().find_all_refs(params.try_conv_with(&world)?)? {
813 None => return Ok(None), 819 None => return Ok(None),
@@ -826,7 +832,7 @@ pub fn publish_diagnostics(
826 file_id: FileId, 832 file_id: FileId,
827) -> Result<req::PublishDiagnosticsParams> { 833) -> Result<req::PublishDiagnosticsParams> {
828 let uri = world.file_id_to_uri(file_id)?; 834 let uri = world.file_id_to_uri(file_id)?;
829 let line_index = world.analysis().file_line_index(file_id); 835 let line_index = world.analysis().file_line_index(file_id)?;
830 let diagnostics = world 836 let diagnostics = world
831 .analysis() 837 .analysis()
832 .diagnostics(file_id)? 838 .diagnostics(file_id)?
@@ -852,7 +858,7 @@ pub fn publish_decorations(
852} 858}
853 859
854fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> { 860fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> {
855 let line_index = world.analysis().file_line_index(file_id); 861 let line_index = world.analysis().file_line_index(file_id)?;
856 let res = world 862 let res = world
857 .analysis() 863 .analysis()
858 .highlight(file_id)? 864 .highlight(file_id)?
@@ -881,7 +887,7 @@ pub fn handle_inlay_hints(
881) -> Result<Vec<InlayHint>> { 887) -> Result<Vec<InlayHint>> {
882 let file_id = params.text_document.try_conv_with(&world)?; 888 let file_id = params.text_document.try_conv_with(&world)?;
883 let analysis = world.analysis(); 889 let analysis = world.analysis();
884 let line_index = analysis.file_line_index(file_id); 890 let line_index = analysis.file_line_index(file_id)?;
885 Ok(analysis 891 Ok(analysis
886 .inlay_hints(file_id)? 892 .inlay_hints(file_id)?
887 .into_iter() 893 .into_iter()
@@ -891,6 +897,12 @@ pub fn handle_inlay_hints(
891 kind: match api_type.kind { 897 kind: match api_type.kind {
892 ra_ide_api::InlayKind::LetBindingType => InlayKind::LetBindingType, 898 ra_ide_api::InlayKind::LetBindingType => InlayKind::LetBindingType,
893 ra_ide_api::InlayKind::ClosureParameterType => InlayKind::ClosureParameterType, 899 ra_ide_api::InlayKind::ClosureParameterType => InlayKind::ClosureParameterType,
900 ra_ide_api::InlayKind::ForExpressionBindingType => {
901 InlayKind::ForExpressionBindingType
902 }
903 ra_ide_api::InlayKind::IfExpressionType => InlayKind::IfExpressionType,
904 ra_ide_api::InlayKind::WhileLetExpressionType => InlayKind::WhileLetExpressionType,
905 ra_ide_api::InlayKind::MatchArmType => InlayKind::MatchArmType,
894 }, 906 },
895 }) 907 })
896 .collect()) 908 .collect())
diff --git a/crates/ra_lsp_server/src/req.rs b/crates/ra_lsp_server/src/req.rs
index 916185f99..570438643 100644
--- a/crates/ra_lsp_server/src/req.rs
+++ b/crates/ra_lsp_server/src/req.rs
@@ -215,6 +215,10 @@ pub struct InlayHintsParams {
215pub enum InlayKind { 215pub enum InlayKind {
216 LetBindingType, 216 LetBindingType,
217 ClosureParameterType, 217 ClosureParameterType,
218 ForExpressionBindingType,
219 IfExpressionType,
220 WhileLetExpressionType,
221 MatchArmType,
218} 222}
219 223
220#[derive(Debug, Deserialize, Serialize)] 224#[derive(Debug, Deserialize, Serialize)]
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 9fd654305..1d7755910 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -215,7 +215,12 @@ impl WorldSnapshot {
215 } 215 }
216 } 216 }
217 res.push_str("\nanalysis:\n"); 217 res.push_str("\nanalysis:\n");
218 res.push_str(&self.analysis.status()); 218 res.push_str(
219 &self
220 .analysis
221 .status()
222 .unwrap_or_else(|_| "Analysis retrieval was cancelled".to_owned()),
223 );
219 res 224 res
220 } 225 }
221 226