aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/descriptors/mod.rs21
-rw-r--r--crates/ra_analysis/src/descriptors/module/nameres.rs82
-rw-r--r--crates/ra_analysis/src/descriptors/path.rs106
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 @@
1pub(crate) mod function; 1pub(crate) mod function;
2pub(crate) mod module; 2pub(crate) mod module;
3mod path;
3 4
4use std::sync::Arc; 5use std::sync::Arc;
5 6
6use ra_syntax::{ 7use ra_syntax::{
7 ast::{self, AstNode, FnDefNode}, 8 ast::{self, FnDefNode},
8 TextRange, SmolStr, 9 TextRange,
9}; 10};
10 11
11use crate::{ 12use crate::{
@@ -18,6 +19,8 @@ use crate::{
18 Cancelable, 19 Cancelable,
19}; 20};
20 21
22pub(crate) use self::path::{Path, PathKind};
23
21salsa::query_group! { 24salsa::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)]
54pub(crate) struct Path {
55 kind: PathKind,
56 segments: Vec<SmolStr>,
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub(crate) enum PathKind {
61 Abs,
62 Self_,
63 Super,
64 Crate,
65}
66
67#[derive(Debug)] 56#[derive(Debug)]
68pub struct ReferenceDescriptor { 57pub 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
231fn 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
278impl ModuleItem { 208impl 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 @@
1use ra_syntax::{SmolStr, ast, AstNode};
2
3use crate::syntax_ptr::LocalSyntaxPtr;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub(crate) struct Path {
7 pub(crate) kind: PathKind,
8 pub(crate) segments: Vec<SmolStr>,
9}
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub(crate) enum PathKind {
13 Abs,
14 Self_,
15 Super,
16 Crate,
17}
18
19impl 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
30fn 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
61fn 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}