aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-10-25 16:04:48 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-10-25 16:04:48 +0100
commit5932bd0bb5fcd066a9d16abcd1597b7097978085 (patch)
tree7b6ea86855fe34c3d45d14262c8cf94e315566e8 /crates/ra_lsp_server/src
parent2cb2074c4b7219b32993abdcc7084637c0123d49 (diff)
parent363adf07b7763cfe7e13fac0ee148361d51834e4 (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/src')
-rw-r--r--crates/ra_lsp_server/src/main_loop/mod.rs20
-rw-r--r--crates/ra_lsp_server/src/path_map.rs26
-rw-r--r--crates/ra_lsp_server/src/server_world.rs73
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};
10use languageserver_types::NumberOrString; 10use languageserver_types::NumberOrString;
11use ra_analysis::{FileId, LibraryData}; 11use ra_analysis::{Canceled, FileId, LibraryData};
12use rayon::{self, ThreadPool}; 12use rayon::{self, ThreadPool};
13use rustc_hash::FxHashSet; 13use rustc_hash::FxHashSet;
14use serde::{de::DeserializeOwned, Serialize}; 14use 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>(&params); 417 let not = RawNotification::new::<req::PublishDiagnostics>(&params);
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>(&params); 428 let not = RawNotification::new::<req::PublishDecorations>(&params);
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
444fn 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 @@
1use std::path::{Component, Path, PathBuf}; 1use std::{
2 fmt,
3 path::{Component, Path, PathBuf},
4};
2 5
3use im; 6use im;
4use ra_analysis::{FileId, FileResolver}; 7use 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)]
14pub struct PathMap { 17pub 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
24impl fmt::Debug for PathMap {
25 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26 f.write_str("PathMap { ... }")
27 }
28}
29
21impl PathMap { 30impl 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
7use languageserver_types::Url; 7use languageserver_types::Url;
8use ra_analysis::{Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, LibraryData}; 8use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, FileId, FileResolver, LibraryData};
9use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
10 10
11use crate::{ 11use 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 {