diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 25 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 14 | ||||
-rw-r--r-- | crates/ra_hir/src/module.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/module/imp.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/module/nameres.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/query_definitions.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/source_binder.rs | 11 | ||||
-rw-r--r-- | crates/ra_lsp_server/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main.rs | 10 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/main_loop.rs | 6 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/project_model.rs | 10 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/vfs.rs | 7 | ||||
-rw-r--r-- | crates/ra_lsp_server/tests/heavy_tests/support.rs | 6 | ||||
-rw-r--r-- | crates/thread_worker/Cargo.toml | 11 | ||||
-rw-r--r-- | crates/thread_worker/src/lib.rs (renamed from crates/ra_lsp_server/src/thread_watcher.rs) | 56 |
17 files changed, 106 insertions, 80 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 03d17de0d..0de0e2645 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -10,7 +10,7 @@ use ra_syntax::{ | |||
10 | SyntaxKind::*, | 10 | SyntaxKind::*, |
11 | SyntaxNodeRef, TextRange, TextUnit, | 11 | SyntaxNodeRef, TextRange, TextUnit, |
12 | }; | 12 | }; |
13 | use ra_db::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE, SyntaxDatabase, SourceFileQuery}; | 13 | use ra_db::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE, SyntaxDatabase}; |
14 | use rayon::prelude::*; | 14 | use rayon::prelude::*; |
15 | use rustc_hash::FxHashSet; | 15 | use rustc_hash::FxHashSet; |
16 | use salsa::{Database, ParallelDatabase}; | 16 | use salsa::{Database, ParallelDatabase}; |
@@ -43,6 +43,7 @@ impl AnalysisHostImpl { | |||
43 | } | 43 | } |
44 | pub fn apply_change(&mut self, change: AnalysisChange) { | 44 | pub fn apply_change(&mut self, change: AnalysisChange) { |
45 | log::info!("apply_change {:?}", change); | 45 | log::info!("apply_change {:?}", change); |
46 | // self.gc_syntax_trees(); | ||
46 | 47 | ||
47 | for (file_id, text) in change.files_changed { | 48 | for (file_id, text) in change.files_changed { |
48 | self.db | 49 | self.db |
@@ -115,6 +116,25 @@ impl AnalysisHostImpl { | |||
115 | .set((), Arc::new(crate_graph)) | 116 | .set((), Arc::new(crate_graph)) |
116 | } | 117 | } |
117 | } | 118 | } |
119 | |||
120 | #[allow(unused)] | ||
121 | /// Ideally, we should call this function from time to time to collect heavy | ||
122 | /// syntax trees. However, if we actually do that, everything is recomputed | ||
123 | /// for some reason. Needs investigation. | ||
124 | fn gc_syntax_trees(&mut self) { | ||
125 | self.db | ||
126 | .query(ra_db::SourceFileQuery) | ||
127 | .sweep(salsa::SweepStrategy::default().discard_values()); | ||
128 | self.db | ||
129 | .query(hir::db::FnSyntaxQuery) | ||
130 | .sweep(salsa::SweepStrategy::default().discard_values()); | ||
131 | self.db | ||
132 | .query(hir::db::SourceFileItemsQuery) | ||
133 | .sweep(salsa::SweepStrategy::default().discard_values()); | ||
134 | self.db | ||
135 | .query(hir::db::FileItemQuery) | ||
136 | .sweep(salsa::SweepStrategy::default().discard_values()); | ||
137 | } | ||
118 | } | 138 | } |
119 | 139 | ||
120 | pub(crate) struct AnalysisImpl { | 140 | pub(crate) struct AnalysisImpl { |
@@ -160,9 +180,6 @@ impl AnalysisImpl { | |||
160 | .filter_map(|it| it.ok()) | 180 | .filter_map(|it| it.ok()) |
161 | .collect() | 181 | .collect() |
162 | }; | 182 | }; |
163 | self.db | ||
164 | .query(SourceFileQuery) | ||
165 | .sweep(salsa::SweepStrategy::default().discard_values()); | ||
166 | Ok(query.search(&buf)) | 183 | Ok(query.search(&buf)) |
167 | } | 184 | } |
168 | /// This returns `Vec` because a module may be included from several places. We | 185 | /// This returns `Vec` because a module may be included from several places. We |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index ff41fd326..62cf9ab17 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -27,20 +27,16 @@ pub trait HirDatabase: SyntaxDatabase | |||
27 | } | 27 | } |
28 | fn fn_syntax(fn_id: FnId) -> FnDefNode { | 28 | fn fn_syntax(fn_id: FnId) -> FnDefNode { |
29 | type FnSyntaxQuery; | 29 | type FnSyntaxQuery; |
30 | // Don't retain syntax trees in memory | ||
31 | storage dependencies; | ||
32 | use fn query_definitions::fn_syntax; | 30 | use fn query_definitions::fn_syntax; |
33 | } | 31 | } |
34 | 32 | ||
35 | fn file_items(file_id: FileId) -> Arc<SourceFileItems> { | 33 | fn file_items(file_id: FileId) -> Arc<SourceFileItems> { |
36 | type SourceFileItemsQuery; | 34 | type SourceFileItemsQuery; |
37 | storage dependencies; | ||
38 | use fn query_definitions::file_items; | 35 | use fn query_definitions::file_items; |
39 | } | 36 | } |
40 | 37 | ||
41 | fn file_item(source_item_id: SourceItemId) -> SyntaxNode { | 38 | fn file_item(source_item_id: SourceItemId) -> SyntaxNode { |
42 | type FileItemQuery; | 39 | type FileItemQuery; |
43 | storage dependencies; | ||
44 | use fn query_definitions::file_item; | 40 | use fn query_definitions::file_item; |
45 | } | 41 | } |
46 | 42 | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 760524f6b..5941a9ea3 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -109,7 +109,8 @@ pub(crate) type SourceFileItemId = Id<SyntaxNode>; | |||
109 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 109 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
110 | pub struct SourceItemId { | 110 | pub struct SourceItemId { |
111 | file_id: FileId, | 111 | file_id: FileId, |
112 | item_id: SourceFileItemId, | 112 | /// None for the whole file. |
113 | item_id: Option<SourceFileItemId>, | ||
113 | } | 114 | } |
114 | 115 | ||
115 | /// Maps item's `SyntaxNode`s to `SourceFileItemId` and back. | 116 | /// Maps item's `SyntaxNode`s to `SourceFileItemId` and back. |
@@ -143,11 +144,14 @@ impl SourceFileItems { | |||
143 | return id; | 144 | return id; |
144 | } | 145 | } |
145 | // This should not happen. Let's try to give a sensible diagnostics. | 146 | // This should not happen. Let's try to give a sensible diagnostics. |
146 | if let Some((_, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) { | 147 | if let Some((id, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) { |
147 | panic!( | 148 | // FIXME(#288): whyyy are we getting here? |
149 | log::error!( | ||
148 | "unequal syntax nodes with the same range:\n{:?}\n{:?}", | 150 | "unequal syntax nodes with the same range:\n{:?}\n{:?}", |
149 | item, i | 151 | item, |
150 | ) | 152 | i |
153 | ); | ||
154 | return id; | ||
151 | } | 155 | } |
152 | panic!( | 156 | panic!( |
153 | "Can't find {:?} in SourceFileItems:\n{:?}", | 157 | "Can't find {:?} in SourceFileItems:\n{:?}", |
diff --git a/crates/ra_hir/src/module.rs b/crates/ra_hir/src/module.rs index c6bb76d56..d5866f6ef 100644 --- a/crates/ra_hir/src/module.rs +++ b/crates/ra_hir/src/module.rs | |||
@@ -271,15 +271,13 @@ pub struct ModuleData { | |||
271 | 271 | ||
272 | impl ModuleSource { | 272 | impl ModuleSource { |
273 | // precondition: item_id **must** point to module | 273 | // precondition: item_id **must** point to module |
274 | fn new(file_id: FileId, item_id: SourceFileItemId) -> ModuleSource { | 274 | fn new(file_id: FileId, item_id: Option<SourceFileItemId>) -> ModuleSource { |
275 | let source_item_id = SourceItemId { file_id, item_id }; | 275 | let source_item_id = SourceItemId { file_id, item_id }; |
276 | ModuleSource(source_item_id) | 276 | ModuleSource(source_item_id) |
277 | } | 277 | } |
278 | 278 | ||
279 | pub(crate) fn new_file(db: &impl HirDatabase, file_id: FileId) -> ModuleSource { | 279 | pub(crate) fn new_file(file_id: FileId) -> ModuleSource { |
280 | let file_items = db.file_items(file_id); | 280 | ModuleSource::new(file_id, None) |
281 | let item_id = file_items.id_of_source_file(); | ||
282 | ModuleSource::new(file_id, item_id) | ||
283 | } | 281 | } |
284 | 282 | ||
285 | pub(crate) fn new_inline( | 283 | pub(crate) fn new_inline( |
@@ -290,7 +288,7 @@ impl ModuleSource { | |||
290 | assert!(!m.has_semi()); | 288 | assert!(!m.has_semi()); |
291 | let file_items = db.file_items(file_id); | 289 | let file_items = db.file_items(file_id); |
292 | let item_id = file_items.id_of(file_id, m.syntax()); | 290 | let item_id = file_items.id_of(file_id, m.syntax()); |
293 | ModuleSource::new(file_id, item_id) | 291 | ModuleSource::new(file_id, Some(item_id)) |
294 | } | 292 | } |
295 | 293 | ||
296 | pub fn file_id(self) -> FileId { | 294 | pub fn file_id(self) -> FileId { |
diff --git a/crates/ra_hir/src/module/imp.rs b/crates/ra_hir/src/module/imp.rs index 9f144e139..4a19842c4 100644 --- a/crates/ra_hir/src/module/imp.rs +++ b/crates/ra_hir/src/module/imp.rs | |||
@@ -66,7 +66,7 @@ fn create_module_tree<'a>( | |||
66 | 66 | ||
67 | let source_root = db.source_root(source_root); | 67 | let source_root = db.source_root(source_root); |
68 | for &file_id in source_root.files.iter() { | 68 | for &file_id in source_root.files.iter() { |
69 | let source = ModuleSource::new_file(db, file_id); | 69 | let source = ModuleSource::new_file(file_id); |
70 | if visited.contains(&source) { | 70 | if visited.contains(&source) { |
71 | continue; // TODO: use explicit crate_roots here | 71 | continue; // TODO: use explicit crate_roots here |
72 | } | 72 | } |
@@ -126,7 +126,7 @@ fn build_subtree( | |||
126 | visited, | 126 | visited, |
127 | roots, | 127 | roots, |
128 | Some(link), | 128 | Some(link), |
129 | ModuleSource::new_file(db, file_id), | 129 | ModuleSource::new_file(file_id), |
130 | ), | 130 | ), |
131 | }) | 131 | }) |
132 | .collect::<Cancelable<Vec<_>>>()?; | 132 | .collect::<Cancelable<Vec<_>>>()?; |
diff --git a/crates/ra_hir/src/module/nameres.rs b/crates/ra_hir/src/module/nameres.rs index 9afeade9e..5540b827f 100644 --- a/crates/ra_hir/src/module/nameres.rs +++ b/crates/ra_hir/src/module/nameres.rs | |||
@@ -98,7 +98,7 @@ impl NamedImport { | |||
98 | pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { | 98 | pub fn range(&self, db: &impl HirDatabase, file_id: FileId) -> TextRange { |
99 | let source_item_id = SourceItemId { | 99 | let source_item_id = SourceItemId { |
100 | file_id, | 100 | file_id, |
101 | item_id: self.file_item_id, | 101 | item_id: Some(self.file_item_id), |
102 | }; | 102 | }; |
103 | let syntax = db.file_item(source_item_id); | 103 | let syntax = db.file_item(source_item_id); |
104 | let offset = syntax.borrowed().range().start(); | 104 | let offset = syntax.borrowed().range().start(); |
@@ -281,7 +281,7 @@ where | |||
281 | module_id, | 281 | module_id, |
282 | source_item_id: SourceItemId { | 282 | source_item_id: SourceItemId { |
283 | file_id, | 283 | file_id, |
284 | item_id: item.id, | 284 | item_id: Some(item.id), |
285 | }, | 285 | }, |
286 | }; | 286 | }; |
287 | let def_id = def_loc.id(self.db); | 287 | let def_id = def_loc.id(self.db); |
diff --git a/crates/ra_hir/src/query_definitions.rs b/crates/ra_hir/src/query_definitions.rs index 37c4f9e4f..efaeb1525 100644 --- a/crates/ra_hir/src/query_definitions.rs +++ b/crates/ra_hir/src/query_definitions.rs | |||
@@ -38,7 +38,6 @@ pub(super) fn fn_scopes(db: &impl HirDatabase, fn_id: FnId) -> Arc<FnScopes> { | |||
38 | pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { | 38 | pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFileItems> { |
39 | let mut res = SourceFileItems::new(file_id); | 39 | let mut res = SourceFileItems::new(file_id); |
40 | let source_file = db.source_file(file_id); | 40 | let source_file = db.source_file(file_id); |
41 | res.alloc(source_file.syntax().owned()); | ||
42 | let source_file = source_file.borrowed(); | 41 | let source_file = source_file.borrowed(); |
43 | source_file | 42 | source_file |
44 | .syntax() | 43 | .syntax() |
@@ -52,7 +51,10 @@ pub(super) fn file_items(db: &impl HirDatabase, file_id: FileId) -> Arc<SourceFi | |||
52 | } | 51 | } |
53 | 52 | ||
54 | pub(super) fn file_item(db: &impl HirDatabase, source_item_id: SourceItemId) -> SyntaxNode { | 53 | pub(super) fn file_item(db: &impl HirDatabase, source_item_id: SourceItemId) -> SyntaxNode { |
55 | db.file_items(source_item_id.file_id)[source_item_id.item_id].clone() | 54 | match source_item_id.item_id { |
55 | Some(id) => db.file_items(source_item_id.file_id)[id].clone(), | ||
56 | None => db.source_file(source_item_id.file_id).syntax().owned(), | ||
57 | } | ||
56 | } | 58 | } |
57 | 59 | ||
58 | pub(crate) fn submodules( | 60 | pub(crate) fn submodules( |
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 0c16ccc24..ce2a0f2e8 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs | |||
@@ -20,7 +20,7 @@ use crate::{ | |||
20 | 20 | ||
21 | /// Locates the module by `FileId`. Picks topmost module in the file. | 21 | /// Locates the module by `FileId`. Picks topmost module in the file. |
22 | pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> { | 22 | pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Cancelable<Option<Module>> { |
23 | let module_source = ModuleSource::new_file(db, file_id); | 23 | let module_source = ModuleSource::new_file(file_id); |
24 | module_from_source(db, module_source) | 24 | module_from_source(db, module_source) |
25 | } | 25 | } |
26 | 26 | ||
@@ -32,7 +32,7 @@ pub fn module_from_position( | |||
32 | let file = db.source_file(position.file_id); | 32 | let file = db.source_file(position.file_id); |
33 | let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) { | 33 | let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) { |
34 | Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m), | 34 | Some(m) if !m.has_semi() => ModuleSource::new_inline(db, position.file_id, m), |
35 | _ => ModuleSource::new_file(db, position.file_id), | 35 | _ => ModuleSource::new_file(position.file_id), |
36 | }; | 36 | }; |
37 | module_from_source(db, module_source) | 37 | module_from_source(db, module_source) |
38 | } | 38 | } |
@@ -50,7 +50,7 @@ pub fn module_from_child_node( | |||
50 | { | 50 | { |
51 | ModuleSource::new_inline(db, file_id, m) | 51 | ModuleSource::new_inline(db, file_id, m) |
52 | } else { | 52 | } else { |
53 | ModuleSource::new_file(db, file_id) | 53 | ModuleSource::new_file(file_id) |
54 | }; | 54 | }; |
55 | module_from_source(db, module_source) | 55 | module_from_source(db, module_source) |
56 | } | 56 | } |
@@ -76,7 +76,10 @@ pub fn function_from_source( | |||
76 | let module = ctry!(module_from_child_node(db, file_id, fn_def.syntax())?); | 76 | let module = ctry!(module_from_child_node(db, file_id, fn_def.syntax())?); |
77 | let file_items = db.file_items(file_id); | 77 | let file_items = db.file_items(file_id); |
78 | let item_id = file_items.id_of(file_id, fn_def.syntax()); | 78 | let item_id = file_items.id_of(file_id, fn_def.syntax()); |
79 | let source_item_id = SourceItemId { file_id, item_id }; | 79 | let source_item_id = SourceItemId { |
80 | file_id, | ||
81 | item_id: Some(item_id), | ||
82 | }; | ||
80 | let def_loc = DefLoc { | 83 | let def_loc = DefLoc { |
81 | kind: DefKind::Function, | 84 | kind: DefKind::Function, |
82 | source_root_id: module.source_root_id, | 85 | source_root_id: module.source_root_id, |
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml index 133decc52..30a8d35cd 100644 --- a/crates/ra_lsp_server/Cargo.toml +++ b/crates/ra_lsp_server/Cargo.toml | |||
@@ -26,6 +26,7 @@ text_unit = { version = "0.1.2", features = ["serde"] } | |||
26 | smol_str = { version = "0.1.5", features = ["serde"] } | 26 | smol_str = { version = "0.1.5", features = ["serde"] } |
27 | rustc-hash = "1.0" | 27 | rustc-hash = "1.0" |
28 | 28 | ||
29 | thread_worker = { path = "../thread_worker" } | ||
29 | ra_syntax = { path = "../ra_syntax" } | 30 | ra_syntax = { path = "../ra_syntax" } |
30 | ra_editor = { path = "../ra_editor" } | 31 | ra_editor = { path = "../ra_editor" } |
31 | ra_text_edit = { path = "../ra_text_edit" } | 32 | ra_text_edit = { path = "../ra_text_edit" } |
diff --git a/crates/ra_lsp_server/src/lib.rs b/crates/ra_lsp_server/src/lib.rs index 75c6fa1b8..1d7258c35 100644 --- a/crates/ra_lsp_server/src/lib.rs +++ b/crates/ra_lsp_server/src/lib.rs | |||
@@ -5,7 +5,6 @@ mod path_map; | |||
5 | mod project_model; | 5 | mod project_model; |
6 | pub mod req; | 6 | pub mod req; |
7 | mod server_world; | 7 | mod server_world; |
8 | pub mod thread_watcher; | ||
9 | mod vfs; | 8 | mod vfs; |
10 | 9 | ||
11 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; | 10 | pub type Result<T> = ::std::result::Result<T, ::failure::Error>; |
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs index 9ba972562..4497980e5 100644 --- a/crates/ra_lsp_server/src/main.rs +++ b/crates/ra_lsp_server/src/main.rs | |||
@@ -6,11 +6,11 @@ use ra_lsp_server::Result; | |||
6 | 6 | ||
7 | fn main() -> Result<()> { | 7 | fn main() -> Result<()> { |
8 | ::std::env::set_var("RUST_BACKTRACE", "short"); | 8 | ::std::env::set_var("RUST_BACKTRACE", "short"); |
9 | Logger::with_env_or_str("error") | 9 | let logger = Logger::with_env_or_str("error").duplicate_to_stderr(Duplicate::All); |
10 | .duplicate_to_stderr(Duplicate::All) | 10 | match ::std::env::var("RA_INTERNAL_MODE") { |
11 | .log_to_file() | 11 | Ok(ref v) if v == "1" => logger.log_to_file().directory("log").start()?, |
12 | .directory("log") | 12 | _ => logger.start()?, |
13 | .start()?; | 13 | }; |
14 | log::info!("lifecycle: server started"); | 14 | log::info!("lifecycle: server started"); |
15 | match ::std::panic::catch_unwind(main_inner) { | 15 | match ::std::panic::catch_unwind(main_inner) { |
16 | Ok(res) => { | 16 | Ok(res) => { |
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs index 41f70f263..eab82ee85 100644 --- a/crates/ra_lsp_server/src/main_loop.rs +++ b/crates/ra_lsp_server/src/main_loop.rs | |||
@@ -10,6 +10,7 @@ use gen_lsp_server::{ | |||
10 | use languageserver_types::NumberOrString; | 10 | use languageserver_types::NumberOrString; |
11 | use ra_analysis::{Canceled, FileId, LibraryData}; | 11 | use ra_analysis::{Canceled, FileId, LibraryData}; |
12 | use rayon; | 12 | use rayon; |
13 | use thread_worker::Worker; | ||
13 | use threadpool::ThreadPool; | 14 | use threadpool::ThreadPool; |
14 | use rustc_hash::FxHashSet; | 15 | use rustc_hash::FxHashSet; |
15 | use serde::{de::DeserializeOwned, Serialize}; | 16 | use serde::{de::DeserializeOwned, Serialize}; |
@@ -21,7 +22,6 @@ use crate::{ | |||
21 | project_model::{workspace_loader, CargoWorkspace}, | 22 | project_model::{workspace_loader, CargoWorkspace}, |
22 | req, | 23 | req, |
23 | server_world::{ServerWorld, ServerWorldState}, | 24 | server_world::{ServerWorld, ServerWorldState}, |
24 | thread_watcher::Worker, | ||
25 | vfs::{self, FileEvent}, | 25 | vfs::{self, FileEvent}, |
26 | Result, | 26 | Result, |
27 | }; | 27 | }; |
@@ -92,8 +92,8 @@ pub fn main_loop( | |||
92 | let ws_res = ws_watcher.stop(); | 92 | let ws_res = ws_watcher.stop(); |
93 | 93 | ||
94 | main_res?; | 94 | main_res?; |
95 | fs_res?; | 95 | fs_res.map_err(|_| format_err!("fs watcher died"))?; |
96 | ws_res?; | 96 | ws_res.map_err(|_| format_err!("ws watcher died"))?; |
97 | 97 | ||
98 | Ok(()) | 98 | Ok(()) |
99 | } | 99 | } |
diff --git a/crates/ra_lsp_server/src/project_model.rs b/crates/ra_lsp_server/src/project_model.rs index cb91ada90..b881f8b6f 100644 --- a/crates/ra_lsp_server/src/project_model.rs +++ b/crates/ra_lsp_server/src/project_model.rs | |||
@@ -4,11 +4,9 @@ use cargo_metadata::{metadata_run, CargoOpt}; | |||
4 | use ra_syntax::SmolStr; | 4 | use ra_syntax::SmolStr; |
5 | use rustc_hash::{FxHashMap, FxHashSet}; | 5 | use rustc_hash::{FxHashMap, FxHashSet}; |
6 | use failure::{format_err, bail}; | 6 | use failure::{format_err, bail}; |
7 | use thread_worker::{WorkerHandle, Worker}; | ||
7 | 8 | ||
8 | use crate::{ | 9 | use crate::Result; |
9 | Result, | ||
10 | thread_watcher::{ThreadWatcher, Worker}, | ||
11 | }; | ||
12 | 10 | ||
13 | /// `CargoWorksapce` represents the logical structure of, well, a Cargo | 11 | /// `CargoWorksapce` represents the logical structure of, well, a Cargo |
14 | /// workspace. It pretty closely mirrors `cargo metadata` output. | 12 | /// workspace. It pretty closely mirrors `cargo metadata` output. |
@@ -199,8 +197,8 @@ impl TargetKind { | |||
199 | } | 197 | } |
200 | } | 198 | } |
201 | 199 | ||
202 | pub fn workspace_loader() -> (Worker<PathBuf, Result<CargoWorkspace>>, ThreadWatcher) { | 200 | pub fn workspace_loader() -> (Worker<PathBuf, Result<CargoWorkspace>>, WorkerHandle) { |
203 | Worker::<PathBuf, Result<CargoWorkspace>>::spawn( | 201 | thread_worker::spawn::<PathBuf, Result<CargoWorkspace>, _>( |
204 | "workspace loader", | 202 | "workspace loader", |
205 | 1, | 203 | 1, |
206 | |input_receiver, output_sender| { | 204 | |input_receiver, output_sender| { |
diff --git a/crates/ra_lsp_server/src/vfs.rs b/crates/ra_lsp_server/src/vfs.rs index 00ab3e6c3..fcf7693d8 100644 --- a/crates/ra_lsp_server/src/vfs.rs +++ b/crates/ra_lsp_server/src/vfs.rs | |||
@@ -4,8 +4,7 @@ use std::{ | |||
4 | }; | 4 | }; |
5 | 5 | ||
6 | use walkdir::WalkDir; | 6 | use walkdir::WalkDir; |
7 | 7 | use thread_worker::{WorkerHandle, Worker}; | |
8 | use crate::thread_watcher::{ThreadWatcher, Worker}; | ||
9 | 8 | ||
10 | #[derive(Debug)] | 9 | #[derive(Debug)] |
11 | pub struct FileEvent { | 10 | pub struct FileEvent { |
@@ -18,8 +17,8 @@ pub enum FileEventKind { | |||
18 | Add(String), | 17 | Add(String), |
19 | } | 18 | } |
20 | 19 | ||
21 | pub fn roots_loader() -> (Worker<PathBuf, (PathBuf, Vec<FileEvent>)>, ThreadWatcher) { | 20 | pub fn roots_loader() -> (Worker<PathBuf, (PathBuf, Vec<FileEvent>)>, WorkerHandle) { |
22 | Worker::<PathBuf, (PathBuf, Vec<FileEvent>)>::spawn( | 21 | thread_worker::spawn::<PathBuf, (PathBuf, Vec<FileEvent>), _>( |
23 | "roots loader", | 22 | "roots loader", |
24 | 128, | 23 | 128, |
25 | |input_receiver, output_sender| { | 24 | |input_receiver, output_sender| { |
diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs index 4b75be3ee..07a878a26 100644 --- a/crates/ra_lsp_server/tests/heavy_tests/support.rs +++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs | |||
@@ -17,11 +17,11 @@ use languageserver_types::{ | |||
17 | use serde::Serialize; | 17 | use serde::Serialize; |
18 | use serde_json::{to_string_pretty, Value}; | 18 | use serde_json::{to_string_pretty, Value}; |
19 | use tempdir::TempDir; | 19 | use tempdir::TempDir; |
20 | use thread_worker::{WorkerHandle, Worker}; | ||
20 | use test_utils::{parse_fixture, find_mismatch}; | 21 | use test_utils::{parse_fixture, find_mismatch}; |
21 | 22 | ||
22 | use ra_lsp_server::{ | 23 | use ra_lsp_server::{ |
23 | main_loop, req, | 24 | main_loop, req, |
24 | thread_watcher::{ThreadWatcher, Worker}, | ||
25 | }; | 25 | }; |
26 | 26 | ||
27 | pub fn project(fixture: &str) -> Server { | 27 | pub fn project(fixture: &str) -> Server { |
@@ -45,13 +45,13 @@ pub struct Server { | |||
45 | messages: RefCell<Vec<RawMessage>>, | 45 | messages: RefCell<Vec<RawMessage>>, |
46 | dir: TempDir, | 46 | dir: TempDir, |
47 | worker: Option<Worker<RawMessage, RawMessage>>, | 47 | worker: Option<Worker<RawMessage, RawMessage>>, |
48 | watcher: Option<ThreadWatcher>, | 48 | watcher: Option<WorkerHandle>, |
49 | } | 49 | } |
50 | 50 | ||
51 | impl Server { | 51 | impl Server { |
52 | fn new(dir: TempDir, files: Vec<(PathBuf, String)>) -> Server { | 52 | fn new(dir: TempDir, files: Vec<(PathBuf, String)>) -> Server { |
53 | let path = dir.path().to_path_buf(); | 53 | let path = dir.path().to_path_buf(); |
54 | let (worker, watcher) = Worker::<RawMessage, RawMessage>::spawn( | 54 | let (worker, watcher) = thread_worker::spawn::<RawMessage, RawMessage, _>( |
55 | "test server", | 55 | "test server", |
56 | 128, | 56 | 128, |
57 | move |mut msg_receiver, mut msg_sender| { | 57 | move |mut msg_receiver, mut msg_sender| { |
diff --git a/crates/thread_worker/Cargo.toml b/crates/thread_worker/Cargo.toml new file mode 100644 index 000000000..62d66a1a3 --- /dev/null +++ b/crates/thread_worker/Cargo.toml | |||
@@ -0,0 +1,11 @@ | |||
1 | [package] | ||
2 | edition = "2018" | ||
3 | name = "thread_worker" | ||
4 | version = "0.1.0" | ||
5 | authors = ["Aleksey Kladov <[email protected]>"] | ||
6 | |||
7 | [dependencies] | ||
8 | drop_bomb = "0.1.0" | ||
9 | crossbeam-channel = "0.2.4" | ||
10 | log = "0.4.3" | ||
11 | |||
diff --git a/crates/ra_lsp_server/src/thread_watcher.rs b/crates/thread_worker/src/lib.rs index 99825d440..e558559ef 100644 --- a/crates/ra_lsp_server/src/thread_watcher.rs +++ b/crates/thread_worker/src/lib.rs | |||
@@ -1,28 +1,35 @@ | |||
1 | //! Small utility to correctly spawn crossbeam-channel based worker threads. | ||
2 | |||
1 | use std::thread; | 3 | use std::thread; |
2 | 4 | ||
3 | use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; | 5 | use crossbeam_channel::{bounded, unbounded, Receiver, Sender}; |
4 | use drop_bomb::DropBomb; | 6 | use drop_bomb::DropBomb; |
5 | use failure::format_err; | ||
6 | |||
7 | use crate::Result; | ||
8 | 7 | ||
9 | pub struct Worker<I, O> { | 8 | pub struct Worker<I, O> { |
10 | pub inp: Sender<I>, | 9 | pub inp: Sender<I>, |
11 | pub out: Receiver<O>, | 10 | pub out: Receiver<O>, |
12 | } | 11 | } |
13 | 12 | ||
14 | impl<I, O> Worker<I, O> { | 13 | pub struct WorkerHandle { |
15 | pub fn spawn<F>(name: &'static str, buf: usize, f: F) -> (Self, ThreadWatcher) | 14 | name: &'static str, |
16 | where | 15 | thread: thread::JoinHandle<()>, |
17 | F: FnOnce(Receiver<I>, Sender<O>) + Send + 'static, | 16 | bomb: DropBomb, |
18 | I: Send + 'static, | 17 | } |
19 | O: Send + 'static, | ||
20 | { | ||
21 | let (worker, inp_r, out_s) = worker_chan(buf); | ||
22 | let watcher = ThreadWatcher::spawn(name, move || f(inp_r, out_s)); | ||
23 | (worker, watcher) | ||
24 | } | ||
25 | 18 | ||
19 | pub fn spawn<I, O, F>(name: &'static str, buf: usize, f: F) -> (Worker<I, O>, WorkerHandle) | ||
20 | where | ||
21 | F: FnOnce(Receiver<I>, Sender<O>) + Send + 'static, | ||
22 | I: Send + 'static, | ||
23 | O: Send + 'static, | ||
24 | { | ||
25 | let (worker, inp_r, out_s) = worker_chan(buf); | ||
26 | let watcher = WorkerHandle::spawn(name, move || f(inp_r, out_s)); | ||
27 | (worker, watcher) | ||
28 | } | ||
29 | |||
30 | impl<I, O> Worker<I, O> { | ||
31 | /// Stops the worker. Returns the message receiver to fetch results which | ||
32 | /// have become ready before the worker is stopped. | ||
26 | pub fn stop(self) -> Receiver<O> { | 33 | pub fn stop(self) -> Receiver<O> { |
27 | self.out | 34 | self.out |
28 | } | 35 | } |
@@ -32,30 +39,21 @@ impl<I, O> Worker<I, O> { | |||
32 | } | 39 | } |
33 | } | 40 | } |
34 | 41 | ||
35 | pub struct ThreadWatcher { | 42 | impl WorkerHandle { |
36 | name: &'static str, | 43 | fn spawn(name: &'static str, f: impl FnOnce() + Send + 'static) -> WorkerHandle { |
37 | thread: thread::JoinHandle<()>, | ||
38 | bomb: DropBomb, | ||
39 | } | ||
40 | |||
41 | impl ThreadWatcher { | ||
42 | fn spawn(name: &'static str, f: impl FnOnce() + Send + 'static) -> ThreadWatcher { | ||
43 | let thread = thread::spawn(f); | 44 | let thread = thread::spawn(f); |
44 | ThreadWatcher { | 45 | WorkerHandle { |
45 | name, | 46 | name, |
46 | thread, | 47 | thread, |
47 | bomb: DropBomb::new(format!("ThreadWatcher {} was not stopped", name)), | 48 | bomb: DropBomb::new(format!("WorkerHandle {} was not stopped", name)), |
48 | } | 49 | } |
49 | } | 50 | } |
50 | 51 | ||
51 | pub fn stop(mut self) -> Result<()> { | 52 | pub fn stop(mut self) -> thread::Result<()> { |
52 | log::info!("waiting for {} to finish ...", self.name); | 53 | log::info!("waiting for {} to finish ...", self.name); |
53 | let name = self.name; | 54 | let name = self.name; |
54 | self.bomb.defuse(); | 55 | self.bomb.defuse(); |
55 | let res = self | 56 | let res = self.thread.join(); |
56 | .thread | ||
57 | .join() | ||
58 | .map_err(|_| format_err!("ThreadWatcher {} died", name)); | ||
59 | match &res { | 57 | match &res { |
60 | Ok(()) => log::info!("... {} terminated with ok", name), | 58 | Ok(()) => log::info!("... {} terminated with ok", name), |
61 | Err(_) => log::error!("... {} terminated with err", name), | 59 | Err(_) => log::error!("... {} terminated with err", name), |