From 0a5877630cdc1f01091db814e3e4f78ae4689528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luiz=20Felipe=20Gon=C3=A7alves?= Date: Sat, 9 May 2026 15:38:38 -0300 Subject: [PATCH] fix(derive/help): support field-level fmt interpolation --- miette-derive/src/help.rs | 18 +++++++++++++++++ tests/derive.rs | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/miette-derive/src/help.rs b/miette-derive/src/help.rs index 1c21054..263f5ca 100644 --- a/miette-derive/src/help.rs +++ b/miette-derive/src/help.rs @@ -70,6 +70,23 @@ impl Help { for (i, field) in fields.iter().enumerate() { for attr in &field.attrs { if attr.path().is_ident("help") { + if let syn::Meta::List(_) = &attr.meta { + let display = attr.parse_args_with(|input: ParseStream| { + let fmt = input.parse()?; + let args = if input.is_empty() { + TokenStream::new() + } else { + fmt::parse_token_expr(input, false)? + }; + Ok(Display { + fmt, + args, + has_bonus_display: false, + }) + })?; + return Ok(Some(Help::Display(display))); + } + let help = if let Some(ident) = field.ident.clone() { syn::Member::Named(ident) } else { @@ -84,6 +101,7 @@ impl Help { } Ok(None) } + pub(crate) fn gen_enum(variants: &[DiagnosticDef]) -> Option { gen_all_variants_with( variants, diff --git a/tests/derive.rs b/tests/derive.rs index aa631dc..57bdd1f 100644 --- a/tests/derive.rs +++ b/tests/derive.rs @@ -632,3 +632,45 @@ fn test_optional_source_code() { .source_code() .is_some()); } + +#[test] +fn field_fmt_help() { + #[derive(Debug, Diagnostic, Error)] + #[error("welp")] + struct Foo { + #[help("do {suggestion} instead")] + suggestion: String, + } + + assert_eq!( + "do that instead".to_string(), + Foo { suggestion: "that".into() }.help().unwrap().to_string() + ); + + #[derive(Debug, Diagnostic, Error)] + #[error("welp")] + enum Bar { + #[error("variant")] + Variant { + #[help("do {suggestion} instead")] + suggestion: String, + }, + } + + assert_eq!( + "do that instead".to_string(), + Bar::Variant { suggestion: "that".into() }.help().unwrap().to_string() + ); +} + +#[test] +fn field_fmt_help_positional() { + #[derive(Debug, Diagnostic, Error)] + #[error("welp")] + struct Foo(#[help("do {0} instead")] String); + + assert_eq!( + "do that instead".to_string(), + Foo("that".into()).help().unwrap().to_string() + ); +}