aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_analysis/src/completion.rs19
-rw-r--r--crates/ra_analysis/src/completion/completion_item.rs13
-rw-r--r--crates/ra_analysis/src/completion/reference_completion.rs32
3 files changed, 38 insertions, 26 deletions
diff --git a/crates/ra_analysis/src/completion.rs b/crates/ra_analysis/src/completion.rs
index 222b6854c..074033ad8 100644
--- a/crates/ra_analysis/src/completion.rs
+++ b/crates/ra_analysis/src/completion.rs
@@ -15,7 +15,8 @@ use hir::source_binder;
15 15
16use crate::{ 16use crate::{
17 db, 17 db,
18 Cancelable, FilePosition 18 Cancelable, FilePosition,
19 completion::completion_item::Completions,
19}; 20};
20 21
21pub use crate::completion::completion_item::{CompletionItem, InsertText}; 22pub use crate::completion::completion_item::{CompletionItem, InsertText};
@@ -33,15 +34,15 @@ pub(crate) fn completions(
33 34
34 let module = ctry!(source_binder::module_from_position(db, position)?); 35 let module = ctry!(source_binder::module_from_position(db, position)?);
35 36
36 let mut res = Vec::new(); 37 let mut acc = Completions::default();
37 let mut has_completions = false; 38 let mut has_completions = false;
38 // First, let's try to complete a reference to some declaration. 39 // First, let's try to complete a reference to some declaration.
39 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { 40 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
40 has_completions = true; 41 has_completions = true;
41 reference_completion::completions(&mut res, db, &module, &file, name_ref)?; 42 reference_completion::completions(&mut acc, db, &module, &file, name_ref)?;
42 // special case, `trait T { fn foo(i_am_a_name_ref) {} }` 43 // special case, `trait T { fn foo(i_am_a_name_ref) {} }`
43 if is_node::<ast::Param>(name_ref.syntax()) { 44 if is_node::<ast::Param>(name_ref.syntax()) {
44 param_completions(&mut res, name_ref.syntax()); 45 param_completions(&mut acc, name_ref.syntax());
45 } 46 }
46 } 47 }
47 48
@@ -49,10 +50,14 @@ pub(crate) fn completions(
49 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) { 50 if let Some(name) = find_node_at_offset::<ast::Name>(file.syntax(), position.offset) {
50 if is_node::<ast::Param>(name.syntax()) { 51 if is_node::<ast::Param>(name.syntax()) {
51 has_completions = true; 52 has_completions = true;
52 param_completions(&mut res, name.syntax()); 53 param_completions(&mut acc, name.syntax());
53 } 54 }
54 } 55 }
55 let res = if has_completions { Some(res) } else { None }; 56 let res = if has_completions {
57 Some(acc.into())
58 } else {
59 None
60 };
56 Ok(res) 61 Ok(res)
57} 62}
58 63
@@ -60,7 +65,7 @@ pub(crate) fn completions(
60/// functions in a file have a `spam: &mut Spam` parameter, a completion with 65/// functions in a file have a `spam: &mut Spam` parameter, a completion with
61/// `spam: &mut Spam` insert text/label and `spam` lookup string will be 66/// `spam: &mut Spam` insert text/label and `spam` lookup string will be
62/// suggested. 67/// suggested.
63fn param_completions(acc: &mut Vec<CompletionItem>, ctx: SyntaxNodeRef) { 68fn param_completions(acc: &mut Completions, ctx: SyntaxNodeRef) {
64 let mut params = FxHashMap::default(); 69 let mut params = FxHashMap::default();
65 for node in ctx.ancestors() { 70 for node in ctx.ancestors() {
66 let _ = visitor_ctx(&mut params) 71 let _ = visitor_ctx(&mut params)
diff --git a/crates/ra_analysis/src/completion/completion_item.rs b/crates/ra_analysis/src/completion/completion_item.rs
index 445d6bf41..8aa9da005 100644
--- a/crates/ra_analysis/src/completion/completion_item.rs
+++ b/crates/ra_analysis/src/completion/completion_item.rs
@@ -53,8 +53,8 @@ pub(crate) struct Builder {
53} 53}
54 54
55impl Builder { 55impl Builder {
56 pub fn add_to(self, acc: &mut Vec<CompletionItem>) { 56 pub fn add_to(self, acc: &mut Completions) {
57 acc.push(self.build()) 57 acc.add(self.build())
58 } 58 }
59 59
60 pub fn build(self) -> CompletionItem { 60 pub fn build(self) -> CompletionItem {
@@ -81,7 +81,7 @@ impl Into<CompletionItem> for Builder {
81} 81}
82 82
83/// Represents an in-progress set of completions being built. 83/// Represents an in-progress set of completions being built.
84#[derive(Debug)] 84#[derive(Debug, Default)]
85pub(crate) struct Completions { 85pub(crate) struct Completions {
86 buf: Vec<CompletionItem>, 86 buf: Vec<CompletionItem>,
87} 87}
@@ -90,6 +90,13 @@ impl Completions {
90 pub(crate) fn add(&mut self, item: impl Into<CompletionItem>) { 90 pub(crate) fn add(&mut self, item: impl Into<CompletionItem>) {
91 self.buf.push(item.into()) 91 self.buf.push(item.into())
92 } 92 }
93 pub(crate) fn add_all<I>(&mut self, items: I)
94 where
95 I: IntoIterator,
96 I::Item: Into<CompletionItem>,
97 {
98 items.into_iter().for_each(|item| self.add(item.into()))
99 }
93} 100}
94 101
95impl Into<Vec<CompletionItem>> for Completions { 102impl Into<Vec<CompletionItem>> for Completions {
diff --git a/crates/ra_analysis/src/completion/reference_completion.rs b/crates/ra_analysis/src/completion/reference_completion.rs
index f9f01a642..c578e9e8b 100644
--- a/crates/ra_analysis/src/completion/reference_completion.rs
+++ b/crates/ra_analysis/src/completion/reference_completion.rs
@@ -13,12 +13,12 @@ use hir::{
13 13
14use crate::{ 14use crate::{
15 db::RootDatabase, 15 db::RootDatabase,
16 completion::CompletionItem, 16 completion::{CompletionItem, Completions},
17 Cancelable 17 Cancelable
18}; 18};
19 19
20pub(super) fn completions( 20pub(super) fn completions(
21 acc: &mut Vec<CompletionItem>, 21 acc: &mut Completions,
22 db: &RootDatabase, 22 db: &RootDatabase,
23 module: &hir::Module, 23 module: &hir::Module,
24 file: &SourceFileNode, 24 file: &SourceFileNode,
@@ -117,7 +117,7 @@ fn classify_name_ref(name_ref: ast::NameRef) -> Option<NameRefKind> {
117 None 117 None
118} 118}
119 119
120fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<CompletionItem>) { 120fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Completions) {
121 let mut shadowed = FxHashSet::default(); 121 let mut shadowed = FxHashSet::default();
122 scopes 122 scopes
123 .scope_chain(name_ref.syntax()) 123 .scope_chain(name_ref.syntax())
@@ -130,7 +130,7 @@ fn complete_fn(name_ref: ast::NameRef, scopes: &FnScopes, acc: &mut Vec<Completi
130} 130}
131 131
132fn complete_path( 132fn complete_path(
133 acc: &mut Vec<CompletionItem>, 133 acc: &mut Completions,
134 db: &RootDatabase, 134 db: &RootDatabase,
135 module: &hir::Module, 135 module: &hir::Module,
136 mut path: Path, 136 mut path: Path,
@@ -154,7 +154,7 @@ fn complete_path(
154 Ok(()) 154 Ok(())
155} 155}
156 156
157fn complete_mod_item_snippets(acc: &mut Vec<CompletionItem>) { 157fn complete_mod_item_snippets(acc: &mut Completions) {
158 CompletionItem::new("Test function") 158 CompletionItem::new("Test function")
159 .lookup_by("tfn") 159 .lookup_by("tfn")
160 .snippet( 160 .snippet(
@@ -174,26 +174,26 @@ fn complete_expr_keywords(
174 file: &SourceFileNode, 174 file: &SourceFileNode,
175 fn_def: ast::FnDef, 175 fn_def: ast::FnDef,
176 name_ref: ast::NameRef, 176 name_ref: ast::NameRef,
177 acc: &mut Vec<CompletionItem>, 177 acc: &mut Completions,
178) { 178) {
179 acc.push(keyword("if", "if $0 {}")); 179 acc.add(keyword("if", "if $0 {}"));
180 acc.push(keyword("match", "match $0 {}")); 180 acc.add(keyword("match", "match $0 {}"));
181 acc.push(keyword("while", "while $0 {}")); 181 acc.add(keyword("while", "while $0 {}"));
182 acc.push(keyword("loop", "loop {$0}")); 182 acc.add(keyword("loop", "loop {$0}"));
183 183
184 if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) { 184 if let Some(off) = name_ref.syntax().range().start().checked_sub(2.into()) {
185 if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) { 185 if let Some(if_expr) = find_node_at_offset::<ast::IfExpr>(file.syntax(), off) {
186 if if_expr.syntax().range().end() < name_ref.syntax().range().start() { 186 if if_expr.syntax().range().end() < name_ref.syntax().range().start() {
187 acc.push(keyword("else", "else {$0}")); 187 acc.add(keyword("else", "else {$0}"));
188 acc.push(keyword("else if", "else if $0 {}")); 188 acc.add(keyword("else if", "else if $0 {}"));
189 } 189 }
190 } 190 }
191 } 191 }
192 if is_in_loop_body(name_ref) { 192 if is_in_loop_body(name_ref) {
193 acc.push(keyword("continue", "continue")); 193 acc.add(keyword("continue", "continue"));
194 acc.push(keyword("break", "break")); 194 acc.add(keyword("break", "break"));
195 } 195 }
196 acc.extend(complete_return(fn_def, name_ref)); 196 acc.add_all(complete_return(fn_def, name_ref));
197} 197}
198 198
199fn is_in_loop_body(name_ref: ast::NameRef) -> bool { 199fn is_in_loop_body(name_ref: ast::NameRef) -> bool {
@@ -252,7 +252,7 @@ fn keyword(kw: &str, snippet: &str) -> CompletionItem {
252 CompletionItem::new(kw).snippet(snippet).build() 252 CompletionItem::new(kw).snippet(snippet).build()
253} 253}
254 254
255fn complete_expr_snippets(acc: &mut Vec<CompletionItem>) { 255fn complete_expr_snippets(acc: &mut Completions) {
256 CompletionItem::new("pd") 256 CompletionItem::new("pd")
257 .snippet("eprintln!(\"$0 = {:?}\", $0);") 257 .snippet("eprintln!(\"$0 = {:?}\", $0);")
258 .add_to(acc); 258 .add_to(acc);