From 0ab3c65d9819765016c926df4aca634b5be8344c Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 20 Nov 2018 16:40:15 +0300 Subject: Use OO API in crate_for --- crates/ra_analysis/src/descriptors/module/mod.rs | 37 ++++++++++++++++++++++-- crates/ra_analysis/src/imp.rs | 25 +++++++++------- 2 files changed, 50 insertions(+), 12 deletions(-) diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs index 8a75e11be..16faea94e 100644 --- a/crates/ra_analysis/src/descriptors/module/mod.rs +++ b/crates/ra_analysis/src/descriptors/module/mod.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use ra_editor::find_node_at_offset; use ra_syntax::{ + algo::generate, ast::{self, AstNode, NameOwner}, SmolStr, SyntaxNode, SyntaxNodeRef, }; @@ -27,6 +28,16 @@ pub(crate) struct ModuleDescriptor { } impl ModuleDescriptor { + /// Lookup `ModuleDescriptor` by `FileId`. Note that this is inherently + /// lossy transformation: in general, a single source might correspond to + /// several modules. + pub fn guess_from_file_id( + db: &impl DescriptorDatabase, + file_id: FileId, + ) -> Cancelable> { + ModuleDescriptor::guess_from_source(db, file_id, ModuleSource::SourceFile(file_id)) + } + /// Lookup `ModuleDescriptor` by position in the source code. Note that this /// is inherently lossy transformation: in general, a single source might /// correspond to several modules. @@ -34,14 +45,23 @@ impl ModuleDescriptor { db: &impl DescriptorDatabase, position: FilePosition, ) -> Cancelable> { - let source_root = db.file_source_root(position.file_id); - let module_tree = db.module_tree(source_root)?; let file = db.file_syntax(position.file_id); let module_source = match find_node_at_offset::(file.syntax(), position.offset) { Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m), _ => ModuleSource::SourceFile(position.file_id), }; + ModuleDescriptor::guess_from_source(db, position.file_id, module_source) + } + + fn guess_from_source( + db: &impl DescriptorDatabase, + file_id: FileId, + module_source: ModuleSource, + ) -> Cancelable> { + let source_root = db.file_source_root(file_id); + let module_tree = db.module_tree(source_root)?; + let res = match module_tree.any_module_for_source(module_source) { None => None, Some(module_id) => Some(ModuleDescriptor { @@ -64,6 +84,11 @@ impl ModuleDescriptor { Some((file_id, src)) } + pub fn source(&self) -> ModuleSource { + self.module_id.source(&self.tree) + } + + /// Parent module. Returns `None` if this is a root module. pub fn parent(&self) -> Option { let parent_id = self.module_id.parent(&self.tree)?; Some(ModuleDescriptor { @@ -71,6 +96,14 @@ impl ModuleDescriptor { module_id: parent_id, }) } + + /// The root of the tree this module is part of + pub fn crate_root(&self) -> ModuleDescriptor { + generate(Some(self.clone()), |it| it.parent()) + .last() + .unwrap() + } + /// `name` is `None` for the crate's root module pub fn name(&self) -> Option { let link = self.module_id.parent_link(&self.tree)?; diff --git a/crates/ra_analysis/src/imp.rs b/crates/ra_analysis/src/imp.rs index c0bed04bf..49b863756 100644 --- a/crates/ra_analysis/src/imp.rs +++ b/crates/ra_analysis/src/imp.rs @@ -220,6 +220,8 @@ impl AnalysisImpl { let source_root = self.db.file_source_root(file_id); self.db.module_tree(source_root) } + /// This return `Vec`: a module may be inclucded from several places. + /// We don't handle this case yet though, so the Vec has length at most one. pub fn parent_module(&self, position: FilePosition) -> Cancelable> { let descr = match ModuleDescriptor::guess_from_position(&*self.db, position)? { None => return Ok(Vec::new()), @@ -238,18 +240,21 @@ impl AnalysisImpl { }; Ok(vec![(file_id, sym)]) } + /// Returns `Vec` for the same reason as `parent_module` pub fn crate_for(&self, file_id: FileId) -> Cancelable> { - let module_tree = self.module_tree(file_id)?; - let crate_graph = self.db.crate_graph(); - let res = module_tree - .modules_for_source(ModuleSource::SourceFile(file_id)) - .into_iter() - .map(|it| it.root(&module_tree)) - .filter_map(|it| it.source(&module_tree).as_file()) - .filter_map(|it| crate_graph.crate_id_for_crate_root(it)) - .collect(); + let descr = match ModuleDescriptor::guess_from_file_id(&*self.db, file_id)? { + None => return Ok(Vec::new()), + Some(it) => it, + }; + let root = descr.crate_root(); + let file_id = root + .source() + .as_file() + .expect("root module always has a file as a source"); - Ok(res) + let crate_graph = self.db.crate_graph(); + let crate_id = crate_graph.crate_id_for_crate_root(file_id); + Ok(crate_id.into_iter().collect()) } pub fn crate_root(&self, crate_id: CrateId) -> FileId { self.db.crate_graph().crate_roots[&crate_id] -- cgit v1.2.3