From b5021411a84822cb3f1e3aeffad9550dd15bdeb6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 16 Sep 2018 12:54:24 +0300 Subject: rename all things --- crates/ra_lsp_server/src/server_world.rs | 167 +++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 crates/ra_lsp_server/src/server_world.rs (limited to 'crates/ra_lsp_server/src/server_world.rs') 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 @@ +use std::{ + fs, + path::{PathBuf, Path}, + collections::HashMap, + sync::Arc, +}; + +use languageserver_types::Url; +use ra_analysis::{FileId, AnalysisHost, Analysis, CrateGraph, CrateId, LibraryData, FileResolver}; + +use { + Result, + path_map::{PathMap, Root}, + vfs::{FileEvent, FileEventKind}, + project_model::CargoWorkspace, +}; + +#[derive(Debug)] +pub struct ServerWorldState { + pub workspaces: Arc>, + pub analysis_host: AnalysisHost, + pub path_map: PathMap, + pub mem_map: HashMap>, +} + +#[derive(Clone)] +pub struct ServerWorld { + pub workspaces: Arc>, + pub analysis: Analysis, + pub path_map: PathMap, +} + +impl ServerWorldState { + pub fn new() -> ServerWorldState { + ServerWorldState { + workspaces: Arc::new(Vec::new()), + analysis_host: AnalysisHost::new(), + path_map: PathMap::new(), + mem_map: HashMap::new(), + } + } + pub fn apply_fs_changes(&mut self, events: Vec) { + { + let pm = &mut self.path_map; + let mm = &mut self.mem_map; + let changes = events.into_iter() + .map(|event| { + let text = match event.kind { + FileEventKind::Add(text) => Some(text), + }; + (event.path, text) + }) + .map(|(path, text)| { + (pm.get_or_insert(path, Root::Workspace), text) + }) + .filter_map(|(id, text)| { + if mm.contains_key(&id) { + mm.insert(id, text); + None + } else { + Some((id, text)) + } + }); + self.analysis_host.change_files(changes); + } + self.analysis_host.set_file_resolver(Arc::new(self.path_map.clone())); + } + pub fn events_to_files(&mut self, events: Vec) -> (Vec<(FileId, String)>, Arc) { + let files = { + let pm = &mut self.path_map; + events.into_iter() + .map(|event| { + let text = match event.kind { + FileEventKind::Add(text) => text, + }; + (event.path, text) + }) + .map(|(path, text)| (pm.get_or_insert(path, Root::Lib), text)) + .collect() + }; + let resolver = Arc::new(self.path_map.clone()); + (files, resolver) + } + pub fn add_lib(&mut self, data: LibraryData) { + self.analysis_host.add_library(data); + } + + pub fn add_mem_file(&mut self, path: PathBuf, text: String) -> FileId { + let file_id = self.path_map.get_or_insert(path, Root::Workspace); + self.analysis_host.set_file_resolver(Arc::new(self.path_map.clone())); + self.mem_map.insert(file_id, None); + if self.path_map.get_root(file_id) != Root::Lib { + self.analysis_host.change_file(file_id, Some(text)); + } + file_id + } + + pub fn change_mem_file(&mut self, path: &Path, text: String) -> Result<()> { + let file_id = self.path_map.get_id(path).ok_or_else(|| { + format_err!("change to unknown file: {}", path.display()) + })?; + if self.path_map.get_root(file_id) != Root::Lib { + self.analysis_host.change_file(file_id, Some(text)); + } + Ok(()) + } + + pub fn remove_mem_file(&mut self, path: &Path) -> Result { + let file_id = self.path_map.get_id(path).ok_or_else(|| { + format_err!("change to unknown file: {}", path.display()) + })?; + match self.mem_map.remove(&file_id) { + Some(_) => (), + None => bail!("unmatched close notification"), + }; + // Do this via file watcher ideally. + let text = fs::read_to_string(path).ok(); + if self.path_map.get_root(file_id) != Root::Lib { + self.analysis_host.change_file(file_id, text); + } + Ok(file_id) + } + pub fn set_workspaces(&mut self, ws: Vec) { + let mut crate_roots = HashMap::new(); + ws.iter() + .flat_map(|ws| { + ws.packages() + .flat_map(move |pkg| pkg.targets(ws)) + .map(move |tgt| tgt.root(ws)) + }) + .for_each(|root| { + if let Some(file_id) = self.path_map.get_id(root) { + let crate_id = CrateId(crate_roots.len() as u32); + crate_roots.insert(crate_id, file_id); + } + }); + let crate_graph = CrateGraph { crate_roots }; + self.workspaces = Arc::new(ws); + self.analysis_host.set_crate_graph(crate_graph); + } + pub fn snapshot(&self) -> ServerWorld { + ServerWorld { + workspaces: Arc::clone(&self.workspaces), + analysis: self.analysis_host.analysis(), + path_map: self.path_map.clone() + } + } +} + +impl ServerWorld { + pub fn analysis(&self) -> &Analysis { + &self.analysis + } + + pub fn uri_to_file_id(&self, uri: &Url) -> Result { + let path = uri.to_file_path() + .map_err(|()| format_err!("invalid uri: {}", uri))?; + self.path_map.get_id(&path).ok_or_else(|| format_err!("unknown file: {}", path.display())) + } + + pub fn file_id_to_uri(&self, id: FileId) -> Result { + let path = self.path_map.get_path(id); + let url = Url::from_file_path(path) + .map_err(|()| format_err!("can't convert path to url: {}", path.display()))?; + Ok(url) + } +} -- cgit v1.2.3