aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide_api/src
diff options
context:
space:
mode:
authorKirill Bulatov <[email protected]>2019-07-25 18:22:41 +0100
committerKirill Bulatov <[email protected]>2019-07-25 18:22:41 +0100
commitdbbb0beb3ec9f11a635f43e60f3b3a42ba61338a (patch)
tree47edb8102902df9e291d5d0c8274ef1388546d03 /crates/ra_ide_api/src
parenta8e37ddbc8fa666105a5eca8e2dc9f261d8934e8 (diff)
Make Analysis api cancellable
Diffstat (limited to 'crates/ra_ide_api/src')
-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
4 files changed, 58 insertions, 49 deletions
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);