diff options
Diffstat (limited to 'crates/ra_analysis/src/completion')
-rw-r--r-- | crates/ra_analysis/src/completion/reference_completion.rs | 64 |
1 files changed, 22 insertions, 42 deletions
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs index 84383b547..a96570415 100644 --- a/crates/ra_analysis/src/completion/reference_completion.rs +++ b/crates/ra_analysis/src/completion/reference_completion.rs | |||
@@ -10,8 +10,11 @@ use ra_syntax::{ | |||
10 | use crate::{ | 10 | use crate::{ |
11 | db::RootDatabase, | 11 | db::RootDatabase, |
12 | completion::CompletionItem, | 12 | completion::CompletionItem, |
13 | descriptors::module::{ModuleDescriptor}, | 13 | descriptors::{ |
14 | descriptors::function::FnScopes, | 14 | module::{ModuleDescriptor}, |
15 | function::FnScopes, | ||
16 | Path, PathKind, | ||
17 | }, | ||
15 | Cancelable | 18 | Cancelable |
16 | }; | 19 | }; |
17 | 20 | ||
@@ -55,7 +58,7 @@ pub(super) fn completions( | |||
55 | }), | 58 | }), |
56 | ); | 59 | ); |
57 | } | 60 | } |
58 | NameRefKind::CratePath(path) => complete_path(acc, db, module, path)?, | 61 | NameRefKind::Path(path) => complete_path(acc, db, module, path)?, |
59 | NameRefKind::BareIdentInMod => { | 62 | NameRefKind::BareIdentInMod => { |
60 | let name_range = name_ref.syntax().range(); | 63 | let name_range = name_ref.syntax().range(); |
61 | let top_node = name_ref | 64 | let top_node = name_ref |
@@ -79,8 +82,8 @@ enum NameRefKind<'a> { | |||
79 | LocalRef { | 82 | LocalRef { |
80 | enclosing_fn: Option<ast::FnDef<'a>>, | 83 | enclosing_fn: Option<ast::FnDef<'a>>, |
81 | }, | 84 | }, |
82 | /// NameRef is the last segment in crate:: path | 85 | /// NameRef is the last segment in some path |
83 | CratePath(Vec<ast::NameRef<'a>>), | 86 | Path(Path), |
84 | /// NameRef is bare identifier at the module's root. | 87 | /// NameRef is bare identifier at the module's root. |
85 | /// Used for keyword completion | 88 | /// Used for keyword completion |
86 | BareIdentInMod, | 89 | BareIdentInMod, |
@@ -102,8 +105,10 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> { | |||
102 | let parent = name_ref.syntax().parent()?; | 105 | let parent = name_ref.syntax().parent()?; |
103 | if let Some(segment) = ast::PathSegment::cast(parent) { | 106 | if let Some(segment) = ast::PathSegment::cast(parent) { |
104 | let path = segment.parent_path(); | 107 | let path = segment.parent_path(); |
105 | if let Some(crate_path) = crate_path(path) { | 108 | if let Some(path) = Path::from_ast(path) { |
106 | return Some(NameRefKind::CratePath(crate_path)); | 109 | if !path.is_ident() { |
110 | return Some(NameRefKind::Path(path)); | ||
111 | } | ||
107 | } | 112 | } |
108 | if path.qualifier().is_none() { | 113 | if path.qualifier().is_none() { |
109 | let enclosing_fn = name_ref | 114 | let enclosing_fn = name_ref |
@@ -117,32 +122,6 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> { | |||
117 | None | 122 | None |
118 | } | 123 | } |
119 | 124 | ||
120 | fn crate_path(mut path: ast::Path) -> Option<Vec<ast::NameRef>> { | ||
121 | let mut res = Vec::new(); | ||
122 | loop { | ||
123 | let segment = path.segment()?; | ||
124 | match segment.kind()? { | ||
125 | ast::PathSegmentKind::Name(name) => res.push(name), | ||
126 | ast::PathSegmentKind::CrateKw => break, | ||
127 | ast::PathSegmentKind::SelfKw | ast::PathSegmentKind::SuperKw => return None, | ||
128 | } | ||
129 | path = qualifier(path)?; | ||
130 | } | ||
131 | res.reverse(); | ||
132 | return Some(res); | ||
133 | |||
134 | fn qualifier(path: ast::Path) -> Option<ast::Path> { | ||
135 | if let Some(q) = path.qualifier() { | ||
136 | return Some(q); | ||
137 | } | ||
138 | // TODO: this bottom up traversal is not too precise. | ||
139 | // Should we handle do a top-down analysiss, recording results? | ||
140 | let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?; | ||
141 | let use_tree = use_tree_list.parent_use_tree(); | ||
142 | use_tree.path() | ||
143 | } | ||
144 | } | ||
145 | |||
146 | fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { | 125 | fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { |
147 | let mut shadowed = FxHashSet::default(); | 126 | let mut shadowed = FxHashSet::default(); |
148 | acc.extend( | 127 | acc.extend( |
@@ -169,9 +148,9 @@ fn complete_path( | |||
169 | acc: &mut Vec<CompletionItem>, | 148 | acc: &mut Vec<CompletionItem>, |
170 | db: &RootDatabase, | 149 | db: &RootDatabase, |
171 | module: &ModuleDescriptor, | 150 | module: &ModuleDescriptor, |
172 | crate_path: Vec<ast::NameRef>, | 151 | path: Path, |
173 | ) -> Cancelable<()> { | 152 | ) -> Cancelable<()> { |
174 | let target_module = match find_target_module(module, crate_path) { | 153 | let target_module = match find_target_module(module, path) { |
175 | None => return Ok(()), | 154 | None => return Ok(()), |
176 | Some(it) => it, | 155 | Some(it) => it, |
177 | }; | 156 | }; |
@@ -188,14 +167,15 @@ fn complete_path( | |||
188 | Ok(()) | 167 | Ok(()) |
189 | } | 168 | } |
190 | 169 | ||
191 | fn find_target_module( | 170 | fn find_target_module(module: &ModuleDescriptor, path: Path) -> Option<ModuleDescriptor> { |
192 | module: &ModuleDescriptor, | 171 | if path.kind != PathKind::Crate { |
193 | mut crate_path: Vec<ast::NameRef>, | 172 | return None; |
194 | ) -> Option<ModuleDescriptor> { | 173 | } |
195 | crate_path.pop(); | 174 | let mut segments = path.segments; |
175 | segments.pop(); | ||
196 | let mut target_module = module.crate_root(); | 176 | let mut target_module = module.crate_root(); |
197 | for name in crate_path { | 177 | for name in segments { |
198 | target_module = target_module.child(name.text().as_str())?; | 178 | target_module = target_module.child(&name)?; |
199 | } | 179 | } |
200 | Some(target_module) | 180 | Some(target_module) |
201 | } | 181 | } |