aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-07-25 18:32:17 +0100
committerbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-07-25 18:32:17 +0100
commitceb16591deef2190daaf5eb9a6480f20dc5d169c (patch)
tree47edb8102902df9e291d5d0c8274ef1388546d03
parenta8e37ddbc8fa666105a5eca8e2dc9f261d8934e8 (diff)
parentdbbb0beb3ec9f11a635f43e60f3b3a42ba61338a (diff)
Merge #1591
1591: Make Analysis api cancellable r=matklad a=SomeoneToIgnore Based on the discussion from here: https://github.com/rust-analyzer/rust-analyzer/pull/1549#discussion_r305593236 Co-authored-by: Kirill Bulatov <[email protected]>
-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 639ac763e..5e9d0c16d 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<()> {
55 Op::Complete { line, column, .. } => { 55 Op::Complete { line, column, .. } => {
56 let offset = host 56 let offset = host
57 .analysis() 57 .analysis()
58 .file_line_index(file_id) 58 .file_line_index(file_id)?
59 .offset(LineCol { line, col_utf16: column }); 59 .offset(LineCol { line, col_utf16: column });
60 let file_postion = FilePosition { file_id, offset }; 60 let file_postion = FilePosition { file_id, offset };
61 61
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 16ffb03ce..edb646c11 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -317,24 +317,24 @@ impl Analysis {
317 } 317 }
318 318
319 /// Debug info about the current state of the analysis 319 /// Debug info about the current state of the analysis
320 pub fn status(&self) -> String { 320 pub fn status(&self) -> Cancelable<String> {
321 status::status(&*self.db) 321 self.with_db(|db| status::status(&*db))
322 } 322 }
323 323
324 /// Gets the text of the source file. 324 /// Gets the text of the source file.
325 pub fn file_text(&self, file_id: FileId) -> Arc<String> { 325 pub fn file_text(&self, file_id: FileId) -> Cancelable<Arc<String>> {
326 self.db.file_text(file_id) 326 self.with_db(|db| db.file_text(file_id))
327 } 327 }
328 328
329 /// Gets the syntax tree of the file. 329 /// Gets the syntax tree of the file.
330 pub fn parse(&self, file_id: FileId) -> SourceFile { 330 pub fn parse(&self, file_id: FileId) -> Cancelable<SourceFile> {
331 self.db.parse(file_id).tree() 331 self.with_db(|db| db.parse(file_id).tree())
332 } 332 }
333 333
334 /// Gets the file's `LineIndex`: data structure to convert between absolute 334 /// Gets the file's `LineIndex`: data structure to convert between absolute
335 /// offsets and line/column representation. 335 /// offsets and line/column representation.
336 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> { 336 pub fn file_line_index(&self, file_id: FileId) -> Cancelable<Arc<LineIndex>> {
337 self.db.line_index(file_id) 337 self.with_db(|db| db.line_index(file_id))
338 } 338 }
339 339
340 /// Selects the next syntactic nodes encompassing the range. 340 /// Selects the next syntactic nodes encompassing the range.
@@ -344,58 +344,67 @@ impl Analysis {
344 344
345 /// Returns position of the matching brace (all types of braces are 345 /// Returns position of the matching brace (all types of braces are
346 /// supported). 346 /// supported).
347 pub fn matching_brace(&self, position: FilePosition) -> Option<TextUnit> { 347 pub fn matching_brace(&self, position: FilePosition) -> Cancelable<Option<TextUnit>> {
348 let parse = self.db.parse(position.file_id); 348 self.with_db(|db| {
349 let file = parse.tree(); 349 let parse = db.parse(position.file_id);
350 matching_brace::matching_brace(&file, position.offset) 350 let file = parse.tree();
351 matching_brace::matching_brace(&file, position.offset)
352 })
351 } 353 }
352 354
353 /// Returns a syntax tree represented as `String`, for debug purposes. 355 /// Returns a syntax tree represented as `String`, for debug purposes.
354 // FIXME: use a better name here. 356 // FIXME: use a better name here.
355 pub fn syntax_tree(&self, file_id: FileId, text_range: Option<TextRange>) -> String { 357 pub fn syntax_tree(
356 syntax_tree::syntax_tree(&self.db, file_id, text_range) 358 &self,
359 file_id: FileId,
360 text_range: Option<TextRange>,
361 ) -> Cancelable<String> {
362 self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range))
357 } 363 }
358 364
359 /// Returns an edit to remove all newlines in the range, cleaning up minor 365 /// Returns an edit to remove all newlines in the range, cleaning up minor
360 /// stuff like trailing commas. 366 /// stuff like trailing commas.
361 pub fn join_lines(&self, frange: FileRange) -> SourceChange { 367 pub fn join_lines(&self, frange: FileRange) -> Cancelable<SourceChange> {
362 let parse = self.db.parse(frange.file_id); 368 self.with_db(|db| {
363 let file_edit = SourceFileEdit { 369 let parse = db.parse(frange.file_id);
364 file_id: frange.file_id, 370 let file_edit = SourceFileEdit {
365 edit: join_lines::join_lines(&parse.tree(), frange.range), 371 file_id: frange.file_id,
366 }; 372 edit: join_lines::join_lines(&parse.tree(), frange.range),
367 SourceChange::source_file_edit("join lines", file_edit) 373 };
374 SourceChange::source_file_edit("join lines", file_edit)
375 })
368 } 376 }
369 377
370 /// Returns an edit which should be applied when opening a new line, fixing 378 /// Returns an edit which should be applied when opening a new line, fixing
371 /// up minor stuff like continuing the comment. 379 /// up minor stuff like continuing the comment.
372 pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> { 380 pub fn on_enter(&self, position: FilePosition) -> Cancelable<Option<SourceChange>> {
373 typing::on_enter(&self.db, position) 381 self.with_db(|db| typing::on_enter(&db, position))
374 } 382 }
375 383
376 /// Returns an edit which should be applied after `=` was typed. Primarily, 384 /// Returns an edit which should be applied after `=` was typed. Primarily,
377 /// this works when adding `let =`. 385 /// this works when adding `let =`.
378 // FIXME: use a snippet completion instead of this hack here. 386 // FIXME: use a snippet completion instead of this hack here.
379 pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> { 387 pub fn on_eq_typed(&self, position: FilePosition) -> Cancelable<Option<SourceChange>> {
380 let parse = self.db.parse(position.file_id); 388 self.with_db(|db| {
381 let file = parse.tree(); 389 let parse = db.parse(position.file_id);
382 let edit = typing::on_eq_typed(&file, position.offset)?; 390 let file = parse.tree();
383 Some(SourceChange::source_file_edit( 391 let edit = typing::on_eq_typed(&file, position.offset)?;
384 "add semicolon", 392 Some(SourceChange::source_file_edit(
385 SourceFileEdit { edit, file_id: position.file_id }, 393 "add semicolon",
386 )) 394 SourceFileEdit { edit, file_id: position.file_id },
395 ))
396 })
387 } 397 }
388 398
389 /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately. 399 /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
390 pub fn on_dot_typed(&self, position: FilePosition) -> Option<SourceChange> { 400 pub fn on_dot_typed(&self, position: FilePosition) -> Cancelable<Option<SourceChange>> {
391 typing::on_dot_typed(&self.db, position) 401 self.with_db(|db| typing::on_dot_typed(&db, position))
392 } 402 }
393 403
394 /// Returns a tree representation of symbols in the file. Useful to draw a 404 /// Returns a tree representation of symbols in the file. Useful to draw a
395 /// file outline. 405 /// file outline.
396 pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> { 406 pub fn file_structure(&self, file_id: FileId) -> Cancelable<Vec<StructureNode>> {
397 let parse = self.db.parse(file_id); 407 self.with_db(|db| file_structure(&db.parse(file_id).tree()))
398 file_structure(&parse.tree())
399 } 408 }
400 409
401 /// Returns a list of the places in the file where type hints can be displayed. 410 /// Returns a list of the places in the file where type hints can be displayed.
@@ -404,9 +413,8 @@ impl Analysis {
404 } 413 }
405 414
406 /// Returns the set of folding ranges. 415 /// Returns the set of folding ranges.
407 pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> { 416 pub fn folding_ranges(&self, file_id: FileId) -> Cancelable<Vec<Fold>> {
408 let parse = self.db.parse(file_id); 417 self.with_db(|db| folding_ranges::folding_ranges(&db.parse(file_id).tree()))
409 folding_ranges::folding_ranges(&parse.tree())
410 } 418 }
411 419
412 /// Fuzzy searches for a symbol. 420 /// Fuzzy searches for a symbol.
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index 5c74d3e36..89984e642 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -372,7 +372,8 @@ mod tests {
372 } 372 }
373 } 373 }
374 } 374 }
375 let result = text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap())); 375 let result =
376 text_edit_builder.finish().apply(&*analysis.file_text(file_id.unwrap()).unwrap());
376 assert_eq_text!(expected, &*result); 377 assert_eq_text!(expected, &*result);
377 } 378 }
378} 379}
diff --git a/crates/ra_ide_api/src/syntax_tree.rs b/crates/ra_ide_api/src/syntax_tree.rs
index a07e670fa..dd31b9093 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 {
101 fn test_syntax_tree_without_range() { 101 fn test_syntax_tree_without_range() {
102 // Basic syntax 102 // Basic syntax
103 let (analysis, file_id) = single_file(r#"fn foo() {}"#); 103 let (analysis, file_id) = single_file(r#"fn foo() {}"#);
104 let syn = analysis.syntax_tree(file_id, None); 104 let syn = analysis.syntax_tree(file_id, None).unwrap();
105 105
106 assert_eq_text!( 106 assert_eq_text!(
107 syn.trim(), 107 syn.trim(),
@@ -133,7 +133,7 @@ fn test() {
133}"# 133}"#
134 .trim(), 134 .trim(),
135 ); 135 );
136 let syn = analysis.syntax_tree(file_id, None); 136 let syn = analysis.syntax_tree(file_id, None).unwrap();
137 137
138 assert_eq_text!( 138 assert_eq_text!(
139 syn.trim(), 139 syn.trim(),
@@ -176,7 +176,7 @@ SOURCE_FILE@[0; 60)
176 #[test] 176 #[test]
177 fn test_syntax_tree_with_range() { 177 fn test_syntax_tree_with_range() {
178 let (analysis, range) = single_file_with_range(r#"<|>fn foo() {}<|>"#.trim()); 178 let (analysis, range) = single_file_with_range(r#"<|>fn foo() {}<|>"#.trim());
179 let syn = analysis.syntax_tree(range.file_id, Some(range.range)); 179 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
180 180
181 assert_eq_text!( 181 assert_eq_text!(
182 syn.trim(), 182 syn.trim(),
@@ -206,7 +206,7 @@ FN_DEF@[0; 11)
206}"# 206}"#
207 .trim(), 207 .trim(),
208 ); 208 );
209 let syn = analysis.syntax_tree(range.file_id, Some(range.range)); 209 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
210 210
211 assert_eq_text!( 211 assert_eq_text!(
212 syn.trim(), 212 syn.trim(),
@@ -244,7 +244,7 @@ fn bar() {
244}"# 244}"#
245 .trim(), 245 .trim(),
246 ); 246 );
247 let syn = analysis.syntax_tree(range.file_id, Some(range.range)); 247 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
248 assert_eq_text!( 248 assert_eq_text!(
249 syn.trim(), 249 syn.trim(),
250 r#" 250 r#"
@@ -278,7 +278,7 @@ fn bar() {
278}"### 278}"###
279 .trim(), 279 .trim(),
280 ); 280 );
281 let syn = analysis.syntax_tree(range.file_id, Some(range.range)); 281 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
282 assert_eq_text!( 282 assert_eq_text!(
283 syn.trim(), 283 syn.trim(),
284 r#" 284 r#"
@@ -311,7 +311,7 @@ fn bar() {
311}"### 311}"###
312 .trim(), 312 .trim(),
313 ); 313 );
314 let syn = analysis.syntax_tree(range.file_id, Some(range.range)); 314 let syn = analysis.syntax_tree(range.file_id, Some(range.range)).unwrap();
315 assert_eq_text!( 315 assert_eq_text!(
316 syn.trim(), 316 syn.trim(),
317 r#" 317 r#"
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs
index 6b3fd5904..2d4491442 100644
--- a/crates/ra_ide_api/src/typing.rs
+++ b/crates/ra_ide_api/src/typing.rs
@@ -195,7 +195,7 @@ fn foo() {
195 edit.insert(offset, ".".to_string()); 195 edit.insert(offset, ".".to_string());
196 let before = edit.finish().apply(&before); 196 let before = edit.finish().apply(&before);
197 let (analysis, file_id) = single_file(&before); 197 let (analysis, file_id) = single_file(&before);
198 if let Some(result) = analysis.on_dot_typed(FilePosition { offset, file_id }) { 198 if let Some(result) = analysis.on_dot_typed(FilePosition { offset, file_id }).unwrap() {
199 assert_eq!(result.source_file_edits.len(), 1); 199 assert_eq!(result.source_file_edits.len(), 1);
200 let actual = result.source_file_edits[0].edit.apply(&before); 200 let actual = result.source_file_edits[0].edit.apply(&before);
201 assert_eq_text!(after, &actual); 201 assert_eq_text!(after, &actual);
@@ -377,7 +377,7 @@ fn foo() {
377 fn apply_on_enter(before: &str) -> Option<String> { 377 fn apply_on_enter(before: &str) -> Option<String> {
378 let (offset, before) = extract_offset(before); 378 let (offset, before) = extract_offset(before);
379 let (analysis, file_id) = single_file(&before); 379 let (analysis, file_id) = single_file(&before);
380 let result = analysis.on_enter(FilePosition { offset, file_id })?; 380 let result = analysis.on_enter(FilePosition { offset, file_id }).unwrap()?;
381 381
382 assert_eq!(result.source_file_edits.len(), 1); 382 assert_eq!(result.source_file_edits.len(), 1);
383 let actual = result.source_file_edits[0].edit.apply(&before); 383 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 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..14619ede2 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()
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