diff options
Diffstat (limited to 'crates/ra_analysis/src/descriptors/module')
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/mod.rs | 37 |
1 files changed, 35 insertions, 2 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; | |||
6 | use ra_editor::find_node_at_offset; | 6 | use ra_editor::find_node_at_offset; |
7 | 7 | ||
8 | use ra_syntax::{ | 8 | use ra_syntax::{ |
9 | algo::generate, | ||
9 | ast::{self, AstNode, NameOwner}, | 10 | ast::{self, AstNode, NameOwner}, |
10 | SmolStr, SyntaxNode, SyntaxNodeRef, | 11 | SmolStr, SyntaxNode, SyntaxNodeRef, |
11 | }; | 12 | }; |
@@ -27,6 +28,16 @@ pub(crate) struct ModuleDescriptor { | |||
27 | } | 28 | } |
28 | 29 | ||
29 | impl ModuleDescriptor { | 30 | impl ModuleDescriptor { |
31 | /// Lookup `ModuleDescriptor` by `FileId`. Note that this is inherently | ||
32 | /// lossy transformation: in general, a single source might correspond to | ||
33 | /// several modules. | ||
34 | pub fn guess_from_file_id( | ||
35 | db: &impl DescriptorDatabase, | ||
36 | file_id: FileId, | ||
37 | ) -> Cancelable<Option<ModuleDescriptor>> { | ||
38 | ModuleDescriptor::guess_from_source(db, file_id, ModuleSource::SourceFile(file_id)) | ||
39 | } | ||
40 | |||
30 | /// Lookup `ModuleDescriptor` by position in the source code. Note that this | 41 | /// Lookup `ModuleDescriptor` by position in the source code. Note that this |
31 | /// is inherently lossy transformation: in general, a single source might | 42 | /// is inherently lossy transformation: in general, a single source might |
32 | /// correspond to several modules. | 43 | /// correspond to several modules. |
@@ -34,14 +45,23 @@ impl ModuleDescriptor { | |||
34 | db: &impl DescriptorDatabase, | 45 | db: &impl DescriptorDatabase, |
35 | position: FilePosition, | 46 | position: FilePosition, |
36 | ) -> Cancelable<Option<ModuleDescriptor>> { | 47 | ) -> Cancelable<Option<ModuleDescriptor>> { |
37 | let source_root = db.file_source_root(position.file_id); | ||
38 | let module_tree = db.module_tree(source_root)?; | ||
39 | let file = db.file_syntax(position.file_id); | 48 | let file = db.file_syntax(position.file_id); |
40 | let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) | 49 | let module_source = match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) |
41 | { | 50 | { |
42 | Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m), | 51 | Some(m) if !m.has_semi() => ModuleSource::new_inline(position.file_id, m), |
43 | _ => ModuleSource::SourceFile(position.file_id), | 52 | _ => ModuleSource::SourceFile(position.file_id), |
44 | }; | 53 | }; |
54 | ModuleDescriptor::guess_from_source(db, position.file_id, module_source) | ||
55 | } | ||
56 | |||
57 | fn guess_from_source( | ||
58 | db: &impl DescriptorDatabase, | ||
59 | file_id: FileId, | ||
60 | module_source: ModuleSource, | ||
61 | ) -> Cancelable<Option<ModuleDescriptor>> { | ||
62 | let source_root = db.file_source_root(file_id); | ||
63 | let module_tree = db.module_tree(source_root)?; | ||
64 | |||
45 | let res = match module_tree.any_module_for_source(module_source) { | 65 | let res = match module_tree.any_module_for_source(module_source) { |
46 | None => None, | 66 | None => None, |
47 | Some(module_id) => Some(ModuleDescriptor { | 67 | Some(module_id) => Some(ModuleDescriptor { |
@@ -64,6 +84,11 @@ impl ModuleDescriptor { | |||
64 | Some((file_id, src)) | 84 | Some((file_id, src)) |
65 | } | 85 | } |
66 | 86 | ||
87 | pub fn source(&self) -> ModuleSource { | ||
88 | self.module_id.source(&self.tree) | ||
89 | } | ||
90 | |||
91 | /// Parent module. Returns `None` if this is a root module. | ||
67 | pub fn parent(&self) -> Option<ModuleDescriptor> { | 92 | pub fn parent(&self) -> Option<ModuleDescriptor> { |
68 | let parent_id = self.module_id.parent(&self.tree)?; | 93 | let parent_id = self.module_id.parent(&self.tree)?; |
69 | Some(ModuleDescriptor { | 94 | Some(ModuleDescriptor { |
@@ -71,6 +96,14 @@ impl ModuleDescriptor { | |||
71 | module_id: parent_id, | 96 | module_id: parent_id, |
72 | }) | 97 | }) |
73 | } | 98 | } |
99 | |||
100 | /// The root of the tree this module is part of | ||
101 | pub fn crate_root(&self) -> ModuleDescriptor { | ||
102 | generate(Some(self.clone()), |it| it.parent()) | ||
103 | .last() | ||
104 | .unwrap() | ||
105 | } | ||
106 | |||
74 | /// `name` is `None` for the crate's root module | 107 | /// `name` is `None` for the crate's root module |
75 | pub fn name(&self) -> Option<SmolStr> { | 108 | pub fn name(&self) -> Option<SmolStr> { |
76 | let link = self.module_id.parent_link(&self.tree)?; | 109 | let link = self.module_id.parent_link(&self.tree)?; |