aboutsummaryrefslogtreecommitdiff
path: root/crates/server/src/server_world.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-17 17:54:08 +0100
committerAleksey Kladov <[email protected]>2018-08-17 17:54:08 +0100
commited7ae78c6fd9e508f6e959c6a164cf8481f6b377 (patch)
tree556e8d4daffefa64dcdc5db8e75299514a0e85e4 /crates/server/src/server_world.rs
parent41570f60bf268c97223a864b8aa11a339929f55a (diff)
ServerWorld
Diffstat (limited to 'crates/server/src/server_world.rs')
-rw-r--r--crates/server/src/server_world.rs117
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 @@
1use std::{
2 path::{PathBuf, Path},
3 collections::HashMap,
4};
5
6use languageserver_types::Url;
7use libanalysis::{FileId, WorldState, World};
8
9use {
10 Result,
11 path_map::PathMap,
12 vfs::{FileEvent, FileEventKind},
13};
14
15#[derive(Debug)]
16pub struct ServerWorldState {
17 pub analysis: WorldState,
18 pub path_map: PathMap,
19 pub mem_map: HashMap<FileId, Option<String>>,
20}
21
22#[derive(Clone)]
23pub struct ServerWorld {
24 pub analysis: World,
25 pub path_map: PathMap,
26}
27
28impl 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
100impl 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}