diff options
Diffstat (limited to 'crates/ra_lsp_server/src/server_world.rs')
-rw-r--r-- | crates/ra_lsp_server/src/server_world.rs | 73 |
1 files changed, 48 insertions, 25 deletions
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 { |