diff options
Diffstat (limited to 'crates/libanalysis/src/roots.rs')
-rw-r--r-- | crates/libanalysis/src/roots.rs | 166 |
1 files changed, 77 insertions, 89 deletions
diff --git a/crates/libanalysis/src/roots.rs b/crates/libanalysis/src/roots.rs index 629a697c5..191d0d821 100644 --- a/crates/libanalysis/src/roots.rs +++ b/crates/libanalysis/src/roots.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | collections::HashMap, | 2 | collections::HashMap, |
3 | time::Instant, | ||
4 | sync::Arc, | 3 | sync::Arc, |
5 | panic, | 4 | panic, |
6 | }; | 5 | }; |
@@ -13,94 +12,82 @@ use libsyntax2::File; | |||
13 | use { | 12 | use { |
14 | FileId, | 13 | FileId, |
15 | imp::FileResolverImp, | 14 | imp::FileResolverImp, |
16 | module_map::{ModuleMap, ChangeKind}, | ||
17 | symbol_index::SymbolIndex, | 15 | symbol_index::SymbolIndex, |
16 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | ||
17 | db::Db, | ||
18 | }; | 18 | }; |
19 | 19 | ||
20 | pub(crate) trait SourceRoot { | 20 | pub(crate) trait SourceRoot { |
21 | fn contains(&self, file_id: FileId) -> bool; | 21 | fn contains(&self, file_id: FileId) -> bool; |
22 | fn module_map(&self) -> &ModuleMap; | 22 | fn module_tree(&self) -> Arc<ModuleTreeDescriptor>; |
23 | fn lines(&self, file_id: FileId) -> &LineIndex; | 23 | fn lines(&self, file_id: FileId) -> Arc<LineIndex>; |
24 | fn syntax(&self, file_id: FileId) -> &File; | 24 | fn syntax(&self, file_id: FileId) -> File; |
25 | fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>); | 25 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>); |
26 | } | 26 | } |
27 | 27 | ||
28 | #[derive(Clone, Default, Debug)] | 28 | #[derive(Default, Debug)] |
29 | pub(crate) struct WritableSourceRoot { | 29 | pub(crate) struct WritableSourceRoot { |
30 | file_map: HashMap<FileId, Arc<(FileData, OnceCell<SymbolIndex>)>>, | 30 | db: Db, |
31 | module_map: ModuleMap, | ||
32 | } | 31 | } |
33 | 32 | ||
34 | impl WritableSourceRoot { | 33 | impl WritableSourceRoot { |
35 | pub fn update(&mut self, file_id: FileId, text: Option<String>) { | 34 | pub fn apply_changes( |
36 | let change_kind = if self.file_map.remove(&file_id).is_some() { | 35 | &self, |
37 | if text.is_some() { | 36 | changes: &mut dyn Iterator<Item=(FileId, Option<String>)>, |
38 | ChangeKind::Update | 37 | file_resolver: Option<FileResolverImp>, |
39 | } else { | 38 | ) -> WritableSourceRoot { |
40 | ChangeKind::Delete | 39 | let resolver_changed = file_resolver.is_some(); |
40 | let mut changed_files = Vec::new(); | ||
41 | let mut new_state = self.db.state().clone(); | ||
42 | |||
43 | for (file_id, text) in changes { | ||
44 | changed_files.push(file_id); | ||
45 | match text { | ||
46 | Some(text) => { | ||
47 | new_state.file_map.insert(file_id, Arc::new(text)); | ||
48 | }, | ||
49 | None => { | ||
50 | new_state.file_map.remove(&file_id); | ||
51 | } | ||
41 | } | 52 | } |
42 | } else { | ||
43 | ChangeKind::Insert | ||
44 | }; | ||
45 | self.module_map.update_file(file_id, change_kind); | ||
46 | self.file_map.remove(&file_id); | ||
47 | if let Some(text) = text { | ||
48 | let file_data = FileData::new(text); | ||
49 | self.file_map.insert(file_id, Arc::new((file_data, Default::default()))); | ||
50 | } | 53 | } |
51 | } | 54 | if let Some(file_resolver) = file_resolver { |
52 | pub fn set_file_resolver(&mut self, file_resolver: FileResolverImp) { | 55 | new_state.file_resolver = file_resolver |
53 | self.module_map.set_file_resolver(file_resolver) | 56 | } |
54 | } | 57 | WritableSourceRoot { |
55 | pub fn reindex(&self) { | 58 | db: self.db.with_changes(new_state, &changed_files, resolver_changed) |
56 | let now = Instant::now(); | ||
57 | self.file_map | ||
58 | .par_iter() | ||
59 | .for_each(|(&file_id, data)| { | ||
60 | symbols(file_id, data); | ||
61 | }); | ||
62 | info!("parallel indexing took {:?}", now.elapsed()); | ||
63 | |||
64 | } | ||
65 | fn data(&self, file_id: FileId) -> &FileData { | ||
66 | match self.file_map.get(&file_id) { | ||
67 | Some(data) => &data.0, | ||
68 | None => panic!("unknown file: {:?}", file_id), | ||
69 | } | 59 | } |
70 | } | 60 | } |
71 | } | 61 | } |
72 | 62 | ||
73 | impl SourceRoot for WritableSourceRoot { | 63 | impl SourceRoot for WritableSourceRoot { |
74 | fn contains(&self, file_id: FileId) -> bool { | 64 | fn module_tree(&self) -> Arc<ModuleTreeDescriptor> { |
75 | self.file_map.contains_key(&file_id) | 65 | self.db.make_query(::module_map::module_tree) |
76 | } | 66 | } |
77 | fn module_map(&self) -> &ModuleMap { | 67 | |
78 | &self.module_map | 68 | fn contains(&self, file_id: FileId) -> bool { |
69 | self.db.state().file_map.contains_key(&file_id) | ||
79 | } | 70 | } |
80 | fn lines(&self, file_id: FileId) -> &LineIndex { | 71 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { |
81 | self.data(file_id).lines() | 72 | self.db.make_query(|ctx| ::queries::file_lines(ctx, file_id)) |
82 | } | 73 | } |
83 | fn syntax(&self, file_id: FileId) -> &File { | 74 | fn syntax(&self, file_id: FileId) -> File { |
84 | self.data(file_id).syntax() | 75 | self.db.make_query(|ctx| ::queries::file_syntax(ctx, file_id)) |
85 | } | 76 | } |
86 | fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>) { | 77 | fn symbols<'a>(&'a self, acc: &mut Vec<Arc<SymbolIndex>>) { |
87 | acc.extend( | 78 | self.db.make_query(|ctx| { |
88 | self.file_map | 79 | let file_set = ::queries::file_set(ctx); |
89 | .iter() | 80 | let syms = file_set.0.iter() |
90 | .map(|(&file_id, data)| symbols(file_id, data)) | 81 | .map(|file_id| ::queries::file_symbols(ctx, *file_id)); |
91 | ) | 82 | acc.extend(syms); |
83 | }); | ||
92 | } | 84 | } |
93 | } | 85 | } |
94 | 86 | ||
95 | fn symbols(file_id: FileId, (data, symbols): &(FileData, OnceCell<SymbolIndex>)) -> &SymbolIndex { | ||
96 | let syntax = data.syntax_transient(); | ||
97 | symbols.get_or_init(|| SymbolIndex::for_file(file_id, syntax)) | ||
98 | } | ||
99 | |||
100 | #[derive(Debug)] | 87 | #[derive(Debug)] |
101 | struct FileData { | 88 | struct FileData { |
102 | text: String, | 89 | text: String, |
103 | lines: OnceCell<LineIndex>, | 90 | lines: OnceCell<Arc<LineIndex>>, |
104 | syntax: OnceCell<File>, | 91 | syntax: OnceCell<File>, |
105 | } | 92 | } |
106 | 93 | ||
@@ -112,8 +99,8 @@ impl FileData { | |||
112 | lines: OnceCell::new(), | 99 | lines: OnceCell::new(), |
113 | } | 100 | } |
114 | } | 101 | } |
115 | fn lines(&self) -> &LineIndex { | 102 | fn lines(&self) -> &Arc<LineIndex> { |
116 | self.lines.get_or_init(|| LineIndex::new(&self.text)) | 103 | self.lines.get_or_init(|| Arc::new(LineIndex::new(&self.text))) |
117 | } | 104 | } |
118 | fn syntax(&self) -> &File { | 105 | fn syntax(&self) -> &File { |
119 | let text = &self.text; | 106 | let text = &self.text; |
@@ -126,40 +113,41 @@ impl FileData { | |||
126 | } | 113 | } |
127 | } | 114 | } |
128 | } | 115 | } |
129 | fn syntax_transient(&self) -> File { | ||
130 | self.syntax.get().map(|s| s.clone()) | ||
131 | .unwrap_or_else(|| File::parse(&self.text)) | ||
132 | } | ||
133 | } | 116 | } |
134 | 117 | ||
135 | #[derive(Debug)] | 118 | #[derive(Debug)] |
136 | pub(crate) struct ReadonlySourceRoot { | 119 | pub(crate) struct ReadonlySourceRoot { |
137 | symbol_index: SymbolIndex, | 120 | symbol_index: Arc<SymbolIndex>, |
138 | file_map: HashMap<FileId, FileData>, | 121 | file_map: HashMap<FileId, FileData>, |
139 | module_map: ModuleMap, | 122 | module_tree: Arc<ModuleTreeDescriptor>, |
140 | } | 123 | } |
141 | 124 | ||
142 | impl ReadonlySourceRoot { | 125 | impl ReadonlySourceRoot { |
143 | pub(crate) fn new(files: Vec<(FileId, String)>, file_resolver: FileResolverImp) -> ReadonlySourceRoot { | 126 | pub(crate) fn new(files: Vec<(FileId, String)>, file_resolver: FileResolverImp) -> ReadonlySourceRoot { |
144 | let mut module_map = ModuleMap::new(); | 127 | let modules = files.par_iter() |
145 | module_map.set_file_resolver(file_resolver); | 128 | .map(|(file_id, text)| { |
146 | let symbol_index = SymbolIndex::for_files( | 129 | let syntax = File::parse(text); |
147 | files.par_iter().map(|(file_id, text)| { | 130 | let mod_descr = ModuleDescriptor::new(syntax.ast()); |
148 | (*file_id, File::parse(text)) | 131 | (*file_id, syntax, mod_descr) |
149 | }) | 132 | }) |
133 | .collect::<Vec<_>>(); | ||
134 | let module_tree = ModuleTreeDescriptor::new( | ||
135 | modules.iter().map(|it| (it.0, &it.2)), | ||
136 | &file_resolver, | ||
137 | ); | ||
138 | |||
139 | let symbol_index = SymbolIndex::for_files( | ||
140 | modules.par_iter().map(|it| (it.0, it.1.clone())) | ||
150 | ); | 141 | ); |
151 | let file_map: HashMap<FileId, FileData> = files | 142 | let file_map: HashMap<FileId, FileData> = files |
152 | .into_iter() | 143 | .into_iter() |
153 | .map(|(id, text)| { | 144 | .map(|(id, text)| (id, FileData::new(text))) |
154 | module_map.update_file(id, ChangeKind::Insert); | ||
155 | (id, FileData::new(text)) | ||
156 | }) | ||
157 | .collect(); | 145 | .collect(); |
158 | 146 | ||
159 | ReadonlySourceRoot { | 147 | ReadonlySourceRoot { |
160 | symbol_index, | 148 | symbol_index: Arc::new(symbol_index), |
161 | file_map, | 149 | file_map, |
162 | module_map, | 150 | module_tree: Arc::new(module_tree), |
163 | } | 151 | } |
164 | } | 152 | } |
165 | 153 | ||
@@ -172,19 +160,19 @@ impl ReadonlySourceRoot { | |||
172 | } | 160 | } |
173 | 161 | ||
174 | impl SourceRoot for ReadonlySourceRoot { | 162 | impl SourceRoot for ReadonlySourceRoot { |
163 | fn module_tree(&self) -> Arc<ModuleTreeDescriptor> { | ||
164 | Arc::clone(&self.module_tree) | ||
165 | } | ||
175 | fn contains(&self, file_id: FileId) -> bool { | 166 | fn contains(&self, file_id: FileId) -> bool { |
176 | self.file_map.contains_key(&file_id) | 167 | self.file_map.contains_key(&file_id) |
177 | } | 168 | } |
178 | fn module_map(&self) -> &ModuleMap { | 169 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { |
179 | &self.module_map | 170 | Arc::clone(self.data(file_id).lines()) |
180 | } | ||
181 | fn lines(&self, file_id: FileId) -> &LineIndex { | ||
182 | self.data(file_id).lines() | ||
183 | } | 171 | } |
184 | fn syntax(&self, file_id: FileId) -> &File { | 172 | fn syntax(&self, file_id: FileId) -> File { |
185 | self.data(file_id).syntax() | 173 | self.data(file_id).syntax().clone() |
186 | } | 174 | } |
187 | fn symbols<'a>(&'a self, acc: &mut Vec<&'a SymbolIndex>) { | 175 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) { |
188 | acc.push(&self.symbol_index) | 176 | acc.push(Arc::clone(&self.symbol_index)) |
189 | } | 177 | } |
190 | } | 178 | } |