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}