aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/imp.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/libanalysis/src/imp.rs')
-rw-r--r--crates/libanalysis/src/imp.rs146
1 files changed, 62 insertions, 84 deletions
diff --git a/crates/libanalysis/src/imp.rs b/crates/libanalysis/src/imp.rs
index 3e65ee14a..6f3191fe7 100644
--- a/crates/libanalysis/src/imp.rs
+++ b/crates/libanalysis/src/imp.rs
@@ -5,6 +5,7 @@ use std::{
5 }, 5 },
6 fmt, 6 fmt,
7 collections::{HashSet, VecDeque}, 7 collections::{HashSet, VecDeque},
8 iter,
8}; 9};
9 10
10use relative_path::RelativePath; 11use relative_path::RelativePath;
@@ -18,8 +19,8 @@ use libsyntax2::{
18use { 19use {
19 FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit, 20 FileId, FileResolver, Query, Diagnostic, SourceChange, SourceFileEdit, Position, FileSystemEdit,
20 JobToken, CrateGraph, CrateId, 21 JobToken, CrateGraph, CrateId,
21 module_map::{ModuleMap, Problem},
22 roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot}, 22 roots::{SourceRoot, ReadonlySourceRoot, WritableSourceRoot},
23 descriptors::{ModuleTreeDescriptor, Problem},
23}; 24};
24 25
25 26
@@ -75,14 +76,12 @@ impl AnalysisHostImpl {
75 } 76 }
76 pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) { 77 pub fn change_files(&mut self, changes: &mut dyn Iterator<Item=(FileId, Option<String>)>) {
77 let data = self.data_mut(); 78 let data = self.data_mut();
78 for (file_id, text) in changes { 79 data.root = Arc::new(data.root.apply_changes(changes, None));
79 data.root.update(file_id, text);
80 }
81 } 80 }
82 pub fn set_file_resolver(&mut self, resolver: FileResolverImp) { 81 pub fn set_file_resolver(&mut self, resolver: FileResolverImp) {
83 let data = self.data_mut(); 82 let data = self.data_mut();
84 data.file_resolver = resolver.clone(); 83 data.file_resolver = resolver.clone();
85 data.root.set_file_resolver(resolver); 84 data.root = Arc::new(data.root.apply_changes(&mut iter::empty(), Some(resolver)));
86 } 85 }
87 pub fn set_crate_graph(&mut self, graph: CrateGraph) { 86 pub fn set_crate_graph(&mut self, graph: CrateGraph) {
88 let mut visited = HashSet::new(); 87 let mut visited = HashSet::new();
@@ -124,18 +123,17 @@ impl Clone for AnalysisImpl {
124impl AnalysisImpl { 123impl AnalysisImpl {
125 fn root(&self, file_id: FileId) -> &SourceRoot { 124 fn root(&self, file_id: FileId) -> &SourceRoot {
126 if self.data.root.contains(file_id) { 125 if self.data.root.contains(file_id) {
127 return &self.data.root; 126 return &*self.data.root;
128 } 127 }
129 &**self.data.libs.iter().find(|it| it.contains(file_id)).unwrap() 128 &**self.data.libs.iter().find(|it| it.contains(file_id)).unwrap()
130 } 129 }
131 pub fn file_syntax(&self, file_id: FileId) -> &File { 130 pub fn file_syntax(&self, file_id: FileId) -> File {
132 self.root(file_id).syntax(file_id) 131 self.root(file_id).syntax(file_id)
133 } 132 }
134 pub fn file_line_index(&self, file_id: FileId) -> &LineIndex { 133 pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
135 self.root(file_id).lines(file_id) 134 self.root(file_id).lines(file_id)
136 } 135 }
137 pub fn world_symbols(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> { 136 pub fn world_symbols(&self, query: Query, token: &JobToken) -> Vec<(FileId, FileSymbol)> {
138 self.reindex();
139 let mut buf = Vec::new(); 137 let mut buf = Vec::new();
140 if query.libs { 138 if query.libs {
141 self.data.libs.iter() 139 self.data.libs.iter()
@@ -148,25 +146,24 @@ impl AnalysisImpl {
148 } 146 }
149 pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> { 147 pub fn parent_module(&self, file_id: FileId) -> Vec<(FileId, FileSymbol)> {
150 let root = self.root(file_id); 148 let root = self.root(file_id);
151 let module_map = root.module_map(); 149 let module_tree = root.module_tree();
152 let id = module_map.file2module(file_id); 150 module_tree.parent_modules(file_id)
153 module_map 151 .iter()
154 .parent_modules(id, &|file_id| root.syntax(file_id)) 152 .map(|link| {
155 .into_iter() 153 let file_id = link.owner(&module_tree);
156 .map(|(id, name, node)| { 154 let syntax = root.syntax(file_id);
157 let id = module_map.module2file(id); 155 let decl = link.bind_source(&module_tree, syntax.ast());
158 let sym = FileSymbol { 156 let sym = FileSymbol {
159 name, 157 name: link.name(&module_tree),
160 node_range: node.range(), 158 node_range: decl.syntax().range(),
161 kind: MODULE, 159 kind: MODULE,
162 }; 160 };
163 (id, sym) 161 (file_id, sym)
164 }) 162 })
165 .collect() 163 .collect()
166 } 164 }
167
168 pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> { 165 pub fn crate_for(&self, file_id: FileId) -> Vec<CrateId> {
169 let module_map = self.root(file_id).module_map(); 166 let module_tree = self.root(file_id).module_tree();
170 let crate_graph = &self.data.crate_graph; 167 let crate_graph = &self.data.crate_graph;
171 let mut res = Vec::new(); 168 let mut res = Vec::new();
172 let mut work = VecDeque::new(); 169 let mut work = VecDeque::new();
@@ -177,11 +174,10 @@ impl AnalysisImpl {
177 res.push(crate_id); 174 res.push(crate_id);
178 continue; 175 continue;
179 } 176 }
180 let mid = module_map.file2module(id); 177 let parents = module_tree
181 let parents = module_map 178 .parent_modules(id)
182 .parent_module_ids(mid, &|file_id| self.file_syntax(file_id))
183 .into_iter() 179 .into_iter()
184 .map(|id| module_map.module2file(id)) 180 .map(|link| link.owner(&module_tree))
185 .filter(|&id| visited.insert(id)); 181 .filter(|&id| visited.insert(id));
186 work.extend(parents); 182 work.extend(parents);
187 } 183 }
@@ -197,7 +193,7 @@ impl AnalysisImpl {
197 token: &JobToken, 193 token: &JobToken,
198 ) -> Vec<(FileId, FileSymbol)> { 194 ) -> Vec<(FileId, FileSymbol)> {
199 let root = self.root(file_id); 195 let root = self.root(file_id);
200 let module_map = root.module_map(); 196 let module_tree = root.module_tree();
201 let file = root.syntax(file_id); 197 let file = root.syntax(file_id);
202 let syntax = file.syntax(); 198 let syntax = file.syntax();
203 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) { 199 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, offset) {
@@ -206,7 +202,7 @@ impl AnalysisImpl {
206 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) { 202 if let Some(name) = find_node_at_offset::<ast::Name>(syntax, offset) {
207 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { 203 if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) {
208 if module.has_semi() { 204 if module.has_semi() {
209 let file_ids = self.resolve_module(module_map, file_id, module); 205 let file_ids = self.resolve_module(&*module_tree, file_id, module);
210 206
211 let res = file_ids.into_iter().map(|id| { 207 let res = file_ids.into_iter().map(|id| {
212 let name = module.name() 208 let name = module.name()
@@ -229,7 +225,7 @@ impl AnalysisImpl {
229 225
230 pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> { 226 pub fn diagnostics(&self, file_id: FileId) -> Vec<Diagnostic> {
231 let root = self.root(file_id); 227 let root = self.root(file_id);
232 let module_map = root.module_map(); 228 let module_tree = root.module_tree();
233 let syntax = root.syntax(file_id); 229 let syntax = root.syntax(file_id);
234 230
235 let mut res = libeditor::diagnostics(&syntax) 231 let mut res = libeditor::diagnostics(&syntax)
@@ -237,47 +233,43 @@ impl AnalysisImpl {
237 .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None }) 233 .map(|d| Diagnostic { range: d.range, message: d.msg, fix: None })
238 .collect::<Vec<_>>(); 234 .collect::<Vec<_>>();
239 235
240 module_map.problems( 236 for (name_node, problem) in module_tree.problems(file_id, syntax.ast()) {
241 file_id, 237 let diag = match problem {
242 &|file_id| self.file_syntax(file_id), 238 Problem::UnresolvedModule { candidate } => {
243 |name_node, problem| { 239 let create_file = FileSystemEdit::CreateFile {
244 let diag = match problem { 240 anchor: file_id,
245 Problem::UnresolvedModule { candidate } => { 241 path: candidate.clone(),
246 let create_file = FileSystemEdit::CreateFile { 242 };
247 anchor: file_id, 243 let fix = SourceChange {
248 path: candidate.clone(), 244 label: "create module".to_string(),
249 }; 245 source_file_edits: Vec::new(),
250 let fix = SourceChange { 246 file_system_edits: vec![create_file],
251 label: "create module".to_string(), 247 cursor_position: None,
252 source_file_edits: Vec::new(), 248 };
253 file_system_edits: vec![create_file], 249 Diagnostic {
254 cursor_position: None, 250 range: name_node.syntax().range(),
255 }; 251 message: "unresolved module".to_string(),
256 Diagnostic { 252 fix: Some(fix),
257 range: name_node.syntax().range(),
258 message: "unresolved module".to_string(),
259 fix: Some(fix),
260 }
261 } 253 }
262 Problem::NotDirOwner { move_to, candidate } => { 254 }
263 let move_file = FileSystemEdit::MoveFile { file: file_id, path: move_to.clone() }; 255 Problem::NotDirOwner { move_to, candidate } => {
264 let create_file = FileSystemEdit::CreateFile { anchor: file_id, path: move_to.join(candidate) }; 256 let move_file = FileSystemEdit::MoveFile { file: file_id, path: move_to.clone() };
265 let fix = SourceChange { 257 let create_file = FileSystemEdit::CreateFile { anchor: file_id, path: move_to.join(candidate) };
266 label: "move file and create module".to_string(), 258 let fix = SourceChange {
267 source_file_edits: Vec::new(), 259 label: "move file and create module".to_string(),
268 file_system_edits: vec![move_file, create_file], 260 source_file_edits: Vec::new(),
269 cursor_position: None, 261 file_system_edits: vec![move_file, create_file],
270 }; 262 cursor_position: None,
271 Diagnostic { 263 };
272 range: name_node.syntax().range(), 264 Diagnostic {
273 message: "can't declare module at this location".to_string(), 265 range: name_node.syntax().range(),
274 fix: Some(fix), 266 message: "can't declare module at this location".to_string(),
275 } 267 fix: Some(fix),
276 } 268 }
277 }; 269 }
278 res.push(diag) 270 };
279 } 271 res.push(diag)
280 ); 272 }
281 res 273 res
282 } 274 }
283 275
@@ -307,26 +299,12 @@ impl AnalysisImpl {
307 self.world_symbols(query, token) 299 self.world_symbols(query, token)
308 } 300 }
309 301
310 fn resolve_module(&self, module_map: &ModuleMap, file_id: FileId, module: ast::Module) -> Vec<FileId> { 302 fn resolve_module(&self, module_tree: &ModuleTreeDescriptor, file_id: FileId, module: ast::Module) -> Vec<FileId> {
311 let name = match module.name() { 303 let name = match module.name() {
312 Some(name) => name.text(), 304 Some(name) => name.text(),
313 None => return Vec::new(), 305 None => return Vec::new(),
314 }; 306 };
315 let id = module_map.file2module(file_id); 307 module_tree.child_module_by_name(file_id, name.as_str())
316 module_map
317 .child_module_by_name(
318 id, name.as_str(),
319 &|file_id| self.file_syntax(file_id),
320 )
321 .into_iter()
322 .map(|id| module_map.module2file(id))
323 .collect()
324 }
325
326 fn reindex(&self) {
327 if self.needs_reindex.compare_and_swap(true, false, SeqCst) {
328 self.data.root.reindex();
329 }
330 } 308 }
331} 309}
332 310
@@ -334,7 +312,7 @@ impl AnalysisImpl {
334struct WorldData { 312struct WorldData {
335 file_resolver: FileResolverImp, 313 file_resolver: FileResolverImp,
336 crate_graph: CrateGraph, 314 crate_graph: CrateGraph,
337 root: WritableSourceRoot, 315 root: Arc<WritableSourceRoot>,
338 libs: Vec<Arc<ReadonlySourceRoot>>, 316 libs: Vec<Arc<ReadonlySourceRoot>>,
339} 317}
340 318