1#![warn(missing_docs)]
5#![feature(trait_alias)]
6
7use proc_macro2::TokenStream;
8use proc_macro2::TokenTree;
9use quote::quote;
10use std::iter::FromIterator;
11use syn::visit::Visit;
12use syn::WhereClause;
13use syn::WherePredicate;
14
15
16
17pub trait Str = Into<String> + AsRef<str>;
22
23
24
25pub fn map_tokens<F:Fn(TokenTree) -> TokenTree>
31(input:TokenStream, f:F) -> TokenStream {
32 let ret_iter = input.into_iter().map(f);
33 ret_iter.collect()
34}
35
36pub fn rewrite_stream
40<F:Fn(TokenTree) -> TokenStream + Copy>
41(input:TokenStream, f:F) -> TokenStream {
42 let mut ret = TokenStream::new();
43 for token in input.into_iter() {
44 match token {
45 proc_macro2::TokenTree::Group(group) => {
46 let delim = group.delimiter();
47 let span = group.span();
48 let rewritten = rewrite_stream(group.stream(), f);
49 let mut new_group = proc_macro2::Group::new(delim,rewritten);
50 new_group.set_span(span);
51 let new_group = vec![TokenTree::from(new_group)];
52 ret.extend(new_group.into_iter())
53 }
54 _ => ret.extend(f(token)),
55 }
56 }
57 ret
58}
59
60
61
62pub fn matching_ident(token:&TokenTree, name:&str) -> bool {
68 match token {
69 TokenTree::Ident(ident) => *ident == name,
70 _ => false,
71 }
72}
73
74
75
76pub fn repr<T: quote::ToTokens>(t:&T) -> String {
82 quote!(#t).to_string()
83}
84
85
86
87pub fn fields_list(fields:&syn::Fields) -> Vec<&syn::Field> {
93 match fields {
94 syn::Fields::Named (ref f) => f.named .iter().collect(),
95 syn::Fields::Unnamed(ref f) => f.unnamed.iter().collect(),
96 syn::Fields::Unit => Default::default(),
97 }
98}
99
100pub fn field_ident_token(field:&syn::Field, index:syn::Index) -> TokenStream {
104 match &field.ident {
105 Some(ident) => quote!(#ident),
106 None => quote!(#index),
107 }
108}
109
110pub fn field_names(fields:&syn::FieldsNamed) -> Vec<&syn::Ident> {
112 fields.named.iter().map(|field| {
113 field.ident.as_ref().expect("Impossible: no name on a named field.")
114 }).collect()
115}
116
117
118
119pub fn path_matching_ident(path:&syn::Path, str:impl Str) -> bool {
125 path.get_ident().map_or(false, |ident| ident == str.as_ref())
126}
127
128
129
130pub fn index_sequence(len:usize) -> Vec<syn::Index> {
137 (0..len).map(syn::Index::from).collect()
138}
139
140pub fn identifier_sequence(len:usize) -> Vec<syn::Ident> {
142 let format_field = |ix| quote::format_ident!("field{}",ix);
143 (0..len).map(format_field).collect()
144}
145
146
147
148pub fn path_segment_generic_args
154(segment:&syn::PathSegment) -> Vec<&syn::GenericArgument> {
155 match segment.arguments {
156 syn::PathArguments::AngleBracketed(ref args) =>
157 args.args.iter().collect(),
158 _ =>
159 Vec::new(),
160 }
161}
162
163pub fn ty_path_generic_args
167(ty_path:&syn::TypePath) -> Vec<&syn::GenericArgument> {
168 ty_path.path.segments.last().map_or(Vec::new(), path_segment_generic_args)
169}
170
171pub fn ty_path_type_args
173(ty_path:&syn::TypePath) -> Vec<&syn::Type> {
174 ty_path_generic_args(ty_path).iter().filter_map( |generic_arg| {
175 match generic_arg {
176 syn::GenericArgument::Type(t) => Some(t),
177 _ => None,
178 }
179 }).collect()
180}
181
182pub fn last_type_arg(ty_path:&syn::TypePath) -> Option<&syn::GenericArgument> {
184 ty_path_generic_args(ty_path).last().copied()
185}
186
187
188
189#[derive(Default)]
195pub struct TypeGatherer<'ast> {
196 pub types: Vec<&'ast syn::TypePath>
198}
199
200impl<'ast> Visit<'ast> for TypeGatherer<'ast> {
201 fn visit_type_path(&mut self, node:&'ast syn::TypePath) {
202 self.types.push(node);
203 syn::visit::visit_type_path(self, node);
204 }
205}
206
207pub fn gather_all_types(node:&syn::Type) -> Vec<&syn::TypePath> {
209 let mut type_gather = TypeGatherer::default();
210 type_gather.visit_type(node);
211 type_gather.types
212}
213
214pub fn gather_all_type_reprs(node:&syn::Type) -> Vec<String> {
216 gather_all_types(node).iter().map(|t| repr(t)).collect()
217}
218
219
220
221pub fn type_matches_repr(ty:&syn::Type, target_repr:&str) -> bool {
227 repr(ty) == target_repr
228}
229
230pub fn type_matches(ty:&syn::Type, target_param:&syn::GenericParam) -> bool {
232 type_matches_repr(ty, &repr(target_param))
233}
234
235pub fn type_depends_on(ty:&syn::Type, target_param:&syn::GenericParam) -> bool {
237 let target_param = repr(target_param);
238 let relevant_types = gather_all_types(ty);
239 relevant_types.iter().any(|ty| repr(ty) == target_param)
240}
241
242pub fn variant_depends_on
244(var:&syn::Variant, target_param:&syn::GenericParam) -> bool {
245 var.fields.iter().any(|field| type_depends_on(&field.ty, target_param))
246}
247
248
249
250pub fn new_where_clause(predicates:impl IntoIterator<Item=WherePredicate>) -> WhereClause {
256 let predicates = syn::punctuated::Punctuated::from_iter(predicates);
257 WhereClause {where_token:Default::default(),predicates}
258}
259
260
261
262#[cfg(test)]
267mod tests {
268 use super::*;
269 use proc_macro2::TokenStream;
270
271 fn parse<T:syn::parse::Parse>(code:&str) -> T {
272 syn::parse_str(code).unwrap()
273 }
274
275 #[test]
276 fn repr_round_trips() {
277 let program = "pub fn repr<T: quote::ToTokens>(t: &T) -> String {}";
278 let tokens = parse::<TokenStream>(program);
279 let quoted_program = repr(&tokens);
280 let tokens2 = parse::<TokenStream>("ed_program);
281 assert_eq!(repr(&tokens), repr(&tokens2));
283 }
284
285 #[test]
286 fn fields_list_test() {
287 let tuple_like = "struct Unnamed(i32, String, T);";
288 let proper_struct = "struct Named{i: i32, s: String, t: T}";
289 let expected_types = vec!["i32", "String", "T"];
290
291 fn assert_field_types(program:&str, expected_types:&[&str]) {
292 let tokens = parse::<syn::ItemStruct>(program);
293 let fields = fields_list(&tokens.fields);
294 let types = fields.iter().map(|f| repr(&f.ty));
295 assert_eq!(Vec::from_iter(types), expected_types);
296 }
297
298 assert_field_types(tuple_like, &expected_types);
299 assert_field_types(proper_struct, &expected_types);
300 }
301
302 #[test]
303 fn type_dependency() {
304 let param:syn::GenericParam = parse("T");
305 let depends = |code| {
306 let ty:syn::Type = parse(code);
307 type_depends_on(&ty, ¶m)
308 };
309
310 let dependents = vec!{
312 "T",
313 "Option<T>",
314 "Pair<T, U>",
315 "Pair<U, T>",
316 "Pair<U, (T,)>",
317 "&T",
318 "&'t mut T",
319 };
320 let independents = vec!{
322 "Tt",
323 "Option<Tt>",
324 "Pair<Tt, U>",
325 "Pair<U, Tt>",
326 "Pair<U, Tt>",
327 "i32",
328 "&str",
329 };
330 for dependent in dependents {
331 assert!(depends(dependent), "{} must depend on {}"
332 , repr(&dependent), repr(¶m));
333 }
334 for independent in independents {
335 assert!(!depends(independent), "{} must not depend on {}"
336 , repr(&independent), repr(¶m));
337 }
338 }
339
340 #[test]
341 fn collecting_type_path_args() {
342 fn check(expected_type_args:Vec<&str>, ty_path:&str) {
343 let ty_path = parse(ty_path);
344 let args = super::ty_path_type_args(&ty_path);
345 assert_eq!(expected_type_args.len(), args.len());
346 let zipped = expected_type_args.iter().zip(args.iter());
347 for (expected,got) in zipped {
348 assert_eq!(expected, &repr(got));
349 }
350 }
351 check(vec!["T"] , "std::Option<T>");
352 check(vec!["U"] , "std::Option<U>");
353 check(vec!["A", "B"], "Either<A,B>");
354 assert_eq!(super::last_type_arg(&parse("i32")), None);
355 assert_eq!(repr(&super::last_type_arg(&parse("Foo<C>"))), "C");
356 }
357}