diff options
Diffstat (limited to 'crates/server/src/server_world.rs')
-rw-r--r-- | crates/server/src/server_world.rs | 167 |
1 files changed, 0 insertions, 167 deletions
diff --git a/crates/server/src/server_world.rs b/crates/server/src/server_world.rs deleted file mode 100644 index 6853efc00..000000000 --- a/crates/server/src/server_world.rs +++ /dev/null | |||
@@ -1,167 +0,0 @@ | |||
1 | use std::{ | ||
2 | fs, | ||
3 | path::{PathBuf, Path}, | ||
4 | collections::HashMap, | ||
5 | sync::Arc, | ||
6 | }; | ||
7 | |||
8 | use languageserver_types::Url; | ||
9 | use libanalysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver}; | ||
10 | |||
11 | use { | ||
12 | Result, | ||
13 | path_map::{PathMap, Root}, | ||
14 | vfs::{FileEvent, FileEventKind}, | ||
15 | project_model::CargoWorkspace, | ||
16 | }; | ||
17 | |||
18 | #[derive(Debug)] | ||
19 | pub struct ServerWorldState { | ||
20 | pub workspaces: Arc<Vec<CargoWorkspace>>, | ||
21 | pub analysis_host: AnalysisHost, | ||
22 | pub path_map: PathMap, | ||
23 | pub mem_map: HashMap<FileId, Option<String>>, | ||
24 | } | ||
25 | |||
26 | #[derive(Clone)] | ||
27 | pub struct ServerWorld { | ||
28 | pub workspaces: Arc<Vec<CargoWorkspace>>, | ||
29 | pub analysis: Analysis, | ||
30 | pub path_map: PathMap, | ||
31 | } | ||
32 | |||
33 | impl ServerWorldState { | ||
34 | pub fn new() -> ServerWorldState { | ||
35 | ServerWorldState { | ||
36 | workspaces: Arc::new(Vec::new()), | ||
37 | analysis_host: AnalysisHost::new(), | ||
38 | path_map: PathMap::new(), | ||
39 | mem_map: HashMap::new(), | ||
40 | } | ||
41 | } | ||
42 | pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) { | ||
43 | { | ||
44 | let pm = &mut self.path_map; | ||
45 | let mm = &mut self.mem_map; | ||
46 | let changes = events.into_iter() | ||
47 | .map(|event| { | ||
48 | let text = match event.kind { | ||
49 | FileEventKind::Add(text) => Some(text), | ||
50 | }; | ||
51 | (event.path, text) | ||
52 | }) | ||
53 | .map(|(path, text)| { | ||
54 | (pm.get_or_insert(path, Root::Workspace), text) | ||
55 | }) | ||
56 | .filter_map(|(id, text)| { | ||
57 | if mm.contains_key(&id) { | ||
58 | mm.insert(id, text); | ||
59 | None | ||
60 | } else { | ||
61 | Some((id, text)) | ||
62 | } | ||
63 | }); | ||
64 | self.analysis_host.change_files(changes); | ||
65 | } | ||
66 | self.analysis_host.set_file_resolver(Arc::new(self.path_map.clone())); | ||
67 | } | ||
68 | pub fn events_to_files(&mut self, events: Vec<FileEvent>) -> (Vec<(FileId, String)>, Arc<FileResolver>) { | ||
69 | let files = { | ||
70 | let pm = &mut self.path_map; | ||
71 | events.into_iter() | ||
72 | .map(|event| { | ||
73 | let text = match event.kind { | ||
74 | FileEventKind::Add(text) => text, | ||
75 | }; | ||
76 | (event.path, text) | ||
77 | }) | ||
78 | .map(|(path, text)| (pm.get_or_insert(path, Root::Lib), text)) | ||
79 | .collect() | ||
80 | }; | ||
81 | let resolver = Arc::new(self.path_map.clone()); | ||
82 | (files, resolver) | ||
83 | } | ||
84 | pub fn add_lib(&mut self, data: LibraryData) { | ||
85 | self.analysis_host.add_library(data); | ||
86 | } | ||
87 | |||
88 | pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId { | ||
89 | let file_id = self.path_map.get_or_insert(path, Root::Workspace); | ||
90 | self.analysis_host.set_file_resolver(Arc::new(self.path_map.clone())); | ||
91 | self.mem_map.insert(file_id, None); | ||
92 | if self.path_map.get_root(file_id) != Root::Lib { | ||
93 | self.analysis_host.change_file(file_id, Some(text)); | ||
94 | } | ||
95 | file_id | ||
96 | } | ||
97 | |||
98 | pub fn change_mem_file(&mut self, path: &Path, text: String) -> Result<()> { | ||
99 | let file_id = self.path_map.get_id(path).ok_or_else(|| { | ||
100 | format_err!("change to unknown file: {}", path.display()) | ||
101 | })?; | ||
102 | if self.path_map.get_root(file_id) != Root::Lib { | ||
103 | self.analysis_host.change_file(file_id, Some(text)); | ||
104 | } | ||
105 | Ok(()) | ||
106 | } | ||
107 | |||
108 | pub fn remove_mem_file(&mut self, path: &Path) -> Result<FileId> { | ||
109 | let file_id = self.path_map.get_id(path).ok_or_else(|| { | ||
110 | format_err!("change to unknown file: {}", path.display()) | ||
111 | })?; | ||
112 | match self.mem_map.remove(&file_id) { | ||
113 | Some(_) => (), | ||
114 | None => bail!("unmatched close notification"), | ||
115 | }; | ||
116 | // Do this via file watcher ideally. | ||
117 | let text = fs::read_to_string(path).ok(); | ||
118 | if self.path_map.get_root(file_id) != Root::Lib { | ||
119 | self.analysis_host.change_file(file_id, text); | ||
120 | } | ||
121 | Ok(file_id) | ||
122 | } | ||
123 | pub fn set_workspaces(&mut self, ws: Vec<CargoWorkspace>) { | ||
124 | let mut crate_roots = HashMap::new(); | ||
125 | ws.iter() | ||
126 | .flat_map(|ws| { | ||
127 | ws.packages() | ||
128 | .flat_map(move |pkg| pkg.targets(ws)) | ||
129 | .map(move |tgt| tgt.root(ws)) | ||
130 | }) | ||
131 | .for_each(|root| { | ||
132 | if let Some(file_id) = self.path_map.get_id(root) { | ||
133 | let crate_id = CrateId(crate_roots.len() as u32); | ||
134 | crate_roots.insert(crate_id, file_id); | ||
135 | } | ||
136 | }); | ||
137 | let crate_graph = CrateGraph { crate_roots }; | ||
138 | self.workspaces = Arc::new(ws); | ||
139 | self.analysis_host.set_crate_graph(crate_graph); | ||
140 | } | ||
141 | pub fn snapshot(&self) -> ServerWorld { | ||
142 | ServerWorld { | ||
143 | workspaces: Arc::clone(&self.workspaces), | ||
144 | analysis: self.analysis_host.analysis(), | ||
145 | path_map: self.path_map.clone() | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | |||
150 | impl ServerWorld { | ||
151 | pub fn analysis(&self) -> &Analysis { | ||
152 | &self.analysis | ||
153 | } | ||
154 | |||
155 | pub fn uri_to_file_id(&self, uri: &Url) -> Result<FileId> { | ||
156 | let path = uri.to_file_path() | ||
157 | .map_err(|()| format_err!("invalid uri: {}", uri))?; | ||
158 | self.path_map.get_id(&path).ok_or_else(|| format_err!("unknown file: {}", path.display())) | ||
159 | } | ||
160 | |||
161 | pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> { | ||
162 | let path = self.path_map.get_path(id); | ||
163 | let url = Url::from_file_path(path) | ||
164 | .map_err(|()| format_err!("can't convert path to url: {}", path.display()))?; | ||
165 | Ok(url) | ||
166 | } | ||
167 | } | ||