about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_cli/src/analysis_bench.rs2
-rw-r--r--crates/ra_ide_api/src/lib.rs86
-rw-r--r--crates/ra_ide_api/src/references.rs3
-rw-r--r--crates/ra_ide_api/src/syntax_tree.rs14
-rw-r--r--crates/ra_ide_api/src/typing.rs4
-rw-r--r--crates/ra_lsp_server/src/conv.rs14
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs64
-rw-r--r--crates/ra_lsp_server/src/world.rs7
8 files changed, 107 insertions, 87 deletions
diff --git a/crates/ra_cli/src/analysis_bench.rs b/crates/ra_cli/src/analysis_bench.rs
index 639ac763eef..5e9d0c16d64 100644
--- a/crates/ra_cli/src/analysis_bench.rs
+++ b/crates/ra_cli/src/analysis_bench.rs
@@ -55,7 +55,7 @@ pub(crate) fn run(verbose: bool, path: &Path, op: Op) -> Result<()> {
         Op::Complete { line, column, .. } => {
             let offset = host
                 .analysis()
-                .file_line_index(file_id)
+                .file_line_index(file_id)?
                 .offset(LineCol { line, col_utf16: column });
             let file_postion = FilePosition { file_id, offset };
 
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 16ffb03ce92..edb646c1130 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -317,24 +317,24 @@ impl Analysis {
     }
 
     /// Debug info about the current state of the analysis
-    pub fn status(&self) -> String {
-        status::status(&*self.db)
+    pub fn status(&self) -> Cancelable<String> {
+        self.with_db(|db| status::status(&*db))
     }
 
     /// Gets the text of the source file.
-    pub fn file_text(&self, file_id: FileId) -> Arc<String> {
-        self.db.file_text(file_id)
+    pub fn file_text(&self, file_id: FileId) -> Cancelable<Arc<String>> {
+        self.with_db(|db| db.file_text(file_id))
     }
 
     /// Gets the syntax tree of the file.
-    pub fn parse(&self, file_id: FileId) -> SourceFile {
-        self.db.parse(file_id).tree()
+    pub fn parse(&self, file_id: FileId) -> Cancelable<SourceFile> {
+        self.with_db(|db| db.parse(file_id).tree())
     }
 
     /// Gets the file's `LineIndex`: data structure to convert between absolute
     /// offsets and line/column representation.
-    pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
-        self.db.line_index(file_id)
+    pub fn file_line_index(&self, file_id: FileId) -> Cancelable<Arc<LineIndex>> {
+        self.with_db(|db| db.line_index(file_id))
     }
 
     /// Selects the next syntactic nodes encompassing the range.
@@ -344,58 +344,67 @@ impl Analysis {
 
     /// Returns position of the matching brace (all types of braces are
     /// supported).
-    pub fn matching_brace(&self, position: FilePosition) -> Option<TextUnit> {
-        let parse = self.db.parse(position.file_id);
-        let file = parse.tree();
-        matching_brace::matching_brace(&file, position.offset)
+    pub fn matching_brace(&self, position: FilePosition) -> Cancelable<Option<TextUnit>> {
+        self.with_db(|db| {
+            let parse = db.parse(position.file_id);
+            let file = parse.tree();
+            matching_brace::matching_brace(&file, position.offset)
+        })
     }
 
     /// Returns a syntax tree represented as `String`, for debug purposes.
     // FIXME: use a better name here.
-    pub fn syntax_tree(&self, file_id: FileId, text_range: Option<TextRange>) -> String {
-        syntax_tree::syntax_tree(&self.db, file_id, text_range)
+    pub fn syntax_tree(
+        &self,
+        file_id: FileId,
+        text_range: Option<TextRange>,
+    ) -> Cancelable<String> {
+        self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range))
     }
 
     /// Returns an edit to remove all newlines in the range, cleaning up minor
     /// stuff like trailing commas.
-    pub fn join_lines(&self, frange: FileRange) -> SourceChange {
-        let parse = self.db.parse(frange.file_id);
-        let file_edit = SourceFileEdit {
-            file_id: frange.file_id,
-            edit: join_lines::join_lines(&parse.tree(), frange.range),
-        };
-        SourceChange::source_file_edit("join lines", file_edit)
+    pub fn join_lines(&self, frange: FileRange) -> Cancelable<SourceChange> {
+        self.with_db(|db| {
+            let parse = db.parse(frange.file_id);
+            let file_edit = SourceFileEdit {
+                file_id: frange.file_id,
+                edit: join_lines::join_lines(&parse.tree(), frange.range),
+            };
+            SourceChange::source_file_edit("join lines", file_edit)
+        })
     }
 
     /// Returns an edit which should be applied when opening a new line, fixing
     /// up minor stuff like continuing the comment.
-    pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> {
-        typing::on_enter(&self.db, position)
+    pub fn on_enter(&self, position: FilePosition) -> Cancelable<Option<SourceChange>> {
+        self.with_db(|db| typing::on_enter(&db, position))
     }
 
     /// Returns an edit which should be applied after `=` was typed. Primarily,
     /// this works when adding `let =`.
     // FIXME: use a snippet completion instead of this hack here.
-    pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> {
-        let parse = self.db.parse(position.file_id);
-        let file = parse.tree();
-        let edit = typing::on_eq_typed(&file, position.offset)?;
-        Some(SourceChange::source_file_edit(
-            "add semicolon",
-            SourceFileEdit { edit, file_id: position.file_id },
-        ))
+    pub fn on_eq_typed(&self, position: FilePosition) -> Cancelable<Option<SourceChange>> {
+        self.with_db(|db| {
+            let parse = db.parse(position.file_id);
+            let file = parse.tree();
+            let edit = typing::on_eq_typed(&file, position.offset)?;
+            Some(SourceChange::source_file_edit(
+                "add semicolon",
+                SourceFileEdit { edit, file_id: position.file_id },
+            ))
+        })
     }
 
     /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
-    pub fn on_dot_typed(&self, position: FilePosition) -> Option<SourceChange> {
-        typing::on_dot_typed(&self.db, position)
+    pub fn on_dot_typed(&self, position: FilePosition) -> Cancelable<Option<SourceChange>> {
+        self.with_db(|db| typing::on_dot_typed(&db, position))
     }
 
     /// Returns a tree representation of symbols in the file. Useful to draw a
     /// file outline.
-    pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> {
-        let parse = self.db.parse(file_id);
-        file_structure(&parse.tree())
+    pub fn file_structure(&self, file_id: FileId) -> Cancelable<Vec<StructureNode>> {
+        self.with_db(|db| file_structure(&db.parse(file_id).tree()))
     }
 
     /// Returns a list of the places in the file where type hints can be displayed.
@@ -404,9 +413,8 @@ impl Analysis {
     }
 
     /// Returns the set of folding ranges.
-    pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> {
-        let parse = self.db.parse(file_id);
-        folding_ranges::folding_ranges(&parse.tree())
+    pub fn folding_ranges(&self, file_id: FileId) -> Cancelable<Vec<Fold>> {
+        self.with_db(|db| folding_ranges::folding_ranges(&db.parse(file_id).tree()))
     }
 
     /// Fuzzy searches for a symbol.
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index 5c74d3e363e..89984e6426f 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -372,7 +372,8 @@ mod tests {
                 }
             }
         }
-        let result = text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap()));
+        let result =
+            text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap()).unwrap());
         assert_eq_text!(expected, &*result);
     }
 }
diff --git a/crates/ra_ide_api/src/syntax_tree.rs b/crates/ra_ide_api/src/syntax_tree.rs
index a07e670fa44..dd31b909329 100644
--- a/crates/ra_ide_api/src/syntax_tree.rs
+++ b/crates/ra_ide_api/src/syntax_tree.rs
@@ -101,7 +101,7 @@ mod tests {
     fn test_syntax_tree_without_range() {

         // Basic syntax

         let (analysis, file_id) = single_file(r#"fn foo() {}"#);

-        let syn = analysis.syntax_tree(file_id, None);

+        let syn = analysis.syntax_tree(file_id, None).unwrap();

 

         assert_eq_text!(

             syn.trim(),

@@ -133,7 +133,7 @@ fn test() {
 }"#

             .trim(),

         );

-        let syn = analysis.syntax_tree(file_id, None);

+        let syn = analysis.syntax_tree(file_id, None).unwrap();

 

         assert_eq_text!(

             syn.trim(),

@@ -176,7 +176,7 @@ SOURCE_FILE@[0; 60)
     #[test]

     fn test_syntax_tree_with_range() {

         let (analysis, range) = single_file_with_range(r#"<|>fn foo() {}<|>"#.trim());

-        let syn = analysis.syntax_tree(range.file_id, Some(range.range));

+        let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();

 

         assert_eq_text!(

             syn.trim(),

@@ -206,7 +206,7 @@ FN_DEF@[0; 11)
 }"#

             .trim(),

         );

-        let syn = analysis.syntax_tree(range.file_id, Some(range.range));

+        let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();

 

         assert_eq_text!(

             syn.trim(),

@@ -244,7 +244,7 @@ fn bar() {
 }"#

             .trim(),

         );

-        let syn = analysis.syntax_tree(range.file_id, Some(range.range));

+        let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();

         assert_eq_text!(

             syn.trim(),

             r#"

@@ -278,7 +278,7 @@ fn bar() {
 }"###

                 .trim(),

         );

-        let syn = analysis.syntax_tree(range.file_id, Some(range.range));

+        let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();

         assert_eq_text!(

             syn.trim(),

             r#"

@@ -311,7 +311,7 @@ fn bar() {
 }"###

                 .trim(),

         );

-        let syn = analysis.syntax_tree(range.file_id, Some(range.range));

+        let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();

         assert_eq_text!(

             syn.trim(),

             r#"

diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs
index 6b3fd5904e6..2d4491442c1 100644
--- a/crates/ra_ide_api/src/typing.rs
+++ b/crates/ra_ide_api/src/typing.rs
@@ -195,7 +195,7 @@ fn foo() {
         edit.insert(offset, ".".to_string());
         let before = edit.finish().apply(&before);
         let (analysis, file_id) = single_file(&before);
-        if let Some(result) = analysis.on_dot_typed(FilePosition { offset, file_id }) {
+        if let Some(result) = analysis.on_dot_typed(FilePosition { offset, file_id }).unwrap() {
             assert_eq!(result.source_file_edits.len(), 1);
             let actual = result.source_file_edits[0].edit.apply(&before);
             assert_eq_text!(after, &actual);
@@ -377,7 +377,7 @@ fn foo() {
         fn apply_on_enter(before: &str) -> Option<String> {
             let (offset, before) = extract_offset(before);
             let (analysis, file_id) = single_file(&before);
-            let result = analysis.on_enter(FilePosition { offset, file_id })?;
+            let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?;
 
             assert_eq!(result.source_file_edits.len(), 1);
             let actual = result.source_file_edits[0].edit.apply(&before);
diff --git a/crates/ra_lsp_server/src/conv.rs b/crates/ra_lsp_server/src/conv.rs
index 82c7e757fac..6b3be444fdf 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 {
     type Output = FilePosition;
     fn try_conv_with(self, world: &WorldSnapshot) -> Result<FilePosition> {
         let file_id = self.text_document.try_conv_with(world)?;
-        let line_index = world.analysis().file_line_index(file_id);
+        let line_index = world.analysis().file_line_index(file_id)?;
         let offset = self.position.conv_with(&line_index);
         Ok(FilePosition { file_id, offset })
     }
@@ -283,7 +283,7 @@ impl<'a> TryConvWith for (&'a TextDocumentIdentifier, Range) {
     type Output = FileRange;
     fn try_conv_with(self, world: &WorldSnapshot) -> Result<FileRange> {
         let file_id = self.0.try_conv_with(world)?;
-        let line_index = world.analysis().file_line_index(file_id);
+        let line_index = world.analysis().file_line_index(file_id)?;
         let range = self.1.conv_with(&line_index);
         Ok(FileRange { file_id, range })
     }
@@ -308,7 +308,7 @@ impl TryConvWith for SourceChange {
         let cursor_position = match self.cursor_position {
             None => None,
             Some(pos) => {
-                let line_index = world.analysis().file_line_index(pos.file_id);
+                let line_index = world.analysis().file_line_index(pos.file_id)?;
                 let edit = self
                     .source_file_edits
                     .iter()
@@ -349,7 +349,7 @@ impl TryConvWith for SourceFileEdit {
             uri: self.file_id.try_conv_with(world)?,
             version: None,
         };
-        let line_index = world.analysis().file_line_index(self.file_id);
+        let line_index = world.analysis().file_line_index(self.file_id)?;
         let edits = self.edit.as_atoms().iter().map_conv_with(&line_index).collect();
         Ok(TextDocumentEdit { text_document, edits })
     }
@@ -378,7 +378,7 @@ impl TryConvWith for &NavigationTarget {
     type Ctx = WorldSnapshot;
     type Output = Location;
     fn try_conv_with(self, world: &WorldSnapshot) -> Result<Location> {
-        let line_index = world.analysis().file_line_index(self.file_id());
+        let line_index = world.analysis().file_line_index(self.file_id())?;
         let range = self.range();
         to_location(self.file_id(), range, &world, &line_index)
     }
@@ -391,8 +391,8 @@ impl TryConvWith for (FileId, RangeInfo<NavigationTarget>) {
         let (src_file_id, target) = self;
 
         let target_uri = target.info.file_id().try_conv_with(world)?;
-        let src_line_index = world.analysis().file_line_index(src_file_id);
-        let tgt_line_index = world.analysis().file_line_index(target.info.file_id());
+        let src_line_index = world.analysis().file_line_index(src_file_id)?;
+        let tgt_line_index = world.analysis().file_line_index(target.info.file_id())?;
 
         let target_range = target.info.full_range().conv_with(&tgt_line_index);
 
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 5bf950a5378..14619ede223 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> {
 
 pub fn handle_syntax_tree(world: WorldSnapshot, params: req::SyntaxTreeParams) -> Result<String> {
     let id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(id);
+    let line_index = world.analysis().file_line_index(id)?;
     let text_range = params.range.map(|p| p.conv_with(&line_index));
-    let res = world.analysis().syntax_tree(id, text_range);
+    let res = world.analysis().syntax_tree(id, text_range)?;
     Ok(res)
 }
 
@@ -55,7 +55,7 @@ pub fn handle_extend_selection(
          use the new selection range API in LSP",
     );
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
     let selections = params
         .selections
         .into_iter()
@@ -72,7 +72,7 @@ pub fn handle_selection_range(
 ) -> Result<Vec<req::SelectionRange>> {
     let _p = profile("handle_selection_range");
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
     params
         .positions
         .into_iter()
@@ -113,13 +113,19 @@ pub fn handle_find_matching_brace(
 ) -> Result<Vec<Position>> {
     let _p = profile("handle_find_matching_brace");
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
     let res = params
         .offsets
         .into_iter()
         .map_conv_with(&line_index)
         .map(|offset| {
-            world.analysis().matching_brace(FilePosition { file_id, offset }).unwrap_or(offset)
+            if let Ok(Some(matching_brace_offset)) =
+                world.analysis().matching_brace(FilePosition { file_id, offset })
+            {
+                matching_brace_offset
+            } else {
+                offset
+            }
         })
         .map_conv_with(&line_index)
         .collect();
@@ -132,7 +138,7 @@ pub fn handle_join_lines(
 ) -> Result<req::SourceChange> {
     let _p = profile("handle_join_lines");
     let frange = (&params.text_document, params.range).try_conv_with(&world)?;
-    world.analysis().join_lines(frange).try_conv_with(&world)
+    world.analysis().join_lines(frange)?.try_conv_with(&world)
 }
 
 pub fn handle_on_enter(
@@ -141,7 +147,7 @@ pub fn handle_on_enter(
 ) -> Result<Option<req::SourceChange>> {
     let _p = profile("handle_on_enter");
     let position = params.try_conv_with(&world)?;
-    match world.analysis().on_enter(position) {
+    match world.analysis().on_enter(position)? {
         None => Ok(None),
         Some(edit) => Ok(Some(edit.try_conv_with(&world)?)),
     }
@@ -153,7 +159,7 @@ pub fn handle_on_type_formatting(
 ) -> Result<Option<Vec<TextEdit>>> {
     let _p = profile("handle_on_type_formatting");
     let mut position = params.text_document_position.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(position.file_id);
+    let line_index = world.analysis().file_line_index(position.file_id)?;
 
     // in `ra_ide_api`, the `on_type` invariant is that
     // `text.char_at(position) == typed_char`.
@@ -163,7 +169,7 @@ pub fn handle_on_type_formatting(
         "=" => world.analysis().on_eq_typed(position),
         "." => world.analysis().on_dot_typed(position),
         _ => return Ok(None),
-    };
+    }?;
     let mut edit = match edit {
         Some(it) => it,
         None => return Ok(None),
@@ -181,11 +187,11 @@ pub fn handle_document_symbol(
     params: req::DocumentSymbolParams,
 ) -> Result<Option<req::DocumentSymbolResponse>> {
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
 
     let mut parents: Vec<(DocumentSymbol, Option<usize>)> = Vec::new();
 
-    for symbol in world.analysis().file_structure(file_id) {
+    for symbol in world.analysis().file_structure(file_id)? {
         let doc_symbol = DocumentSymbol {
             name: symbol.label,
             detail: symbol.detail,
@@ -309,7 +315,7 @@ pub fn handle_runnables(
     params: req::RunnablesParams,
 ) -> Result<Vec<req::Runnable>> {
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
     let offset = params.position.map(|it| it.conv_with(&line_index));
     let mut res = Vec::new();
     let workspace_root = world.workspace_root_for(file_id);
@@ -383,7 +389,7 @@ pub fn handle_completion(
         let mut res = false;
         if let Some(ctx) = params.context {
             if ctx.trigger_character.unwrap_or_default() == ":" {
-                let source_file = world.analysis().parse(position.file_id);
+                let source_file = world.analysis().parse(position.file_id)?;
                 let syntax = source_file.syntax();
                 let text = syntax.text();
                 if let Some(next_char) = text.char_at(position.offset) {
@@ -405,7 +411,7 @@ pub fn handle_completion(
         None => return Ok(None),
         Some(items) => items,
     };
-    let line_index = world.analysis().file_line_index(position.file_id);
+    let line_index = world.analysis().file_line_index(position.file_id)?;
     let items: Vec<CompletionItem> =
         items.into_iter().map(|item| item.conv_with(&line_index)).collect();
 
@@ -417,12 +423,12 @@ pub fn handle_folding_range(
     params: FoldingRangeParams,
 ) -> Result<Option<Vec<FoldingRange>>> {
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
 
     let res = Some(
         world
             .analysis()
-            .folding_ranges(file_id)
+            .folding_ranges(file_id)?
             .into_iter()
             .map(|fold| {
                 let kind = match fold.kind {
@@ -474,7 +480,7 @@ pub fn handle_hover(
         None => return Ok(None),
         Some(info) => info,
     };
-    let line_index = world.analysis.file_line_index(position.file_id);
+    let line_index = world.analysis.file_line_index(position.file_id)?;
     let range = info.range.conv_with(&line_index);
     let res = Hover {
         contents: HoverContents::Markup(MarkupContent {
@@ -503,7 +509,7 @@ pub fn handle_prepare_rename(
     // Refs should always have a declaration
     let r = refs.declaration();
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
     let loc = to_location(r.file_id(), r.range(), &world, &line_index)?;
 
     Ok(Some(PrepareRenameResponse::Range(loc.range)))
@@ -536,7 +542,7 @@ pub fn handle_references(
     params: req::ReferenceParams,
 ) -> Result<Option<Vec<Location>>> {
     let position = params.text_document_position.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(position.file_id);
+    let line_index = world.analysis().file_line_index(position.file_id)?;
 
     let refs = match world.analysis().find_all_refs(position)? {
         None => return Ok(None),
@@ -563,9 +569,9 @@ pub fn handle_formatting(
     params: DocumentFormattingParams,
 ) -> Result<Option<Vec<TextEdit>>> {
     let file_id = params.text_document.try_conv_with(&world)?;
-    let file = world.analysis().file_text(file_id);
+    let file = world.analysis().file_text(file_id)?;
 
-    let file_line_index = world.analysis().file_line_index(file_id);
+    let file_line_index = world.analysis().file_line_index(file_id)?;
     let end_position = TextUnit::of_str(&file).conv_with(&file_line_index);
 
     use std::process;
@@ -623,7 +629,7 @@ pub fn handle_code_action(
 ) -> Result<Option<CodeActionResponse>> {
     let _p = profile("handle_code_action");
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
     let range = params.range.conv_with(&line_index);
 
     let assists = world.analysis().assists(FileRange { file_id, range })?.into_iter();
@@ -685,7 +691,7 @@ pub fn handle_code_lens(
     params: req::CodeLensParams,
 ) -> Result<Option<Vec<CodeLens>>> {
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
 
     let mut lenses: Vec<CodeLens> = Default::default();
     let workspace_root = world.workspace_root_for(file_id);
@@ -730,7 +736,7 @@ pub fn handle_code_lens(
     lenses.extend(
         world
             .analysis()
-            .file_structure(file_id)
+            .file_structure(file_id)?
             .into_iter()
             .filter(|it| match it.kind {
                 SyntaxKind::TRAIT_DEF | SyntaxKind::STRUCT_DEF | SyntaxKind::ENUM_DEF => true,
@@ -807,7 +813,7 @@ pub fn handle_document_highlight(
     params: req::TextDocumentPositionParams,
 ) -> Result<Option<Vec<DocumentHighlight>>> {
     let file_id = params.text_document.try_conv_with(&world)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
 
     let refs = match world.analysis().find_all_refs(params.try_conv_with(&world)?)? {
         None => return Ok(None),
@@ -826,7 +832,7 @@ pub fn publish_diagnostics(
     file_id: FileId,
 ) -> Result<req::PublishDiagnosticsParams> {
     let uri = world.file_id_to_uri(file_id)?;
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
     let diagnostics = world
         .analysis()
         .diagnostics(file_id)?
@@ -852,7 +858,7 @@ pub fn publish_decorations(
 }
 
 fn highlight(world: &WorldSnapshot, file_id: FileId) -> Result<Vec<Decoration>> {
-    let line_index = world.analysis().file_line_index(file_id);
+    let line_index = world.analysis().file_line_index(file_id)?;
     let res = world
         .analysis()
         .highlight(file_id)?
@@ -881,7 +887,7 @@ pub fn handle_inlay_hints(
 ) -> Result<Vec<InlayHint>> {
     let file_id = params.text_document.try_conv_with(&world)?;
     let analysis = world.analysis();
-    let line_index = analysis.file_line_index(file_id);
+    let line_index = analysis.file_line_index(file_id)?;
     Ok(analysis
         .inlay_hints(file_id)?
         .into_iter()
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 9fd654305c3..1d775591046 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -215,7 +215,12 @@ impl WorldSnapshot {
             }
         }
         res.push_str("\nanalysis:\n");
-        res.push_str(&self.analysis.status());
+        res.push_str(
+            &self
+                .analysis
+                .status()
+                .unwrap_or_else(|_| "Analysis retrieval was cancelled".to_owned()),
+        );
         res
     }