aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_ide/src/completion
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_ide/src/completion')
-rw-r--r--crates/ra_ide/src/completion/complete_macro_in_item_position.rs6
-rw-r--r--crates/ra_ide/src/completion/complete_pattern.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_qualified_path.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_unqualified_path.rs18
-rw-r--r--crates/ra_ide/src/completion/presentation.rs79
5 files changed, 59 insertions, 48 deletions
diff --git a/crates/ra_ide/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs
index 270e96df0..6000106d0 100644
--- a/crates/ra_ide/src/completion/complete_macro_in_item_position.rs
+++ b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs
@@ -41,7 +41,7 @@ mod tests {
41 @r###" 41 @r###"
42 [ 42 [
43 CompletionItem { 43 CompletionItem {
44 label: "foo!", 44 label: "foo!(…)",
45 source_range: [46; 46), 45 source_range: [46; 46),
46 delete: [46; 46), 46 delete: [46; 46),
47 insert: "foo!($0)", 47 insert: "foo!($0)",
@@ -81,7 +81,7 @@ mod tests {
81 @r###" 81 @r###"
82 [ 82 [
83 CompletionItem { 83 CompletionItem {
84 label: "vec!", 84 label: "vec![…]",
85 source_range: [280; 280), 85 source_range: [280; 280),
86 delete: [280; 280), 86 delete: [280; 280),
87 insert: "vec![$0]", 87 insert: "vec![$0]",
@@ -118,7 +118,7 @@ mod tests {
118 @r###" 118 @r###"
119 [ 119 [
120 CompletionItem { 120 CompletionItem {
121 label: "foo!", 121 label: "foo! {…}",
122 source_range: [163; 163), 122 source_range: [163; 163),
123 delete: [163; 163), 123 delete: [163; 163),
124 insert: "foo! {$0}", 124 insert: "foo! {$0}",
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs
index a8b4ce114..218829b10 100644
--- a/crates/ra_ide/src/completion/complete_pattern.rs
+++ b/crates/ra_ide/src/completion/complete_pattern.rs
@@ -125,7 +125,7 @@ mod tests {
125 kind: Enum, 125 kind: Enum,
126 }, 126 },
127 CompletionItem { 127 CompletionItem {
128 label: "m!", 128 label: "m!(…)",
129 source_range: [151; 151), 129 source_range: [151; 151),
130 delete: [151; 151), 130 delete: [151; 151),
131 insert: "m!($0)", 131 insert: "m!($0)",
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs
index d98523406..9f795e441 100644
--- a/crates/ra_ide/src/completion/complete_qualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_qualified_path.rs
@@ -869,7 +869,7 @@ mod tests {
869 @r###" 869 @r###"
870 [ 870 [
871 CompletionItem { 871 CompletionItem {
872 label: "foo!", 872 label: "foo!(…)",
873 source_range: [179; 179), 873 source_range: [179; 179),
874 delete: [179; 179), 874 delete: [179; 179),
875 insert: "foo!($0)", 875 insert: "foo!($0)",
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs
index ad00154a3..638f86eda 100644
--- a/crates/ra_ide/src/completion/complete_unqualified_path.rs
+++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs
@@ -733,7 +733,7 @@ mod tests {
733 @r###" 733 @r###"
734 [ 734 [
735 CompletionItem { 735 CompletionItem {
736 label: "bar!", 736 label: "bar!(…)",
737 source_range: [252; 252), 737 source_range: [252; 252),
738 delete: [252; 252), 738 delete: [252; 252),
739 insert: "bar!($0)", 739 insert: "bar!($0)",
@@ -741,7 +741,7 @@ mod tests {
741 detail: "macro_rules! bar", 741 detail: "macro_rules! bar",
742 }, 742 },
743 CompletionItem { 743 CompletionItem {
744 label: "baz!", 744 label: "baz!(…)",
745 source_range: [252; 252), 745 source_range: [252; 252),
746 delete: [252; 252), 746 delete: [252; 252),
747 insert: "baz!($0)", 747 insert: "baz!($0)",
@@ -749,7 +749,7 @@ mod tests {
749 detail: "#[macro_export]\nmacro_rules! baz", 749 detail: "#[macro_export]\nmacro_rules! baz",
750 }, 750 },
751 CompletionItem { 751 CompletionItem {
752 label: "foo!", 752 label: "foo!(…)",
753 source_range: [252; 252), 753 source_range: [252; 252),
754 delete: [252; 252), 754 delete: [252; 252),
755 insert: "foo!($0)", 755 insert: "foo!($0)",
@@ -802,7 +802,7 @@ mod tests {
802 @r###" 802 @r###"
803 [ 803 [
804 CompletionItem { 804 CompletionItem {
805 label: "foo!", 805 label: "foo!(…)",
806 source_range: [49; 49), 806 source_range: [49; 49),
807 delete: [49; 49), 807 delete: [49; 49),
808 insert: "foo!($0)", 808 insert: "foo!($0)",
@@ -841,7 +841,7 @@ mod tests {
841 @r###" 841 @r###"
842 [ 842 [
843 CompletionItem { 843 CompletionItem {
844 label: "foo!", 844 label: "foo!(…)",
845 source_range: [57; 57), 845 source_range: [57; 57),
846 delete: [57; 57), 846 delete: [57; 57),
847 insert: "foo!($0)", 847 insert: "foo!($0)",
@@ -880,7 +880,7 @@ mod tests {
880 @r###" 880 @r###"
881 [ 881 [
882 CompletionItem { 882 CompletionItem {
883 label: "foo!", 883 label: "foo!(…)",
884 source_range: [50; 50), 884 source_range: [50; 50),
885 delete: [50; 50), 885 delete: [50; 50),
886 insert: "foo!($0)", 886 insert: "foo!($0)",
@@ -953,7 +953,7 @@ mod tests {
953 @r###" 953 @r###"
954 [ 954 [
955 CompletionItem { 955 CompletionItem {
956 label: "m!", 956 label: "m!(…)",
957 source_range: [145; 145), 957 source_range: [145; 145),
958 delete: [145; 145), 958 delete: [145; 145),
959 insert: "m!($0)", 959 insert: "m!($0)",
@@ -1006,7 +1006,7 @@ mod tests {
1006 @r###" 1006 @r###"
1007 [ 1007 [
1008 CompletionItem { 1008 CompletionItem {
1009 label: "m!", 1009 label: "m!(…)",
1010 source_range: [145; 146), 1010 source_range: [145; 146),
1011 delete: [145; 146), 1011 delete: [145; 146),
1012 insert: "m!($0)", 1012 insert: "m!($0)",
@@ -1059,7 +1059,7 @@ mod tests {
1059 @r###" 1059 @r###"
1060 [ 1060 [
1061 CompletionItem { 1061 CompletionItem {
1062 label: "m!", 1062 label: "m!(…)",
1063 source_range: [145; 146), 1063 source_range: [145; 146),
1064 delete: [145; 146), 1064 delete: [145; 146),
1065 insert: "m!($0)", 1065 insert: "m!($0)",
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs
index 5e2b8b920..6a6ddc7bd 100644
--- a/crates/ra_ide/src/completion/presentation.rs
+++ b/crates/ra_ide/src/completion/presentation.rs
@@ -133,29 +133,6 @@ impl Completions {
133 completion_item.kind(kind).set_documentation(docs).add_to(self) 133 completion_item.kind(kind).set_documentation(docs).add_to(self)
134 } 134 }
135 135
136 fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str {
137 let mut votes = [0, 0, 0];
138 for (idx, s) in docs.match_indices(&macro_name) {
139 let (before, after) = (&docs[..idx], &docs[idx + s.len()..]);
140 // Ensure to match the full word
141 if after.starts_with('!')
142 && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric())
143 {
144 // It may have spaces before the braces like `foo! {}`
145 match after[1..].chars().find(|&c| !c.is_whitespace()) {
146 Some('{') => votes[0] += 1,
147 Some('[') => votes[1] += 1,
148 Some('(') => votes[2] += 1,
149 _ => {}
150 }
151 }
152 }
153
154 // Insert a space before `{}`.
155 // We prefer the last one when some votes equal.
156 *votes.iter().zip(&[" {$0}", "[$0]", "($0)"]).max_by_key(|&(&vote, _)| vote).unwrap().1
157 }
158
159 pub(crate) fn add_macro( 136 pub(crate) fn add_macro(
160 &mut self, 137 &mut self,
161 ctx: &CompletionContext, 138 ctx: &CompletionContext,
@@ -177,21 +154,27 @@ impl Completions {
177 let detail = macro_label(&ast_node); 154 let detail = macro_label(&ast_node);
178 155
179 let docs = macro_.docs(ctx.db); 156 let docs = macro_.docs(ctx.db);
180 let macro_declaration = format!("{}!", name);
181 157
182 let mut builder = 158 let mut builder = CompletionItem::new(
183 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), &macro_declaration) 159 CompletionKind::Reference,
184 .kind(CompletionItemKind::Macro) 160 ctx.source_range(),
185 .set_documentation(docs.clone()) 161 &format!("{}!", name),
186 .set_deprecated(is_deprecated(macro_, ctx.db)) 162 )
187 .detail(detail); 163 .kind(CompletionItemKind::Macro)
164 .set_documentation(docs.clone())
165 .set_deprecated(is_deprecated(macro_, ctx.db))
166 .detail(detail);
188 167
168 let needs_bang = ctx.use_item_syntax.is_none() && !ctx.is_macro_call;
189 builder = match ctx.config.snippet_cap { 169 builder = match ctx.config.snippet_cap {
190 Some(cap) if ctx.use_item_syntax.is_none() && !ctx.is_macro_call => { 170 Some(cap) if needs_bang => {
191 let macro_braces_to_insert = 171 let docs = docs.as_ref().map_or("", |s| s.as_str());
192 self.guess_macro_braces(&name, docs.as_ref().map_or("", |s| s.as_str())); 172 let (bra, ket) = guess_macro_braces(&name, docs);
193 builder.insert_snippet(cap, macro_declaration + macro_braces_to_insert) 173 builder
174 .insert_snippet(cap, format!("{}!{}$0{}", name, bra, ket))
175 .label(format!("{}!{}…{}", name, bra, ket))
194 } 176 }
177 None if needs_bang => builder.insert_text(format!("{}!", name)),
195 _ => { 178 _ => {
196 tested_by!(dont_insert_macro_call_parens_unncessary); 179 tested_by!(dont_insert_macro_call_parens_unncessary);
197 builder.insert_text(name) 180 builder.insert_text(name)
@@ -404,6 +387,34 @@ fn is_deprecated(node: impl HasAttrs, db: &RootDatabase) -> bool {
404 node.attrs(db).by_key("deprecated").exists() 387 node.attrs(db).by_key("deprecated").exists()
405} 388}
406 389
390fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static str) {
391 let mut votes = [0, 0, 0];
392 for (idx, s) in docs.match_indices(&macro_name) {
393 let (before, after) = (&docs[..idx], &docs[idx + s.len()..]);
394 // Ensure to match the full word
395 if after.starts_with('!')
396 && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric())
397 {
398 // It may have spaces before the braces like `foo! {}`
399 match after[1..].chars().find(|&c| !c.is_whitespace()) {
400 Some('{') => votes[0] += 1,
401 Some('[') => votes[1] += 1,
402 Some('(') => votes[2] += 1,
403 _ => {}
404 }
405 }
406 }
407
408 // Insert a space before `{}`.
409 // We prefer the last one when some votes equal.
410 let (_vote, (bra, ket)) = votes
411 .iter()
412 .zip(&[(" {", "}"), ("[", "]"), ("(", ")")])
413 .max_by_key(|&(&vote, _)| vote)
414 .unwrap();
415 (*bra, *ket)
416}
417
407#[cfg(test)] 418#[cfg(test)]
408mod tests { 419mod tests {
409 use insta::assert_debug_snapshot; 420 use insta::assert_debug_snapshot;