diff options
Diffstat (limited to 'crates/ra_lsp_server')
-rw-r--r-- | crates/ra_lsp_server/src/path_map.rs | 13 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 70 |
2 files changed, 56 insertions, 27 deletions
diff --git a/crates/ra_lsp_server/src/path_map.rs b/crates/ra_lsp_server/src/path_map.rs index d32829382..b3d1dc3db 100644 --- a/crates/ra_lsp_server/src/path_map.rs +++ b/crates/ra_lsp_server/src/path_map.rs | |||
@@ -22,15 +22,18 @@ impl PathMap { | |||
22 | pub fn new() -> PathMap { | 22 | pub fn new() -> PathMap { |
23 | Default::default() | 23 | Default::default() |
24 | } | 24 | } |
25 | pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> FileId { | 25 | pub fn get_or_insert(&mut self, path: PathBuf, root: Root) -> (bool, FileId) { |
26 | self.path2id | 26 | let mut inserted = false; |
27 | let file_id = self.path2id | ||
27 | .get(path.as_path()) | 28 | .get(path.as_path()) |
28 | .map(|&id| id) | 29 | .map(|&id| id) |
29 | .unwrap_or_else(|| { | 30 | .unwrap_or_else(|| { |
31 | inserted = true; | ||
30 | let id = self.new_file_id(); | 32 | let id = self.new_file_id(); |
31 | self.insert(path, id, root); | 33 | self.insert(path, id, root); |
32 | id | 34 | id |
33 | }) | 35 | }); |
36 | (inserted, file_id) | ||
34 | } | 37 | } |
35 | pub fn get_id(&self, path: &Path) -> Option<FileId> { | 38 | pub fn get_id(&self, path: &Path) -> Option<FileId> { |
36 | self.path2id.get(path).map(|&id| id) | 39 | self.path2id.get(path).map(|&id| id) |
@@ -105,8 +108,8 @@ mod test { | |||
105 | #[test] | 108 | #[test] |
106 | fn test_resolve() { | 109 | fn test_resolve() { |
107 | let mut m = PathMap::new(); | 110 | let mut m = PathMap::new(); |
108 | let id1 = m.get_or_insert(PathBuf::from("/foo"), Root::Workspace); | 111 | 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); | 112 | 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),) | 113 | assert_eq!(m.resolve(id1, &RelativePath::new("bar.rs")), Some(id2),) |
111 | } | 114 | } |
112 | } | 115 | } |
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs index 69b2a1cd1..555de66ff 100644 --- a/crates/ra_lsp_server/src/server_world.rs +++ b/crates/ra_lsp_server/src/server_world.rs | |||
@@ -2,10 +2,11 @@ use std::{ | |||
2 | fs, | 2 | fs, |
3 | path::{Path, PathBuf}, | 3 | path::{Path, PathBuf}, |
4 | sync::Arc, | 4 | sync::Arc, |
5 | collections::BTreeMap, | ||
5 | }; | 6 | }; |
6 | 7 | ||
7 | use languageserver_types::Url; | 8 | use languageserver_types::Url; |
8 | use ra_analysis::{Analysis, AnalysisHost, CrateGraph, CrateId, FileId, FileResolver, LibraryData}; | 9 | use ra_analysis::{Analysis, AnalysisHost, AnalysisChange, CrateGraph, CrateId, FileId, FileResolver, LibraryData}; |
9 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
10 | 11 | ||
11 | use crate::{ | 12 | use crate::{ |
@@ -39,30 +40,40 @@ impl ServerWorldState { | |||
39 | } | 40 | } |
40 | } | 41 | } |
41 | pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) { | 42 | pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) { |
43 | let mut change = AnalysisChange::new(); | ||
44 | let mut inserted = false; | ||
42 | { | 45 | { |
43 | let pm = &mut self.path_map; | 46 | let pm = &mut self.path_map; |
44 | let mm = &mut self.mem_map; | 47 | let mm = &mut self.mem_map; |
45 | let changes = events | 48 | events |
46 | .into_iter() | 49 | .into_iter() |
47 | .map(|event| { | 50 | .map(|event| { |
48 | let text = match event.kind { | 51 | let text = match event.kind { |
49 | FileEventKind::Add(text) => Some(text), | 52 | FileEventKind::Add(text) => text, |
50 | }; | 53 | }; |
51 | (event.path, text) | 54 | (event.path, text) |
52 | }) | 55 | }) |
53 | .map(|(path, text)| (pm.get_or_insert(path, Root::Workspace), text)) | 56 | .map(|(path, text)| { |
54 | .filter_map(|(id, text)| { | 57 | let (ins, file_id) = pm.get_or_insert(path, Root::Workspace); |
55 | if mm.contains_key(&id) { | 58 | inserted |= ins; |
56 | mm.insert(id, text); | 59 | (file_id, text) |
60 | }) | ||
61 | .filter_map(|(file_id, text)| { | ||
62 | if mm.contains_key(&file_id) { | ||
63 | mm.insert(file_id, Some(text)); | ||
57 | None | 64 | None |
58 | } else { | 65 | } else { |
59 | Some((id, text)) | 66 | Some((file_id, text)) |
60 | } | 67 | } |
68 | }) | ||
69 | .for_each(|(file_id, text)| { | ||
70 | change.add_file(file_id, text) | ||
61 | }); | 71 | }); |
62 | self.analysis_host.change_files(changes); | ||
63 | } | 72 | } |
64 | self.analysis_host | 73 | if inserted { |
65 | .set_file_resolver(Arc::new(self.path_map.clone())); | 74 | change.set_file_resolver(Arc::new(self.path_map.clone())) |
75 | } | ||
76 | self.analysis_host.apply_change(change); | ||
66 | } | 77 | } |
67 | pub fn events_to_files( | 78 | pub fn events_to_files( |
68 | &mut self, | 79 | &mut self, |
@@ -76,24 +87,31 @@ impl ServerWorldState { | |||
76 | let FileEventKind::Add(text) = event.kind; | 87 | let FileEventKind::Add(text) = event.kind; |
77 | (event.path, text) | 88 | (event.path, text) |
78 | }) | 89 | }) |
79 | .map(|(path, text)| (pm.get_or_insert(path, Root::Lib), text)) | 90 | .map(|(path, text)| (pm.get_or_insert(path, Root::Lib).1, text)) |
80 | .collect() | 91 | .collect() |
81 | }; | 92 | }; |
82 | let resolver = Arc::new(self.path_map.clone()); | 93 | let resolver = Arc::new(self.path_map.clone()); |
83 | (files, resolver) | 94 | (files, resolver) |
84 | } | 95 | } |
85 | pub fn add_lib(&mut self, data: LibraryData) { | 96 | pub fn add_lib(&mut self, data: LibraryData) { |
86 | self.analysis_host.add_library(data); | 97 | let mut change = AnalysisChange::new(); |
98 | change.add_library(data); | ||
99 | self.analysis_host.apply_change(change); | ||
87 | } | 100 | } |
88 | 101 | ||
89 | pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId { | 102 | 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); | 103 | 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 { | 104 | if self.path_map.get_root(file_id) != Root::Lib { |
95 | self.analysis_host.change_file(file_id, Some(text)); | 105 | let mut change = AnalysisChange::new(); |
106 | if inserted { | ||
107 | change.add_file(file_id, text); | ||
108 | change.set_file_resolver(Arc::new(self.path_map.clone())); | ||
109 | } else { | ||
110 | change.change_file(file_id, text); | ||
111 | } | ||
112 | self.analysis_host.apply_change(change); | ||
96 | } | 113 | } |
114 | self.mem_map.insert(file_id, None); | ||
97 | file_id | 115 | file_id |
98 | } | 116 | } |
99 | 117 | ||
@@ -103,7 +121,9 @@ impl ServerWorldState { | |||
103 | .get_id(path) | 121 | .get_id(path) |
104 | .ok_or_else(|| format_err!("change to unknown file: {}", path.display()))?; | 122 | .ok_or_else(|| format_err!("change to unknown file: {}", path.display()))?; |
105 | if self.path_map.get_root(file_id) != Root::Lib { | 123 | if self.path_map.get_root(file_id) != Root::Lib { |
106 | self.analysis_host.change_file(file_id, Some(text)); | 124 | let mut change = AnalysisChange::new(); |
125 | change.change_file(file_id, text); | ||
126 | self.analysis_host.apply_change(change); | ||
107 | } | 127 | } |
108 | Ok(()) | 128 | Ok(()) |
109 | } | 129 | } |
@@ -120,12 +140,16 @@ impl ServerWorldState { | |||
120 | // Do this via file watcher ideally. | 140 | // Do this via file watcher ideally. |
121 | let text = fs::read_to_string(path).ok(); | 141 | let text = fs::read_to_string(path).ok(); |
122 | if self.path_map.get_root(file_id) != Root::Lib { | 142 | if self.path_map.get_root(file_id) != Root::Lib { |
123 | self.analysis_host.change_file(file_id, text); | 143 | let mut change = AnalysisChange::new(); |
144 | if let Some(text) = text { | ||
145 | change.change_file(file_id, text); | ||
146 | } | ||
147 | self.analysis_host.apply_change(change); | ||
124 | } | 148 | } |
125 | Ok(file_id) | 149 | Ok(file_id) |
126 | } | 150 | } |
127 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { | 151 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { |
128 | let mut crate_roots = FxHashMap::default(); | 152 | let mut crate_roots = BTreeMap::default(); |
129 | ws.iter() | 153 | ws.iter() |
130 | .flat_map(|ws| { | 154 | .flat_map(|ws| { |
131 | ws.packages() | 155 | ws.packages() |
@@ -140,7 +164,9 @@ impl ServerWorldState { | |||
140 | }); | 164 | }); |
141 | let crate_graph = CrateGraph { crate_roots }; | 165 | let crate_graph = CrateGraph { crate_roots }; |
142 | self.workspaces = Arc::new(ws); | 166 | self.workspaces = Arc::new(ws); |
143 | self.analysis_host.set_crate_graph(crate_graph); | 167 | let mut change = AnalysisChange::new(); |
168 | change.set_crate_graph(crate_graph); | ||
169 | self.analysis_host.apply_change(change); | ||
144 | } | 170 | } |
145 | pub fn snapshot(&self) -> ServerWorld { | 171 | pub fn snapshot(&self) -> ServerWorld { |
146 | ServerWorld { | 172 | ServerWorld { |