aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/descriptors')
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs8
-rw-r--r--crates/ra_analysis/src/descriptors/module/imp.rs149
-rw-r--r--crates/ra_analysis/src/descriptors/module/mod.rs29
3 files changed, 132 insertions, 54 deletions
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs
index eaeef54c1..56bde3849 100644
--- a/crates/ra_analysis/src/descriptors/mod.rs
+++ b/crates/ra_analysis/src/descriptors/mod.rs
@@ -5,16 +5,16 @@ use std::sync::Arc;
5 5
6use ra_syntax::{ 6use ra_syntax::{
7 ast::{self, AstNode, FnDefNode}, 7 ast::{self, AstNode, FnDefNode},
8 SmolStr, TextRange, 8 TextRange,
9}; 9};
10 10
11use crate::{ 11use crate::{
12 db::SyntaxDatabase, 12 db::SyntaxDatabase,
13 descriptors::function::{resolve_local_name, FnId, FnScopes}, 13 descriptors::function::{resolve_local_name, FnId, FnScopes},
14 descriptors::module::{ModuleId, ModuleScope, ModuleTree}, 14 descriptors::module::{ModuleId, ModuleScope, ModuleTree, ModuleSource},
15 input::SourceRootId, 15 input::SourceRootId,
16 syntax_ptr::LocalSyntaxPtr, 16 syntax_ptr::LocalSyntaxPtr,
17 Cancelable, FileId, 17 Cancelable,
18}; 18};
19 19
20salsa::query_group! { 20salsa::query_group! {
@@ -23,7 +23,7 @@ salsa::query_group! {
23 type ModuleTreeQuery; 23 type ModuleTreeQuery;
24 use fn module::imp::module_tree; 24 use fn module::imp::module_tree;
25 } 25 }
26 fn submodules(file_id: FileId) -> Cancelable<Arc<Vec<SmolStr>>> { 26 fn submodules(source: ModuleSource) -> Cancelable<Arc<Vec<module::imp::Submodule>>> {
27 type SubmodulesQuery; 27 type SubmodulesQuery;
28 use fn module::imp::submodules; 28 use fn module::imp::submodules;
29 } 29 }
diff --git a/crates/ra_analysis/src/descriptors/module/imp.rs b/crates/ra_analysis/src/descriptors/module/imp.rs
index 3a010ecf5..b3b1f1f21 100644
--- a/crates/ra_analysis/src/descriptors/module/imp.rs
+++ b/crates/ra_analysis/src/descriptors/module/imp.rs
@@ -19,25 +19,66 @@ use super::{
19 ModuleTree, Problem, 19 ModuleTree, Problem,
20}; 20};
21 21
22#[derive(Clone, Hash, PartialEq, Eq, Debug)]
23pub(crate) enum Submodule {
24 Declaration(SmolStr),
25 Definition(SmolStr, ModuleSource),
26}
27
28impl Submodule {
29 fn name(&self) -> &SmolStr {
30 match self {
31 Submodule::Declaration(name) => name,
32 Submodule::Definition(name, _) => name,
33 }
34 }
35}
36
22pub(crate) fn submodules( 37pub(crate) fn submodules(
23 db: &impl DescriptorDatabase, 38 db: &impl DescriptorDatabase,
24 file_id: FileId, 39 source: ModuleSource,
25) -> Cancelable<Arc<Vec<SmolStr>>> { 40) -> Cancelable<Arc<Vec<Submodule>>> {
26 db::check_canceled(db)?; 41 db::check_canceled(db)?;
27 let file = db.file_syntax(file_id); 42 let file_id = source.file_id();
28 let root = file.ast(); 43 let submodules = match source.resolve(db) {
29 let submodules = modules(root).map(|(name, _)| name).collect(); 44 ModuleSourceNode::Root(it) => collect_submodules(file_id, it.ast()),
30 Ok(Arc::new(submodules)) 45 ModuleSourceNode::Inline(it) => it
46 .ast()
47 .item_list()
48 .map(|it| collect_submodules(file_id, it))
49 .unwrap_or_else(Vec::new),
50 };
51 return Ok(Arc::new(submodules));
52
53 fn collect_submodules<'a>(
54 file_id: FileId,
55 root: impl ast::ModuleItemOwner<'a>,
56 ) -> Vec<Submodule> {
57 modules(root)
58 .map(|(name, m)| {
59 if m.has_semi() {
60 Submodule::Declaration(name)
61 } else {
62 let src = ModuleSource::new_inline(file_id, m);
63 Submodule::Definition(name, src)
64 }
65 })
66 .collect()
67 }
31} 68}
32 69
33pub(crate) fn modules(root: ast::Root<'_>) -> impl Iterator<Item = (SmolStr, ast::Module<'_>)> { 70pub(crate) fn modules<'a>(
34 root.modules().filter_map(|module| { 71 root: impl ast::ModuleItemOwner<'a>,
35 let name = module.name()?.text(); 72) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> {
36 if !module.has_semi() { 73 root.items()
37 return None; 74 .filter_map(|item| match item {
38 } 75 ast::ModuleItem::Module(m) => Some(m),
39 Some((name, module)) 76 _ => None,
40 }) 77 })
78 .filter_map(|module| {
79 let name = module.name()?.text();
80 Some((name, module))
81 })
41} 82}
42 83
43pub(crate) fn module_scope( 84pub(crate) fn module_scope(
@@ -66,11 +107,6 @@ pub(crate) fn module_tree(
66 Ok(Arc::new(res)) 107 Ok(Arc::new(res))
67} 108}
68 109
69#[derive(Clone, Hash, PartialEq, Eq, Debug)]
70pub struct Submodule {
71 pub name: SmolStr,
72}
73
74fn create_module_tree<'a>( 110fn create_module_tree<'a>(
75 db: &impl DescriptorDatabase, 111 db: &impl DescriptorDatabase,
76 source_root: SourceRootId, 112 source_root: SourceRootId,
@@ -85,7 +121,8 @@ fn create_module_tree<'a>(
85 121
86 let source_root = db.source_root(source_root); 122 let source_root = db.source_root(source_root);
87 for &file_id in source_root.files.iter() { 123 for &file_id in source_root.files.iter() {
88 if visited.contains(&file_id) { 124 let source = ModuleSource::File(file_id);
125 if visited.contains(&source) {
89 continue; // TODO: use explicit crate_roots here 126 continue; // TODO: use explicit crate_roots here
90 } 127 }
91 assert!(!roots.contains_key(&file_id)); 128 assert!(!roots.contains_key(&file_id));
@@ -96,7 +133,7 @@ fn create_module_tree<'a>(
96 &mut visited, 133 &mut visited,
97 &mut roots, 134 &mut roots,
98 None, 135 None,
99 file_id, 136 source,
100 )?; 137 )?;
101 roots.insert(file_id, module_id); 138 roots.insert(file_id, module_id);
102 } 139 }
@@ -107,36 +144,63 @@ fn build_subtree(
107 db: &impl DescriptorDatabase, 144 db: &impl DescriptorDatabase,
108 source_root: &SourceRoot, 145 source_root: &SourceRoot,
109 tree: &mut ModuleTree, 146 tree: &mut ModuleTree,
110 visited: &mut FxHashSet<FileId>, 147 visited: &mut FxHashSet<ModuleSource>,
111 roots: &mut FxHashMap<FileId, ModuleId>, 148 roots: &mut FxHashMap<FileId, ModuleId>,
112 parent: Option<LinkId>, 149 parent: Option<LinkId>,
113 file_id: FileId, 150 source: ModuleSource,
114) -> Cancelable<ModuleId> { 151) -> Cancelable<ModuleId> {
115 visited.insert(file_id); 152 visited.insert(source);
116 let id = tree.push_mod(ModuleData { 153 let id = tree.push_mod(ModuleData {
117 source: ModuleSource::File(file_id), 154 source,
118 parent, 155 parent,
119 children: Vec::new(), 156 children: Vec::new(),
120 }); 157 });
121 for name in db.submodules(file_id)?.iter() { 158 for sub in db.submodules(source)?.iter() {
122 let (points_to, problem) = resolve_submodule(file_id, name, &source_root.file_resolver);
123 let link = tree.push_link(LinkData { 159 let link = tree.push_link(LinkData {
124 name: name.clone(), 160 name: sub.name().clone(),
125 owner: id, 161 owner: id,
126 points_to: Vec::new(), 162 points_to: Vec::new(),
127 problem: None, 163 problem: None,
128 }); 164 });
129 165
130 let points_to = points_to 166 let (points_to, problem) = match sub {
131 .into_iter() 167 Submodule::Declaration(name) => {
132 .map(|file_id| match roots.remove(&file_id) { 168 let (points_to, problem) =
133 Some(module_id) => { 169 resolve_submodule(source, &name, &source_root.file_resolver);
134 tree.module_mut(module_id).parent = Some(link); 170 let points_to = points_to
135 Ok(module_id) 171 .into_iter()
136 } 172 .map(|file_id| match roots.remove(&file_id) {
137 None => build_subtree(db, source_root, tree, visited, roots, Some(link), file_id), 173 Some(module_id) => {
138 }) 174 tree.module_mut(module_id).parent = Some(link);
139 .collect::<Cancelable<Vec<_>>>()?; 175 Ok(module_id)
176 }
177 None => build_subtree(
178 db,
179 source_root,
180 tree,
181 visited,
182 roots,
183 Some(link),
184 ModuleSource::File(file_id),
185 ),
186 })
187 .collect::<Cancelable<Vec<_>>>()?;
188 (points_to, problem)
189 }
190 Submodule::Definition(_name, submodule_source) => {
191 let points_to = build_subtree(
192 db,
193 source_root,
194 tree,
195 visited,
196 roots,
197 Some(link),
198 *submodule_source,
199 )?;
200 (vec![points_to], None)
201 }
202 };
203
140 tree.link_mut(link).points_to = points_to; 204 tree.link_mut(link).points_to = points_to;
141 tree.link_mut(link).problem = problem; 205 tree.link_mut(link).problem = problem;
142 } 206 }
@@ -144,10 +208,17 @@ fn build_subtree(
144} 208}
145 209
146fn resolve_submodule( 210fn resolve_submodule(
147 file_id: FileId, 211 source: ModuleSource,
148 name: &SmolStr, 212 name: &SmolStr,
149 file_resolver: &FileResolverImp, 213 file_resolver: &FileResolverImp,
150) -> (Vec<FileId>, Option<Problem>) { 214) -> (Vec<FileId>, Option<Problem>) {
215 let file_id = match source {
216 ModuleSource::File(it) => it,
217 ModuleSource::Inline(..) => {
218 // TODO
219 return (Vec::new(), None);
220 }
221 };
151 let mod_name = file_resolver.file_stem(file_id); 222 let mod_name = file_resolver.file_stem(file_id);
152 let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; 223 let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main";
153 224
diff --git a/crates/ra_analysis/src/descriptors/module/mod.rs b/crates/ra_analysis/src/descriptors/module/mod.rs
index e22489fc1..3d799ba05 100644
--- a/crates/ra_analysis/src/descriptors/module/mod.rs
+++ b/crates/ra_analysis/src/descriptors/module/mod.rs
@@ -25,17 +25,17 @@ pub(crate) struct ModuleTree {
25} 25}
26 26
27impl ModuleTree { 27impl ModuleTree {
28 pub(crate) fn modules_for_file(&self, file_id: FileId) -> Vec<ModuleId> { 28 pub(crate) fn modules_for_source(&self, source: ModuleSource) -> Vec<ModuleId> {
29 self.mods 29 self.mods
30 .iter() 30 .iter()
31 .enumerate() 31 .enumerate()
32 .filter(|(_idx, it)| it.source.is_file(file_id)) 32 .filter(|(_idx, it)| it.source == source)
33 .map(|(idx, _)| ModuleId(idx as u32)) 33 .map(|(idx, _)| ModuleId(idx as u32))
34 .collect() 34 .collect()
35 } 35 }
36 36
37 pub(crate) fn any_module_for_file(&self, file_id: FileId) -> Option<ModuleId> { 37 pub(crate) fn any_module_for_source(&self, source: ModuleSource) -> Option<ModuleId> {
38 self.modules_for_file(file_id).pop() 38 self.modules_for_source(source).pop()
39 } 39 }
40} 40}
41 41
@@ -142,9 +142,7 @@ impl LinkId {
142 .1; 142 .1;
143 ast.into() 143 ast.into()
144 } 144 }
145 ModuleSourceNode::Inline(..) => { 145 ModuleSourceNode::Inline(it) => it,
146 unimplemented!("https://github.com/rust-analyzer/rust-analyzer/issues/181")
147 }
148 } 146 }
149 } 147 }
150} 148}
@@ -157,6 +155,12 @@ struct ModuleData {
157} 155}
158 156
159impl ModuleSource { 157impl ModuleSource {
158 pub(crate) fn new_inline(file_id: FileId, module: ast::Module) -> ModuleSource {
159 assert!(!module.has_semi());
160 let ptr = SyntaxPtr::new(file_id, module.syntax());
161 ModuleSource::Inline(ptr)
162 }
163
160 pub(crate) fn as_file(self) -> Option<FileId> { 164 pub(crate) fn as_file(self) -> Option<FileId> {
161 match self { 165 match self {
162 ModuleSource::File(f) => Some(f), 166 ModuleSource::File(f) => Some(f),
@@ -164,6 +168,13 @@ impl ModuleSource {
164 } 168 }
165 } 169 }
166 170
171 pub(crate) fn file_id(self) -> FileId {
172 match self {
173 ModuleSource::File(f) => f,
174 ModuleSource::Inline(ptr) => ptr.file_id(),
175 }
176 }
177
167 fn resolve(self, db: &impl SyntaxDatabase) -> ModuleSourceNode { 178 fn resolve(self, db: &impl SyntaxDatabase) -> ModuleSourceNode {
168 match self { 179 match self {
169 ModuleSource::File(file_id) => { 180 ModuleSource::File(file_id) => {
@@ -178,10 +189,6 @@ impl ModuleSource {
178 } 189 }
179 } 190 }
180 } 191 }
181
182 fn is_file(self, file_id: FileId) -> bool {
183 self.as_file() == Some(file_id)
184 }
185} 192}
186 193
187#[derive(Hash, Debug, PartialEq, Eq)] 194#[derive(Hash, Debug, PartialEq, Eq)]