diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-11-20 14:33:54 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2018-11-20 14:33:54 +0000 |
commit | 713c3ea30b38199e05e1f70094d85177f16915f8 (patch) | |
tree | f4f3c59a59e4a607b77321cb685bf616824dc8f7 /crates/ra_analysis/src/imp.rs | |
parent | 902778ccaefc7b51548cab459715aaf8653bbbc6 (diff) | |
parent | a2fdb41ace4de7737a3ba0e4ef5e68d0a41e924d (diff) |
Merge #234
234: Global module r=matklad a=matklad
This series of commits re-introdces `ModuleDescriptor` as one stop shop for all information about a module.
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_analysis/src/imp.rs')
-rw-r--r-- | crates/ra_analysis/src/imp.rs | 136 |
1 files changed, 50 insertions, 86 deletions
diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index 812fed32d..e1493bdaa 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | db::{self, FileSyntaxQuery, SyntaxDatabase}, | 21 | db::{self, FileSyntaxQuery, SyntaxDatabase}, |
22 | descriptors::{ | 22 | descriptors::{ |
23 | function::{FnDescriptor, FnId}, | 23 | function::{FnDescriptor, FnId}, |
24 | module::{ModuleSource, ModuleTree, Problem}, | 24 | module::{ModuleDescriptor, Problem}, |
25 | DeclarationDescriptor, DescriptorDatabase, | 25 | DeclarationDescriptor, DescriptorDatabase, |
26 | }, | 26 | }, |
27 | input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, | 27 | input::{FilesDatabase, SourceRoot, SourceRootId, WORKSPACE}, |
@@ -216,52 +216,41 @@ impl AnalysisImpl { | |||
216 | .sweep(salsa::SweepStrategy::default().discard_values()); | 216 | .sweep(salsa::SweepStrategy::default().discard_values()); |
217 | Ok(query.search(&buf)) | 217 | Ok(query.search(&buf)) |
218 | } | 218 | } |
219 | fn module_tree(&self, file_id: FileId) -> Cancelable<Arc<ModuleTree>> { | 219 | /// This return `Vec`: a module may be included from several places. We |
220 | let source_root = self.db.file_source_root(file_id); | 220 | /// don't handle this case yet though, so the Vec has length at most one. |
221 | self.db.module_tree(source_root) | ||
222 | } | ||
223 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 221 | pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
224 | let module_tree = self.module_tree(position.file_id)?; | 222 | let descr = match ModuleDescriptor::guess_from_position(&*self.db, position)? { |
225 | let file = self.db.file_syntax(position.file_id); | 223 | None => return Ok(Vec::new()), |
226 | let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) | 224 | Some(it) => it, |
227 | { | ||
228 | Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m), | ||
229 | _ => ModuleSource::SourceFile(position.file_id), | ||
230 | }; | 225 | }; |
231 | 226 | let (file_id, decl) = match descr.parent_link_source(&*self.db) { | |
232 | let res = module_tree | 227 | None => return Ok(Vec::new()), |
233 | .modules_for_source(module_source) | 228 | Some(it) => it, |
234 | .into_iter() | 229 | }; |
235 | .filter_map(|module_id| { | 230 | let decl = decl.borrowed(); |
236 | let link = module_id.parent_link(&module_tree)?; | 231 | let decl_name = decl.name().unwrap(); |
237 | let file_id = link.owner(&module_tree).source(&module_tree).file_id(); | 232 | let sym = FileSymbol { |
238 | let decl = link.bind_source(&module_tree, &*self.db); | 233 | name: decl_name.text(), |
239 | let decl = decl.borrowed(); | 234 | node_range: decl_name.syntax().range(), |
240 | 235 | kind: MODULE, | |
241 | let decl_name = decl.name().unwrap(); | 236 | }; |
242 | 237 | Ok(vec![(file_id, sym)]) | |
243 | let sym = FileSymbol { | ||
244 | name: decl_name.text(), | ||
245 | node_range: decl_name.syntax().range(), | ||
246 | kind: MODULE, | ||
247 | }; | ||
248 | Some((file_id, sym)) | ||
249 | }) | ||
250 | .collect(); | ||
251 | Ok(res) | ||
252 | } | 238 | } |
239 | /// Returns `Vec` for the same reason as `parent_module` | ||
253 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { | 240 | pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> { |
254 | let module_tree = self.module_tree(file_id)?; | 241 | let descr = match ModuleDescriptor::guess_from_file_id(&*self.db, file_id)? { |
255 | let crate_graph = self.db.crate_graph(); | 242 | None => return Ok(Vec::new()), |
256 | let res = module_tree | 243 | Some(it) => it, |
257 | .modules_for_source(ModuleSource::SourceFile(file_id)) | 244 | }; |
258 | .into_iter() | 245 | let root = descr.crate_root(); |
259 | .map(|it| it.root(&module_tree)) | 246 | let file_id = root |
260 | .filter_map(|it| it.source(&module_tree).as_file()) | 247 | .source() |
261 | .filter_map(|it| crate_graph.crate_id_for_crate_root(it)) | 248 | .as_file() |
262 | .collect(); | 249 | .expect("root module always has a file as a source"); |
263 | 250 | ||
264 | Ok(res) | 251 | let crate_graph = self.db.crate_graph(); |
252 | let crate_id = crate_graph.crate_id_for_crate_root(file_id); | ||
253 | Ok(crate_id.into_iter().collect()) | ||
265 | } | 254 | } |
266 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { | 255 | pub fn crate_root(&self, crate_id: CrateId) -> FileId { |
267 | self.db.crate_graph().crate_roots[&crate_id] | 256 | self.db.crate_graph().crate_roots[&crate_id] |
@@ -273,7 +262,6 @@ impl AnalysisImpl { | |||
273 | &self, | 262 | &self, |
274 | position: FilePosition, | 263 | position: FilePosition, |
275 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { | 264 | ) -> Cancelable<Vec<(FileId, FileSymbol)>> { |
276 | let module_tree = self.module_tree(position.file_id)?; | ||
277 | let file = self.db.file_syntax(position.file_id); | 265 | let file = self.db.file_syntax(position.file_id); |
278 | let syntax = file.syntax(); | 266 | let syntax = file.syntax(); |
279 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { | 267 | if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(syntax, position.offset) { |
@@ -299,25 +287,23 @@ impl AnalysisImpl { | |||
299 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { | 287 | if let Some(name) = find_node_at_offset::<ast::Name>(syntax, position.offset) { |
300 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { | 288 | if let Some(module) = name.syntax().parent().and_then(ast::Module::cast) { |
301 | if module.has_semi() { | 289 | if module.has_semi() { |
302 | let file_ids = self.resolve_module(&*module_tree, position.file_id, module); | 290 | let parent_module = |
303 | 291 | ModuleDescriptor::guess_from_file_id(&*self.db, position.file_id)?; | |
304 | let res = file_ids | 292 | let child_name = module.name(); |
305 | .into_iter() | 293 | match (parent_module, child_name) { |
306 | .map(|id| { | 294 | (Some(parent_module), Some(child_name)) => { |
307 | let name = module | 295 | if let Some(child) = parent_module.child(&child_name.text()) { |
308 | .name() | 296 | let file_id = child.source().file_id(); |
309 | .map(|n| n.text()) | 297 | let symbol = FileSymbol { |
310 | .unwrap_or_else(|| SmolStr::new("")); | 298 | name: child_name.text(), |
311 | let symbol = FileSymbol { | 299 | node_range: TextRange::offset_len(0.into(), 0.into()), |
312 | name, | 300 | kind: MODULE, |
313 | node_range: TextRange::offset_len(0.into(), 0.into()), | 301 | }; |
314 | kind: MODULE, | 302 | return Ok(vec![(file_id, symbol)]); |
315 | }; | 303 | } |
316 | (id, symbol) | 304 | } |
317 | }) | 305 | _ => (), |
318 | .collect(); | 306 | } |
319 | |||
320 | return Ok(res); | ||
321 | } | 307 | } |
322 | } | 308 | } |
323 | } | 309 | } |
@@ -364,7 +350,6 @@ impl AnalysisImpl { | |||
364 | } | 350 | } |
365 | 351 | ||
366 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { | 352 | pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> { |
367 | let module_tree = self.module_tree(file_id)?; | ||
368 | let syntax = self.db.file_syntax(file_id); | 353 | let syntax = self.db.file_syntax(file_id); |
369 | 354 | ||
370 | let mut res = ra_editor::diagnostics(&syntax) | 355 | let mut res = ra_editor::diagnostics(&syntax) |
@@ -375,8 +360,8 @@ impl AnalysisImpl { | |||
375 | fix: None, | 360 | fix: None, |
376 | }) | 361 | }) |
377 | .collect::<Vec<_>>(); | 362 | .collect::<Vec<_>>(); |
378 | if let Some(m) = module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) { | 363 | if let Some(m) = ModuleDescriptor::guess_from_file_id(&*self.db, file_id)? { |
379 | for (name_node, problem) in m.problems(&module_tree, &*self.db) { | 364 | for (name_node, problem) in m.problems(&*self.db) { |
380 | let diag = match problem { | 365 | let diag = match problem { |
381 | Problem::UnresolvedModule { candidate } => { | 366 | Problem::UnresolvedModule { candidate } => { |
382 | let create_file = FileSystemEdit::CreateFile { | 367 | let create_file = FileSystemEdit::CreateFile { |
@@ -526,27 +511,6 @@ impl AnalysisImpl { | |||
526 | query.limit(4); | 511 | query.limit(4); |
527 | self.world_symbols(query) | 512 | self.world_symbols(query) |
528 | } | 513 | } |
529 | |||
530 | fn resolve_module( | ||
531 | &self, | ||
532 | module_tree: &ModuleTree, | ||
533 | file_id: FileId, | ||
534 | module: ast::Module, | ||
535 | ) -> Vec<FileId> { | ||
536 | let name = match module.name() { | ||
537 | Some(name) => name.text(), | ||
538 | None => return Vec::new(), | ||
539 | }; | ||
540 | let module_id = match module_tree.any_module_for_source(ModuleSource::SourceFile(file_id)) { | ||
541 | Some(id) => id, | ||
542 | None => return Vec::new(), | ||
543 | }; | ||
544 | module_id | ||
545 | .child(module_tree, name.as_str()) | ||
546 | .and_then(|it| it.source(&module_tree).as_file()) | ||
547 | .into_iter() | ||
548 | .collect() | ||
549 | } | ||
550 | } | 514 | } |
551 | 515 | ||
552 | impl SourceChange { | 516 | impl SourceChange { |