diff options
Diffstat (limited to 'crates/ide')
-rw-r--r-- | crates/ide/src/diagnostics.rs | 5 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 128 |
2 files changed, 75 insertions, 58 deletions
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs index 6cf5810fa..d5c954b8b 100644 --- a/crates/ide/src/diagnostics.rs +++ b/crates/ide/src/diagnostics.rs | |||
@@ -182,6 +182,11 @@ pub(crate) fn diagnostics( | |||
182 | res.borrow_mut() | 182 | res.borrow_mut() |
183 | .push(Diagnostic::error(display_range, d.message()).with_code(Some(d.code()))); | 183 | .push(Diagnostic::error(display_range, d.message()).with_code(Some(d.code()))); |
184 | }) | 184 | }) |
185 | .on::<hir::diagnostics::UnimplementedBuiltinMacro, _>(|d| { | ||
186 | let display_range = sema.diagnostics_display_range(d.display_source()).range; | ||
187 | res.borrow_mut() | ||
188 | .push(Diagnostic::hint(display_range, d.message()).with_code(Some(d.code()))); | ||
189 | }) | ||
185 | // Only collect experimental diagnostics when they're enabled. | 190 | // Only collect experimental diagnostics when they're enabled. |
186 | .filter(|diag| !(diag.is_experimental() && config.disable_experimental)) | 191 | .filter(|diag| !(diag.is_experimental() && config.disable_experimental)) |
187 | .filter(|diag| !config.disabled.contains(diag.code().as_str())); | 192 | .filter(|diag| !config.disabled.contains(diag.code().as_str())); |
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index ff2a54117..97c9e5d2b 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -58,7 +58,7 @@ use cfg::CfgOptions; | |||
58 | 58 | ||
59 | use ide_db::base_db::{ | 59 | use ide_db::base_db::{ |
60 | salsa::{self, ParallelDatabase}, | 60 | salsa::{self, ParallelDatabase}, |
61 | CheckCanceled, Env, FileLoader, FileSet, SourceDatabase, VfsPath, | 61 | Env, FileLoader, FileSet, SourceDatabase, VfsPath, |
62 | }; | 62 | }; |
63 | use ide_db::{ | 63 | use ide_db::{ |
64 | symbol_index::{self, FileSymbol}, | 64 | symbol_index::{self, FileSymbol}, |
@@ -98,7 +98,7 @@ pub use ide_completion::{ | |||
98 | }; | 98 | }; |
99 | pub use ide_db::{ | 99 | pub use ide_db::{ |
100 | base_db::{ | 100 | base_db::{ |
101 | Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, | 101 | Cancelled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, |
102 | SourceRoot, SourceRootId, | 102 | SourceRoot, SourceRootId, |
103 | }, | 103 | }, |
104 | call_info::CallInfo, | 104 | call_info::CallInfo, |
@@ -113,7 +113,7 @@ pub use ide_ssr::SsrError; | |||
113 | pub use syntax::{TextRange, TextSize}; | 113 | pub use syntax::{TextRange, TextSize}; |
114 | pub use text_edit::{Indel, TextEdit}; | 114 | pub use text_edit::{Indel, TextEdit}; |
115 | 115 | ||
116 | pub type Cancelable<T> = Result<T, Canceled>; | 116 | pub type Cancellable<T> = Result<T, Cancelled>; |
117 | 117 | ||
118 | /// Info associated with a text range. | 118 | /// Info associated with a text range. |
119 | #[derive(Debug)] | 119 | #[derive(Debug)] |
@@ -227,11 +227,11 @@ impl Analysis { | |||
227 | } | 227 | } |
228 | 228 | ||
229 | /// Debug info about the current state of the analysis. | 229 | /// Debug info about the current state of the analysis. |
230 | pub fn status(&self, file_id: Option<FileId>) -> Cancelable<String> { | 230 | pub fn status(&self, file_id: Option<FileId>) -> Cancellable<String> { |
231 | self.with_db(|db| status::status(&*db, file_id)) | 231 | self.with_db(|db| status::status(&*db, file_id)) |
232 | } | 232 | } |
233 | 233 | ||
234 | pub fn prime_caches<F>(&self, cb: F) -> Cancelable<()> | 234 | pub fn prime_caches<F>(&self, cb: F) -> Cancellable<()> |
235 | where | 235 | where |
236 | F: Fn(PrimeCachesProgress) + Sync + std::panic::UnwindSafe, | 236 | F: Fn(PrimeCachesProgress) + Sync + std::panic::UnwindSafe, |
237 | { | 237 | { |
@@ -239,35 +239,35 @@ impl Analysis { | |||
239 | } | 239 | } |
240 | 240 | ||
241 | /// Gets the text of the source file. | 241 | /// Gets the text of the source file. |
242 | pub fn file_text(&self, file_id: FileId) -> Cancelable<Arc<String>> { | 242 | pub fn file_text(&self, file_id: FileId) -> Cancellable<Arc<String>> { |
243 | self.with_db(|db| db.file_text(file_id)) | 243 | self.with_db(|db| db.file_text(file_id)) |
244 | } | 244 | } |
245 | 245 | ||
246 | /// Gets the syntax tree of the file. | 246 | /// Gets the syntax tree of the file. |
247 | pub fn parse(&self, file_id: FileId) -> Cancelable<SourceFile> { | 247 | pub fn parse(&self, file_id: FileId) -> Cancellable<SourceFile> { |
248 | self.with_db(|db| db.parse(file_id).tree()) | 248 | self.with_db(|db| db.parse(file_id).tree()) |
249 | } | 249 | } |
250 | 250 | ||
251 | /// Returns true if this file belongs to an immutable library. | 251 | /// Returns true if this file belongs to an immutable library. |
252 | pub fn is_library_file(&self, file_id: FileId) -> Cancelable<bool> { | 252 | pub fn is_library_file(&self, file_id: FileId) -> Cancellable<bool> { |
253 | use ide_db::base_db::SourceDatabaseExt; | 253 | use ide_db::base_db::SourceDatabaseExt; |
254 | self.with_db(|db| db.source_root(db.file_source_root(file_id)).is_library) | 254 | self.with_db(|db| db.source_root(db.file_source_root(file_id)).is_library) |
255 | } | 255 | } |
256 | 256 | ||
257 | /// Gets the file's `LineIndex`: data structure to convert between absolute | 257 | /// Gets the file's `LineIndex`: data structure to convert between absolute |
258 | /// offsets and line/column representation. | 258 | /// offsets and line/column representation. |
259 | pub fn file_line_index(&self, file_id: FileId) -> Cancelable<Arc<LineIndex>> { | 259 | pub fn file_line_index(&self, file_id: FileId) -> Cancellable<Arc<LineIndex>> { |
260 | self.with_db(|db| db.line_index(file_id)) | 260 | self.with_db(|db| db.line_index(file_id)) |
261 | } | 261 | } |
262 | 262 | ||
263 | /// Selects the next syntactic nodes encompassing the range. | 263 | /// Selects the next syntactic nodes encompassing the range. |
264 | pub fn extend_selection(&self, frange: FileRange) -> Cancelable<TextRange> { | 264 | pub fn extend_selection(&self, frange: FileRange) -> Cancellable<TextRange> { |
265 | self.with_db(|db| extend_selection::extend_selection(db, frange)) | 265 | self.with_db(|db| extend_selection::extend_selection(db, frange)) |
266 | } | 266 | } |
267 | 267 | ||
268 | /// Returns position of the matching brace (all types of braces are | 268 | /// Returns position of the matching brace (all types of braces are |
269 | /// supported). | 269 | /// supported). |
270 | pub fn matching_brace(&self, position: FilePosition) -> Cancelable<Option<TextSize>> { | 270 | pub fn matching_brace(&self, position: FilePosition) -> Cancellable<Option<TextSize>> { |
271 | self.with_db(|db| { | 271 | self.with_db(|db| { |
272 | let parse = db.parse(position.file_id); | 272 | let parse = db.parse(position.file_id); |
273 | let file = parse.tree(); | 273 | let file = parse.tree(); |
@@ -281,30 +281,30 @@ impl Analysis { | |||
281 | &self, | 281 | &self, |
282 | file_id: FileId, | 282 | file_id: FileId, |
283 | text_range: Option<TextRange>, | 283 | text_range: Option<TextRange>, |
284 | ) -> Cancelable<String> { | 284 | ) -> Cancellable<String> { |
285 | self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range)) | 285 | self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range)) |
286 | } | 286 | } |
287 | 287 | ||
288 | pub fn view_hir(&self, position: FilePosition) -> Cancelable<String> { | 288 | pub fn view_hir(&self, position: FilePosition) -> Cancellable<String> { |
289 | self.with_db(|db| view_hir::view_hir(&db, position)) | 289 | self.with_db(|db| view_hir::view_hir(&db, position)) |
290 | } | 290 | } |
291 | 291 | ||
292 | pub fn view_item_tree(&self, file_id: FileId) -> Cancelable<String> { | 292 | pub fn view_item_tree(&self, file_id: FileId) -> Cancellable<String> { |
293 | self.with_db(|db| view_item_tree::view_item_tree(&db, file_id)) | 293 | self.with_db(|db| view_item_tree::view_item_tree(&db, file_id)) |
294 | } | 294 | } |
295 | 295 | ||
296 | /// Renders the crate graph to GraphViz "dot" syntax. | 296 | /// Renders the crate graph to GraphViz "dot" syntax. |
297 | pub fn view_crate_graph(&self) -> Cancelable<Result<String, String>> { | 297 | pub fn view_crate_graph(&self) -> Cancellable<Result<String, String>> { |
298 | self.with_db(|db| view_crate_graph::view_crate_graph(&db)) | 298 | self.with_db(|db| view_crate_graph::view_crate_graph(&db)) |
299 | } | 299 | } |
300 | 300 | ||
301 | pub fn expand_macro(&self, position: FilePosition) -> Cancelable<Option<ExpandedMacro>> { | 301 | pub fn expand_macro(&self, position: FilePosition) -> Cancellable<Option<ExpandedMacro>> { |
302 | self.with_db(|db| expand_macro::expand_macro(db, position)) | 302 | self.with_db(|db| expand_macro::expand_macro(db, position)) |
303 | } | 303 | } |
304 | 304 | ||
305 | /// Returns an edit to remove all newlines in the range, cleaning up minor | 305 | /// Returns an edit to remove all newlines in the range, cleaning up minor |
306 | /// stuff like trailing commas. | 306 | /// stuff like trailing commas. |
307 | pub fn join_lines(&self, frange: FileRange) -> Cancelable<TextEdit> { | 307 | pub fn join_lines(&self, frange: FileRange) -> Cancellable<TextEdit> { |
308 | self.with_db(|db| { | 308 | self.with_db(|db| { |
309 | let parse = db.parse(frange.file_id); | 309 | let parse = db.parse(frange.file_id); |
310 | join_lines::join_lines(&parse.tree(), frange.range) | 310 | join_lines::join_lines(&parse.tree(), frange.range) |
@@ -314,7 +314,7 @@ impl Analysis { | |||
314 | /// Returns an edit which should be applied when opening a new line, fixing | 314 | /// Returns an edit which should be applied when opening a new line, fixing |
315 | /// up minor stuff like continuing the comment. | 315 | /// up minor stuff like continuing the comment. |
316 | /// The edit will be a snippet (with `$0`). | 316 | /// The edit will be a snippet (with `$0`). |
317 | pub fn on_enter(&self, position: FilePosition) -> Cancelable<Option<TextEdit>> { | 317 | pub fn on_enter(&self, position: FilePosition) -> Cancellable<Option<TextEdit>> { |
318 | self.with_db(|db| typing::on_enter(&db, position)) | 318 | self.with_db(|db| typing::on_enter(&db, position)) |
319 | } | 319 | } |
320 | 320 | ||
@@ -326,7 +326,7 @@ impl Analysis { | |||
326 | &self, | 326 | &self, |
327 | position: FilePosition, | 327 | position: FilePosition, |
328 | char_typed: char, | 328 | char_typed: char, |
329 | ) -> Cancelable<Option<SourceChange>> { | 329 | ) -> Cancellable<Option<SourceChange>> { |
330 | // Fast path to not even parse the file. | 330 | // Fast path to not even parse the file. |
331 | if !typing::TRIGGER_CHARS.contains(char_typed) { | 331 | if !typing::TRIGGER_CHARS.contains(char_typed) { |
332 | return Ok(None); | 332 | return Ok(None); |
@@ -336,7 +336,7 @@ impl Analysis { | |||
336 | 336 | ||
337 | /// Returns a tree representation of symbols in the file. Useful to draw a | 337 | /// Returns a tree representation of symbols in the file. Useful to draw a |
338 | /// file outline. | 338 | /// file outline. |
339 | pub fn file_structure(&self, file_id: FileId) -> Cancelable<Vec<StructureNode>> { | 339 | pub fn file_structure(&self, file_id: FileId) -> Cancellable<Vec<StructureNode>> { |
340 | self.with_db(|db| file_structure::file_structure(&db.parse(file_id).tree())) | 340 | self.with_db(|db| file_structure::file_structure(&db.parse(file_id).tree())) |
341 | } | 341 | } |
342 | 342 | ||
@@ -345,17 +345,17 @@ impl Analysis { | |||
345 | &self, | 345 | &self, |
346 | file_id: FileId, | 346 | file_id: FileId, |
347 | config: &InlayHintsConfig, | 347 | config: &InlayHintsConfig, |
348 | ) -> Cancelable<Vec<InlayHint>> { | 348 | ) -> Cancellable<Vec<InlayHint>> { |
349 | self.with_db(|db| inlay_hints::inlay_hints(db, file_id, config)) | 349 | self.with_db(|db| inlay_hints::inlay_hints(db, file_id, config)) |
350 | } | 350 | } |
351 | 351 | ||
352 | /// Returns the set of folding ranges. | 352 | /// Returns the set of folding ranges. |
353 | pub fn folding_ranges(&self, file_id: FileId) -> Cancelable<Vec<Fold>> { | 353 | pub fn folding_ranges(&self, file_id: FileId) -> Cancellable<Vec<Fold>> { |
354 | self.with_db(|db| folding_ranges::folding_ranges(&db.parse(file_id).tree())) | 354 | self.with_db(|db| folding_ranges::folding_ranges(&db.parse(file_id).tree())) |
355 | } | 355 | } |
356 | 356 | ||
357 | /// Fuzzy searches for a symbol. | 357 | /// Fuzzy searches for a symbol. |
358 | pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> { | 358 | pub fn symbol_search(&self, query: Query) -> Cancellable<Vec<NavigationTarget>> { |
359 | self.with_db(|db| { | 359 | self.with_db(|db| { |
360 | symbol_index::world_symbols(db, query) | 360 | symbol_index::world_symbols(db, query) |
361 | .into_iter() | 361 | .into_iter() |
@@ -368,7 +368,7 @@ impl Analysis { | |||
368 | pub fn goto_definition( | 368 | pub fn goto_definition( |
369 | &self, | 369 | &self, |
370 | position: FilePosition, | 370 | position: FilePosition, |
371 | ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> { | 371 | ) -> Cancellable<Option<RangeInfo<Vec<NavigationTarget>>>> { |
372 | self.with_db(|db| goto_definition::goto_definition(db, position)) | 372 | self.with_db(|db| goto_definition::goto_definition(db, position)) |
373 | } | 373 | } |
374 | 374 | ||
@@ -376,7 +376,7 @@ impl Analysis { | |||
376 | pub fn goto_implementation( | 376 | pub fn goto_implementation( |
377 | &self, | 377 | &self, |
378 | position: FilePosition, | 378 | position: FilePosition, |
379 | ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> { | 379 | ) -> Cancellable<Option<RangeInfo<Vec<NavigationTarget>>>> { |
380 | self.with_db(|db| goto_implementation::goto_implementation(db, position)) | 380 | self.with_db(|db| goto_implementation::goto_implementation(db, position)) |
381 | } | 381 | } |
382 | 382 | ||
@@ -384,7 +384,7 @@ impl Analysis { | |||
384 | pub fn goto_type_definition( | 384 | pub fn goto_type_definition( |
385 | &self, | 385 | &self, |
386 | position: FilePosition, | 386 | position: FilePosition, |
387 | ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> { | 387 | ) -> Cancellable<Option<RangeInfo<Vec<NavigationTarget>>>> { |
388 | self.with_db(|db| goto_type_definition::goto_type_definition(db, position)) | 388 | self.with_db(|db| goto_type_definition::goto_type_definition(db, position)) |
389 | } | 389 | } |
390 | 390 | ||
@@ -393,12 +393,12 @@ impl Analysis { | |||
393 | &self, | 393 | &self, |
394 | position: FilePosition, | 394 | position: FilePosition, |
395 | search_scope: Option<SearchScope>, | 395 | search_scope: Option<SearchScope>, |
396 | ) -> Cancelable<Option<ReferenceSearchResult>> { | 396 | ) -> Cancellable<Option<ReferenceSearchResult>> { |
397 | self.with_db(|db| references::find_all_refs(&Semantics::new(db), position, search_scope)) | 397 | self.with_db(|db| references::find_all_refs(&Semantics::new(db), position, search_scope)) |
398 | } | 398 | } |
399 | 399 | ||
400 | /// Finds all methods and free functions for the file. Does not return tests! | 400 | /// Finds all methods and free functions for the file. Does not return tests! |
401 | pub fn find_all_methods(&self, file_id: FileId) -> Cancelable<Vec<FileRange>> { | 401 | pub fn find_all_methods(&self, file_id: FileId) -> Cancellable<Vec<FileRange>> { |
402 | self.with_db(|db| fn_references::find_all_methods(db, file_id)) | 402 | self.with_db(|db| fn_references::find_all_methods(db, file_id)) |
403 | } | 403 | } |
404 | 404 | ||
@@ -408,7 +408,7 @@ impl Analysis { | |||
408 | position: FilePosition, | 408 | position: FilePosition, |
409 | links_in_hover: bool, | 409 | links_in_hover: bool, |
410 | markdown: bool, | 410 | markdown: bool, |
411 | ) -> Cancelable<Option<RangeInfo<HoverResult>>> { | 411 | ) -> Cancellable<Option<RangeInfo<HoverResult>>> { |
412 | self.with_db(|db| hover::hover(db, position, links_in_hover, markdown)) | 412 | self.with_db(|db| hover::hover(db, position, links_in_hover, markdown)) |
413 | } | 413 | } |
414 | 414 | ||
@@ -416,12 +416,12 @@ impl Analysis { | |||
416 | pub fn external_docs( | 416 | pub fn external_docs( |
417 | &self, | 417 | &self, |
418 | position: FilePosition, | 418 | position: FilePosition, |
419 | ) -> Cancelable<Option<doc_links::DocumentationLink>> { | 419 | ) -> Cancellable<Option<doc_links::DocumentationLink>> { |
420 | self.with_db(|db| doc_links::external_docs(db, &position)) | 420 | self.with_db(|db| doc_links::external_docs(db, &position)) |
421 | } | 421 | } |
422 | 422 | ||
423 | /// Computes parameter information for the given call expression. | 423 | /// Computes parameter information for the given call expression. |
424 | pub fn call_info(&self, position: FilePosition) -> Cancelable<Option<CallInfo>> { | 424 | pub fn call_info(&self, position: FilePosition) -> Cancellable<Option<CallInfo>> { |
425 | self.with_db(|db| ide_db::call_info::call_info(db, position)) | 425 | self.with_db(|db| ide_db::call_info::call_info(db, position)) |
426 | } | 426 | } |
427 | 427 | ||
@@ -429,42 +429,42 @@ impl Analysis { | |||
429 | pub fn call_hierarchy( | 429 | pub fn call_hierarchy( |
430 | &self, | 430 | &self, |
431 | position: FilePosition, | 431 | position: FilePosition, |
432 | ) -> Cancelable<Option<RangeInfo<Vec<NavigationTarget>>>> { | 432 | ) -> Cancellable<Option<RangeInfo<Vec<NavigationTarget>>>> { |
433 | self.with_db(|db| call_hierarchy::call_hierarchy(db, position)) | 433 | self.with_db(|db| call_hierarchy::call_hierarchy(db, position)) |
434 | } | 434 | } |
435 | 435 | ||
436 | /// Computes incoming calls for the given file position. | 436 | /// Computes incoming calls for the given file position. |
437 | pub fn incoming_calls(&self, position: FilePosition) -> Cancelable<Option<Vec<CallItem>>> { | 437 | pub fn incoming_calls(&self, position: FilePosition) -> Cancellable<Option<Vec<CallItem>>> { |
438 | self.with_db(|db| call_hierarchy::incoming_calls(db, position)) | 438 | self.with_db(|db| call_hierarchy::incoming_calls(db, position)) |
439 | } | 439 | } |
440 | 440 | ||
441 | /// Computes incoming calls for the given file position. | 441 | /// Computes incoming calls for the given file position. |
442 | pub fn outgoing_calls(&self, position: FilePosition) -> Cancelable<Option<Vec<CallItem>>> { | 442 | pub fn outgoing_calls(&self, position: FilePosition) -> Cancellable<Option<Vec<CallItem>>> { |
443 | self.with_db(|db| call_hierarchy::outgoing_calls(db, position)) | 443 | self.with_db(|db| call_hierarchy::outgoing_calls(db, position)) |
444 | } | 444 | } |
445 | 445 | ||
446 | /// Returns a `mod name;` declaration which created the current module. | 446 | /// Returns a `mod name;` declaration which created the current module. |
447 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> { | 447 | pub fn parent_module(&self, position: FilePosition) -> Cancellable<Vec<NavigationTarget>> { |
448 | self.with_db(|db| parent_module::parent_module(db, position)) | 448 | self.with_db(|db| parent_module::parent_module(db, position)) |
449 | } | 449 | } |
450 | 450 | ||
451 | /// Returns crates this file belongs too. | 451 | /// Returns crates this file belongs too. |
452 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { | 452 | pub fn crate_for(&self, file_id: FileId) -> Cancellable<Vec<CrateId>> { |
453 | self.with_db(|db| parent_module::crate_for(db, file_id)) | 453 | self.with_db(|db| parent_module::crate_for(db, file_id)) |
454 | } | 454 | } |
455 | 455 | ||
456 | /// Returns the edition of the given crate. | 456 | /// Returns the edition of the given crate. |
457 | pub fn crate_edition(&self, crate_id: CrateId) -> Cancelable<Edition> { | 457 | pub fn crate_edition(&self, crate_id: CrateId) -> Cancellable<Edition> { |
458 | self.with_db(|db| db.crate_graph()[crate_id].edition) | 458 | self.with_db(|db| db.crate_graph()[crate_id].edition) |
459 | } | 459 | } |
460 | 460 | ||
461 | /// Returns the root file of the given crate. | 461 | /// Returns the root file of the given crate. |
462 | pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> { | 462 | pub fn crate_root(&self, crate_id: CrateId) -> Cancellable<FileId> { |
463 | self.with_db(|db| db.crate_graph()[crate_id].root_file_id) | 463 | self.with_db(|db| db.crate_graph()[crate_id].root_file_id) |
464 | } | 464 | } |
465 | 465 | ||
466 | /// Returns the set of possible targets to run for the current file. | 466 | /// Returns the set of possible targets to run for the current file. |
467 | pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> { | 467 | pub fn runnables(&self, file_id: FileId) -> Cancellable<Vec<Runnable>> { |
468 | self.with_db(|db| runnables::runnables(db, file_id)) | 468 | self.with_db(|db| runnables::runnables(db, file_id)) |
469 | } | 469 | } |
470 | 470 | ||
@@ -473,24 +473,24 @@ impl Analysis { | |||
473 | &self, | 473 | &self, |
474 | position: FilePosition, | 474 | position: FilePosition, |
475 | search_scope: Option<SearchScope>, | 475 | search_scope: Option<SearchScope>, |
476 | ) -> Cancelable<Vec<Runnable>> { | 476 | ) -> Cancellable<Vec<Runnable>> { |
477 | self.with_db(|db| runnables::related_tests(db, position, search_scope)) | 477 | self.with_db(|db| runnables::related_tests(db, position, search_scope)) |
478 | } | 478 | } |
479 | 479 | ||
480 | /// Computes syntax highlighting for the given file | 480 | /// Computes syntax highlighting for the given file |
481 | pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HlRange>> { | 481 | pub fn highlight(&self, file_id: FileId) -> Cancellable<Vec<HlRange>> { |
482 | self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false)) | 482 | self.with_db(|db| syntax_highlighting::highlight(db, file_id, None, false)) |
483 | } | 483 | } |
484 | 484 | ||
485 | /// Computes syntax highlighting for the given file range. | 485 | /// Computes syntax highlighting for the given file range. |
486 | pub fn highlight_range(&self, frange: FileRange) -> Cancelable<Vec<HlRange>> { | 486 | pub fn highlight_range(&self, frange: FileRange) -> Cancellable<Vec<HlRange>> { |
487 | self.with_db(|db| { | 487 | self.with_db(|db| { |
488 | syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false) | 488 | syntax_highlighting::highlight(db, frange.file_id, Some(frange.range), false) |
489 | }) | 489 | }) |
490 | } | 490 | } |
491 | 491 | ||
492 | /// Computes syntax highlighting for the given file. | 492 | /// Computes syntax highlighting for the given file. |
493 | pub fn highlight_as_html(&self, file_id: FileId, rainbow: bool) -> Cancelable<String> { | 493 | pub fn highlight_as_html(&self, file_id: FileId, rainbow: bool) -> Cancellable<String> { |
494 | self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id, rainbow)) | 494 | self.with_db(|db| syntax_highlighting::highlight_as_html(db, file_id, rainbow)) |
495 | } | 495 | } |
496 | 496 | ||
@@ -499,7 +499,7 @@ impl Analysis { | |||
499 | &self, | 499 | &self, |
500 | config: &CompletionConfig, | 500 | config: &CompletionConfig, |
501 | position: FilePosition, | 501 | position: FilePosition, |
502 | ) -> Cancelable<Option<Vec<CompletionItem>>> { | 502 | ) -> Cancellable<Option<Vec<CompletionItem>>> { |
503 | self.with_db(|db| ide_completion::completions(db, config, position).map(Into::into)) | 503 | self.with_db(|db| ide_completion::completions(db, config, position).map(Into::into)) |
504 | } | 504 | } |
505 | 505 | ||
@@ -510,7 +510,7 @@ impl Analysis { | |||
510 | position: FilePosition, | 510 | position: FilePosition, |
511 | full_import_path: &str, | 511 | full_import_path: &str, |
512 | imported_name: String, | 512 | imported_name: String, |
513 | ) -> Cancelable<Vec<TextEdit>> { | 513 | ) -> Cancellable<Vec<TextEdit>> { |
514 | Ok(self | 514 | Ok(self |
515 | .with_db(|db| { | 515 | .with_db(|db| { |
516 | ide_completion::resolve_completion_edits( | 516 | ide_completion::resolve_completion_edits( |
@@ -533,7 +533,7 @@ impl Analysis { | |||
533 | config: &AssistConfig, | 533 | config: &AssistConfig, |
534 | resolve: AssistResolveStrategy, | 534 | resolve: AssistResolveStrategy, |
535 | frange: FileRange, | 535 | frange: FileRange, |
536 | ) -> Cancelable<Vec<Assist>> { | 536 | ) -> Cancellable<Vec<Assist>> { |
537 | self.with_db(|db| { | 537 | self.with_db(|db| { |
538 | let ssr_assists = ssr::ssr_assists(db, &resolve, frange); | 538 | let ssr_assists = ssr::ssr_assists(db, &resolve, frange); |
539 | let mut acc = Assist::get(db, config, resolve, frange); | 539 | let mut acc = Assist::get(db, config, resolve, frange); |
@@ -548,7 +548,7 @@ impl Analysis { | |||
548 | config: &DiagnosticsConfig, | 548 | config: &DiagnosticsConfig, |
549 | resolve: AssistResolveStrategy, | 549 | resolve: AssistResolveStrategy, |
550 | file_id: FileId, | 550 | file_id: FileId, |
551 | ) -> Cancelable<Vec<Diagnostic>> { | 551 | ) -> Cancellable<Vec<Diagnostic>> { |
552 | self.with_db(|db| diagnostics::diagnostics(db, config, &resolve, file_id)) | 552 | self.with_db(|db| diagnostics::diagnostics(db, config, &resolve, file_id)) |
553 | } | 553 | } |
554 | 554 | ||
@@ -559,7 +559,7 @@ impl Analysis { | |||
559 | diagnostics_config: &DiagnosticsConfig, | 559 | diagnostics_config: &DiagnosticsConfig, |
560 | resolve: AssistResolveStrategy, | 560 | resolve: AssistResolveStrategy, |
561 | frange: FileRange, | 561 | frange: FileRange, |
562 | ) -> Cancelable<Vec<Assist>> { | 562 | ) -> Cancellable<Vec<Assist>> { |
563 | let include_fixes = match &assist_config.allowed { | 563 | let include_fixes = match &assist_config.allowed { |
564 | Some(it) => it.iter().any(|&it| it == AssistKind::None || it == AssistKind::QuickFix), | 564 | Some(it) => it.iter().any(|&it| it == AssistKind::None || it == AssistKind::QuickFix), |
565 | None => true, | 565 | None => true, |
@@ -591,14 +591,14 @@ impl Analysis { | |||
591 | &self, | 591 | &self, |
592 | position: FilePosition, | 592 | position: FilePosition, |
593 | new_name: &str, | 593 | new_name: &str, |
594 | ) -> Cancelable<Result<SourceChange, RenameError>> { | 594 | ) -> Cancellable<Result<SourceChange, RenameError>> { |
595 | self.with_db(|db| references::rename::rename(db, position, new_name)) | 595 | self.with_db(|db| references::rename::rename(db, position, new_name)) |
596 | } | 596 | } |
597 | 597 | ||
598 | pub fn prepare_rename( | 598 | pub fn prepare_rename( |
599 | &self, | 599 | &self, |
600 | position: FilePosition, | 600 | position: FilePosition, |
601 | ) -> Cancelable<Result<RangeInfo<()>, RenameError>> { | 601 | ) -> Cancellable<Result<RangeInfo<()>, RenameError>> { |
602 | self.with_db(|db| references::rename::prepare_rename(db, position)) | 602 | self.with_db(|db| references::rename::prepare_rename(db, position)) |
603 | } | 603 | } |
604 | 604 | ||
@@ -606,7 +606,7 @@ impl Analysis { | |||
606 | &self, | 606 | &self, |
607 | file_id: FileId, | 607 | file_id: FileId, |
608 | new_name_stem: &str, | 608 | new_name_stem: &str, |
609 | ) -> Cancelable<Option<SourceChange>> { | 609 | ) -> Cancellable<Option<SourceChange>> { |
610 | self.with_db(|db| references::rename::will_rename_file(db, file_id, new_name_stem)) | 610 | self.with_db(|db| references::rename::will_rename_file(db, file_id, new_name_stem)) |
611 | } | 611 | } |
612 | 612 | ||
@@ -616,7 +616,7 @@ impl Analysis { | |||
616 | parse_only: bool, | 616 | parse_only: bool, |
617 | resolve_context: FilePosition, | 617 | resolve_context: FilePosition, |
618 | selections: Vec<FileRange>, | 618 | selections: Vec<FileRange>, |
619 | ) -> Cancelable<Result<SourceChange, SsrError>> { | 619 | ) -> Cancellable<Result<SourceChange, SsrError>> { |
620 | self.with_db(|db| { | 620 | self.with_db(|db| { |
621 | let rule: ide_ssr::SsrRule = query.parse()?; | 621 | let rule: ide_ssr::SsrRule = query.parse()?; |
622 | let mut match_finder = | 622 | let mut match_finder = |
@@ -631,11 +631,11 @@ impl Analysis { | |||
631 | &self, | 631 | &self, |
632 | file_id: FileId, | 632 | file_id: FileId, |
633 | config: AnnotationConfig, | 633 | config: AnnotationConfig, |
634 | ) -> Cancelable<Vec<Annotation>> { | 634 | ) -> Cancellable<Vec<Annotation>> { |
635 | self.with_db(|db| annotations::annotations(db, file_id, config)) | 635 | self.with_db(|db| annotations::annotations(db, file_id, config)) |
636 | } | 636 | } |
637 | 637 | ||
638 | pub fn resolve_annotation(&self, annotation: Annotation) -> Cancelable<Annotation> { | 638 | pub fn resolve_annotation(&self, annotation: Annotation) -> Cancellable<Annotation> { |
639 | self.with_db(|db| annotations::resolve_annotation(db, annotation)) | 639 | self.with_db(|db| annotations::resolve_annotation(db, annotation)) |
640 | } | 640 | } |
641 | 641 | ||
@@ -643,16 +643,28 @@ impl Analysis { | |||
643 | &self, | 643 | &self, |
644 | range: FileRange, | 644 | range: FileRange, |
645 | direction: Direction, | 645 | direction: Direction, |
646 | ) -> Cancelable<Option<TextEdit>> { | 646 | ) -> Cancellable<Option<TextEdit>> { |
647 | self.with_db(|db| move_item::move_item(db, range, direction)) | 647 | self.with_db(|db| move_item::move_item(db, range, direction)) |
648 | } | 648 | } |
649 | 649 | ||
650 | /// Performs an operation on that may be Canceled. | 650 | /// Performs an operation on the database that may be canceled. |
651 | fn with_db<F, T>(&self, f: F) -> Cancelable<T> | 651 | /// |
652 | /// rust-analyzer needs to be able to answer semantic questions about the | ||
653 | /// code while the code is being modified. A common problem is that a | ||
654 | /// long-running query is being calculated when a new change arrives. | ||
655 | /// | ||
656 | /// We can't just apply the change immediately: this will cause the pending | ||
657 | /// query to see inconsistent state (it will observe an absence of | ||
658 | /// repeatable read). So what we do is we **cancel** all pending queries | ||
659 | /// before applying the change. | ||
660 | /// | ||
661 | /// Salsa implements cancelation by unwinding with a special value and | ||
662 | /// catching it on the API boundary. | ||
663 | fn with_db<F, T>(&self, f: F) -> Cancellable<T> | ||
652 | where | 664 | where |
653 | F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, | 665 | F: FnOnce(&RootDatabase) -> T + std::panic::UnwindSafe, |
654 | { | 666 | { |
655 | self.db.catch_canceled(f) | 667 | Cancelled::catch(|| f(&self.db)) |
656 | } | 668 | } |
657 | } | 669 | } |
658 | 670 | ||