diff options
Diffstat (limited to 'crates/libanalysis/src/imp.rs')
-rw-r--r-- | crates/libanalysis/src/imp.rs | 121 |
1 files changed, 16 insertions, 105 deletions
diff --git a/crates/libanalysis/src/imp.rs b/crates/libanalysis/src/imp.rs index b80ce1ab5..73a6f4306 100644 --- a/crates/libanalysis/src/imp.rs +++ b/crates/libanalysis/src/imp.rs | |||
@@ -4,13 +4,9 @@ use std::{ | |||
4 | atomic::{AtomicBool, Ordering::SeqCst}, | 4 | atomic::{AtomicBool, Ordering::SeqCst}, |
5 | }, | 5 | }, |
6 | fmt, | 6 | fmt, |
7 | time::Instant, | 7 | collections::{HashSet, VecDeque}, |
8 | collections::{HashMap, HashSet, VecDeque}, | ||
9 | panic, | ||
10 | }; | 8 | }; |
11 | 9 | ||
12 | use rayon::prelude::*; | ||
13 | use once_cell::sync::OnceCell; | ||
14 | use libeditor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit}; | 10 | use libeditor::{self, FileSymbol, LineIndex, find_node_at_offset, LocalEdit}; |
15 | use libsyntax2::{ | 11 | use libsyntax2::{ |
16 | TextUnit, TextRange, SmolStr, File, AstNode, | 12 | TextUnit, TextRange, SmolStr, File, AstNode, |
@@ -20,10 +16,9 @@ use libsyntax2::{ | |||
20 | 16 | ||
21 | use { | 17 | use { |
22 | FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, | 18 | FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, |
23 | module_map::Problem, | ||
24 | symbol_index::FileSymbols, | ||
25 | module_map::{ModuleMap, ChangeKind}, | ||
26 | JobToken, CrateGraph, CrateId, | 19 | JobToken, CrateGraph, CrateId, |
20 | module_map::Problem, | ||
21 | roots::SourceRoot, | ||
27 | }; | 22 | }; |
28 | 23 | ||
29 | #[derive(Debug)] | 24 | #[derive(Debug)] |
@@ -50,23 +45,7 @@ impl AnalysisHostImpl { | |||
50 | pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) { | 45 | pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) { |
51 | let data = self.data_mut(); | 46 | let data = self.data_mut(); |
52 | for (file_id, text) in changes { | 47 | for (file_id, text) in changes { |
53 | let change_kind = if data.file_map.remove(&file_id).is_some() { | 48 | data.root.update(file_id, text); |
54 | if text.is_some() { | ||
55 | ChangeKind::Update | ||
56 | } else { | ||
57 | ChangeKind::Delete | ||
58 | } | ||
59 | } else { | ||
60 | ChangeKind::Insert | ||
61 | }; | ||
62 | data.module_map.update_file(file_id, change_kind); | ||
63 | data.file_map.remove(&file_id); | ||
64 | if let Some(text) = text { | ||
65 | let file_data = FileData::new(text); | ||
66 | data.file_map.insert(file_id, Arc::new(file_data)); | ||
67 | } else { | ||
68 | data.file_map.remove(&file_id); | ||
69 | } | ||
70 | } | 49 | } |
71 | } | 50 | } |
72 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { | 51 | pub fn set_crate_graph(&mut self, graph: CrateGraph) { |
@@ -106,31 +85,18 @@ impl Clone for AnalysisImpl { | |||
106 | } | 85 | } |
107 | 86 | ||
108 | impl AnalysisImpl { | 87 | impl AnalysisImpl { |
109 | pub fn file_syntax(&self, file_id: FileId) -> File { | 88 | pub fn file_syntax(&self, file_id: FileId) -> &File { |
110 | self.file_data(file_id).syntax().clone() | 89 | self.data.root.syntax(file_id) |
111 | } | 90 | } |
112 | 91 | pub fn file_line_index(&self, file_id: FileId) -> &LineIndex { | |
113 | pub fn file_line_index(&self, id: FileId) -> LineIndex { | 92 | self.data.root.lines(file_id) |
114 | let data = self.file_data(id); | ||
115 | data | ||
116 | .lines | ||
117 | .get_or_init(|| LineIndex::new(&data.text)) | ||
118 | .clone() | ||
119 | } | 93 | } |
120 | 94 | pub fn world_symbols(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | |
121 | pub fn world_symbols(&self, mut query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { | ||
122 | self.reindex(); | 95 | self.reindex(); |
123 | self.data.file_map.iter() | 96 | query.search(&self.data.root.symbols(), token) |
124 | .take_while(move |_| !token.is_canceled()) | ||
125 | .flat_map(move |(id, data)| { | ||
126 | let symbols = data.symbols(); | ||
127 | query.process(symbols).into_iter().map(move |s| (*id, s)) | ||
128 | }) | ||
129 | .collect() | ||
130 | } | 97 | } |
131 | |||
132 | pub fn parent_module(&self, id: FileId) -> Vec<(FileId, FileSymbol)> { | 98 | pub fn parent_module(&self, id: FileId) -> Vec<(FileId, FileSymbol)> { |
133 | let module_map = &self.data.module_map; | 99 | let module_map = self.data.root.module_map(); |
134 | let id = module_map.file2module(id); | 100 | let id = module_map.file2module(id); |
135 | module_map | 101 | module_map |
136 | .parent_modules( | 102 | .parent_modules( |
@@ -152,7 +118,7 @@ impl AnalysisImpl { | |||
152 | } | 118 | } |
153 | 119 | ||
154 | pub fn crate_for(&self, id: FileId) -> Vec<CrateId> { | 120 | pub fn crate_for(&self, id: FileId) -> Vec<CrateId> { |
155 | let module_map = &self.data.module_map; | 121 | let module_map = self.data.root.module_map(); |
156 | let crate_graph = &self.data.crate_graph; | 122 | let crate_graph = &self.data.crate_graph; |
157 | let mut res = Vec::new(); | 123 | let mut res = Vec::new(); |
158 | let mut work = VecDeque::new(); | 124 | let mut work = VecDeque::new(); |
@@ -222,7 +188,7 @@ impl AnalysisImpl { | |||
222 | .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None }) | 188 | .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None }) |
223 | .collect::<Vec<_>>(); | 189 | .collect::<Vec<_>>(); |
224 | 190 | ||
225 | self.data.module_map.problems( | 191 | self.data.root.module_map().problems( |
226 | file_id, | 192 | file_id, |
227 | &*self.file_resolver, | 193 | &*self.file_resolver, |
228 | &|file_id| self.file_syntax(file_id), | 194 | &|file_id| self.file_syntax(file_id), |
@@ -296,7 +262,7 @@ impl AnalysisImpl { | |||
296 | Some(name) => name.text(), | 262 | Some(name) => name.text(), |
297 | None => return Vec::new(), | 263 | None => return Vec::new(), |
298 | }; | 264 | }; |
299 | let module_map = &self.data.module_map; | 265 | let module_map = self.data.root.module_map(); |
300 | let id = module_map.file2module(id); | 266 | let id = module_map.file2module(id); |
301 | module_map | 267 | module_map |
302 | .child_module_by_name( | 268 | .child_module_by_name( |
@@ -311,19 +277,7 @@ impl AnalysisImpl { | |||
311 | 277 | ||
312 | fn reindex(&self) { | 278 | fn reindex(&self) { |
313 | if self.needs_reindex.compare_and_swap(true, false, SeqCst) { | 279 | if self.needs_reindex.compare_and_swap(true, false, SeqCst) { |
314 | let now = Instant::now(); | 280 | self.data.root.reindex(); |
315 | let data = &*self.data; | ||
316 | data.file_map | ||
317 | .par_iter() | ||
318 | .for_each(|(_, data)| drop(data.symbols())); | ||
319 | info!("parallel indexing took {:?}", now.elapsed()); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | fn file_data(&self, file_id: FileId) -> Arc<FileData> { | ||
324 | match self.data.file_map.get(&file_id) { | ||
325 | Some(data) => data.clone(), | ||
326 | None => panic!("unknown file: {:?}", file_id), | ||
327 | } | 281 | } |
328 | } | 282 | } |
329 | } | 283 | } |
@@ -331,50 +285,7 @@ impl AnalysisImpl { | |||
331 | #[derive(Clone, Default, Debug)] | 285 | #[derive(Clone, Default, Debug)] |
332 | struct WorldData { | 286 | struct WorldData { |
333 | crate_graph: CrateGraph, | 287 | crate_graph: CrateGraph, |
334 | file_map: HashMap<FileId, Arc<FileData>>, | 288 | root: SourceRoot, |
335 | module_map: ModuleMap, | ||
336 | } | ||
337 | |||
338 | #[derive(Debug)] | ||
339 | struct FileData { | ||
340 | text: String, | ||
341 | symbols: OnceCell<FileSymbols>, | ||
342 | syntax: OnceCell<File>, | ||
343 | lines: OnceCell<LineIndex>, | ||
344 | } | ||
345 | |||
346 | impl FileData { | ||
347 | fn new(text: String) -> FileData { | ||
348 | FileData { | ||
349 | text, | ||
350 | symbols: OnceCell::new(), | ||
351 | syntax: OnceCell::new(), | ||
352 | lines: OnceCell::new(), | ||
353 | } | ||
354 | } | ||
355 | |||
356 | fn syntax(&self) -> &File { | ||
357 | let text = &self.text; | ||
358 | let syntax = &self.syntax; | ||
359 | match panic::catch_unwind(panic::AssertUnwindSafe(|| syntax.get_or_init(|| File::parse(text)))) { | ||
360 | Ok(file) => file, | ||
361 | Err(err) => { | ||
362 | error!("Parser paniced on:\n------\n{}\n------\n", &self.text); | ||
363 | panic::resume_unwind(err) | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | fn syntax_transient(&self) -> File { | ||
369 | self.syntax.get().map(|s| s.clone()) | ||
370 | .unwrap_or_else(|| File::parse(&self.text)) | ||
371 | } | ||
372 | |||
373 | fn symbols(&self) -> &FileSymbols { | ||
374 | let syntax = self.syntax_transient(); | ||
375 | self.symbols | ||
376 | .get_or_init(|| FileSymbols::new(&syntax)) | ||
377 | } | ||
378 | } | 289 | } |
379 | 290 | ||
380 | impl SourceChange { | 291 | impl SourceChange { |