fix ifmt spans

This commit is contained in:
Evan Almloff 2024-01-31 12:41:35 -06:00
parent af75fb855f
commit a7a3513b3f
2 changed files with 19 additions and 57 deletions

View file

@ -1,8 +1,8 @@
use std::{collections::HashSet, str::FromStr};
use std::str::FromStr;
use proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens, TokenStreamExt};
use quote::{quote, quote_spanned, ToTokens, TokenStreamExt};
use syn::{
parse::{Parse, ParseStream},
*,
@ -188,20 +188,10 @@ impl ToTokens for IfmtInput {
for segment in self.segments.iter() {
match segment {
Segment::Literal(s) => format_literal += &s.replace('{', "{{").replace('}', "}}"),
Segment::Formatted(FormattedSegment {
format_args,
segment,
}) => {
Segment::Formatted(FormattedSegment { format_args, .. }) => {
format_literal += "{";
match segment {
FormattedSegmentType::Expr(_) => {
format_literal += &expr_counter.to_string();
expr_counter += 1;
}
FormattedSegmentType::Ident(ident) => {
format_literal += &ident.to_string();
}
}
format_literal += &expr_counter.to_string();
expr_counter += 1;
format_literal += ":";
format_literal += format_args;
format_literal += "}";
@ -209,43 +199,29 @@ impl ToTokens for IfmtInput {
}
}
let span = match self.source.as_ref() {
Some(source) => source.span(),
None => Span::call_site(),
};
let positional_args = self.segments.iter().filter_map(|seg| {
if let Segment::Formatted(FormattedSegment {
segment: FormattedSegmentType::Expr(expr),
..
}) = seg
{
Some(expr)
if let Segment::Formatted(FormattedSegment { segment, .. }) = seg {
let mut segment = segment.clone();
// We set the span of the ident here, so that we can use it in diagnostics
if let FormattedSegmentType::Ident(ident) = &mut segment {
ident.set_span(span);
}
Some(segment)
} else {
None
}
});
// remove duplicate idents
let named_args_idents: HashSet<_> = self
.segments
.iter()
.filter_map(|seg| {
if let Segment::Formatted(FormattedSegment {
segment: FormattedSegmentType::Ident(ident),
..
}) = seg
{
Some(ident)
} else {
None
}
})
.collect();
let named_args = named_args_idents
.iter()
.map(|ident| quote!(#ident = #ident));
quote! {
quote_spanned! {
span =>
::std::format_args!(
#format_literal
#(, #positional_args)*
#(, #named_args)*
)
}
.to_tokens(tokens)

View file

@ -110,20 +110,6 @@ impl Parse for CallBody {
}
}
/// Serialize the same way, regardless of flavor
impl ToTokens for CallBody {
fn to_tokens(&self, out_tokens: &mut TokenStream2) {
let body = TemplateRenderer {
roots: &self.roots,
location: None,
};
out_tokens.append_all(quote! {
#body
})
}
}
#[derive(Default, Debug)]
pub struct RenderCallBody(pub CallBody);