aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_lsp_server/src/server_world.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-09-16 10:54:24 +0100
committerAleksey Kladov <[email protected]>2018-09-16 11:07:39 +0100
commitb5021411a84822cb3f1e3aeffad9550dd15bdeb6 (patch)
tree9dca564f8e51b298dced01c4ce669c756dce3142 /crates/ra_lsp_server/src/server_world.rs
parentba0bfeee12e19da40b5eabc8d0408639af10e96f (diff)
rename all things
Diffstat (limited to 'crates/ra_lsp_server/src/server_world.rs')
-rw-r--r--crates/ra_lsp_server/src/server_world.rs167
1 files changed, 167 insertions, 0 deletions
diff --git a/crates/ra_lsp_server/src/server_world.rs b/crates/ra_lsp_server/src/server_world.rs
new file mode 100644
index 000000000..865f7c491
--- /dev/null
+++ b/crates/ra_lsp_server/src/server_world.rs
@@ -0,0 +1,167 @@
1use std::{
2 fs,
3 path::{PathBuf, Path},
4 collections::HashMap,
5 sync::Arc,
6};
7
8use languageserver_types::Url;
9use ra_analysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver};
10
11use {
12 Result,
13 path_map::{PathMap, Root},
14 vfs::{FileEvent, FileEventKind},
15 project_model::CargoWorkspace,
16};
17
18#[derive(Debug)]
19pub 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)]
27pub struct ServerWorld {
28 pub workspaces: Arc<Vec<CargoWorkspace>>,
29 pub analysis: Analysis,
30 pub path_map: PathMap,
31}
32
33impl 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
150impl 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}