diff options
Diffstat (limited to 'crates/completion/src/render')
-rw-r--r-- | crates/completion/src/render/macro_.rs | 72 |
1 files changed, 40 insertions, 32 deletions
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs index 96be59cc3..b41c00b98 100644 --- a/crates/completion/src/render/macro_.rs +++ b/crates/completion/src/render/macro_.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Renderer for macro invocations. | 1 | //! Renderer for macro invocations. |
2 | 2 | ||
3 | use hir::{Documentation, HasSource}; | 3 | use hir::{db::HirDatabase, Documentation, HasAttrs, HasSource}; |
4 | use syntax::display::macro_label; | 4 | use syntax::display::macro_label; |
5 | use test_utils::mark; | 5 | use test_utils::mark; |
6 | 6 | ||
@@ -27,12 +27,48 @@ struct MacroRender<'a> { | |||
27 | ket: &'static str, | 27 | ket: &'static str, |
28 | } | 28 | } |
29 | 29 | ||
30 | pub fn guess_macro_braces( | ||
31 | db: &dyn HirDatabase, | ||
32 | macro_: hir::MacroDef, | ||
33 | ) -> (&'static str, &'static str) { | ||
34 | let macro_name = match macro_.name(db) { | ||
35 | Some(name) => name.to_string(), | ||
36 | None => return ("(", ")"), | ||
37 | }; | ||
38 | let macro_docs = macro_.docs(db); | ||
39 | let macro_docs = macro_docs.as_ref().map(Documentation::as_str).unwrap_or(""); | ||
40 | |||
41 | let mut votes = [0, 0, 0]; | ||
42 | for (idx, s) in macro_docs.match_indices(¯o_name) { | ||
43 | let (before, after) = (¯o_docs[..idx], ¯o_docs[idx + s.len()..]); | ||
44 | // Ensure to match the full word | ||
45 | if after.starts_with('!') | ||
46 | && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric()) | ||
47 | { | ||
48 | // It may have spaces before the braces like `foo! {}` | ||
49 | match after[1..].chars().find(|&c| !c.is_whitespace()) { | ||
50 | Some('{') => votes[0] += 1, | ||
51 | Some('[') => votes[1] += 1, | ||
52 | Some('(') => votes[2] += 1, | ||
53 | _ => {} | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | |||
58 | // Insert a space before `{}`. | ||
59 | // We prefer the last one when some votes equal. | ||
60 | let (_vote, (bra, ket)) = votes | ||
61 | .iter() | ||
62 | .zip(&[(" {", "}"), ("[", "]"), ("(", ")")]) | ||
63 | .max_by_key(|&(&vote, _)| vote) | ||
64 | .unwrap(); | ||
65 | (*bra, *ket) | ||
66 | } | ||
67 | |||
30 | impl<'a> MacroRender<'a> { | 68 | impl<'a> MacroRender<'a> { |
31 | fn new(ctx: RenderContext<'a>, name: String, macro_: hir::MacroDef) -> MacroRender<'a> { | 69 | fn new(ctx: RenderContext<'a>, name: String, macro_: hir::MacroDef) -> MacroRender<'a> { |
32 | let docs = ctx.docs(macro_); | 70 | let docs = ctx.docs(macro_); |
33 | let docs_str = docs.as_ref().map_or("", |s| s.as_str()); | 71 | let (bra, ket) = guess_macro_braces(ctx.db(), macro_); |
34 | let (bra, ket) = guess_macro_braces(&name, docs_str); | ||
35 | |||
36 | MacroRender { ctx, name, macro_, docs, bra, ket } | 72 | MacroRender { ctx, name, macro_, docs, bra, ket } |
37 | } | 73 | } |
38 | 74 | ||
@@ -97,34 +133,6 @@ impl<'a> MacroRender<'a> { | |||
97 | } | 133 | } |
98 | } | 134 | } |
99 | 135 | ||
100 | fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static str) { | ||
101 | let mut votes = [0, 0, 0]; | ||
102 | for (idx, s) in docs.match_indices(¯o_name) { | ||
103 | let (before, after) = (&docs[..idx], &docs[idx + s.len()..]); | ||
104 | // Ensure to match the full word | ||
105 | if after.starts_with('!') | ||
106 | && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric()) | ||
107 | { | ||
108 | // It may have spaces before the braces like `foo! {}` | ||
109 | match after[1..].chars().find(|&c| !c.is_whitespace()) { | ||
110 | Some('{') => votes[0] += 1, | ||
111 | Some('[') => votes[1] += 1, | ||
112 | Some('(') => votes[2] += 1, | ||
113 | _ => {} | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | // Insert a space before `{}`. | ||
119 | // We prefer the last one when some votes equal. | ||
120 | let (_vote, (bra, ket)) = votes | ||
121 | .iter() | ||
122 | .zip(&[(" {", "}"), ("[", "]"), ("(", ")")]) | ||
123 | .max_by_key(|&(&vote, _)| vote) | ||
124 | .unwrap(); | ||
125 | (*bra, *ket) | ||
126 | } | ||
127 | |||
128 | #[cfg(test)] | 136 | #[cfg(test)] |
129 | mod tests { | 137 | mod tests { |
130 | use test_utils::mark; | 138 | use test_utils::mark; |