Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/ide-completion/src/render/macro_.rs')
| -rw-r--r-- | crates/ide-completion/src/render/macro_.rs | 100 |
1 files changed, 94 insertions, 6 deletions
diff --git a/crates/ide-completion/src/render/macro_.rs b/crates/ide-completion/src/render/macro_.rs index 35fe407b2e..8cdeb8abbf 100644 --- a/crates/ide-completion/src/render/macro_.rs +++ b/crates/ide-completion/src/render/macro_.rs @@ -1,6 +1,6 @@ //! Renderer for macro invocations. -use hir::HirDisplay; +use hir::{HirDisplay, db::HirDatabase}; use ide_db::{SymbolKind, documentation::Documentation}; use syntax::{SmolStr, ToSmolStr, format_smolstr}; @@ -49,9 +49,12 @@ fn render( let (name, escaped_name) = (name.as_str(), name.display(ctx.db(), completion.edition).to_smolstr()); let docs = ctx.docs(macro_); - let docs_str = docs.as_ref().map(Documentation::as_str).unwrap_or_default(); let is_fn_like = macro_.is_fn_like(completion.db); - let (bra, ket) = if is_fn_like { guess_macro_braces(name, docs_str) } else { ("", "") }; + let (bra, ket) = if is_fn_like { + guess_macro_braces(ctx.db(), macro_, name, docs.as_ref()) + } else { + ("", "") + }; let needs_bang = is_fn_like && !is_use_path && !has_macro_bang; @@ -109,9 +112,25 @@ fn banged_name(name: &str) -> SmolStr { SmolStr::from_iter([name, "!"]) } -fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static str) { +fn guess_macro_braces( + db: &dyn HirDatabase, + macro_: hir::Macro, + macro_name: &str, + docs: Option<&Documentation<'_>>, +) -> (&'static str, &'static str) { + if let Some(style) = macro_.preferred_brace_style(db) { + return match style { + hir::MacroBraces::Braces => (" {", "}"), + hir::MacroBraces::Brackets => ("[", "]"), + hir::MacroBraces::Parentheses => ("(", ")"), + }; + } + + let orig_name = macro_.name(db); + let docs = docs.map(Documentation::as_str).unwrap_or_default(); + let mut votes = [0, 0, 0]; - for (idx, s) in docs.match_indices(¯o_name) { + for (idx, s) in docs.match_indices(macro_name).chain(docs.match_indices(orig_name.as_str())) { let (before, after) = (&docs[..idx], &docs[idx + s.len()..]); // Ensure to match the full word if after.starts_with('!') @@ -191,6 +210,57 @@ fn main() { } #[test] + fn preferred_macro_braces() { + check_edit( + "vec!", + r#" +#[rust_analyzer::macro_style(brackets)] +macro_rules! vec { () => {} } + +fn main() { v$0 } +"#, + r#" +#[rust_analyzer::macro_style(brackets)] +macro_rules! vec { () => {} } + +fn main() { vec![$0] } +"#, + ); + + check_edit( + "foo!", + r#" +#[rust_analyzer::macro_style(braces)] +macro_rules! foo { () => {} } +fn main() { $0 } +"#, + r#" +#[rust_analyzer::macro_style(braces)] +macro_rules! foo { () => {} } +fn main() { foo! {$0} } +"#, + ); + + check_edit( + "bar!", + r#" +#[macro_export] +#[rust_analyzer::macro_style(brackets)] +macro_rules! foo { () => {} } +pub use crate::foo as bar; +fn main() { $0 } +"#, + r#" +#[macro_export] +#[rust_analyzer::macro_style(brackets)] +macro_rules! foo { () => {} } +pub use crate::foo as bar; +fn main() { bar![$0] } +"#, + ); + } + + #[test] fn guesses_macro_braces() { check_edit( "vec!", @@ -240,7 +310,25 @@ fn main() { $0 } macro_rules! foo { () => {} } fn main() { foo! {$0} } "#, - ) + ); + + check_edit( + "bar!", + r#" +/// `foo![]` +#[macro_export] +macro_rules! foo { () => {} } +pub use crate::foo as bar; +fn main() { $0 } +"#, + r#" +/// `foo![]` +#[macro_export] +macro_rules! foo { () => {} } +pub use crate::foo as bar; +fn main() { bar![$0] } +"#, + ); } #[test] |