aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_analysis
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_analysis')
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs68
1 files changed, 30 insertions, 38 deletions
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index 13d4de9d5..f708f07a0 100644
--- a/crates/ra_analysis/src/completion/reference_completion.rs
+++ b/crates/ra_analysis/src/completion/reference_completion.rs
@@ -11,7 +11,7 @@ use crate::{
11 db::RootDatabase, 11 db::RootDatabase,
12 input::{SourceRootId}, 12 input::{SourceRootId},
13 completion::CompletionItem, 13 completion::CompletionItem,
14 descriptors::module::{ModuleId, ModuleScope, ModuleTree}, 14 descriptors::module::{ModuleId, ModuleTree},
15 descriptors::function::FnScopes, 15 descriptors::function::FnScopes,
16 descriptors::DescriptorDatabase, 16 descriptors::DescriptorDatabase,
17 Cancelable 17 Cancelable
@@ -32,12 +32,29 @@ pub(super) fn completions(
32 }; 32 };
33 33
34 match kind { 34 match kind {
35 NameRefKind::LocalRef => { 35 NameRefKind::LocalRef { enclosing_fn } => {
36 let module_scope = db.module_scope(source_root_id, module_id)?; 36 if let Some(fn_def) = enclosing_fn {
37 if let Some(fn_def) = complete_local_name(acc, &module_scope, name_ref) { 37 let scopes = FnScopes::new(fn_def);
38 complete_fn(name_ref, &scopes, acc);
38 complete_expr_keywords(&file, fn_def, name_ref, acc); 39 complete_expr_keywords(&file, fn_def, name_ref, acc);
39 complete_expr_snippets(acc); 40 complete_expr_snippets(acc);
40 } 41 }
42
43 let module_scope = db.module_scope(source_root_id, module_id)?;
44 acc.extend(
45 module_scope
46 .entries()
47 .iter()
48 .filter(|entry| {
49 // Don't expose this item
50 !entry.ptr().range().is_subrange(&name_ref.syntax().range())
51 })
52 .map(|entry| CompletionItem {
53 label: entry.name().to_string(),
54 lookup: None,
55 snippet: None,
56 }),
57 );
41 } 58 }
42 NameRefKind::CratePath(path) => { 59 NameRefKind::CratePath(path) => {
43 complete_path(acc, db, source_root_id, module_tree, module_id, path)? 60 complete_path(acc, db, source_root_id, module_tree, module_id, path)?
@@ -62,7 +79,9 @@ pub(super) fn completions(
62enum NameRefKind<'a> { 79enum NameRefKind<'a> {
63 /// NameRef is a part of single-segment path, for example, a refernece to a 80 /// NameRef is a part of single-segment path, for example, a refernece to a
64 /// local variable. 81 /// local variable.
65 LocalRef, 82 LocalRef {
83 enclosing_fn: Option<ast::FnDef<'a>>,
84 },
66 /// NameRef is the last segment in crate:: path 85 /// NameRef is the last segment in crate:: path
67 CratePath(Vec<ast::NameRef<'a>>), 86 CratePath(Vec<ast::NameRef<'a>>),
68 /// NameRef is bare identifier at the module's root. 87 /// NameRef is bare identifier at the module's root.
@@ -87,7 +106,12 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
87 if let Some(segment) = ast::PathSegment::cast(parent) { 106 if let Some(segment) = ast::PathSegment::cast(parent) {
88 let path = segment.parent_path(); 107 let path = segment.parent_path();
89 if path.qualifier().is_none() { 108 if path.qualifier().is_none() {
90 return Some(NameRefKind::LocalRef); 109 let enclosing_fn = name_ref
110 .syntax()
111 .ancestors()
112 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
113 .find_map(ast::FnDef::cast);
114 return Some(NameRefKind::LocalRef { enclosing_fn });
91 } 115 }
92 if let Some(crate_path) = crate_path(path) { 116 if let Some(crate_path) = crate_path(path) {
93 return Some(NameRefKind::CratePath(crate_path)); 117 return Some(NameRefKind::CratePath(crate_path));
@@ -111,38 +135,6 @@ fn crate_path(mut path: ast::Path) -> Option<Vec<ast::NameRef>> {
111 Some(res) 135 Some(res)
112} 136}
113 137
114fn complete_local_name<'a>(
115 acc: &mut Vec<CompletionItem>,
116 module_scope: &ModuleScope,
117 name_ref: ast::NameRef<'a>,
118) -> Option<ast::FnDef<'a>> {
119 let enclosing_fn = name_ref
120 .syntax()
121 .ancestors()
122 .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE)
123 .find_map(ast::FnDef::cast);
124 if let Some(fn_def) = enclosing_fn {
125 let scopes = FnScopes::new(fn_def);
126 complete_fn(name_ref, &scopes, acc);
127 }
128
129 acc.extend(
130 module_scope
131 .entries()
132 .iter()
133 .filter(|entry| {
134 // Don't expose this item
135 !entry.ptr().range().is_subrange(&name_ref.syntax().range())
136 })
137 .map(|entry| CompletionItem {
138 label: entry.name().to_string(),
139 lookup: None,
140 snippet: None,
141 }),
142 );
143 enclosing_fn
144}
145
146fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { 138fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) {
147 let mut shadowed = FxHashSet::default(); 139 let mut shadowed = FxHashSet::default();
148 acc.extend( 140 acc.extend(