diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/base_db/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/base_db/src/cancellation.rs | 48 | ||||
-rw-r--r-- | crates/base_db/src/lib.rs | 45 | ||||
-rw-r--r-- | crates/hir/src/diagnostics.rs | 24 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 12 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 2 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/collector.rs | 52 | ||||
-rw-r--r-- | crates/hir_def/src/nameres/diagnostics.rs | 9 | ||||
-rw-r--r-- | crates/hir_def/src/test_db.rs | 7 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/traits.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/diagnostics.rs | 5 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 128 | ||||
-rw-r--r-- | crates/ide_db/src/lib.rs | 20 | ||||
-rw-r--r-- | crates/ide_db/src/symbol_index.rs | 2 | ||||
-rw-r--r-- | crates/rust-analyzer/src/dispatch.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/global_state.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_utils.rs | 6 | ||||
-rw-r--r-- | crates/rust-analyzer/src/main_loop.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 6 |
20 files changed, 181 insertions, 203 deletions
diff --git a/crates/base_db/Cargo.toml b/crates/base_db/Cargo.toml index 1724d2f85..69173ad1f 100644 --- a/crates/base_db/Cargo.toml +++ b/crates/base_db/Cargo.toml | |||
@@ -10,7 +10,7 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | salsa = "0.16.0" | 13 | salsa = "0.17.0-pre.1" |
14 | rustc-hash = "1.1.0" | 14 | rustc-hash = "1.1.0" |
15 | 15 | ||
16 | syntax = { path = "../syntax", version = "0.0.0" } | 16 | syntax = { path = "../syntax", version = "0.0.0" } |
diff --git a/crates/base_db/src/cancellation.rs b/crates/base_db/src/cancellation.rs deleted file mode 100644 index 7420a1976..000000000 --- a/crates/base_db/src/cancellation.rs +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | //! Utility types to support cancellation. | ||
2 | //! | ||
3 | //! In a typical IDE use-case, requests and modification happen concurrently, as | ||
4 | //! in the following scenario: | ||
5 | //! | ||
6 | //! * user types a character, | ||
7 | //! * a syntax highlighting process is started | ||
8 | //! * user types next character, while syntax highlighting *is still in | ||
9 | //! progress*. | ||
10 | //! | ||
11 | //! In this situation, we want to react to modification as quickly as possible. | ||
12 | //! At the same time, in-progress results are not very interesting, because they | ||
13 | //! are invalidated by the edit anyway. So, we first cancel all in-flight | ||
14 | //! requests, and then apply modification knowing that it won't interfere with | ||
15 | //! any background processing (this bit is handled by salsa, see the | ||
16 | //! `BaseDatabase::check_canceled` method). | ||
17 | |||
18 | /// An "error" signifying that the operation was canceled. | ||
19 | #[derive(Clone, PartialEq, Eq, Hash)] | ||
20 | pub struct Canceled { | ||
21 | _private: (), | ||
22 | } | ||
23 | |||
24 | impl Canceled { | ||
25 | pub(crate) fn new() -> Canceled { | ||
26 | Canceled { _private: () } | ||
27 | } | ||
28 | |||
29 | pub fn throw() -> ! { | ||
30 | // We use resume and not panic here to avoid running the panic | ||
31 | // hook (that is, to avoid collecting and printing backtrace). | ||
32 | std::panic::resume_unwind(Box::new(Canceled::new())) | ||
33 | } | ||
34 | } | ||
35 | |||
36 | impl std::fmt::Display for Canceled { | ||
37 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
38 | fmt.write_str("canceled") | ||
39 | } | ||
40 | } | ||
41 | |||
42 | impl std::fmt::Debug for Canceled { | ||
43 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||
44 | write!(fmt, "Canceled") | ||
45 | } | ||
46 | } | ||
47 | |||
48 | impl std::error::Error for Canceled {} | ||
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs index 980a0ed98..62bf2a4b2 100644 --- a/crates/base_db/src/lib.rs +++ b/crates/base_db/src/lib.rs | |||
@@ -1,5 +1,4 @@ | |||
1 | //! base_db defines basic database traits. The concrete DB is defined by ide. | 1 | //! base_db defines basic database traits. The concrete DB is defined by ide. |
2 | mod cancellation; | ||
3 | mod input; | 2 | mod input; |
4 | mod change; | 3 | mod change; |
5 | pub mod fixture; | 4 | pub mod fixture; |
@@ -10,14 +9,13 @@ use rustc_hash::FxHashSet; | |||
10 | use syntax::{ast, Parse, SourceFile, TextRange, TextSize}; | 9 | use syntax::{ast, Parse, SourceFile, TextRange, TextSize}; |
11 | 10 | ||
12 | pub use crate::{ | 11 | pub use crate::{ |
13 | cancellation::Canceled, | ||
14 | change::Change, | 12 | change::Change, |
15 | input::{ | 13 | input::{ |
16 | CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, | 14 | CrateData, CrateDisplayName, CrateGraph, CrateId, CrateName, Dependency, Edition, Env, |
17 | ProcMacro, ProcMacroExpander, ProcMacroId, ProcMacroKind, SourceRoot, SourceRootId, | 15 | ProcMacro, ProcMacroExpander, ProcMacroId, ProcMacroKind, SourceRoot, SourceRootId, |
18 | }, | 16 | }, |
19 | }; | 17 | }; |
20 | pub use salsa; | 18 | pub use salsa::{self, Cancelled}; |
21 | pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, FileId, VfsPath}; | 19 | pub use vfs::{file_set::FileSet, AnchoredPath, AnchoredPathBuf, FileId, VfsPath}; |
22 | 20 | ||
23 | #[macro_export] | 21 | #[macro_export] |
@@ -38,45 +36,6 @@ pub trait Upcast<T: ?Sized> { | |||
38 | fn upcast(&self) -> &T; | 36 | fn upcast(&self) -> &T; |
39 | } | 37 | } |
40 | 38 | ||
41 | pub trait CheckCanceled { | ||
42 | /// Aborts current query if there are pending changes. | ||
43 | /// | ||
44 | /// rust-analyzer needs to be able to answer semantic questions about the | ||
45 | /// code while the code is being modified. A common problem is that a | ||
46 | /// long-running query is being calculated when a new change arrives. | ||
47 | /// | ||
48 | /// We can't just apply the change immediately: this will cause the pending | ||
49 | /// query to see inconsistent state (it will observe an absence of | ||
50 | /// repeatable read). So what we do is we **cancel** all pending queries | ||
51 | /// before applying the change. | ||
52 | /// | ||
53 | /// We implement cancellation by panicking with a special value and catching | ||
54 | /// it on the API boundary. Salsa explicitly supports this use-case. | ||
55 | fn check_canceled(&self); | ||
56 | |||
57 | fn catch_canceled<F, T>(&self, f: F) -> Result<T, Canceled> | ||
58 | where | ||
59 | Self: Sized + panic::RefUnwindSafe, | ||
60 | F: FnOnce(&Self) -> T + panic::UnwindSafe, | ||
61 | { | ||
62 | // Uncomment to debug missing cancellations. | ||
63 | // let _span = profile::heartbeat_span(); | ||
64 | panic::catch_unwind(|| f(self)).map_err(|err| match err.downcast::<Canceled>() { | ||
65 | Ok(canceled) => *canceled, | ||
66 | Err(payload) => panic::resume_unwind(payload), | ||
67 | }) | ||
68 | } | ||
69 | } | ||
70 | |||
71 | impl<T: salsa::Database> CheckCanceled for T { | ||
72 | fn check_canceled(&self) { | ||
73 | // profile::heartbeat(); | ||
74 | if self.salsa_runtime().is_current_revision_canceled() { | ||
75 | Canceled::throw() | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | |||
80 | #[derive(Clone, Copy, Debug)] | 39 | #[derive(Clone, Copy, Debug)] |
81 | pub struct FilePosition { | 40 | pub struct FilePosition { |
82 | pub file_id: FileId, | 41 | pub file_id: FileId, |
@@ -101,7 +60,7 @@ pub trait FileLoader { | |||
101 | /// Database which stores all significant input facts: source code and project | 60 | /// Database which stores all significant input facts: source code and project |
102 | /// model. Everything else in rust-analyzer is derived from these queries. | 61 | /// model. Everything else in rust-analyzer is derived from these queries. |
103 | #[salsa::query_group(SourceDatabaseStorage)] | 62 | #[salsa::query_group(SourceDatabaseStorage)] |
104 | pub trait SourceDatabase: CheckCanceled + FileLoader + std::fmt::Debug { | 63 | pub trait SourceDatabase: FileLoader + std::fmt::Debug { |
105 | // Parses the file into the syntax tree. | 64 | // Parses the file into the syntax tree. |
106 | #[salsa::invoke(parse_query)] | 65 | #[salsa::invoke(parse_query)] |
107 | fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>; | 66 | fn parse(&self, file_id: FileId) -> Parse<ast::SourceFile>; |
diff --git a/crates/hir/src/diagnostics.rs b/crates/hir/src/diagnostics.rs index 22ec7c6ac..2cdbd172a 100644 --- a/crates/hir/src/diagnostics.rs +++ b/crates/hir/src/diagnostics.rs | |||
@@ -227,3 +227,27 @@ impl Diagnostic for MacroError { | |||
227 | true | 227 | true |
228 | } | 228 | } |
229 | } | 229 | } |
230 | |||
231 | #[derive(Debug)] | ||
232 | pub struct UnimplementedBuiltinMacro { | ||
233 | pub file: HirFileId, | ||
234 | pub node: SyntaxNodePtr, | ||
235 | } | ||
236 | |||
237 | impl Diagnostic for UnimplementedBuiltinMacro { | ||
238 | fn code(&self) -> DiagnosticCode { | ||
239 | DiagnosticCode("unimplemented-builtin-macro") | ||
240 | } | ||
241 | |||
242 | fn message(&self) -> String { | ||
243 | "unimplemented built-in macro".to_string() | ||
244 | } | ||
245 | |||
246 | fn display_source(&self) -> InFile<SyntaxNodePtr> { | ||
247 | InFile::new(self.file, self.node.clone()) | ||
248 | } | ||
249 | |||
250 | fn as_any(&self) -> &(dyn Any + Send + 'static) { | ||
251 | self | ||
252 | } | ||
253 | } | ||
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 975ae4869..d3ef29db4 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -36,8 +36,8 @@ use std::{iter, sync::Arc}; | |||
36 | use arrayvec::ArrayVec; | 36 | use arrayvec::ArrayVec; |
37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; | 37 | use base_db::{CrateDisplayName, CrateId, Edition, FileId}; |
38 | use diagnostics::{ | 38 | use diagnostics::{ |
39 | InactiveCode, MacroError, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall, | 39 | InactiveCode, MacroError, UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, |
40 | UnresolvedModule, UnresolvedProcMacro, | 40 | UnresolvedMacroCall, UnresolvedModule, UnresolvedProcMacro, |
41 | }; | 41 | }; |
42 | use either::Either; | 42 | use either::Either; |
43 | use hir_def::{ | 43 | use hir_def::{ |
@@ -565,6 +565,14 @@ impl Module { | |||
565 | }; | 565 | }; |
566 | sink.push(MacroError { file, node: ast, message: message.clone() }); | 566 | sink.push(MacroError { file, node: ast, message: message.clone() }); |
567 | } | 567 | } |
568 | |||
569 | DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => { | ||
570 | let node = ast.to_node(db.upcast()); | ||
571 | // Must have a name, otherwise we wouldn't emit it. | ||
572 | let name = node.name().expect("unimplemented builtin macro with no name"); | ||
573 | let ptr = SyntaxNodePtr::from(AstPtr::new(&name)); | ||
574 | sink.push(UnimplementedBuiltinMacro { file: ast.file_id, node: ptr }); | ||
575 | } | ||
568 | } | 576 | } |
569 | } | 577 | } |
570 | for decl in self.declarations(db) { | 578 | for decl in self.declarations(db) { |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 8d3c43d08..c7f2c02e4 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -361,7 +361,7 @@ impl<'db> SemanticsImpl<'db> { | |||
361 | let sa = self.analyze(&parent); | 361 | let sa = self.analyze(&parent); |
362 | 362 | ||
363 | let token = successors(Some(InFile::new(sa.file_id, token)), |token| { | 363 | let token = successors(Some(InFile::new(sa.file_id, token)), |token| { |
364 | self.db.check_canceled(); | 364 | self.db.unwind_if_cancelled(); |
365 | let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?; | 365 | let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?; |
366 | let tt = macro_call.token_tree()?; | 366 | let tt = macro_call.token_tree()?; |
367 | if !tt.syntax().text_range().contains_range(token.value.text_range()) { | 367 | if !tt.syntax().text_range().contains_range(token.value.text_range()) { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index d9d6c91a8..7f9fdb379 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -351,7 +351,7 @@ impl DefCollector<'_> { | |||
351 | let mut i = 0; | 351 | let mut i = 0; |
352 | 'outer: loop { | 352 | 'outer: loop { |
353 | loop { | 353 | loop { |
354 | self.db.check_canceled(); | 354 | self.db.unwind_if_cancelled(); |
355 | loop { | 355 | loop { |
356 | if self.resolve_imports() == ReachedFixedPoint::Yes { | 356 | if self.resolve_imports() == ReachedFixedPoint::Yes { |
357 | break; | 357 | break; |
@@ -836,7 +836,7 @@ impl DefCollector<'_> { | |||
836 | vis: Visibility, | 836 | vis: Visibility, |
837 | import_type: ImportType, | 837 | import_type: ImportType, |
838 | ) { | 838 | ) { |
839 | self.db.check_canceled(); | 839 | self.db.unwind_if_cancelled(); |
840 | self.update_recursive(module_id, resolutions, vis, import_type, 0) | 840 | self.update_recursive(module_id, resolutions, vis, import_type, 0) |
841 | } | 841 | } |
842 | 842 | ||
@@ -1679,14 +1679,22 @@ impl ModCollector<'_, '_> { | |||
1679 | None => &mac.name, | 1679 | None => &mac.name, |
1680 | }; | 1680 | }; |
1681 | let krate = self.def_collector.def_map.krate; | 1681 | let krate = self.def_collector.def_map.krate; |
1682 | if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) { | 1682 | match find_builtin_macro(name, krate, ast_id) { |
1683 | self.def_collector.define_macro_rules( | 1683 | Some(macro_id) => { |
1684 | self.module_id, | 1684 | self.def_collector.define_macro_rules( |
1685 | mac.name.clone(), | 1685 | self.module_id, |
1686 | macro_id, | 1686 | mac.name.clone(), |
1687 | is_export, | 1687 | macro_id, |
1688 | ); | 1688 | is_export, |
1689 | return; | 1689 | ); |
1690 | return; | ||
1691 | } | ||
1692 | None => { | ||
1693 | self.def_collector | ||
1694 | .def_map | ||
1695 | .diagnostics | ||
1696 | .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id)); | ||
1697 | } | ||
1690 | } | 1698 | } |
1691 | } | 1699 | } |
1692 | 1700 | ||
@@ -1715,15 +1723,23 @@ impl ModCollector<'_, '_> { | |||
1715 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) | 1723 | let macro_id = find_builtin_macro(&mac.name, krate, ast_id) |
1716 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); | 1724 | .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); |
1717 | 1725 | ||
1718 | if let Some(macro_id) = macro_id { | 1726 | match macro_id { |
1719 | self.def_collector.define_macro_def( | 1727 | Some(macro_id) => { |
1720 | self.module_id, | 1728 | self.def_collector.define_macro_def( |
1721 | mac.name.clone(), | 1729 | self.module_id, |
1722 | macro_id, | 1730 | mac.name.clone(), |
1723 | &self.item_tree[mac.visibility], | 1731 | macro_id, |
1724 | ); | 1732 | &self.item_tree[mac.visibility], |
1733 | ); | ||
1734 | return; | ||
1735 | } | ||
1736 | None => { | ||
1737 | self.def_collector | ||
1738 | .def_map | ||
1739 | .diagnostics | ||
1740 | .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id)); | ||
1741 | } | ||
1725 | } | 1742 | } |
1726 | return; | ||
1727 | } | 1743 | } |
1728 | 1744 | ||
1729 | // Case 2: normal `macro` | 1745 | // Case 2: normal `macro` |
diff --git a/crates/hir_def/src/nameres/diagnostics.rs b/crates/hir_def/src/nameres/diagnostics.rs index 57c36c3c6..95061f601 100644 --- a/crates/hir_def/src/nameres/diagnostics.rs +++ b/crates/hir_def/src/nameres/diagnostics.rs | |||
@@ -27,6 +27,8 @@ pub enum DefDiagnosticKind { | |||
27 | UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath }, | 27 | UnresolvedMacroCall { ast: AstId<ast::MacroCall>, path: ModPath }, |
28 | 28 | ||
29 | MacroError { ast: MacroCallKind, message: String }, | 29 | MacroError { ast: MacroCallKind, message: String }, |
30 | |||
31 | UnimplementedBuiltinMacro { ast: AstId<ast::Macro> }, | ||
30 | } | 32 | } |
31 | 33 | ||
32 | #[derive(Debug, PartialEq, Eq)] | 34 | #[derive(Debug, PartialEq, Eq)] |
@@ -93,4 +95,11 @@ impl DefDiagnostic { | |||
93 | ) -> Self { | 95 | ) -> Self { |
94 | Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } } | 96 | Self { in_module: container, kind: DefDiagnosticKind::UnresolvedMacroCall { ast, path } } |
95 | } | 97 | } |
98 | |||
99 | pub(super) fn unimplemented_builtin_macro( | ||
100 | container: LocalModuleId, | ||
101 | ast: AstId<ast::Macro>, | ||
102 | ) -> Self { | ||
103 | Self { in_module: container, kind: DefDiagnosticKind::UnimplementedBuiltinMacro { ast } } | ||
104 | } | ||
96 | } | 105 | } |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index a9c1e13e2..e840fe5e8 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -298,6 +298,13 @@ impl TestDB { | |||
298 | DefDiagnosticKind::MacroError { ast, message } => { | 298 | DefDiagnosticKind::MacroError { ast, message } => { |
299 | (ast.to_node(self.upcast()), message.as_str()) | 299 | (ast.to_node(self.upcast()), message.as_str()) |
300 | } | 300 | } |
301 | DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => { | ||
302 | let node = ast.to_node(self.upcast()); | ||
303 | ( | ||
304 | InFile::new(ast.file_id, node.syntax().clone()), | ||
305 | "UnimplementedBuiltinMacro", | ||
306 | ) | ||
307 | } | ||
301 | }; | 308 | }; |
302 | 309 | ||
303 | let frange = node.as_ref().original_file_range(self); | 310 | let frange = node.as_ref().original_file_range(self); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 97507305c..41ef45326 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -119,7 +119,7 @@ impl<'a> InferenceContext<'a> { | |||
119 | } | 119 | } |
120 | 120 | ||
121 | fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 121 | fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
122 | self.db.check_canceled(); | 122 | self.db.unwind_if_cancelled(); |
123 | 123 | ||
124 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 124 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
125 | let ty = match &body[tgt_expr] { | 125 | let ty = match &body[tgt_expr] { |
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 294cb531c..f589b314b 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -112,7 +112,7 @@ fn solve( | |||
112 | let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL); | 112 | let fuel = std::cell::Cell::new(CHALK_SOLVER_FUEL); |
113 | 113 | ||
114 | let should_continue = || { | 114 | let should_continue = || { |
115 | context.db.check_canceled(); | 115 | db.unwind_if_cancelled(); |
116 | let remaining = fuel.get(); | 116 | let remaining = fuel.get(); |
117 | fuel.set(remaining - 1); | 117 | fuel.set(remaining - 1); |
118 | if remaining == 0 { | 118 | if remaining == 0 { |
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 | ||
diff --git a/crates/ide_db/src/lib.rs b/crates/ide_db/src/lib.rs index 88ee4a87d..1f900aef4 100644 --- a/crates/ide_db/src/lib.rs +++ b/crates/ide_db/src/lib.rs | |||
@@ -19,8 +19,7 @@ use std::{fmt, sync::Arc}; | |||
19 | 19 | ||
20 | use base_db::{ | 20 | use base_db::{ |
21 | salsa::{self, Durability}, | 21 | salsa::{self, Durability}, |
22 | AnchoredPath, Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, | 22 | AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast, |
23 | SourceDatabase, Upcast, | ||
24 | }; | 23 | }; |
25 | use hir::db::{AstDatabase, DefDatabase, HirDatabase}; | 24 | use hir::db::{AstDatabase, DefDatabase, HirDatabase}; |
26 | use rustc_hash::FxHashSet; | 25 | use rustc_hash::FxHashSet; |
@@ -80,20 +79,7 @@ impl FileLoader for RootDatabase { | |||
80 | } | 79 | } |
81 | } | 80 | } |
82 | 81 | ||
83 | impl salsa::Database for RootDatabase { | 82 | impl salsa::Database for RootDatabase {} |
84 | fn on_propagated_panic(&self) -> ! { | ||
85 | Canceled::throw() | ||
86 | } | ||
87 | fn salsa_event(&self, event: salsa::Event) { | ||
88 | match event.kind { | ||
89 | salsa::EventKind::DidValidateMemoizedValue { .. } | ||
90 | | salsa::EventKind::WillExecute { .. } => { | ||
91 | self.check_canceled(); | ||
92 | } | ||
93 | _ => (), | ||
94 | } | ||
95 | } | ||
96 | } | ||
97 | 83 | ||
98 | impl Default for RootDatabase { | 84 | impl Default for RootDatabase { |
99 | fn default() -> RootDatabase { | 85 | fn default() -> RootDatabase { |
@@ -126,7 +112,7 @@ impl salsa::ParallelDatabase for RootDatabase { | |||
126 | } | 112 | } |
127 | 113 | ||
128 | #[salsa::query_group(LineIndexDatabaseStorage)] | 114 | #[salsa::query_group(LineIndexDatabaseStorage)] |
129 | pub trait LineIndexDatabase: base_db::SourceDatabase + CheckCanceled { | 115 | pub trait LineIndexDatabase: base_db::SourceDatabase { |
130 | fn line_index(&self, file_id: FileId) -> Arc<LineIndex>; | 116 | fn line_index(&self, file_id: FileId) -> Arc<LineIndex>; |
131 | } | 117 | } |
132 | 118 | ||
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs index 0f5c4abc4..5c372a7e5 100644 --- a/crates/ide_db/src/symbol_index.rs +++ b/crates/ide_db/src/symbol_index.rs | |||
@@ -127,7 +127,7 @@ fn library_symbols(db: &dyn SymbolsDatabase) -> Arc<FxHashMap<SourceRootId, Symb | |||
127 | } | 127 | } |
128 | 128 | ||
129 | fn file_symbols(db: &dyn SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { | 129 | fn file_symbols(db: &dyn SymbolsDatabase, file_id: FileId) -> Arc<SymbolIndex> { |
130 | db.check_canceled(); | 130 | db.unwind_if_cancelled(); |
131 | let parse = db.parse(file_id); | 131 | let parse = db.parse(file_id); |
132 | 132 | ||
133 | let symbols = source_file_to_file_symbols(&parse.tree(), file_id); | 133 | let symbols = source_file_to_file_symbols(&parse.tree(), file_id); |
diff --git a/crates/rust-analyzer/src/dispatch.rs b/crates/rust-analyzer/src/dispatch.rs index baf2199d9..2011a4132 100644 --- a/crates/rust-analyzer/src/dispatch.rs +++ b/crates/rust-analyzer/src/dispatch.rs | |||
@@ -5,7 +5,7 @@ use serde::{de::DeserializeOwned, Serialize}; | |||
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | global_state::{GlobalState, GlobalStateSnapshot}, | 7 | global_state::{GlobalState, GlobalStateSnapshot}, |
8 | lsp_utils::is_canceled, | 8 | lsp_utils::is_cancelled, |
9 | main_loop::Task, | 9 | main_loop::Task, |
10 | LspError, Result, | 10 | LspError, Result, |
11 | }; | 11 | }; |
@@ -132,7 +132,7 @@ where | |||
132 | Err(e) => match e.downcast::<LspError>() { | 132 | Err(e) => match e.downcast::<LspError>() { |
133 | Ok(lsp_error) => lsp_server::Response::new_err(id, lsp_error.code, lsp_error.message), | 133 | Ok(lsp_error) => lsp_server::Response::new_err(id, lsp_error.code, lsp_error.message), |
134 | Err(e) => { | 134 | Err(e) => { |
135 | if is_canceled(&*e) { | 135 | if is_cancelled(&*e) { |
136 | lsp_server::Response::new_err( | 136 | lsp_server::Response::new_err( |
137 | id, | 137 | id, |
138 | lsp_server::ErrorCode::ContentModified as i32, | 138 | lsp_server::ErrorCode::ContentModified as i32, |
diff --git a/crates/rust-analyzer/src/global_state.rs b/crates/rust-analyzer/src/global_state.rs index 6a36d29d4..ea9dbf7fc 100644 --- a/crates/rust-analyzer/src/global_state.rs +++ b/crates/rust-analyzer/src/global_state.rs | |||
@@ -7,7 +7,7 @@ use std::{sync::Arc, time::Instant}; | |||
7 | 7 | ||
8 | use crossbeam_channel::{unbounded, Receiver, Sender}; | 8 | use crossbeam_channel::{unbounded, Receiver, Sender}; |
9 | use flycheck::FlycheckHandle; | 9 | use flycheck::FlycheckHandle; |
10 | use ide::{Analysis, AnalysisHost, Cancelable, Change, FileId}; | 10 | use ide::{Analysis, AnalysisHost, Cancellable, Change, FileId}; |
11 | use ide_db::base_db::{CrateId, VfsPath}; | 11 | use ide_db::base_db::{CrateId, VfsPath}; |
12 | use lsp_types::{SemanticTokens, Url}; | 12 | use lsp_types::{SemanticTokens, Url}; |
13 | use parking_lot::{Mutex, RwLock}; | 13 | use parking_lot::{Mutex, RwLock}; |
@@ -280,7 +280,7 @@ impl GlobalStateSnapshot { | |||
280 | file_id_to_url(&self.vfs.read().0, id) | 280 | file_id_to_url(&self.vfs.read().0, id) |
281 | } | 281 | } |
282 | 282 | ||
283 | pub(crate) fn file_line_index(&self, file_id: FileId) -> Cancelable<LineIndex> { | 283 | pub(crate) fn file_line_index(&self, file_id: FileId) -> Cancellable<LineIndex> { |
284 | let endings = self.vfs.read().1[&file_id]; | 284 | let endings = self.vfs.read().1[&file_id]; |
285 | let index = self.analysis.file_line_index(file_id)?; | 285 | let index = self.analysis.file_line_index(file_id)?; |
286 | let res = LineIndex { index, endings, encoding: self.config.offset_encoding() }; | 286 | let res = LineIndex { index, endings, encoding: self.config.offset_encoding() }; |
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs index 73c4193e8..8000b5490 100644 --- a/crates/rust-analyzer/src/lsp_utils.rs +++ b/crates/rust-analyzer/src/lsp_utils.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | //! Utilities for LSP-related boilerplate code. | 1 | //! Utilities for LSP-related boilerplate code. |
2 | use std::{error::Error, ops::Range, sync::Arc}; | 2 | use std::{error::Error, ops::Range, sync::Arc}; |
3 | 3 | ||
4 | use ide_db::base_db::Canceled; | 4 | use ide_db::base_db::Cancelled; |
5 | use lsp_server::Notification; | 5 | use lsp_server::Notification; |
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
@@ -10,8 +10,8 @@ use crate::{ | |||
10 | line_index::{LineEndings, LineIndex, OffsetEncoding}, | 10 | line_index::{LineEndings, LineIndex, OffsetEncoding}, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | pub(crate) fn is_canceled(e: &(dyn Error + 'static)) -> bool { | 13 | pub(crate) fn is_cancelled(e: &(dyn Error + 'static)) -> bool { |
14 | e.downcast_ref::<Canceled>().is_some() | 14 | e.downcast_ref::<Cancelled>().is_some() |
15 | } | 15 | } |
16 | 16 | ||
17 | pub(crate) fn notification_is<N: lsp_types::notification::Notification>( | 17 | pub(crate) fn notification_is<N: lsp_types::notification::Notification>( |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 008758ea0..31d8ea9e7 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -22,7 +22,7 @@ use crate::{ | |||
22 | from_proto, | 22 | from_proto, |
23 | global_state::{file_id_to_url, url_to_file_id, GlobalState}, | 23 | global_state::{file_id_to_url, url_to_file_id, GlobalState}, |
24 | handlers, lsp_ext, | 24 | handlers, lsp_ext, |
25 | lsp_utils::{apply_document_changes, is_canceled, notification_is, Progress}, | 25 | lsp_utils::{apply_document_changes, is_cancelled, notification_is, Progress}, |
26 | reload::{BuildDataProgress, ProjectWorkspaceProgress}, | 26 | reload::{BuildDataProgress, ProjectWorkspaceProgress}, |
27 | Result, | 27 | Result, |
28 | }; | 28 | }; |
@@ -752,7 +752,7 @@ impl GlobalState { | |||
752 | .filter_map(|file_id| { | 752 | .filter_map(|file_id| { |
753 | handlers::publish_diagnostics(&snapshot, file_id) | 753 | handlers::publish_diagnostics(&snapshot, file_id) |
754 | .map_err(|err| { | 754 | .map_err(|err| { |
755 | if !is_canceled(&*err) { | 755 | if !is_cancelled(&*err) { |
756 | log::error!("failed to compute diagnostics: {:?}", err); | 756 | log::error!("failed to compute diagnostics: {:?}", err); |
757 | } | 757 | } |
758 | () | 758 | () |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index 2b2ef2c60..7428a3043 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -6,7 +6,7 @@ use std::{ | |||
6 | }; | 6 | }; |
7 | 7 | ||
8 | use ide::{ | 8 | use ide::{ |
9 | Annotation, AnnotationKind, Assist, AssistKind, CallInfo, Cancelable, CompletionItem, | 9 | Annotation, AnnotationKind, Assist, AssistKind, CallInfo, Cancellable, CompletionItem, |
10 | CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, | 10 | CompletionItemKind, CompletionRelevance, Documentation, FileId, FileRange, FileSystemEdit, |
11 | Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, InlayHint, | 11 | Fold, FoldKind, Highlight, HlMod, HlOperator, HlPunct, HlRange, HlTag, Indel, InlayHint, |
12 | InlayKind, InsertTextFormat, Markup, NavigationTarget, ReferenceAccess, RenameError, Runnable, | 12 | InlayKind, InsertTextFormat, Markup, NavigationTarget, ReferenceAccess, RenameError, Runnable, |
@@ -727,7 +727,7 @@ pub(crate) fn snippet_text_document_edit( | |||
727 | pub(crate) fn snippet_text_document_ops( | 727 | pub(crate) fn snippet_text_document_ops( |
728 | snap: &GlobalStateSnapshot, | 728 | snap: &GlobalStateSnapshot, |
729 | file_system_edit: FileSystemEdit, | 729 | file_system_edit: FileSystemEdit, |
730 | ) -> Cancelable<Vec<lsp_ext::SnippetDocumentChangeOperation>> { | 730 | ) -> Cancellable<Vec<lsp_ext::SnippetDocumentChangeOperation>> { |
731 | let mut ops = Vec::new(); | 731 | let mut ops = Vec::new(); |
732 | match file_system_edit { | 732 | match file_system_edit { |
733 | FileSystemEdit::CreateFile { dst, initial_contents } => { | 733 | FileSystemEdit::CreateFile { dst, initial_contents } => { |
@@ -757,7 +757,7 @@ pub(crate) fn snippet_text_document_ops( | |||
757 | let new_uri = snap.anchored_path(&dst); | 757 | let new_uri = snap.anchored_path(&dst); |
758 | let mut rename_file = | 758 | let mut rename_file = |
759 | lsp_types::RenameFile { old_uri, new_uri, options: None, annotation_id: None }; | 759 | lsp_types::RenameFile { old_uri, new_uri, options: None, annotation_id: None }; |
760 | if snap.analysis.is_library_file(src) == Ok(true) | 760 | if snap.analysis.is_library_file(src).ok() == Some(true) |
761 | && snap.config.change_annotation_support() | 761 | && snap.config.change_annotation_support() |
762 | { | 762 | { |
763 | rename_file.annotation_id = Some(outside_workspace_annotation_id()) | 763 | rename_file.annotation_id = Some(outside_workspace_annotation_id()) |