1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
//! Transformers: list elements that rewrite the newest entry and forward.
//!
//! The caller places a transformer right after the definition it rewrites:
//!
//! ```text
//! Partly! { [Partly!, my_lib::public_fields!, cb!] REST }
//! ```
//!
//! `public_fields!` rewrites the newest entry (item and/or META) and forwards
//! to `cb!`. The definer writes a plain `#[announce]`.
use crate;
use TokenStream;
use ;
use quote;
/// Runs a transformer: the body of a `#[proc_macro]` that gets the newest entry,
/// rewrites it and forwards to the next list element.
///
/// - `input` is the input of the proc macro: the tokens that the trampoline before it
/// sends, parsed as an [`Input`].
/// - `f` is the transformer itself. It gets the newest [`Entry`] by value and returns
/// the rewritten one, or a `syn::Error`.
///
/// The result forwards the rewritten entry to the next element of the list
/// ([`Input::forward_transformed`]). A `syn::Error` (the input does not parse, there is
/// no entry, the transformer is the last element of the list, or `f` fails) becomes a
/// `compile_error!`, so the result can be returned from the proc macro as it is.
///
/// In a proc-macro crate this is a `#[proc_macro]` function. The example is run as a
/// doctest, which cannot define a proc macro: it has no attribute, and `proc_macro`
/// stands for `proc_macro2`.
///
/// ```
/// # use announce_core as announce;
/// # use proc_macro2 as proc_macro;
/// # use template_quote as quote;
/// /// Drops non-`pub` fields and lists the kept ones in META.
/// pub fn public_fields(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
/// announce::helper::transformer(input.into(), |mut entry| {
/// // `entry` is an `announce::helper::Entry`.
/// let mut item: syn::ItemStruct = syn::parse2(entry.item.clone())?;
/// if let syn::Fields::Named(fields) = &mut item.fields {
/// let all = std::mem::take(&mut fields.named);
/// fields.named = all
/// .into_iter()
/// .filter(|f| matches!(f.vis, syn::Visibility::Public(_)))
/// .collect();
/// let kept = fields.named.iter().filter_map(|f| f.ident.as_ref());
/// entry.meta.push(syn::parse_quote!(fields(#(#kept),*)));
/// }
/// entry.item = quote::quote!(#item);
/// Ok(entry)
/// })
/// .into()
/// }
/// #
/// # let out = public_fields(syn::parse_quote! {
/// # [t!, cb!] a::S! => [] { struct S { pub a: u8, b: u8, pub c: u8 } } REST
/// # });
/// # let out = out.to_string();
/// # assert!(out.starts_with("cb !"), "{}", out);
/// # assert!(out.contains("struct S { pub a : u8 , pub c : u8 }"), "{}", out);
/// # assert!(out.contains("fields (a , c)"), "{}", out);
/// ```
///
/// The function can be tested with `proc_macro2` streams, because it does not use the
/// `proc_macro` crate:
///
/// ```
/// # use announce_core as announce;
/// use announce::helper::transformer;
/// use proc_macro2::TokenStream;
///
/// let run = |input: TokenStream| {
/// transformer(input, |mut entry| {
/// entry.meta.push(syn::parse_quote!(seen));
/// Ok(entry)
/// })
/// .to_string()
/// };
/// // The next element gets the rewritten entry.
/// let out = run(syn::parse_quote! { [t!, cb!] a::S! => [] { struct S; } REST });
/// assert!(out.starts_with("cb !") && out.contains("[seen]"), "{}", out);
/// // Nothing to transform, and nothing to forward to.
/// assert!(run(syn::parse_quote! { [t!, cb!] REST }).contains("compile_error"));
/// assert!(run(syn::parse_quote! { [t!] a::S! => [] { struct S; } REST }).contains("compile_error"));
/// ```
///
/// The macro `transformer!` (`announce::helper::transformer! { pub fn name(entry) { .. } }`)
/// does the same and defines the `#[proc_macro]` function too. It is kept for
/// compatibility; write the function above instead.
/// Defines a transformer: the same as the function [`transformer()`], in the form
/// of a macro.
///
/// **Kept for compatibility; prefer the function [`transformer()`]**, called from a
/// `#[proc_macro]` function you write yourself. This macro is a thin wrapper that
/// defines that function: the body gets the newest entry as an [`Entry`] (as `entry`,
/// by value, mutable) and returns `syn::Result<Entry>`.
///
/// ```ignore
/// announce::helper::transformer! {
/// /// Drops non-`pub` fields and lists the kept ones in META.
/// pub fn public_fields(entry) {
/// let mut item: syn::ItemStruct = syn::parse2(entry.item.clone())?;
/// // ..
/// entry.item = quote::quote!(#item);
/// entry.meta.push(syn::parse_quote!(fields(a, c)));
/// Ok(entry)
/// }
/// }
/// ```
///
/// is the same as
///
/// ```
/// # use announce_core as announce;
/// # use proc_macro2 as proc_macro; // a doctest cannot define a `#[proc_macro]`
/// # use template_quote as quote;
/// /// Drops non-`pub` fields and lists the kept ones in META.
/// pub fn public_fields(ts: proc_macro::TokenStream) -> proc_macro::TokenStream {
/// announce::helper::transformer(ts.into(), |mut entry| {
/// let mut item: syn::ItemStruct = syn::parse2(entry.item.clone())?;
/// // ..
/// entry.item = quote::quote!(#item);
/// entry.meta.push(syn::parse_quote!(fields(a, c)));
/// Ok(entry)
/// })
/// .into()
/// }
/// #
/// # let out = public_fields(syn::parse_quote! { [t!, cb!] a::S! => [] { struct S; } REST });
/// # let out = out.to_string();
/// # assert!(out.starts_with("cb !") && out.contains("fields (a , c)"), "{}", out);
/// ```
,
))
}
};
}
/// Strips an item down to its signatures. This is what the
/// [`signature_only!`] transformer does, and custom transformers can use it too.
/// That macro lists the rules: function bodies are replaced with
/// `{ ::core::unimplemented!() }`, except in a `const fn` and in a fn that returns
/// `impl Trait`.
///
/// [`signature_only!`]: https://docs.rs/announce/latest/announce/macro.signature_only.html