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 proc_macro2::{Span, TokenStream};
use quote::{quote, ToTokens, TokenStreamExt}; use quote::{quote, quote_spanned, ToTokens, TokenStreamExt};
use syn::{ use syn::{
parse::{Parse, ParseStream}, parse::{Parse, ParseStream},
*, *,
@ -188,20 +188,10 @@ impl ToTokens for IfmtInput {
for segment in self.segments.iter() { for segment in self.segments.iter() {
match segment { match segment {
Segment::Literal(s) => format_literal += &s.replace('{', "{{").replace('}', "}}"), Segment::Literal(s) => format_literal += &s.replace('{', "{{").replace('}', "}}"),
Segment::Formatted(FormattedSegment { Segment::Formatted(FormattedSegment { format_args, .. }) => {
format_args,
segment,
}) => {
format_literal += "{"; format_literal += "{";
match segment {
FormattedSegmentType::Expr(_) => {
format_literal += &expr_counter.to_string(); format_literal += &expr_counter.to_string();
expr_counter += 1; expr_counter += 1;
}
FormattedSegmentType::Ident(ident) => {
format_literal += &ident.to_string();
}
}
format_literal += ":"; format_literal += ":";
format_literal += format_args; format_literal += format_args;
format_literal += "}"; 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| { let positional_args = self.segments.iter().filter_map(|seg| {
if let Segment::Formatted(FormattedSegment { if let Segment::Formatted(FormattedSegment { segment, .. }) = seg {
segment: FormattedSegmentType::Expr(expr), let mut segment = segment.clone();
.. // We set the span of the ident here, so that we can use it in diagnostics
}) = seg if let FormattedSegmentType::Ident(ident) = &mut segment {
{ ident.set_span(span);
Some(expr) }
Some(segment)
} else { } else {
None None
} }
}); });
// remove duplicate idents quote_spanned! {
let named_args_idents: HashSet<_> = self span =>
.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! {
::std::format_args!( ::std::format_args!(
#format_literal #format_literal
#(, #positional_args)* #(, #positional_args)*
#(, #named_args)*
) )
} }
.to_tokens(tokens) .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)] #[derive(Default, Debug)]
pub struct RenderCallBody(pub CallBody); pub struct RenderCallBody(pub CallBody);