//! Implementations of [`fmt`]-like derive macros. //! //! [`fmt`]: std::fmt
#[cfg(feature = "debug")] pub(crate) mod debug; #[cfg(feature = "display")] pub(crate) mod display; mod parsing;
use proc_macro2::TokenStream; use quote::ToTokens; use syn::{
parse::{Parse, ParseStream},
punctuated::Punctuated,
spanned::Spanned as _,
token, Ident,
};
usecrate::parsing::Expr;
/// Representation of a macro attribute expressing additional trait bounds. #[derive(Debug, Default)] struct BoundsAttribute(Punctuated<syn::WherePredicate, syn::token::Comma>);
impl BoundsAttribute { /// Errors in case legacy syntax is encountered: `bound = "..."`. fn check_legacy_fmt(input: ParseStream<'_>) -> syn::Result<()> { let fork = input.fork();
let path = fork
.parse::<syn::Path>()
.and_then(|path| fork.parse::<syn::token::Eq>().map(|_| path)); match path {
Ok(path) if path.is_ident("bound") => fork
.parse::<syn::Lit>()
.ok()
.and_then(|lit| match lit {
syn::Lit::Str(s) => Some(s.value()),
_ => None,
})
.map_or(Ok(()), |bound| {
Err(syn::Error::new(
input.span(),
format!("legacy syntax, use `bound({bound})` instead"),
))
}),
Ok(_) | Err(_) => Ok(()),
}
}
}
/// Representation of a formatting placeholder. #[derive(Debug, PartialEq, Eq)] struct Placeholder { /// Formatting argument (either named or positional) to be used by this placeholder.
arg: Parameter,
#[cfg(test)] mod fmt_attribute_spec { use itertools::Itertools as _; use quote::ToTokens; use syn;
usesuper::FmtAttribute;
fn assert<'a>(input: &'a str, parsed: impl AsRef<[&'a str]>) { let parsed = parsed.as_ref(); let attr = syn::parse_str::<FmtAttribute>(&format!("\"\", {}", input)).unwrap(); let fmt_args = attr
.args
.into_iter()
.map(|arg| arg.into_token_stream().to_string())
.collect::<Vec<String>>();
fmt_args.iter().zip_eq(parsed).enumerate().for_each(
|(i, (found, expected))| {
assert_eq!(
*expected, found, "Mismatch at index {i}\n\
Expected: {parsed:?}\n\
Found: {fmt_args:?}",
);
},
);
}
#[test] fn cases() { let cases = [ "ident", "alias = ident", "[a , b , c , d]", "counter += 1", "async { fut . await }", "a < b", "a > b", "{ let x = (a , b) ; }", "invoke (a , b)", "foo as f64", "| a , b | a + b", "obj . k", "for pat in expr { break pat ; }", "if expr { true } else { false }", "vector [2]", "1", "\"foo\"", "loop { break i ; }", "format ! (\"{}\" , q)", "match n { Some (n) => { } , None => { } }", "x . foo ::< T > (a , b)", "x . foo ::< T < [T < T >; if a < b { 1 } else { 2 }] >, { a < b } > (a , b)", "(a + b)", "i32 :: MAX", "1 .. 2", "& a", "[0u8 ; N]", "(a , b , c , d)", "< Ty as Trait > :: T", "< Ty < Ty < T >, { a < b } > as Trait < T > > :: T",
];
assert("", []); for i in1..4 { for permutations in cases.into_iter().permutations(i) { letmut input = permutations.clone().join(",");
assert(&input, &permutations);
input.push(',');
assert(&input, &permutations);
}
}
}
}
#[cfg(test)] mod placeholder_parse_fmt_string_spec { usesuper::{Parameter, Placeholder};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.