diff options
author | Aleksey Kladov <[email protected]> | 2018-08-17 17:54:08 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2018-08-17 17:54:08 +0100 |
commit | ed7ae78c6fd9e508f6e959c6a164cf8481f6b377 (patch) | |
tree | 556e8d4daffefa64dcdc5db8e75299514a0e85e4 /crates/server/src/server_world.rs | |
parent | 41570f60bf268c97223a864b8aa11a339929f55a (diff) |
ServerWorld
Diffstat (limited to 'crates/server/src/server_world.rs')
-rw-r--r-- | crates/server/src/server_world.rs | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/crates/server/src/server_world.rs b/crates/server/src/server_world.rs new file mode 100644 index 000000000..c0d2efb86 --- /dev/null +++ b/crates/server/src/server_world.rs | |||
@@ -0,0 +1,117 @@ | |||
1 | use std::{ | ||
2 | path::{PathBuf, Path}, | ||
3 | collections::HashMap, | ||
4 | }; | ||
5 | |||
6 | use languageserver_types::Url; | ||
7 | use libanalysis::{FileId, WorldState, World}; | ||
8 | |||
9 | use { | ||
10 | Result, | ||
11 | path_map::PathMap, | ||
12 | vfs::{FileEvent, FileEventKind}, | ||
13 | }; | ||
14 | |||
15 | #[derive(Debug)] | ||
16 | pub struct ServerWorldState { | ||
17 | pub analysis: WorldState, | ||
18 | pub path_map: PathMap, | ||
19 | pub mem_map: HashMap<FileId, Option<String>>, | ||
20 | } | ||
21 | |||
22 | #[derive(Clone)] | ||
23 | pub struct ServerWorld { | ||
24 | pub analysis: World, | ||
25 | pub path_map: PathMap, | ||
26 | } | ||
27 | |||
28 | impl ServerWorldState { | ||
29 | pub fn new() -> ServerWorldState { | ||
30 | ServerWorldState { | ||
31 | analysis: WorldState::new(), | ||
32 | path_map: PathMap::new(), | ||
33 | mem_map: HashMap::new(), | ||
34 | } | ||
35 | } | ||
36 | |||
37 | pub fn apply_fs_changes(&mut self, events: Vec<FileEvent>) { | ||
38 | let pm = &mut self.path_map; | ||
39 | let mm = &mut self.mem_map; | ||
40 | let changes = events.into_iter() | ||
41 | .map(|event| { | ||
42 | let text = match event.kind { | ||
43 | FileEventKind::Add(text) => Some(text), | ||
44 | FileEventKind::Remove => None, | ||
45 | }; | ||
46 | (event.path, text) | ||
47 | }) | ||
48 | .map(|(path, text)| { | ||
49 | (pm.get_or_insert(path), text) | ||
50 | }) | ||
51 | .filter_map(|(id, text)| { | ||
52 | if mm.contains_key(&id) { | ||
53 | mm.insert(id, text); | ||
54 | None | ||
55 | } else { | ||
56 | Some((id, text)) | ||
57 | } | ||
58 | }); | ||
59 | |||
60 | self.analysis.change_files(changes); | ||
61 | } | ||
62 | |||
63 | pub fn add_mem_file(&mut self, path: PathBuf, text: String) { | ||
64 | let file_id = self.path_map.get_or_insert(path); | ||
65 | self.mem_map.insert(file_id, None); | ||
66 | self.analysis.change_file(file_id, Some(text)); | ||
67 | } | ||
68 | |||
69 | pub fn change_mem_file(&mut self, path: &Path, text: String) -> Result<()> { | ||
70 | let file_id = self.path_map.get_id(path).ok_or_else(|| { | ||
71 | format_err!("change to unknown file: {}", path.display()) | ||
72 | })?; | ||
73 | self.analysis.change_file(file_id, Some(text)); | ||
74 | Ok(()) | ||
75 | } | ||
76 | |||
77 | pub fn remove_mem_file(&mut self, path: &Path) -> Result<()> { | ||
78 | let file_id = self.path_map.get_id(path).ok_or_else(|| { | ||
79 | format_err!("change to unknown file: {}", path.display()) | ||
80 | })?; | ||
81 | let text = match self.mem_map.remove(&file_id) { | ||
82 | Some(text) => text, | ||
83 | None => bail!("unmatched close notification"), | ||
84 | }; | ||
85 | self.analysis.change_file(file_id, text); | ||
86 | Ok(()) | ||
87 | } | ||
88 | |||
89 | pub fn snapshot(&self) -> ServerWorld { | ||
90 | let pm = self.path_map.clone(); | ||
91 | ServerWorld { | ||
92 | analysis: self.analysis.snapshot(move |id, path| { | ||
93 | pm.resolve(id, path) | ||
94 | }), | ||
95 | path_map: self.path_map.clone() | ||
96 | } | ||
97 | } | ||
98 | } | ||
99 | |||
100 | impl ServerWorld { | ||
101 | pub fn analysis(&self) -> &World { | ||
102 | &self.analysis | ||
103 | } | ||
104 | |||
105 | pub fn uri_to_file_id(&self, uri: &Url) -> Result<FileId> { | ||
106 | let path = uri.to_file_path() | ||
107 | .map_err(|()| format_err!("invalid uri: {}", uri))?; | ||
108 | self.path_map.get_id(&path).ok_or_else(|| format_err!("unknown file: {}", path.display())) | ||
109 | } | ||
110 | |||
111 | pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> { | ||
112 | let path = self.path_map.get_path(id); | ||
113 | let url = Url::from_file_path(path) | ||
114 | .map_err(|()| format_err!("can't convert path to url: {}", path.display()))?; | ||
115 | Ok(url) | ||
116 | } | ||
117 | } | ||