diff options
author | Kirill Bulatov <[email protected]> | 2020-11-13 19:25:45 +0000 |
---|---|---|
committer | Kirill Bulatov <[email protected]> | 2020-11-16 19:19:06 +0000 |
commit | 1598740292c29613ef2b384a82de3a2735bc5566 (patch) | |
tree | bc2451b9fe6cf7943fcbcaaa762c9591c0bad9c6 /crates/completion/src/render | |
parent | 4c8edd003aa447bd2da10fd81b24f582deacdc11 (diff) |
Reuse existing element rendering
Diffstat (limited to 'crates/completion/src/render')
-rw-r--r-- | crates/completion/src/render/macro_.rs | 72 |
1 files changed, 32 insertions, 40 deletions
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs index b41c00b98..96be59cc3 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::{db::HirDatabase, Documentation, HasAttrs, HasSource}; | 3 | use hir::{Documentation, 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,48 +27,12 @@ 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 | |||
68 | impl<'a> MacroRender<'a> { | 30 | impl<'a> MacroRender<'a> { |
69 | fn new(ctx: RenderContext<'a>, name: String, macro_: hir::MacroDef) -> MacroRender<'a> { | 31 | fn new(ctx: RenderContext<'a>, name: String, macro_: hir::MacroDef) -> MacroRender<'a> { |
70 | let docs = ctx.docs(macro_); | 32 | let docs = ctx.docs(macro_); |
71 | let (bra, ket) = guess_macro_braces(ctx.db(), macro_); | 33 | let docs_str = docs.as_ref().map_or("", |s| s.as_str()); |
34 | let (bra, ket) = guess_macro_braces(&name, docs_str); | ||
35 | |||
72 | MacroRender { ctx, name, macro_, docs, bra, ket } | 36 | MacroRender { ctx, name, macro_, docs, bra, ket } |
73 | } | 37 | } |
74 | 38 | ||
@@ -133,6 +97,34 @@ impl<'a> MacroRender<'a> { | |||
133 | } | 97 | } |
134 | } | 98 | } |
135 | 99 | ||
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 | |||
136 | #[cfg(test)] | 128 | #[cfg(test)] |
137 | mod tests { | 129 | mod tests { |
138 | use test_utils::mark; | 130 | use test_utils::mark; |