diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-10-25 16:04:48 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-10-25 16:04:48 +0100 |
commit | 5932bd0bb5fcd066a9d16abcd1597b7097978085 (patch) | |
tree | 7b6ea86855fe34c3d45d14262c8cf94e315566e8 /crates/ra_lsp_server | |
parent | 2cb2074c4b7219b32993abdcc7084637c0123d49 (diff) | |
parent | 363adf07b7763cfe7e13fac0ee148361d51834e4 (diff) |
Merge #162
162: Db everywhere r=matklad a=matklad
This PR continues our switch to salsa.
Now *all* state is handled by a single salsa database.
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r-- | crates/ra_lsp_server/src/main_loop/mod.rs | 20 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/path_map.rs | 26 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 73 |
3 files changed, 83 insertions, 36 deletions
diff --git a/crates/ra_lsp_server/src/main_loop/mod.rs b/crates/ra_lsp_server/src/main_loop/mod.rs index e681062ca..9ddc3fd0b 100644 --- a/crates/ra_lsp_server/src/main_loop/mod.rs +++ b/crates/ra_lsp_server/src/main_loop/mod.rs | |||
@@ -8,7 +8,7 @@ use gen_lsp_server::{ | |||
8 | handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, | 8 | handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, |
9 | }; | 9 | }; |
10 | use languageserver_types::NumberOrString; | 10 | use languageserver_types::NumberOrString; |
11 | use ra_analysis::{FileId, LibraryData}; | 11 | use ra_analysis::{Canceled, FileId, LibraryData}; |
12 | use rayon::{self, ThreadPool}; | 12 | use rayon::{self, ThreadPool}; |
13 | use rustc_hash::FxHashSet; | 13 | use rustc_hash::FxHashSet; |
14 | use serde::{de::DeserializeOwned, Serialize}; | 14 | use serde::{de::DeserializeOwned, Serialize}; |
@@ -376,7 +376,7 @@ impl<'a> PoolDispatcher<'a> { | |||
376 | Err(e) => { | 376 | Err(e) => { |
377 | match e.downcast::<LspError>() { | 377 | match e.downcast::<LspError>() { |
378 | Ok(lsp_error) => RawResponse::err(id, lsp_error.code, lsp_error.message), | 378 | Ok(lsp_error) => RawResponse::err(id, lsp_error.code, lsp_error.message), |
379 | Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string()) | 379 | Err(e) => RawResponse::err(id, ErrorCode::InternalError as i32, format!("{}\n{}", e, e.backtrace())) |
380 | } | 380 | } |
381 | } | 381 | } |
382 | }; | 382 | }; |
@@ -408,14 +408,22 @@ fn update_file_notifications_on_threadpool( | |||
408 | pool.spawn(move || { | 408 | pool.spawn(move || { |
409 | for file_id in subscriptions { | 409 | for file_id in subscriptions { |
410 | match handlers::publish_diagnostics(&world, file_id) { | 410 | match handlers::publish_diagnostics(&world, file_id) { |
411 | Err(e) => error!("failed to compute diagnostics: {:?}", e), | 411 | Err(e) => { |
412 | if !is_canceled(&e) { | ||
413 | error!("failed to compute diagnostics: {:?}", e); | ||
414 | } | ||
415 | }, | ||
412 | Ok(params) => { | 416 | Ok(params) => { |
413 | let not = RawNotification::new::<req::PublishDiagnostics>(¶ms); | 417 | let not = RawNotification::new::<req::PublishDiagnostics>(¶ms); |
414 | sender.send(Task::Notify(not)); | 418 | sender.send(Task::Notify(not)); |
415 | } | 419 | } |
416 | } | 420 | } |
417 | match handlers::publish_decorations(&world, file_id) { | 421 | match handlers::publish_decorations(&world, file_id) { |
418 | Err(e) => error!("failed to compute decorations: {:?}", e), | 422 | Err(e) => { |
423 | if !is_canceled(&e) { | ||
424 | error!("failed to compute decorations: {:?}", e); | ||
425 | } | ||
426 | }, | ||
419 | Ok(params) => { | 427 | Ok(params) => { |
420 | let not = RawNotification::new::<req::PublishDecorations>(¶ms); | 428 | let not = RawNotification::new::<req::PublishDecorations>(¶ms); |
421 | sender.send(Task::Notify(not)) | 429 | sender.send(Task::Notify(not)) |
@@ -432,3 +440,7 @@ fn feedback(intrnal_mode: bool, msg: &str, sender: &Sender<RawMessage>) { | |||
432 | let not = RawNotification::new::<req::InternalFeedback>(&msg.to_string()); | 440 | let not = RawNotification::new::<req::InternalFeedback>(&msg.to_string()); |
433 | sender.send(RawMessage::Notification(not)); | 441 | sender.send(RawMessage::Notification(not)); |
434 | } | 442 | } |
443 | |||
444 | fn is_canceled(e: &failure::Error) -> bool { | ||
445 | e.downcast_ref::<Canceled>().is_some() | ||
446 | } | ||
diff --git a/crates/ra_lsp_server/src/path_map.rs b/crates/ra_lsp_server/src/path_map.rs index d32829382..d5957d673 100644 --- a/crates/ra_lsp_server/src/path_map.rs +++ b/crates/ra_lsp_server/src/path_map.rs | |||
@@ -1,4 +1,7 @@ | |||
1 | use std::path::{Component, Path, PathBuf}; | 1 | use std::{ |
2 | fmt, | ||
3 | path::{Component, Path, PathBuf}, | ||
4 | }; | ||
2 | 5 | ||
3 | use im; | 6 | use im; |
4 | use ra_analysis::{FileId, FileResolver}; | 7 | use ra_analysis::{FileId, FileResolver}; |
@@ -10,7 +13,7 @@ pub enum Root { | |||
10 | Lib, | 13 | Lib, |
11 | } | 14 | } |
12 | 15 | ||
13 | #[derive(Debug, Default, Clone)] | 16 | #[derive(Default, Clone)] |
14 | pub struct PathMap { | 17 | pub struct PathMap { |
15 | next_id: u32, | 18 | next_id: u32, |
16 | path2id: im::HashMap<PathBuf, FileId>, | 19 | path2id: im::HashMap<PathBuf, FileId>, |
@@ -18,19 +21,28 @@ pub struct PathMap { | |||
18 | id2root: im::HashMap<FileId, Root>, | 21 | id2root: im::HashMap<FileId, Root>, |
19 | } | 22 | } |
20 | 23 | ||
24 | impl fmt::Debug for PathMap { | ||
25 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
26 | f.write_str("PathMap { ... }") | ||
27 | } | ||
28 | } | ||
29 | |||
21 | impl PathMap { | 30 | impl PathMap { |
22 | pub fn new() -> PathMap { | 31 | pub fn new() -> PathMap { |
23 | Default::default() | 32 | Default::default() |
24 | } | 33 | } |
25 | pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> FileId { | 34 | pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> (bool, FileId) { |
26 | self.path2id | 35 | let mut inserted = false; |
36 | let file_id = self.path2id | ||
27 | .get(path.as_path()) | 37 | .get(path.as_path()) |
28 | .map(|&id| id) | 38 | .map(|&id| id) |
29 | .unwrap_or_else(|| { | 39 | .unwrap_or_else(|| { |
40 | inserted = true; | ||
30 | let id = self.new_file_id(); | 41 | let id = self.new_file_id(); |
31 | self.insert(path, id, root); | 42 | self.insert(path, id, root); |
32 | id | 43 | id |
33 | }) | 44 | }); |
45 | (inserted, file_id) | ||
34 | } | 46 | } |
35 | pub fn get_id(&self, path: &Path) -> Option<FileId> { | 47 | pub fn get_id(&self, path: &Path) -> Option<FileId> { |
36 | self.path2id.get(path).map(|&id| id) | 48 | self.path2id.get(path).map(|&id| id) |
@@ -105,8 +117,8 @@ mod test { | |||
105 | #[test] | 117 | #[test] |
106 | fn test_resolve() { | 118 | fn test_resolve() { |
107 | let mut m = PathMap::new(); | 119 | let mut m = PathMap::new(); |
108 | let id1 = m.get_or_insert(PathBuf::from("/foo"), Root::Workspace); | 120 | let (_, id1) = m.get_or_insert(PathBuf::from("/foo"), Root::Workspace); |
109 | let id2 = m.get_or_insert(PathBuf::from("/foo/bar.rs"), Root::Workspace); | 121 | let (_, id2) = m.get_or_insert(PathBuf::from("/foo/bar.rs"), Root::Workspace); |
110 | assert_eq!(m.resolve(id1, &RelativePath::new("bar.rs")), Some(id2),) | 122 | assert_eq!(m.resolve(id1, &RelativePath::new("bar.rs")), Some(id2),) |
111 | } | 123 | } |
112 | } | 124 | } |
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 69b2a1cd1..25986e230 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -5,7 +5,7 @@ use std::{ | |||
5 | }; | 5 | }; |
6 | 6 | ||
7 | use languageserver_types::Url; | 7 | use languageserver_types::Url; |
8 | use ra_analysis::{Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, LibraryData}; | 8 | use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, FileId, FileResolver, LibraryData}; |
9 | use rustc_hash::FxHashMap; | 9 | use rustc_hash::FxHashMap; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
@@ -39,30 +39,40 @@ impl ServerWorldState { | |||
39 | } | 39 | } |
40 | } | 40 | } |
41 | pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) { | 41 | pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) { |
42 | let mut change = AnalysisChange::new(); | ||
43 | let mut inserted = false; | ||
42 | { | 44 | { |
43 | let pm = &mut self.path_map; | 45 | let pm = &mut self.path_map; |
44 | let mm = &mut self.mem_map; | 46 | let mm = &mut self.mem_map; |
45 | let changes = events | 47 | events |
46 | .into_iter() | 48 | .into_iter() |
47 | .map(|event| { | 49 | .map(|event| { |
48 | let text = match event.kind { | 50 | let text = match event.kind { |
49 | FileEventKind::Add(text) => Some(text), | 51 | FileEventKind::Add(text) => text, |
50 | }; | 52 | }; |
51 | (event.path, text) | 53 | (event.path, text) |
52 | }) | 54 | }) |
53 | .map(|(path, text)| (pm.get_or_insert(path, Root::Workspace), text)) | 55 | .map(|(path, text)| { |
54 | .filter_map(|(id, text)| { | 56 | let (ins, file_id) = pm.get_or_insert(path, Root::Workspace); |
55 | if mm.contains_key(&id) { | 57 | inserted |= ins; |
56 | mm.insert(id, text); | 58 | (file_id, text) |
59 | }) | ||
60 | .filter_map(|(file_id, text)| { | ||
61 | if mm.contains_key(&file_id) { | ||
62 | mm.insert(file_id, Some(text)); | ||
57 | None | 63 | None |
58 | } else { | 64 | } else { |
59 | Some((id, text)) | 65 | Some((file_id, text)) |
60 | } | 66 | } |
67 | }) | ||
68 | .for_each(|(file_id, text)| { | ||
69 | change.add_file(file_id, text) | ||
61 | }); | 70 | }); |
62 | self.analysis_host.change_files(changes); | ||
63 | } | 71 | } |
64 | self.analysis_host | 72 | if inserted { |
65 | .set_file_resolver(Arc::new(self.path_map.clone())); | 73 | change.set_file_resolver(Arc::new(self.path_map.clone())) |
74 | } | ||
75 | self.analysis_host.apply_change(change); | ||
66 | } | 76 | } |
67 | pub fn events_to_files( | 77 | pub fn events_to_files( |
68 | &mut self, | 78 | &mut self, |
@@ -76,24 +86,31 @@ impl ServerWorldState { | |||
76 | let FileEventKind::Add(text) = event.kind; | 86 | let FileEventKind::Add(text) = event.kind; |
77 | (event.path, text) | 87 | (event.path, text) |
78 | }) | 88 | }) |
79 | .map(|(path, text)| (pm.get_or_insert(path, Root::Lib), text)) | 89 | .map(|(path, text)| (pm.get_or_insert(path, Root::Lib).1, text)) |
80 | .collect() | 90 | .collect() |
81 | }; | 91 | }; |
82 | let resolver = Arc::new(self.path_map.clone()); | 92 | let resolver = Arc::new(self.path_map.clone()); |
83 | (files, resolver) | 93 | (files, resolver) |
84 | } | 94 | } |
85 | pub fn add_lib(&mut self, data: LibraryData) { | 95 | pub fn add_lib(&mut self, data: LibraryData) { |
86 | self.analysis_host.add_library(data); | 96 | let mut change = AnalysisChange::new(); |
97 | change.add_library(data); | ||
98 | self.analysis_host.apply_change(change); | ||
87 | } | 99 | } |
88 | 100 | ||
89 | pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId { | 101 | pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId { |
90 | let file_id = self.path_map.get_or_insert(path, Root::Workspace); | 102 | let (inserted, file_id) = self.path_map.get_or_insert(path, Root::Workspace); |
91 | self.analysis_host | ||
92 | .set_file_resolver(Arc::new(self.path_map.clone())); | ||
93 | self.mem_map.insert(file_id, None); | ||
94 | if self.path_map.get_root(file_id) != Root::Lib { | 103 | if self.path_map.get_root(file_id) != Root::Lib { |
95 | self.analysis_host.change_file(file_id, Some(text)); | 104 | let mut change = AnalysisChange::new(); |
105 | if inserted { | ||
106 | change.add_file(file_id, text); | ||
107 | change.set_file_resolver(Arc::new(self.path_map.clone())); | ||
108 | } else { | ||
109 | change.change_file(file_id, text); | ||
110 | } | ||
111 | self.analysis_host.apply_change(change); | ||
96 | } | 112 | } |
113 | self.mem_map.insert(file_id, None); | ||
97 | file_id | 114 | file_id |
98 | } | 115 | } |
99 | 116 | ||
@@ -103,7 +120,9 @@ impl ServerWorldState { | |||
103 | .get_id(path) | 120 | .get_id(path) |
104 | .ok_or_else(|| format_err!("change to unknown file: {}", path.display()))?; | 121 | .ok_or_else(|| format_err!("change to unknown file: {}", path.display()))?; |
105 | if self.path_map.get_root(file_id) != Root::Lib { | 122 | if self.path_map.get_root(file_id) != Root::Lib { |
106 | self.analysis_host.change_file(file_id, Some(text)); | 123 | let mut change = AnalysisChange::new(); |
124 | change.change_file(file_id, text); | ||
125 | self.analysis_host.apply_change(change); | ||
107 | } | 126 | } |
108 | Ok(()) | 127 | Ok(()) |
109 | } | 128 | } |
@@ -120,12 +139,16 @@ impl ServerWorldState { | |||
120 | // Do this via file watcher ideally. | 139 | // Do this via file watcher ideally. |
121 | let text = fs::read_to_string(path).ok(); | 140 | let text = fs::read_to_string(path).ok(); |
122 | if self.path_map.get_root(file_id) != Root::Lib { | 141 | if self.path_map.get_root(file_id) != Root::Lib { |
123 | self.analysis_host.change_file(file_id, text); | 142 | let mut change = AnalysisChange::new(); |
143 | if let Some(text) = text { | ||
144 | change.change_file(file_id, text); | ||
145 | } | ||
146 | self.analysis_host.apply_change(change); | ||
124 | } | 147 | } |
125 | Ok(file_id) | 148 | Ok(file_id) |
126 | } | 149 | } |
127 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { | 150 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { |
128 | let mut crate_roots = FxHashMap::default(); | 151 | let mut crate_graph = CrateGraph::new(); |
129 | ws.iter() | 152 | ws.iter() |
130 | .flat_map(|ws| { | 153 | .flat_map(|ws| { |
131 | ws.packages() | 154 | ws.packages() |
@@ -134,13 +157,13 @@ impl ServerWorldState { | |||
134 | }) | 157 | }) |
135 | .for_each(|root| { | 158 | .for_each(|root| { |
136 | if let Some(file_id) = self.path_map.get_id(root) { | 159 | if let Some(file_id) = self.path_map.get_id(root) { |
137 | let crate_id = CrateId(crate_roots.len() as u32); | 160 | crate_graph.add_crate_root(file_id); |
138 | crate_roots.insert(crate_id, file_id); | ||
139 | } | 161 | } |
140 | }); | 162 | }); |
141 | let crate_graph = CrateGraph { crate_roots }; | ||
142 | self.workspaces = Arc::new(ws); | 163 | self.workspaces = Arc::new(ws); |
143 | self.analysis_host.set_crate_graph(crate_graph); | 164 | let mut change = AnalysisChange::new(); |
165 | change.set_crate_graph(crate_graph); | ||
166 | self.analysis_host.apply_change(change); | ||
144 | } | 167 | } |
145 | pub fn snapshot(&self) -> ServerWorld { | 168 | pub fn snapshot(&self) -> ServerWorld { |
146 | ServerWorld { | 169 | ServerWorld { |