From 368c5f6023889f32fd22cf27bd55b3debb9ff69f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 30 Sep 2021 15:53:47 +0200 Subject: [PATCH 1/3] Fix format string highlighting in `panic!` --- crates/ide/src/syntax_highlighting/format.rs | 8 +++--- .../test_data/highlight_strings.html | 27 +++++++++++++++++++ crates/ide/src/syntax_highlighting/tests.rs | 27 +++++++++++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/crates/ide/src/syntax_highlighting/format.rs b/crates/ide/src/syntax_highlighting/format.rs index 5bbadb0f45..ce24311115 100644 --- a/crates/ide/src/syntax_highlighting/format.rs +++ b/crates/ide/src/syntax_highlighting/format.rs @@ -31,14 +31,16 @@ fn is_format_string(string: &ast::String) -> Option<()> { let parent = string.syntax().parent()?; let name = parent.parent().and_then(ast::MacroCall::cast)?.path()?.segment()?.name_ref()?; - if !matches!(name.text().as_str(), "format_args" | "format_args_nl") { + if !matches!( + name.text().as_str(), + "format_args" | "format_args_nl" | "const_format_args" | "panic_2015" | "panic_2021" + ) { return None; } let first_literal = parent .children_with_tokens() - .filter_map(|it| it.as_token().cloned().and_then(ast::String::cast)) - .next()?; + .find_map(|it| it.as_token().cloned().and_then(ast::String::cast))?; if &first_literal != string { return None; } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index 9c20c8ae4b..d0ad7945a7 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -51,6 +51,31 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; } +mod panic { + pub macro panic_2015 { + () => ( + $crate::panicking::panic("explicit panic") + ), + ($msg:literal $(,)?) => ( + $crate::panicking::panic($msg) + ), + // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint. + ($msg:expr $(,)?) => ( + $crate::panicking::panic_str($msg) + ), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ( + $crate::panicking::panic_display(&$arg) + ), + ($fmt:expr, $($arg:tt)+) => ( + $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) + ), + } +} + +#[rustc_builtin_macro(std_panic)] +macro_rules! panic {} + fn main() { // from https://doc.rust-lang.org/std/fmt/index.html println!("Hello"); // => "Hello" @@ -100,4 +125,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd println!("{ничоси}", ничоси = 92); println!("{:x?} {} ", thingy, n2); + panic!("{}", 0); + panic!("more {}", 1); } \ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 9fc730e007..91d29a96bf 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -446,6 +446,31 @@ macro_rules! format_args_nl { ($fmt:expr, $($args:tt)*) => {{ /* compiler built-in */ }}; } +mod panic { + pub macro panic_2015 { + () => ( + $crate::panicking::panic("explicit panic") + ), + ($msg:literal $(,)?) => ( + $crate::panicking::panic($msg) + ), + // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint. + ($msg:expr $(,)?) => ( + $crate::panicking::panic_str($msg) + ), + // Special-case the single-argument case for const_panic. + ("{}", $arg:expr $(,)?) => ( + $crate::panicking::panic_display(&$arg) + ), + ($fmt:expr, $($arg:tt)+) => ( + $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+)) + ), + } +} + +#[rustc_builtin_macro(std_panic)] +macro_rules! panic {} + fn main() { // from https://doc.rust-lang.org/std/fmt/index.html println!("Hello"); // => "Hello" @@ -495,6 +520,8 @@ fn main() { println!("{ничоси}", ничоси = 92); println!("{:x?} {} ", thingy, n2); + panic!("{}", 0); + panic!("more {}", 1); }"# .trim(), expect_file!["./test_data/highlight_strings.html"], From b8437f71b6998f50ec2174786020354bc680eef0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 30 Sep 2021 16:26:41 +0200 Subject: [PATCH 2/3] Less hacky `assert!` expansion --- crates/hir_expand/src/builtin_macro.rs | 36 +++++++++++-------- .../test_data/highlight_strings.html | 5 +++ crates/ide/src/syntax_highlighting/tests.rs | 5 +++ 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 297497ac1b..eeee66cbd9 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs @@ -180,22 +180,28 @@ fn assert_expand( _id: MacroCallId, tt: &tt::Subtree, ) -> ExpandResult { - // A hacky implementation for goto def and hover - // We expand `assert!(cond, arg1, arg2)` to - // ``` - // {(cond, &(arg1), &(arg2));} - // ```, - // which is wrong but useful. - + let krate = tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() }; let args = parse_exprs_with_sep(tt, ','); - - let arg_tts = args.into_iter().flat_map(|arg| { - quote! { &(#arg), } - }.token_trees); - - let expanded = quote! { - { { (##arg_tts); } } + let expanded = match &*args { + [cond, panic_args @ ..] => { + let cond = cond.clone(); + let panic_args = panic_args.iter().cloned().intersperse(tt::Subtree { + delimiter: None, + token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { + char: ',', + spacing: tt::Spacing::Alone, + id: tt::TokenId::unspecified(), + }))], + }); + quote! {{ + if !#cond { + #krate::panic!(##panic_args); + } + }} + } + [] => quote! {{}}, }; + ExpandResult::ok(expanded) } @@ -731,7 +737,7 @@ mod tests { } assert!(true, "{} {:?}", arg1(a, b, c), arg2); "#, - expect![["{{(&(true), &(\"{} {:?}\"), &(arg1(a,b,c)), &(arg2),);}}"]], + expect![[r#"{if!true{$crate::panic!("{} {:?}",arg1(a,b,c),arg2);}}"#]], ); } diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html index d0ad7945a7..2992755ded 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html @@ -74,7 +74,10 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd } #[rustc_builtin_macro(std_panic)] +#[macro_export] macro_rules! panic {} +#[rustc_builtin_macro] +macro_rules! assert {} fn main() { // from https://doc.rust-lang.org/std/fmt/index.html @@ -127,4 +130,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd println!("{:x?} {} ", thingy, n2); panic!("{}", 0); panic!("more {}", 1); + assert!(true, "{}", 1); + assert!(true, "{} asdasd", 1); } \ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 91d29a96bf..d5018f2327 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -469,7 +469,10 @@ mod panic { } #[rustc_builtin_macro(std_panic)] +#[macro_export] macro_rules! panic {} +#[rustc_builtin_macro] +macro_rules! assert {} fn main() { // from https://doc.rust-lang.org/std/fmt/index.html @@ -522,6 +525,8 @@ fn main() { println!("{:x?} {} ", thingy, n2); panic!("{}", 0); panic!("more {}", 1); + assert!(true, "{}", 1); + assert!(true, "{} asdasd", 1); }"# .trim(), expect_file!["./test_data/highlight_strings.html"], From 375a0ff785a296cee66e9a431a8b1671809b579a Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 30 Sep 2021 16:37:12 +0200 Subject: [PATCH 3/3] Use itertools --- crates/hir_expand/src/builtin_macro.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index eeee66cbd9..e148118348 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs @@ -184,15 +184,16 @@ fn assert_expand( let args = parse_exprs_with_sep(tt, ','); let expanded = match &*args { [cond, panic_args @ ..] => { - let cond = cond.clone(); - let panic_args = panic_args.iter().cloned().intersperse(tt::Subtree { + let comma = tt::Subtree { delimiter: None, token_trees: vec![tt::TokenTree::Leaf(tt::Leaf::Punct(tt::Punct { char: ',', spacing: tt::Spacing::Alone, id: tt::TokenId::unspecified(), }))], - }); + }; + let cond = cond.clone(); + let panic_args = itertools::Itertools::intersperse(panic_args.iter().cloned(), comma); quote! {{ if !#cond { #krate::panic!(##panic_args);