aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/roots.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis/src/roots.rs')
-rw-r--r--crates/libanalysis/src/roots.rs143
1 files changed, 103 insertions, 40 deletions
diff --git a/crates/libanalysis/src/roots.rs b/crates/libanalysis/src/roots.rs
index 01de3e128..a65668c9b 100644
--- a/crates/libanalysis/src/roots.rs
+++ b/crates/libanalysis/src/roots.rs
@@ -13,16 +13,24 @@ use libsyntax2::File;
13use { 13use {
14 FileId, 14 FileId,
15 module_map::{ModuleMap, ChangeKind}, 15 module_map::{ModuleMap, ChangeKind},
16 symbol_index::FileSymbols, 16 symbol_index::SymbolIndex,
17}; 17};
18 18
19pub(crate) trait SourceRoot {
20 fn contains(&self, file_id: FileId) -> bool;
21 fn module_map(&self) -> &ModuleMap;
22 fn lines(&self, file_id: FileId) -> &LineIndex;
23 fn syntax(&self, file_id: FileId) -> &File;
24 fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>);
25}
26
19#[derive(Clone, Default, Debug)] 27#[derive(Clone, Default, Debug)]
20pub(crate) struct SourceRoot { 28pub(crate) struct WritableSourceRoot {
21 file_map: HashMap<FileId, Arc<(FileData, OnceCell<FileSymbols>)>>, 29 file_map: HashMap<FileId, Arc<(FileData, OnceCell<SymbolIndex>)>>,
22 module_map: ModuleMap, 30 module_map: ModuleMap,
23} 31}
24 32
25impl SourceRoot { 33impl WritableSourceRoot {
26 pub fn update(&mut self, file_id: FileId, text: Option<String>) { 34 pub fn update(&mut self, file_id: FileId, text: Option<String>) {
27 let change_kind = if self.file_map.remove(&file_id).is_some() { 35 let change_kind = if self.file_map.remove(&file_id).is_some() {
28 if text.is_some() { 36 if text.is_some() {
@@ -40,31 +48,6 @@ impl SourceRoot {
40 self.file_map.insert(file_id, Arc::new((file_data, Default::default()))); 48 self.file_map.insert(file_id, Arc::new((file_data, Default::default())));
41 } 49 }
42 } 50 }
43 pub fn module_map(&self) -> &ModuleMap {
44 &self.module_map
45 }
46 pub fn lines(&self, file_id: FileId) -> &LineIndex {
47 let data = self.data(file_id);
48 data.lines.get_or_init(|| LineIndex::new(&data.text))
49 }
50 pub fn syntax(&self, file_id: FileId) -> &File {
51 let data = self.data(file_id);
52 let text = &data.text;
53 let syntax = &data.syntax;
54 match panic::catch_unwind(panic::AssertUnwindSafe(|| syntax.get_or_init(|| File::parse(text)))) {
55 Ok(file) => file,
56 Err(err) => {
57 error!("Parser paniced on:\n------\n{}\n------\n", &data.text);
58 panic::resume_unwind(err)
59 }
60 }
61 }
62 pub(crate) fn symbols(&self) -> Vec<&FileSymbols> {
63 self.file_map
64 .iter()
65 .map(|(&file_id, data)| symbols(file_id, data))
66 .collect()
67 }
68 pub fn reindex(&self) { 51 pub fn reindex(&self) {
69 let now = Instant::now(); 52 let now = Instant::now();
70 self.file_map 53 self.file_map
@@ -83,9 +66,31 @@ impl SourceRoot {
83 } 66 }
84} 67}
85 68
86fn symbols(file_id: FileId, (data, symbols): &(FileData, OnceCell<FileSymbols>)) -> &FileSymbols { 69impl SourceRoot for WritableSourceRoot {
70 fn contains(&self, file_id: FileId) -> bool {
71 self.file_map.contains_key(&file_id)
72 }
73 fn module_map(&self) -> &ModuleMap {
74 &self.module_map
75 }
76 fn lines(&self, file_id: FileId) -> &LineIndex {
77 self.data(file_id).lines()
78 }
79 fn syntax(&self, file_id: FileId) -> &File {
80 self.data(file_id).syntax()
81 }
82 fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>) {
83 acc.extend(
84 self.file_map
85 .iter()
86 .map(|(&file_id, data)| symbols(file_id, data))
87 )
88 }
89}
90
91fn symbols(file_id: FileId, (data, symbols): &(FileData, OnceCell<SymbolIndex>)) -> &SymbolIndex {
87 let syntax = data.syntax_transient(); 92 let syntax = data.syntax_transient();
88 symbols.get_or_init(|| FileSymbols::new(file_id, &syntax)) 93 symbols.get_or_init(|| SymbolIndex::for_file(file_id, syntax))
89} 94}
90 95
91#[derive(Debug)] 96#[derive(Debug)]
@@ -103,19 +108,77 @@ impl FileData {
103 lines: OnceCell::new(), 108 lines: OnceCell::new(),
104 } 109 }
105 } 110 }
111 fn lines(&self) -> &LineIndex {
112 self.lines.get_or_init(|| LineIndex::new(&self.text))
113 }
114 fn syntax(&self) -> &File {
115 let text = &self.text;
116 let syntax = &self.syntax;
117 match panic::catch_unwind(panic::AssertUnwindSafe(|| syntax.get_or_init(|| File::parse(text)))) {
118 Ok(file) => file,
119 Err(err) => {
120 error!("Parser paniced on:\n------\n{}\n------\n", text);
121 panic::resume_unwind(err)
122 }
123 }
124 }
106 fn syntax_transient(&self) -> File { 125 fn syntax_transient(&self) -> File {
107 self.syntax.get().map(|s| s.clone()) 126 self.syntax.get().map(|s| s.clone())
108 .unwrap_or_else(|| File::parse(&self.text)) 127 .unwrap_or_else(|| File::parse(&self.text))
109 } 128 }
110} 129}
111 130
112// #[derive(Clone, Default, Debug)] 131#[derive(Debug)]
113// pub(crate) struct ReadonlySourceRoot { 132pub(crate) struct ReadonlySourceRoot {
114// data: Arc<ReadonlySourceRoot> 133 symbol_index: SymbolIndex,
115// } 134 file_map: HashMap<FileId, FileData>,
135 module_map: ModuleMap,
136}
116 137
117// #[derive(Clone, Default, Debug)] 138impl ReadonlySourceRoot {
118// pub(crate) struct ReadonlySourceRootInner { 139 pub fn new(files: impl Iterator<Item=(FileId, String)>) -> ReadonlySourceRoot {
119// file_map: HashMap<FileId, FileData>, 140 let mut module_map = ModuleMap::new();
120// module_map: ModuleMap, 141 let file_map: HashMap<FileId, FileData> = files
121// } 142 .map(|(id, text)| {
143 module_map.update_file(id, ChangeKind::Insert);
144 (id, FileData::new(text))
145 })
146 .collect();
147 let symbol_index = SymbolIndex::for_files(
148 file_map.par_iter().map(|(&file_id, file_data)| {
149 (file_id, file_data.syntax_transient())
150 })
151 );
152
153 ReadonlySourceRoot {
154 symbol_index,
155 file_map,
156 module_map,
157 }
158 }
159
160 fn data(&self, file_id: FileId) -> &FileData {
161 match self.file_map.get(&file_id) {
162 Some(data) => data,
163 None => panic!("unknown file: {:?}", file_id),
164 }
165 }
166}
167
168impl SourceRoot for ReadonlySourceRoot {
169 fn contains(&self, file_id: FileId) -> bool {
170 self.file_map.contains_key(&file_id)
171 }
172 fn module_map(&self) -> &ModuleMap {
173 &self.module_map
174 }
175 fn lines(&self, file_id: FileId) -> &LineIndex {
176 self.data(file_id).lines()
177 }
178 fn syntax(&self, file_id: FileId) -> &File {
179 self.data(file_id).syntax()
180 }
181 fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>) {
182 acc.push(&self.symbol_index)
183 }
184}