mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-27 20:42:10 +00:00

Support for `let…else` formatting was just merged to nightly (rust-lang/rust#113225). Rerun `cargo fmt` with Rust nightly 2023-07-02 to pick this up. Followup to #939. Signed-off-by: Anders Kaseorg <andersk@mit.edu>
59 lines
1.8 KiB
Rust
59 lines
1.8 KiB
Rust
use proc_macro2::TokenStream;
|
|
use quote::{quote, quote_spanned, ToTokens};
|
|
use syn::spanned::Spanned;
|
|
use syn::{Block, Expr, ItemFn, Stmt};
|
|
|
|
pub(crate) fn derive_message_formats(func: &ItemFn) -> TokenStream {
|
|
let mut strings = quote!();
|
|
|
|
if let Err(err) = parse_block(&func.block, &mut strings) {
|
|
return err;
|
|
}
|
|
|
|
quote! {
|
|
#func
|
|
fn message_formats() -> &'static [&'static str] {
|
|
&[#strings]
|
|
}
|
|
}
|
|
}
|
|
|
|
fn parse_block(block: &Block, strings: &mut TokenStream) -> Result<(), TokenStream> {
|
|
let Some(Stmt::Expr(last, _)) = block.stmts.last() else {
|
|
panic!("expected last statement in block to be an expression")
|
|
};
|
|
parse_expr(last, strings)?;
|
|
Ok(())
|
|
}
|
|
|
|
fn parse_expr(expr: &Expr, strings: &mut TokenStream) -> Result<(), TokenStream> {
|
|
match expr {
|
|
Expr::Macro(mac) if mac.mac.path.is_ident("format") => {
|
|
let Some(first_token) = mac.mac.tokens.to_token_stream().into_iter().next() else {
|
|
return Err(
|
|
quote_spanned!(expr.span() => compile_error!("expected format! to have an argument")),
|
|
);
|
|
};
|
|
strings.extend(quote! {#first_token,});
|
|
Ok(())
|
|
}
|
|
Expr::Block(block) => parse_block(&block.block, strings),
|
|
Expr::If(expr) => {
|
|
parse_block(&expr.then_branch, strings)?;
|
|
if let Some((_, then)) = &expr.else_branch {
|
|
parse_expr(then, strings)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
Expr::Match(block) => {
|
|
for arm in &block.arms {
|
|
parse_expr(&arm.body, strings)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
_ => Err(quote_spanned!(
|
|
expr.span() =>
|
|
compile_error!("expected last expression to be a format! macro or a match block")
|
|
)),
|
|
}
|
|
}
|