proc_utils/lib.rs
1//! This crate provides a series of traits, macros, functions, and utilities that make writing
2//! and debugging proc macros easier
3
4pub use proc_macro2::TokenStream as TokenStream2;
5pub use proc_util_macros::*;
6use quote::ToTokens;
7
8/// Bring this trait into scope for a blanket `to_pretty()` implementation for all
9/// `syn`-compatible types as well as `TokenStream2`.
10///
11/// Calling [`to_pretty`](`ToPretty::to_pretty`) on any such objects will result in a
12/// pretty-formatted string representation of the (parsed) source code of that item.
13pub trait ToPretty {
14 /// Produces a pretty-formatted [`String`] (formatted by [`prettyplease`]) representation
15 /// of the underlying token stream.
16 ///
17 /// Can be used on anything that implements [`ToTokens`] if [`ToPretty`] is brought into
18 /// scope.
19 ///
20 /// ## Example
21 ///
22 /// Using `to_pretty` directly on a [`TokenStream2`]:
23 /// ```
24 /// use proc_utils::ToPretty;
25 ///
26 /// let struct_tokens = quote::quote!(struct MyStruct;);
27 /// assert_eq!(struct_tokens.to_pretty(), "struct MyStruct;\n");
28 /// ```
29 ///
30 /// Using `to_pretty` on a [`syn::ItemStruct`]:
31 /// ```
32 /// use proc_utils::ToPretty;
33 ///
34 /// let struct_tokens = quote::quote!(struct MyStruct { field1: usize, field2: u32, field3: bool });
35 /// let item_struct = syn::parse2::<syn::ItemStruct>(struct_tokens).unwrap();
36 /// assert_eq!(item_struct.to_pretty(),
37 /// "struct MyStruct {\n \
38 /// field1: usize,\n \
39 /// field2: u32,\n \
40 /// field3: bool,\n\
41 /// }\n"
42 /// );
43 /// ```
44 fn to_pretty(&self) -> String;
45}
46
47impl<T: ToTokens> ToPretty for T {
48 fn to_pretty(&self) -> String {
49 let tokens: TokenStream2 = self.to_token_stream();
50 let file = syn::parse_file(&tokens.to_string()).unwrap();
51 prettyplease::unparse(&file)
52 }
53}
54
55/// Like [`ToPretty`] but prints to the console instead.
56pub trait PrettyPrint {
57 /// Like [`ToPretty::to_pretty`] but prints to the console instead.
58 fn pretty_print(&self);
59}
60
61impl<T: ToTokens> PrettyPrint for T {
62 fn pretty_print(&self) {
63 let tokens: TokenStream2 = self.to_token_stream();
64 let file = syn::parse_file(&tokens.to_string()).unwrap();
65 println!("{}", prettyplease::unparse(&file));
66 }
67}
68
69#[test]
70fn test_pretty_print() {
71 quote::quote!(
72 type Blah = usize;
73 )
74 .pretty_print();
75}