1use crate::{
2 format_str::FormatStr, formatting::FormattingFlags, parse_utils::StrRawness,
3 parse_utils::TokenStream2Ext, shared_arg_parsing::ExprArg, spanned::Spans,
4};
56use proc_macro2::{Ident, Span, TokenStream as TokenStream2};
78use quote::{quote_spanned, TokenStreamExt};
910////////////////////////////////////////////////
1112mod parsing;
1314////////////////////////////////////////////////
1516struct UncheckedFormatArgs {
17 literal: FormatStr,
18 args: Vec<UncheckedFormatArg>,
19}
2021struct UncheckedFormatArg {
22pub(crate) spans: Spans,
23pub(crate) ident: Option<Ident>,
24// The identifier for the Formatter passed to format the argument.
25 // If this is Some, then `expr` is expanded directly,
26pub(crate) fmt_ident: Option<Ident>,
27/// Using a TokenStream2 because it is validated to be a valid expression in
28 /// the macro_rules! macros that call these proc macros.
29pub(crate) expr: TokenStream2,
30}
3132pub(crate) struct FormatArgs {
33pub(crate) condition: Option<ExprArg>,
34pub(crate) local_variables: Vec<LocalVariable>,
35pub(crate) expanded_into: Vec<ExpandInto>,
36}
3738pub(crate) struct FormatIfArgs {
39pub(crate) inner: FormatArgs,
40}
4142/// The arguments of `writec`
43pub(crate) struct WriteArgs {
44pub(crate) writer_expr: TokenStream2,
45pub(crate) writer_span: Span,
46pub(crate) format_args: FormatArgs,
47}
4849pub(crate) enum ExpandInto {
50 Str(String, StrRawness),
51 Formatted(ExpandFormatted),
52 WithFormatter(ExpandWithFormatter),
53}
5455pub(crate) struct ExpandFormatted {
56pub(crate) format: FormattingFlags,
57pub(crate) local_variable: Ident,
58}
5960pub(crate) struct ExpandWithFormatter {
61pub(crate) format: FormattingFlags,
62pub(crate) fmt_ident: Ident,
63pub(crate) expr: TokenStream2,
64}
6566pub(crate) struct LocalVariable {
67// The local variable that the macro will output for this argument,
68 // so that it is not evaluated multiple times when it's used multiple times
69 // in the format string.
70pub(crate) ident: Ident,
71/// Using a TokenStream2 because it is validated to be a valid expression in
72 /// the macro_rules! macros that call these proc macros.
73pub(crate) expr: TokenStream2,
74}
7576pub(crate) enum FormatArg {
77 WithFormatter {
78// The identifier for the Formatter passed to format the argument.
79 // If this is Some, then `expr` is expanded directly,
80fmt_ident: Ident,
81/// Using a TokenStream2 because it is validated to be a valid expression in
82 /// the macro_rules! macros that call these proc macros.
83expr: TokenStream2,
84 },
85 WithLocal(Ident),
86}
8788////////////////////////////////////////////////
8990impl ExpandInto {
91pub(crate) fn fmt_call(&self, formatter: &Ident) -> TokenStream2 {
92match self {
93 ExpandInto::Str(str, rawness) => {
94let str_tokens = rawness.tokenize_sub(str);
9596quote_spanned!(rawness.span()=> #formatter.write_str(#str_tokens) )
97 }
98 ExpandInto::Formatted(fmted) => {
99let flags = fmted.format;
100let fmt_method = fmted.format.fmt_method_name();
101let local_variable = &fmted.local_variable;
102let span = local_variable.span();
103104let mut tokens = quote::quote!(
105__cf_osRcTFl4A::coerce_to_fmt!(&#local_variable)
106 .#fmt_method
107 )
108 .set_span_recursive(span);
109110 tokens.append_all(quote::quote!( (&mut #formatter.make_formatter(#flags)) ));
111112 tokens
113 }
114 ExpandInto::WithFormatter(ExpandWithFormatter {
115 format,
116 fmt_ident,
117 expr,
118 }) => quote::quote!({
119let #fmt_ident = &mut #formatter.make_formatter(#format);
120 __cf_osRcTFl4A::pmr::ToResult( #expr ).to_result()
121 }),
122 }
123 }
124}