diff options
Diffstat (limited to 'crates/ra_analysis/src/roots.rs')
-rw-r--r-- | crates/ra_analysis/src/roots.rs | 103 |
1 files changed, 25 insertions, 78 deletions
diff --git a/crates/ra_analysis/src/roots.rs b/crates/ra_analysis/src/roots.rs index 123c4acfa..7100f7c71 100644 --- a/crates/ra_analysis/src/roots.rs +++ b/crates/ra_analysis/src/roots.rs | |||
@@ -1,25 +1,22 @@ | |||
1 | use std::{panic, sync::Arc}; | 1 | use std::{sync::Arc}; |
2 | 2 | ||
3 | use once_cell::sync::OnceCell; | ||
4 | use ra_editor::LineIndex; | 3 | use ra_editor::LineIndex; |
5 | use ra_syntax::File; | 4 | use ra_syntax::File; |
6 | use rayon::prelude::*; | 5 | use rustc_hash::FxHashSet; |
7 | use rustc_hash::{FxHashMap, FxHashSet}; | ||
8 | use salsa::Database; | 6 | use salsa::Database; |
9 | 7 | ||
10 | use crate::{ | 8 | use crate::{ |
11 | Cancelable, | 9 | Cancelable, |
12 | db::{self, FilesDatabase, SyntaxDatabase}, | 10 | db::{self, FilesDatabase, SyntaxDatabase}, |
13 | descriptors::{ModuleDescriptor, ModuleTreeDescriptor}, | ||
14 | imp::FileResolverImp, | 11 | imp::FileResolverImp, |
15 | module_map::ModulesDatabase, | 12 | descriptors::module::{ModulesDatabase, ModuleTree}, |
16 | symbol_index::SymbolIndex, | 13 | symbol_index::SymbolIndex, |
17 | FileId, | 14 | FileId, |
18 | }; | 15 | }; |
19 | 16 | ||
20 | pub(crate) trait SourceRoot { | 17 | pub(crate) trait SourceRoot { |
21 | fn contains(&self, file_id: FileId) -> bool; | 18 | fn contains(&self, file_id: FileId) -> bool; |
22 | fn module_tree(&self) -> Cancelable<Arc<ModuleTreeDescriptor>>; | 19 | fn module_tree(&self) -> Cancelable<Arc<ModuleTree>>; |
23 | fn lines(&self, file_id: FileId) -> Arc<LineIndex>; | 20 | fn lines(&self, file_id: FileId) -> Arc<LineIndex>; |
24 | fn syntax(&self, file_id: FileId) -> File; | 21 | fn syntax(&self, file_id: FileId) -> File; |
25 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) -> Cancelable<()>; | 22 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) -> Cancelable<()>; |
@@ -65,7 +62,7 @@ impl WritableSourceRoot { | |||
65 | } | 62 | } |
66 | 63 | ||
67 | impl SourceRoot for WritableSourceRoot { | 64 | impl SourceRoot for WritableSourceRoot { |
68 | fn module_tree(&self) -> Cancelable<Arc<ModuleTreeDescriptor>> { | 65 | fn module_tree(&self) -> Cancelable<Arc<ModuleTree>> { |
69 | self.db.module_tree() | 66 | self.db.module_tree() |
70 | } | 67 | } |
71 | fn contains(&self, file_id: FileId) -> bool { | 68 | fn contains(&self, file_id: FileId) -> bool { |
@@ -86,97 +83,47 @@ impl SourceRoot for WritableSourceRoot { | |||
86 | } | 83 | } |
87 | } | 84 | } |
88 | 85 | ||
89 | #[derive(Debug)] | 86 | #[derive(Debug, Clone)] |
90 | struct FileData { | ||
91 | text: String, | ||
92 | lines: OnceCell<Arc<LineIndex>>, | ||
93 | syntax: OnceCell<File>, | ||
94 | } | ||
95 | |||
96 | impl FileData { | ||
97 | fn new(text: String) -> FileData { | ||
98 | FileData { | ||
99 | text, | ||
100 | syntax: OnceCell::new(), | ||
101 | lines: OnceCell::new(), | ||
102 | } | ||
103 | } | ||
104 | fn lines(&self) -> &Arc<LineIndex> { | ||
105 | self.lines | ||
106 | .get_or_init(|| Arc::new(LineIndex::new(&self.text))) | ||
107 | } | ||
108 | fn syntax(&self) -> &File { | ||
109 | let text = &self.text; | ||
110 | let syntax = &self.syntax; | ||
111 | match panic::catch_unwind(panic::AssertUnwindSafe(|| { | ||
112 | syntax.get_or_init(|| File::parse(text)) | ||
113 | })) { | ||
114 | Ok(file) => file, | ||
115 | Err(err) => { | ||
116 | error!("Parser paniced on:\n------\n{}\n------\n", text); | ||
117 | panic::resume_unwind(err) | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | } | ||
122 | |||
123 | #[derive(Debug)] | ||
124 | pub(crate) struct ReadonlySourceRoot { | 87 | pub(crate) struct ReadonlySourceRoot { |
88 | db: db::RootDatabase, | ||
125 | symbol_index: Arc<SymbolIndex>, | 89 | symbol_index: Arc<SymbolIndex>, |
126 | file_map: FxHashMap<FileId, FileData>, | ||
127 | module_tree: Arc<ModuleTreeDescriptor>, | ||
128 | } | 90 | } |
129 | 91 | ||
130 | impl ReadonlySourceRoot { | 92 | impl ReadonlySourceRoot { |
131 | pub(crate) fn new( | 93 | pub(crate) fn new( |
132 | files: Vec<(FileId, String)>, | 94 | files: Vec<(FileId, String)>, |
133 | file_resolver: FileResolverImp, | 95 | resolver: FileResolverImp, |
134 | ) -> ReadonlySourceRoot { | 96 | ) -> ReadonlySourceRoot { |
135 | let modules = files | 97 | let db = db::RootDatabase::default(); |
136 | .par_iter() | 98 | let mut file_ids = FxHashSet::default(); |
137 | .map(|(file_id, text)| { | 99 | for (file_id, text) in files { |
138 | let syntax = File::parse(text); | 100 | file_ids.insert(file_id); |
139 | let mod_descr = ModuleDescriptor::new(syntax.ast()); | 101 | db.query(db::FileTextQuery).set(file_id, Arc::new(text)); |
140 | (*file_id, syntax, mod_descr) | 102 | } |
141 | }) | ||
142 | .collect::<Vec<_>>(); | ||
143 | let module_tree = | ||
144 | ModuleTreeDescriptor::new(modules.iter().map(|it| (it.0, &it.2)), &file_resolver); | ||
145 | 103 | ||
104 | db.query(db::FileSetQuery) | ||
105 | .set((), Arc::new(db::FileSet { files: file_ids, resolver })); | ||
106 | let file_set = db.file_set(); | ||
146 | let symbol_index = | 107 | let symbol_index = |
147 | SymbolIndex::for_files(modules.par_iter().map(|it| (it.0, it.1.clone()))); | 108 | SymbolIndex::for_files(file_set.files.iter() // TODO: par iter |
148 | let file_map: FxHashMap<FileId, FileData> = files | 109 | .map(|&file_id| (file_id, db.file_syntax(file_id)))); |
149 | .into_iter() | ||
150 | .map(|(id, text)| (id, FileData::new(text))) | ||
151 | .collect(); | ||
152 | |||
153 | ReadonlySourceRoot { | ||
154 | symbol_index: Arc::new(symbol_index), | ||
155 | file_map, | ||
156 | module_tree: Arc::new(module_tree), | ||
157 | } | ||
158 | } | ||
159 | 110 | ||
160 | fn data(&self, file_id: FileId) -> &FileData { | 111 | ReadonlySourceRoot { db, symbol_index: Arc::new(symbol_index) } |
161 | match self.file_map.get(&file_id) { | ||
162 | Some(data) => data, | ||
163 | None => panic!("unknown file: {:?}", file_id), | ||
164 | } | ||
165 | } | 112 | } |
166 | } | 113 | } |
167 | 114 | ||
168 | impl SourceRoot for ReadonlySourceRoot { | 115 | impl SourceRoot for ReadonlySourceRoot { |
169 | fn module_tree(&self) -> Cancelable<Arc<ModuleTreeDescriptor>> { | 116 | fn module_tree(&self) -> Cancelable<Arc<ModuleTree>> { |
170 | Ok(Arc::clone(&self.module_tree)) | 117 | self.db.module_tree() |
171 | } | 118 | } |
172 | fn contains(&self, file_id: FileId) -> bool { | 119 | fn contains(&self, file_id: FileId) -> bool { |
173 | self.file_map.contains_key(&file_id) | 120 | self.db.file_set().files.contains(&file_id) |
174 | } | 121 | } |
175 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { | 122 | fn lines(&self, file_id: FileId) -> Arc<LineIndex> { |
176 | Arc::clone(self.data(file_id).lines()) | 123 | self.db.file_lines(file_id) |
177 | } | 124 | } |
178 | fn syntax(&self, file_id: FileId) -> File { | 125 | fn syntax(&self, file_id: FileId) -> File { |
179 | self.data(file_id).syntax().clone() | 126 | self.db.file_syntax(file_id) |
180 | } | 127 | } |
181 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) -> Cancelable<()> { | 128 | fn symbols(&self, acc: &mut Vec<Arc<SymbolIndex>>) -> Cancelable<()> { |
182 | acc.push(Arc::clone(&self.symbol_index)); | 129 | acc.push(Arc::clone(&self.symbol_index)); |