aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis/src/lib.rs')
-rw-r--r--crates/libanalysis/src/lib.rs78
1 files changed, 32 insertions, 46 deletions
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index 74f043a9b..e4df3de2e 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -1,3 +1,4 @@
1#[macro_use]
1extern crate failure; 2extern crate failure;
2extern crate parking_lot; 3extern crate parking_lot;
3#[macro_use] 4#[macro_use]
@@ -9,12 +10,10 @@ extern crate libeditor;
9use once_cell::sync::OnceCell; 10use once_cell::sync::OnceCell;
10 11
11use std::{ 12use std::{
12 fs,
13 sync::Arc, 13 sync::Arc,
14 collections::hash_map::HashMap, 14 collections::hash_map::HashMap,
15 path::{PathBuf, Path}, 15 path::{PathBuf, Path},
16}; 16};
17use parking_lot::RwLock;
18use libsyntax2::ast; 17use libsyntax2::ast;
19use libeditor::LineIndex; 18use libeditor::LineIndex;
20 19
@@ -40,22 +39,27 @@ impl WorldState {
40 World { data: self.data.clone() } 39 World { data: self.data.clone() }
41 } 40 }
42 41
43 pub fn change_overlay(&mut self, path: PathBuf, text: Option<String>) { 42 pub fn change_file(&mut self, path: PathBuf, text: Option<String>) {
43 self.change_files(::std::iter::once((path, text)));
44 }
45
46 pub fn change_files(&mut self, changes: impl Iterator<Item=(PathBuf, Option<String>)>) {
44 let data = self.data_mut(); 47 let data = self.data_mut();
45 data.file_map.get_mut().remove(&path); 48 for (path, text) in changes {
46 if let Some(text) = text { 49 data.file_map.remove(&path);
47 data.mem_map.insert(path, Arc::new(text)); 50 if let Some(text) = text {
48 } else { 51 let file_data = FileData::new(text);
49 data.mem_map.remove(&path); 52 data.file_map.insert(path, Arc::new(file_data));
53 } else {
54 data.file_map.remove(&path);
55 }
50 } 56 }
51 } 57 }
52 58
53 fn data_mut(&mut self) -> &mut WorldData { 59 fn data_mut(&mut self) -> &mut WorldData {
54 if Arc::get_mut(&mut self.data).is_none() { 60 if Arc::get_mut(&mut self.data).is_none() {
55 let file_map = self.data.file_map.read().clone();
56 self.data = Arc::new(WorldData { 61 self.data = Arc::new(WorldData {
57 mem_map: self.data.mem_map.clone(), 62 file_map: self.data.file_map.clone(),
58 file_map: RwLock::new(file_map),
59 }); 63 });
60 } 64 }
61 Arc::get_mut(&mut self.data).unwrap() 65 Arc::get_mut(&mut self.data).unwrap()
@@ -69,7 +73,7 @@ impl World {
69 let syntax = data.syntax 73 let syntax = data.syntax
70 .get_or_init(|| { 74 .get_or_init(|| {
71 trace!("parsing: {}", path.display()); 75 trace!("parsing: {}", path.display());
72 ast::File::parse(self.file_text(path, &data)) 76 ast::File::parse(&data.text)
73 }).clone(); 77 }).clone();
74 Ok(syntax) 78 Ok(syntax)
75 } 79 }
@@ -79,56 +83,38 @@ impl World {
79 let index = data.lines 83 let index = data.lines
80 .get_or_init(|| { 84 .get_or_init(|| {
81 trace!("calc line index: {}", path.display()); 85 trace!("calc line index: {}", path.display());
82 LineIndex::new(self.file_text(path, &data)) 86 LineIndex::new(&data.text)
83 }); 87 });
84 Ok(index.clone()) 88 Ok(index.clone())
85 } 89 }
86 90
87 fn file_text<'a>(&'a self, path: &Path, file_data: &'a FileData) -> &'a str {
88 match file_data.text.as_ref() {
89 Some(text) => text.as_str(),
90 None => self.data.mem_map[path].as_str()
91 }
92 }
93
94 fn file_data(&self, path: &Path) -> Result<Arc<FileData>> { 91 fn file_data(&self, path: &Path) -> Result<Arc<FileData>> {
95 { 92 match self.data.file_map.get(path) {
96 let guard = self.data.file_map.read(); 93 Some(data) => Ok(data.clone()),
97 if let Some(data) = guard.get(path) { 94 None => bail!("unknown file: {}", path.display()),
98 return Ok(data.clone());
99 }
100 } 95 }
101
102 let text = if self.data.mem_map.contains_key(path) {
103 None
104 } else {
105 trace!("loading file from disk: {}", path.display());
106 Some(fs::read_to_string(path)?)
107 };
108 let res = {
109 let mut guard = self.data.file_map.write();
110 guard.entry(path.to_owned())
111 .or_insert_with(|| Arc::new(FileData {
112 text,
113 syntax: OnceCell::new(),
114 lines: OnceCell::new(),
115 }))
116 .clone()
117 };
118 Ok(res)
119 } 96 }
120} 97}
121 98
122 99
123#[derive(Default, Debug)] 100#[derive(Default, Debug)]
124struct WorldData { 101struct WorldData {
125 mem_map: HashMap<PathBuf, Arc<String>>, 102 file_map: HashMap<PathBuf, Arc<FileData>>,
126 file_map: RwLock<HashMap<PathBuf, Arc<FileData>>>,
127} 103}
128 104
129#[derive(Debug)] 105#[derive(Debug)]
130struct FileData { 106struct FileData {
131 text: Option<String>, 107 text: String,
132 syntax: OnceCell<ast::File>, 108 syntax: OnceCell<ast::File>,
133 lines: OnceCell<LineIndex>, 109 lines: OnceCell<LineIndex>,
134} 110}
111
112impl FileData {
113 fn new(text: String) -> FileData {
114 FileData {
115 text,
116 syntax: OnceCell::new(),
117 lines: OnceCell::new(),
118 }
119 }
120}