aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/completion/reference_completion.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis/src/completion/reference_completion.rs')
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs65
1 files changed, 18 insertions, 47 deletions
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index 84383b547..d301a3c02 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::{
10use crate::{ 10use 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,
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
120fn 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
146fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { 125fn 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,13 @@ 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 mut path: Path,
173) -> Cancelable<()> { 152) -> Cancelable<()> {
174 let target_module = match find_target_module(module, crate_path) { 153 if path.segments.is_empty() {
154 return Ok(());
155 }
156 path.segments.pop();
157 let target_module = match module.resolve_path(path) {
175 None => return Ok(()), 158 None => return Ok(()),
176 Some(it) => it, 159 Some(it) => it,
177 }; 160 };
@@ -188,18 +171,6 @@ fn complete_path(
188 Ok(()) 171 Ok(())
189} 172}
190 173
191fn find_target_module(
192 module: &ModuleDescriptor,
193 mut crate_path: Vec<ast::NameRef>,
194) -> Option<ModuleDescriptor> {
195 crate_path.pop();
196 let mut target_module = module.crate_root();
197 for name in crate_path {
198 target_module = target_module.child(name.text().as_str())?;
199 }
200 Some(target_module)
201}
202
203fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) { 174fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) {
204 acc.push(CompletionItem { 175 acc.push(CompletionItem {
205 label: "tfn".to_string(), 176 label: "tfn".to_string(),