diff options
Diffstat (limited to 'crates/ra_analysis/src/descriptors.rs')
-rw-r--r-- | crates/ra_analysis/src/descriptors.rs | 108 |
1 files changed, 58 insertions, 50 deletions
diff --git a/crates/ra_analysis/src/descriptors.rs b/crates/ra_analysis/src/descriptors.rs index 8d9f38ca5..6f26f9935 100644 --- a/crates/ra_analysis/src/descriptors.rs +++ b/crates/ra_analysis/src/descriptors.rs | |||
@@ -1,41 +1,34 @@ | |||
1 | use std::{ | 1 | use crate::{imp::FileResolverImp, FileId}; |
2 | collections::BTreeMap, | ||
3 | }; | ||
4 | use relative_path::RelativePathBuf; | ||
5 | use ra_syntax::{ | 2 | use ra_syntax::{ |
3 | ast::{self, AstNode, NameOwner}, | ||
4 | text_utils::is_subrange, | ||
6 | SmolStr, | 5 | SmolStr, |
7 | ast::{self, NameOwner, AstNode}, | ||
8 | text_utils::is_subrange | ||
9 | }; | ||
10 | use crate::{ | ||
11 | FileId, | ||
12 | imp::FileResolverImp, | ||
13 | }; | 6 | }; |
7 | use relative_path::RelativePathBuf; | ||
8 | |||
9 | use std::collections::BTreeMap; | ||
14 | 10 | ||
15 | #[derive(Debug, PartialEq, Eq, Hash)] | 11 | #[derive(Debug, PartialEq, Eq, Hash)] |
16 | pub struct ModuleDescriptor { | 12 | pub struct ModuleDescriptor { |
17 | pub submodules: Vec<Submodule> | 13 | pub submodules: Vec<Submodule>, |
18 | } | 14 | } |
19 | 15 | ||
20 | impl ModuleDescriptor { | 16 | impl ModuleDescriptor { |
21 | pub fn new(root: ast::Root) -> ModuleDescriptor { | 17 | pub fn new(root: ast::Root) -> ModuleDescriptor { |
22 | let submodules = modules(root) | 18 | let submodules = modules(root).map(|(name, _)| Submodule { name }).collect(); |
23 | .map(|(name, _)| Submodule { name }) | ||
24 | .collect(); | ||
25 | 19 | ||
26 | ModuleDescriptor { submodules } } | 20 | ModuleDescriptor { submodules } |
21 | } | ||
27 | } | 22 | } |
28 | 23 | ||
29 | fn modules<'a>(root: ast::Root<'a>) -> impl Iterator<Item=(SmolStr, ast::Module<'a>)> { | 24 | fn modules<'a>(root: ast::Root<'a>) -> impl Iterator<Item = (SmolStr, ast::Module<'a>)> { |
30 | root | 25 | root.modules().filter_map(|module| { |
31 | .modules() | 26 | let name = module.name()?.text(); |
32 | .filter_map(|module| { | 27 | if !module.has_semi() { |
33 | let name = module.name()?.text(); | 28 | return None; |
34 | if !module.has_semi() { | 29 | } |
35 | return None; | 30 | Some((name, module)) |
36 | } | 31 | }) |
37 | Some((name, module)) | ||
38 | }) | ||
39 | } | 32 | } |
40 | 33 | ||
41 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] | 34 | #[derive(Clone, Hash, PartialEq, Eq, Debug)] |
@@ -56,7 +49,7 @@ struct Node(usize); | |||
56 | struct NodeData { | 49 | struct NodeData { |
57 | file_id: FileId, | 50 | file_id: FileId, |
58 | links: Vec<Link>, | 51 | links: Vec<Link>, |
59 | parents: Vec<Link> | 52 | parents: Vec<Link>, |
60 | } | 53 | } |
61 | 54 | ||
62 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | 55 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
@@ -69,7 +62,6 @@ struct LinkData { | |||
69 | problem: Option<Problem>, | 62 | problem: Option<Problem>, |
70 | } | 63 | } |
71 | 64 | ||
72 | |||
73 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] | 65 | #[derive(Clone, Debug, Hash, PartialEq, Eq)] |
74 | pub enum Problem { | 66 | pub enum Problem { |
75 | UnresolvedModule { | 67 | UnresolvedModule { |
@@ -78,16 +70,18 @@ pub enum Problem { | |||
78 | NotDirOwner { | 70 | NotDirOwner { |
79 | move_to: RelativePathBuf, | 71 | move_to: RelativePathBuf, |
80 | candidate: RelativePathBuf, | 72 | candidate: RelativePathBuf, |
81 | } | 73 | }, |
82 | } | 74 | } |
83 | 75 | ||
84 | impl ModuleTreeDescriptor { | 76 | impl ModuleTreeDescriptor { |
85 | pub(crate) fn new<'a>( | 77 | pub(crate) fn new<'a>( |
86 | files: impl Iterator<Item=(FileId, &'a ModuleDescriptor)> + Clone, | 78 | files: impl Iterator<Item = (FileId, &'a ModuleDescriptor)> + Clone, |
87 | file_resolver: &FileResolverImp, | 79 | file_resolver: &FileResolverImp, |
88 | ) -> ModuleTreeDescriptor { | 80 | ) -> ModuleTreeDescriptor { |
89 | let mut file_id2node = BTreeMap::new(); | 81 | let mut file_id2node = BTreeMap::new(); |
90 | let mut nodes: Vec<NodeData> = files.clone().enumerate() | 82 | let mut nodes: Vec<NodeData> = files |
83 | .clone() | ||
84 | .enumerate() | ||
91 | .map(|(idx, (file_id, _))| { | 85 | .map(|(idx, (file_id, _))| { |
92 | file_id2node.insert(file_id, Node(idx)); | 86 | file_id2node.insert(file_id, Node(idx)); |
93 | NodeData { | 87 | NodeData { |
@@ -120,20 +114,19 @@ impl ModuleTreeDescriptor { | |||
120 | points_to, | 114 | points_to, |
121 | problem, | 115 | problem, |
122 | }) | 116 | }) |
123 | |||
124 | } | 117 | } |
125 | } | 118 | } |
126 | 119 | ||
127 | ModuleTreeDescriptor { | 120 | ModuleTreeDescriptor { |
128 | nodes, links, file_id2node | 121 | nodes, |
122 | links, | ||
123 | file_id2node, | ||
129 | } | 124 | } |
130 | } | 125 | } |
131 | 126 | ||
132 | pub(crate) fn parent_modules(&self, file_id: FileId) -> Vec<Link> { | 127 | pub(crate) fn parent_modules(&self, file_id: FileId) -> Vec<Link> { |
133 | let node = self.file_id2node[&file_id]; | 128 | let node = self.file_id2node[&file_id]; |
134 | self.node(node) | 129 | self.node(node).parents.clone() |
135 | .parents | ||
136 | .clone() | ||
137 | } | 130 | } |
138 | pub(crate) fn child_module_by_name(&self, file_id: FileId, name: &str) -> Vec<FileId> { | 131 | pub(crate) fn child_module_by_name(&self, file_id: FileId, name: &str) -> Vec<FileId> { |
139 | let node = self.file_id2node[&file_id]; | 132 | let node = self.file_id2node[&file_id]; |
@@ -141,10 +134,18 @@ impl ModuleTreeDescriptor { | |||
141 | .links | 134 | .links |
142 | .iter() | 135 | .iter() |
143 | .filter(|it| it.name(self) == name) | 136 | .filter(|it| it.name(self) == name) |
144 | .flat_map(|link| link.points_to(self).iter().map(|&node| self.node(node).file_id)) | 137 | .flat_map(|link| { |
138 | link.points_to(self) | ||
139 | .iter() | ||
140 | .map(|&node| self.node(node).file_id) | ||
141 | }) | ||
145 | .collect() | 142 | .collect() |
146 | } | 143 | } |
147 | pub(crate) fn problems<'a, 'b>(&'b self, file_id: FileId, root: ast::Root<'a>) -> Vec<(ast::Name<'a>, &'b Problem)> { | 144 | pub(crate) fn problems<'a, 'b>( |
145 | &'b self, | ||
146 | file_id: FileId, | ||
147 | root: ast::Root<'a>, | ||
148 | ) -> Vec<(ast::Name<'a>, &'b Problem)> { | ||
148 | let node = self.file_id2node[&file_id]; | 149 | let node = self.file_id2node[&file_id]; |
149 | self.node(node) | 150 | self.node(node) |
150 | .links | 151 | .links |
@@ -176,7 +177,11 @@ impl Link { | |||
176 | fn points_to(self, tree: &ModuleTreeDescriptor) -> &[Node] { | 177 | fn points_to(self, tree: &ModuleTreeDescriptor) -> &[Node] { |
177 | &tree.link(self).points_to | 178 | &tree.link(self).points_to |
178 | } | 179 | } |
179 | pub(crate) fn bind_source<'a>(self, tree: &ModuleTreeDescriptor, root: ast::Root<'a>) -> ast::Module<'a> { | 180 | pub(crate) fn bind_source<'a>( |
181 | self, | ||
182 | tree: &ModuleTreeDescriptor, | ||
183 | root: ast::Root<'a>, | ||
184 | ) -> ast::Module<'a> { | ||
180 | modules(root) | 185 | modules(root) |
181 | .filter(|(name, _)| name == &tree.link(self).name) | 186 | .filter(|(name, _)| name == &tree.link(self).name) |
182 | .next() | 187 | .next() |
@@ -185,22 +190,21 @@ impl Link { | |||
185 | } | 190 | } |
186 | } | 191 | } |
187 | 192 | ||
188 | |||
189 | fn resolve_submodule( | 193 | fn resolve_submodule( |
190 | file_id: FileId, | 194 | file_id: FileId, |
191 | name: &SmolStr, | 195 | name: &SmolStr, |
192 | file_resolver: &FileResolverImp | 196 | file_resolver: &FileResolverImp, |
193 | ) -> (Vec<FileId>, Option<Problem>) { | 197 | ) -> (Vec<FileId>, Option<Problem>) { |
194 | let mod_name = file_resolver.file_stem(file_id); | 198 | let mod_name = file_resolver.file_stem(file_id); |
195 | let is_dir_owner = | 199 | let is_dir_owner = mod_name == "mod" || mod_name == "lib" || mod_name == "main"; |
196 | mod_name == "mod" || mod_name == "lib" || mod_name == "main"; | ||
197 | 200 | ||
198 | let file_mod = RelativePathBuf::from(format!("../{}.rs", name)); | 201 | let file_mod = RelativePathBuf::from(format!("../{}.rs", name)); |
199 | let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name)); | 202 | let dir_mod = RelativePathBuf::from(format!("../{}/mod.rs", name)); |
200 | let points_to: Vec<FileId>; | 203 | let points_to: Vec<FileId>; |
201 | let problem: Option<Problem>; | 204 | let problem: Option<Problem>; |
202 | if is_dir_owner { | 205 | if is_dir_owner { |
203 | points_to = [&file_mod, &dir_mod].iter() | 206 | points_to = [&file_mod, &dir_mod] |
207 | .iter() | ||
204 | .filter_map(|path| file_resolver.resolve(file_id, path)) | 208 | .filter_map(|path| file_resolver.resolve(file_id, path)) |
205 | .collect(); | 209 | .collect(); |
206 | problem = if points_to.is_empty() { | 210 | problem = if points_to.is_empty() { |
@@ -223,7 +227,7 @@ fn resolve_submodule( | |||
223 | #[derive(Debug, Clone)] | 227 | #[derive(Debug, Clone)] |
224 | pub struct FnDescriptor { | 228 | pub struct FnDescriptor { |
225 | pub name: String, | 229 | pub name: String, |
226 | pub label : String, | 230 | pub label: String, |
227 | pub ret_type: Option<String>, | 231 | pub ret_type: Option<String>, |
228 | pub params: Vec<String>, | 232 | pub params: Vec<String>, |
229 | } | 233 | } |
@@ -233,9 +237,11 @@ impl FnDescriptor { | |||
233 | let name = node.name()?.text().to_string(); | 237 | let name = node.name()?.text().to_string(); |
234 | 238 | ||
235 | // Strip the body out for the label. | 239 | // Strip the body out for the label. |
236 | let label : String = if let Some(body) = node.body() { | 240 | let label: String = if let Some(body) = node.body() { |
237 | let body_range = body.syntax().range(); | 241 | let body_range = body.syntax().range(); |
238 | let label : String = node.syntax().children() | 242 | let label: String = node |
243 | .syntax() | ||
244 | .children() | ||
239 | .filter(|child| !is_subrange(body_range, child.range())) | 245 | .filter(|child| !is_subrange(body_range, child.range())) |
240 | .map(|node| node.text().to_string()) | 246 | .map(|node| node.text().to_string()) |
241 | .collect(); | 247 | .collect(); |
@@ -251,7 +257,7 @@ impl FnDescriptor { | |||
251 | name, | 257 | name, |
252 | ret_type, | 258 | ret_type, |
253 | params, | 259 | params, |
254 | label | 260 | label, |
255 | }) | 261 | }) |
256 | } | 262 | } |
257 | 263 | ||
@@ -264,9 +270,11 @@ impl FnDescriptor { | |||
264 | 270 | ||
265 | // Maybe use param.pat here? See if we can just extract the name? | 271 | // Maybe use param.pat here? See if we can just extract the name? |
266 | //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); | 272 | //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); |
267 | res.extend(param_list.params() | 273 | res.extend( |
268 | .filter_map(|p| p.pat()) | 274 | param_list |
269 | .map(|pat| pat.syntax().text().to_string()) | 275 | .params() |
276 | .filter_map(|p| p.pat()) | ||
277 | .map(|pat| pat.syntax().text().to_string()), | ||
270 | ); | 278 | ); |
271 | } | 279 | } |
272 | res | 280 | res |