aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis/src/completion
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2018-11-21 15:35:51 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2018-11-21 15:35:51 +0000
commitac874b64550c103249e2b951d92e2f1a8c9a5828 (patch)
tree50fdd5d9681ff57a5cd15de3c401cd478e6f3ab5 /crates/ra_analysis/src/completion
parent031bc868293539714157e3d93cc338b011f5661d (diff)
parentedeec6a41487e6458a9d96b328c9b784525d8f06 (diff)
Merge #237
237: This moves parts of completion from ad-hockery to descriptors-based resolve r=matklad a=matklad Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_analysis/src/completion')
-rw-r--r--crates/ra_analysis/src/completion/mod.rs14
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs65
2 files changed, 32 insertions, 47 deletions
diff --git a/crates/ra_analysis/src/completion/mod.rs b/crates/ra_analysis/src/completion/mod.rs
index a8a752fc7..c7717ab61 100644
--- a/crates/ra_analysis/src/completion/mod.rs
+++ b/crates/ra_analysis/src/completion/mod.rs
@@ -221,6 +221,20 @@ mod tests {
221 } 221 }
222 222
223 #[test] 223 #[test]
224 fn test_completion_self_path() {
225 check_scope_completion(
226 r"
227 use self::m::<|>;
228
229 mod m {
230 struct Bar;
231 }
232 ",
233 r#"[CompletionItem { label: "Bar", lookup: None, snippet: None }]"#,
234 );
235 }
236
237 #[test]
224 fn test_completion_mod_scope_nested() { 238 fn test_completion_mod_scope_nested() {
225 check_scope_completion( 239 check_scope_completion(
226 r" 240 r"
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(),