|
1 | 1 | //! Renderer for macro invocations. |
2 | 2 |
|
3 | | -use hir::HirDisplay; |
| 3 | +use hir::{HirDisplay, db::HirDatabase}; |
4 | 4 | use ide_db::{SymbolKind, documentation::Documentation}; |
5 | 5 | use syntax::{SmolStr, ToSmolStr, format_smolstr}; |
6 | 6 |
|
@@ -46,17 +46,15 @@ fn render( |
46 | 46 | ctx.source_range() |
47 | 47 | }; |
48 | 48 |
|
49 | | - let orig_name = macro_.name(ctx.db()); |
50 | | - let (name, orig_name, escaped_name) = ( |
51 | | - name.as_str(), |
52 | | - orig_name.as_str(), |
53 | | - name.display(ctx.db(), completion.edition).to_smolstr(), |
54 | | - ); |
| 49 | + let (name, escaped_name) = |
| 50 | + (name.as_str(), name.display(ctx.db(), completion.edition).to_smolstr()); |
55 | 51 | let docs = ctx.docs(macro_); |
56 | | - let docs_str = docs.as_ref().map(Documentation::as_str).unwrap_or_default(); |
57 | 52 | let is_fn_like = macro_.is_fn_like(completion.db); |
58 | | - let (bra, ket) = |
59 | | - if is_fn_like { guess_macro_braces(name, orig_name, docs_str) } else { ("", "") }; |
| 53 | + let (bra, ket) = if is_fn_like { |
| 54 | + guess_macro_braces(ctx.db(), macro_, name, docs.as_ref()) |
| 55 | + } else { |
| 56 | + ("", "") |
| 57 | + }; |
60 | 58 |
|
61 | 59 | let needs_bang = is_fn_like && !is_use_path && !has_macro_bang; |
62 | 60 |
|
@@ -115,12 +113,24 @@ fn banged_name(name: &str) -> SmolStr { |
115 | 113 | } |
116 | 114 |
|
117 | 115 | fn guess_macro_braces( |
| 116 | + db: &dyn HirDatabase, |
| 117 | + macro_: hir::Macro, |
118 | 118 | macro_name: &str, |
119 | | - orig_name: &str, |
120 | | - docs: &str, |
| 119 | + docs: Option<&Documentation<'_>>, |
121 | 120 | ) -> (&'static str, &'static str) { |
| 121 | + if let Some(style) = macro_.preferred_brace_style(db) { |
| 122 | + return match style { |
| 123 | + hir::MacroBraces::Braces => (" {", "}"), |
| 124 | + hir::MacroBraces::Brackets => ("[", "]"), |
| 125 | + hir::MacroBraces::Parentheses => ("(", ")"), |
| 126 | + }; |
| 127 | + } |
| 128 | + |
| 129 | + let orig_name = macro_.name(db); |
| 130 | + let docs = docs.map(Documentation::as_str).unwrap_or_default(); |
| 131 | + |
122 | 132 | let mut votes = [0, 0, 0]; |
123 | | - for (idx, s) in docs.match_indices(macro_name).chain(docs.match_indices(orig_name)) { |
| 133 | + for (idx, s) in docs.match_indices(macro_name).chain(docs.match_indices(orig_name.as_str())) { |
124 | 134 | let (before, after) = (&docs[..idx], &docs[idx + s.len()..]); |
125 | 135 | // Ensure to match the full word |
126 | 136 | if after.starts_with('!') |
@@ -199,6 +209,57 @@ fn main() { |
199 | 209 | ); |
200 | 210 | } |
201 | 211 |
|
| 212 | + #[test] |
| 213 | + fn preferred_macro_braces() { |
| 214 | + check_edit( |
| 215 | + "vec!", |
| 216 | + r#" |
| 217 | +#[rust_analyzer::macro_style(brackets)] |
| 218 | +macro_rules! vec { () => {} } |
| 219 | +
|
| 220 | +fn main() { v$0 } |
| 221 | +"#, |
| 222 | + r#" |
| 223 | +#[rust_analyzer::macro_style(brackets)] |
| 224 | +macro_rules! vec { () => {} } |
| 225 | +
|
| 226 | +fn main() { vec![$0] } |
| 227 | +"#, |
| 228 | + ); |
| 229 | + |
| 230 | + check_edit( |
| 231 | + "foo!", |
| 232 | + r#" |
| 233 | +#[rust_analyzer::macro_style(braces)] |
| 234 | +macro_rules! foo { () => {} } |
| 235 | +fn main() { $0 } |
| 236 | +"#, |
| 237 | + r#" |
| 238 | +#[rust_analyzer::macro_style(braces)] |
| 239 | +macro_rules! foo { () => {} } |
| 240 | +fn main() { foo! {$0} } |
| 241 | +"#, |
| 242 | + ); |
| 243 | + |
| 244 | + check_edit( |
| 245 | + "bar!", |
| 246 | + r#" |
| 247 | +#[macro_export] |
| 248 | +#[rust_analyzer::macro_style(brackets)] |
| 249 | +macro_rules! foo { () => {} } |
| 250 | +pub use crate::foo as bar; |
| 251 | +fn main() { $0 } |
| 252 | +"#, |
| 253 | + r#" |
| 254 | +#[macro_export] |
| 255 | +#[rust_analyzer::macro_style(brackets)] |
| 256 | +macro_rules! foo { () => {} } |
| 257 | +pub use crate::foo as bar; |
| 258 | +fn main() { bar![$0] } |
| 259 | +"#, |
| 260 | + ); |
| 261 | + } |
| 262 | + |
202 | 263 | #[test] |
203 | 264 | fn guesses_macro_braces() { |
204 | 265 | check_edit( |
|
0 commit comments