From 7c67612b8a894187fa3b64725531a5459f9211bf Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Aug 2018 22:33:29 +0300 Subject: organizize --- crates/libanalysis/Cargo.toml | 12 ++++ crates/libanalysis/src/lib.rs | 132 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 crates/libanalysis/Cargo.toml create mode 100644 crates/libanalysis/src/lib.rs (limited to 'crates/libanalysis') diff --git a/crates/libanalysis/Cargo.toml b/crates/libanalysis/Cargo.toml new file mode 100644 index 000000000..c773f4211 --- /dev/null +++ b/crates/libanalysis/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "libanalysis" +version = "0.1.0" +authors = ["Aleksey Kladov "] + +[dependencies] +log = "0.4.2" +failure = "0.1.2" +parking_lot = "0.6.3" +once_cell = "0.1.4" +libsyntax2 = { path = "../libsyntax2" } +libeditor = { path = "../libeditor" } diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs new file mode 100644 index 000000000..6a946a0b0 --- /dev/null +++ b/crates/libanalysis/src/lib.rs @@ -0,0 +1,132 @@ +extern crate failure; +extern crate parking_lot; +#[macro_use] +extern crate log; +extern crate once_cell; +extern crate libsyntax2; +extern crate libeditor; + +use once_cell::sync::OnceCell; + +use std::{ + fs, + sync::Arc, + collections::hash_map::HashMap, + path::{PathBuf, Path}, +}; +use parking_lot::RwLock; +use libsyntax2::ast; +use libeditor::LineIndex; + +pub type Result = ::std::result::Result; + +pub struct WorldState { + data: Arc +} + +pub struct World { + data: Arc, +} + +impl WorldState { + pub fn new() -> WorldState { + WorldState { + data: Arc::new(WorldData::default()) + } + } + + pub fn snapshot(&self) -> World { + World { data: self.data.clone() } + } + + pub fn change_overlay(&mut self, path: PathBuf, text: Option) { + let data = self.data_mut(); + data.file_map.get_mut().remove(&path); + if let Some(text) = text { + data.mem_map.insert(path, Arc::new(text)); + } else { + data.mem_map.remove(&path); + } + } + + fn data_mut(&mut self) -> &mut WorldData { + if Arc::get_mut(&mut self.data).is_none() { + let file_map = self.data.file_map.read().clone(); + self.data = Arc::new(WorldData { + mem_map: self.data.mem_map.clone(), + file_map: RwLock::new(file_map), + }); + } + Arc::get_mut(&mut self.data).unwrap() + } +} + + +impl World { + pub fn file_syntax(&self, path: &Path) -> Result { + let data = self.file_data(path)?; + let syntax = data.syntax + .get_or_init(|| { + trace!("parsing: {}", path.display()); + ast::File::parse(self.file_text(path, &data)) + }).clone(); + Ok(syntax) + } + + pub fn file_line_index(&self, path: &Path) -> Result { + let data = self.file_data(path)?; + let index = data.lines + .get_or_init(|| { + trace!("calc line index: {}", path.display()); + LineIndex::new(self.file_text(path, &data)) + }); + Ok(index.clone()) + } + + fn file_text<'a>(&'a self, path: &Path, file_data: &'a FileData) -> &'a str { + match file_data.text.as_ref() { + Some(text) => text.as_str(), + None => self.data.mem_map[path].as_str() + } + } + + fn file_data(&self, path: &Path) -> Result> { + { + let guard = self.data.file_map.read(); + if let Some(data) = guard.get(path) { + return Ok(data.clone()); + } + } + + let text = if self.data.mem_map.contains_key(path) { + None + } else { + trace!("loading file from disk: {}", path.display()); + Some(fs::read_to_string(path)?) + }; + let res = { + let mut guard = self.data.file_map.write(); + guard.entry(path.to_owned()) + .or_insert_with(|| Arc::new(FileData { + text, + syntax: OnceCell::new(), + lines: OnceCell::new(), + })) + .clone() + }; + Ok(res) + } +} + + +#[derive(Default)] +struct WorldData { + mem_map: HashMap>, + file_map: RwLock>>, +} + +struct FileData { + text: Option, + syntax: OnceCell, + lines: OnceCell, +} -- cgit v1.2.3