aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/descriptors.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/descriptors.rs')
-rw-r--r--crates/ra_analysis/src/descriptors.rs108
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 @@
1use std::{ 1use crate::{imp::FileResolverImp, FileId};
2 collections::BTreeMap,
3};
4use relative_path::RelativePathBuf;
5use ra_syntax::{ 2use 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};
10use crate::{
11 FileId,
12 imp::FileResolverImp,
13}; 6};
7use relative_path::RelativePathBuf;
8
9use std::collections::BTreeMap;
14 10
15#[derive(Debug, PartialEq, Eq, Hash)] 11#[derive(Debug, PartialEq, Eq, Hash)]
16pub struct ModuleDescriptor { 12pub struct ModuleDescriptor {
17 pub submodules: Vec<Submodule> 13 pub submodules: Vec<Submodule>,
18} 14}
19 15
20impl ModuleDescriptor { 16impl 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
29fn modules<'a>(root: ast::Root<'a>) -> impl Iterator<Item=(SmolStr, ast::Module<'a>)> { 24fn 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);
56struct NodeData { 49struct 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)]
74pub enum Problem { 66pub 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
84impl ModuleTreeDescriptor { 76impl 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
189fn resolve_submodule( 193fn 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)]
224pub struct FnDescriptor { 228pub 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