diff options
Diffstat (limited to 'crates/ra_analysis/src/descriptors')
-rw-r--r-- | crates/ra_analysis/src/descriptors/mod.rs | 21 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/module/nameres.rs | 82 | ||||
-rw-r--r-- | crates/ra_analysis/src/descriptors/path.rs | 106 |
3 files changed, 117 insertions, 92 deletions
diff --git a/crates/ra_analysis/src/descriptors/mod.rs b/crates/ra_analysis/src/descriptors/mod.rs index 82658211f..e6225479d 100644 --- a/crates/ra_analysis/src/descriptors/mod.rs +++ b/crates/ra_analysis/src/descriptors/mod.rs | |||
@@ -1,11 +1,12 @@ | |||
1 | pub(crate) mod function; | 1 | pub(crate) mod function; |
2 | pub(crate) mod module; | 2 | pub(crate) mod module; |
3 | mod path; | ||
3 | 4 | ||
4 | use std::sync::Arc; | 5 | use std::sync::Arc; |
5 | 6 | ||
6 | use ra_syntax::{ | 7 | use ra_syntax::{ |
7 | ast::{self, AstNode, FnDefNode}, | 8 | ast::{self, FnDefNode}, |
8 | TextRange, SmolStr, | 9 | TextRange, |
9 | }; | 10 | }; |
10 | 11 | ||
11 | use crate::{ | 12 | use crate::{ |
@@ -18,6 +19,8 @@ use crate::{ | |||
18 | Cancelable, | 19 | Cancelable, |
19 | }; | 20 | }; |
20 | 21 | ||
22 | pub(crate) use self::path::{Path, PathKind}; | ||
23 | |||
21 | salsa::query_group! { | 24 | salsa::query_group! { |
22 | pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase { | 25 | pub(crate) trait DescriptorDatabase: SyntaxDatabase + IdDatabase { |
23 | fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> { | 26 | fn fn_scopes(fn_id: FnId) -> Arc<FnScopes> { |
@@ -50,20 +53,6 @@ salsa::query_group! { | |||
50 | } | 53 | } |
51 | } | 54 | } |
52 | 55 | ||
53 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
54 | pub(crate) struct Path { | ||
55 | kind: PathKind, | ||
56 | segments: Vec<SmolStr>, | ||
57 | } | ||
58 | |||
59 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
60 | pub(crate) enum PathKind { | ||
61 | Abs, | ||
62 | Self_, | ||
63 | Super, | ||
64 | Crate, | ||
65 | } | ||
66 | |||
67 | #[derive(Debug)] | 56 | #[derive(Debug)] |
68 | pub struct ReferenceDescriptor { | 57 | pub struct ReferenceDescriptor { |
69 | pub range: TextRange, | 58 | pub range: TextRange, |
diff --git a/crates/ra_analysis/src/descriptors/module/nameres.rs b/crates/ra_analysis/src/descriptors/module/nameres.rs index 526e42af3..bf671470c 100644 --- a/crates/ra_analysis/src/descriptors/module/nameres.rs +++ b/crates/ra_analysis/src/descriptors/module/nameres.rs | |||
@@ -195,86 +195,16 @@ impl InputModuleItems { | |||
195 | } | 195 | } |
196 | 196 | ||
197 | fn add_use_item(&mut self, item: ast::UseItem) { | 197 | fn add_use_item(&mut self, item: ast::UseItem) { |
198 | if let Some(tree) = item.use_tree() { | 198 | Path::expand_use_item(item, |path, ptr| { |
199 | self.add_use_tree(None, tree); | 199 | let kind = match ptr { |
200 | } | 200 | None => ImportKind::Glob, |
201 | } | 201 | Some(ptr) => ImportKind::Named(ptr), |
202 | |||
203 | fn add_use_tree(&mut self, prefix: Option<Path>, tree: ast::UseTree) { | ||
204 | if let Some(use_tree_list) = tree.use_tree_list() { | ||
205 | let prefix = match tree.path() { | ||
206 | None => prefix, | ||
207 | Some(path) => match convert_path(prefix, path) { | ||
208 | Some(it) => Some(it), | ||
209 | None => return, // TODO: report errors somewhere | ||
210 | }, | ||
211 | }; | 202 | }; |
212 | for tree in use_tree_list.use_trees() { | 203 | self.imports.push(Import { kind, path }) |
213 | self.add_use_tree(prefix.clone(), tree); | 204 | }) |
214 | } | ||
215 | } else { | ||
216 | if let Some(ast_path) = tree.path() { | ||
217 | if let Some(path) = convert_path(prefix, ast_path) { | ||
218 | let kind = if tree.has_star() { | ||
219 | ImportKind::Glob | ||
220 | } else { | ||
221 | let ptr = LocalSyntaxPtr::new(ast_path.segment().unwrap().syntax()); | ||
222 | ImportKind::Named(ptr) | ||
223 | }; | ||
224 | self.imports.push(Import { kind, path }) | ||
225 | } | ||
226 | } | ||
227 | } | ||
228 | } | 205 | } |
229 | } | 206 | } |
230 | 207 | ||
231 | fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> { | ||
232 | let prefix = if let Some(qual) = path.qualifier() { | ||
233 | Some(convert_path(prefix, qual)?) | ||
234 | } else { | ||
235 | None | ||
236 | }; | ||
237 | let segment = path.segment()?; | ||
238 | let res = match segment.kind()? { | ||
239 | ast::PathSegmentKind::Name(name) => { | ||
240 | let mut res = prefix.unwrap_or_else(|| Path { | ||
241 | kind: PathKind::Abs, | ||
242 | segments: Vec::with_capacity(1), | ||
243 | }); | ||
244 | res.segments.push(name.text()); | ||
245 | res | ||
246 | } | ||
247 | ast::PathSegmentKind::CrateKw => { | ||
248 | if prefix.is_some() { | ||
249 | return None; | ||
250 | } | ||
251 | Path { | ||
252 | kind: PathKind::Crate, | ||
253 | segments: Vec::new(), | ||
254 | } | ||
255 | } | ||
256 | ast::PathSegmentKind::SelfKw => { | ||
257 | if prefix.is_some() { | ||
258 | return None; | ||
259 | } | ||
260 | Path { | ||
261 | kind: PathKind::Self_, | ||
262 | segments: Vec::new(), | ||
263 | } | ||
264 | } | ||
265 | ast::PathSegmentKind::SuperKw => { | ||
266 | if prefix.is_some() { | ||
267 | return None; | ||
268 | } | ||
269 | Path { | ||
270 | kind: PathKind::Super, | ||
271 | segments: Vec::new(), | ||
272 | } | ||
273 | } | ||
274 | }; | ||
275 | Some(res) | ||
276 | } | ||
277 | |||
278 | impl ModuleItem { | 208 | impl ModuleItem { |
279 | fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> { | 209 | fn new<'a>(item: impl ast::NameOwner<'a>) -> Option<ModuleItem> { |
280 | let name = item.name()?.text(); | 210 | let name = item.name()?.text(); |
diff --git a/crates/ra_analysis/src/descriptors/path.rs b/crates/ra_analysis/src/descriptors/path.rs new file mode 100644 index 000000000..4ed561b51 --- /dev/null +++ b/crates/ra_analysis/src/descriptors/path.rs | |||
@@ -0,0 +1,106 @@ | |||
1 | use ra_syntax::{SmolStr, ast, AstNode}; | ||
2 | |||
3 | use crate::syntax_ptr::LocalSyntaxPtr; | ||
4 | |||
5 | #[derive(Debug, Clone, PartialEq, Eq)] | ||
6 | pub(crate) struct Path { | ||
7 | pub(crate) kind: PathKind, | ||
8 | pub(crate) segments: Vec<SmolStr>, | ||
9 | } | ||
10 | |||
11 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | ||
12 | pub(crate) enum PathKind { | ||
13 | Abs, | ||
14 | Self_, | ||
15 | Super, | ||
16 | Crate, | ||
17 | } | ||
18 | |||
19 | impl Path { | ||
20 | pub(crate) fn expand_use_item( | ||
21 | item: ast::UseItem, | ||
22 | mut cb: impl FnMut(Path, Option<LocalSyntaxPtr>), | ||
23 | ) { | ||
24 | if let Some(tree) = item.use_tree() { | ||
25 | expand_use_tree(None, tree, &mut cb); | ||
26 | } | ||
27 | } | ||
28 | } | ||
29 | |||
30 | fn expand_use_tree( | ||
31 | prefix: Option<Path>, | ||
32 | tree: ast::UseTree, | ||
33 | cb: &mut impl FnMut(Path, Option<LocalSyntaxPtr>), | ||
34 | ) { | ||
35 | if let Some(use_tree_list) = tree.use_tree_list() { | ||
36 | let prefix = match tree.path() { | ||
37 | None => prefix, | ||
38 | Some(path) => match convert_path(prefix, path) { | ||
39 | Some(it) => Some(it), | ||
40 | None => return, // TODO: report errors somewhere | ||
41 | }, | ||
42 | }; | ||
43 | for tree in use_tree_list.use_trees() { | ||
44 | expand_use_tree(prefix.clone(), tree, cb); | ||
45 | } | ||
46 | } else { | ||
47 | if let Some(ast_path) = tree.path() { | ||
48 | if let Some(path) = convert_path(prefix, ast_path) { | ||
49 | let ptr = if tree.has_star() { | ||
50 | None | ||
51 | } else { | ||
52 | let ptr = LocalSyntaxPtr::new(ast_path.segment().unwrap().syntax()); | ||
53 | Some(ptr) | ||
54 | }; | ||
55 | cb(path, ptr) | ||
56 | } | ||
57 | } | ||
58 | } | ||
59 | } | ||
60 | |||
61 | fn convert_path(prefix: Option<Path>, path: ast::Path) -> Option<Path> { | ||
62 | let prefix = if let Some(qual) = path.qualifier() { | ||
63 | Some(convert_path(prefix, qual)?) | ||
64 | } else { | ||
65 | None | ||
66 | }; | ||
67 | let segment = path.segment()?; | ||
68 | let res = match segment.kind()? { | ||
69 | ast::PathSegmentKind::Name(name) => { | ||
70 | let mut res = prefix.unwrap_or_else(|| Path { | ||
71 | kind: PathKind::Abs, | ||
72 | segments: Vec::with_capacity(1), | ||
73 | }); | ||
74 | res.segments.push(name.text()); | ||
75 | res | ||
76 | } | ||
77 | ast::PathSegmentKind::CrateKw => { | ||
78 | if prefix.is_some() { | ||
79 | return None; | ||
80 | } | ||
81 | Path { | ||
82 | kind: PathKind::Crate, | ||
83 | segments: Vec::new(), | ||
84 | } | ||
85 | } | ||
86 | ast::PathSegmentKind::SelfKw => { | ||
87 | if prefix.is_some() { | ||
88 | return None; | ||
89 | } | ||
90 | Path { | ||
91 | kind: PathKind::Self_, | ||
92 | segments: Vec::new(), | ||
93 | } | ||
94 | } | ||
95 | ast::PathSegmentKind::SuperKw => { | ||
96 | if prefix.is_some() { | ||
97 | return None; | ||
98 | } | ||
99 | Path { | ||
100 | kind: PathKind::Super, | ||
101 | segments: Vec::new(), | ||
102 | } | ||
103 | } | ||
104 | }; | ||
105 | Some(res) | ||
106 | } | ||