proc_macro_assertions/
assert_into.rs

1/// Not meant to be called directly. Use [`assert_into!`] instead.
2// TODO: Add differentiation for Ident / Type asserts added in 0.1.0 here as well
3#[doc(hidden)]
4#[macro_export]
5macro_rules! internal_impl {
6    // ======================= Trait Templates ======================================
7    ($store:ident | $type:ident impl $tokens:tt) => {
8        {
9            internal_impl!(@internal imports);
10            use $crate::generatable::Trait;
11            $store.assert(Trait::from_owned(parse_quote!($tokens)).test::<TokenCmpWrapper<syn::Type>>($type));
12        }
13    };
14    ($store:ident | &$type:ident impl $tokens:tt) => {
15        {
16            internal_impl!(@internal imports);
17            use $crate::generatable::Trait;
18            $store.assert(Trait::from_owned(parse_quote!($tokens)).test::<TokenCmpWrapper<syn::Type>>(&$type));
19        }
20    };
21    ($store:ident | $type:ident with $generics:ident impl $tokens:tt) => {
22        {
23            internal_impl!(@internal imports);
24            use $crate::generatable::Trait;
25            $store.assert(
26                Trait::from_owned(parse_quote!($tokens))
27                    .with_generics::<TokenCmpWrapper<syn::Type>>($generics)
28                    .test::<TokenCmpWrapper<syn::Type>>($type),
29            );
30        }
31    };
32    ($store:ident | $type:ident with &$generics:ident impl $tokens:tt) => {
33        {
34            internal_impl!(@internal imports);
35            use $crate::generatable::Trait;
36            $store.assert(
37                Trait::from_owned(parse_quote!($tokens))
38                    .with_generics::<TokenCmpWrapper<syn::Type>>(&$generics)
39                    .test::<TokenCmpWrapper<syn::Type>>($type),
40            );
41        }
42    };
43    ($store:ident | &$type:ident with $generics:ident impl $tokens:tt) => {
44        {
45            internal_impl!(@internal imports);
46            use $crate::generatable::Trait;
47            $store.assert(
48                Trait::from_owned(parse_quote!($tokens))
49                    .with_generics::<TokenCmpWrapper<syn::Type>>($generics)
50                    .test::<TokenCmpWrapper<syn::Type>>(&$type),
51            );
52        }
53    };
54    ($store:ident | &$type:ident with &$generics:ident impl $tokens:tt) => {
55        {
56            internal_impl!(@internal imports);
57            use $crate::generatable::Trait;
58            $store.assert(
59                Trait::from_owned(parse_quote!($tokens))
60                    .with_generics::<TokenCmpWrapper<syn::Type>>(&$generics)
61                    .test::<TokenCmpWrapper<syn::Type>>(&$type),
62            );
63        }
64    };
65
66    // ======================= Type Templates without generics ======================
67    ($store:ident | $type:ident == $tokens:tt) => {
68        {
69            internal_impl!(@internal imports);
70            use $crate::generatable::Type;
71            $store.assert(Type::from_owned(parse_quote!($tokens), 0).test::<TokenCmpWrapper<syn::Type>>($type));
72        }
73    };
74    ($store:ident | &$type:ident == $tokens:tt) => {
75        {
76            internal_impl!(@internal imports);
77            use $crate::generatable::Type;
78            $store.assert(Type::from_owned(parse_quote!($tokens), 0).test::<TokenCmpWrapper<syn::Type>>(&$type));
79        }
80    };
81    ($store:ident | $type:ident with $generics:ident == $tokens:tt) => {
82        {
83            internal_impl!(@internal imports);
84            use $crate::generatable::Type;
85            $store.assert(
86                Type::from_owned(parse_quote!($tokens), 0)
87                    .with_generics::<TokenCmpWrapper<syn::Type>>($generics)
88                    .test::<TokenCmpWrapper<syn::Type>>($type),
89            );
90        }
91    };
92    ($store:ident | $type:ident with &$generics:ident == $tokens:tt) => {
93        {
94            internal_impl!(@internal imports);
95            use $crate::generatable::Type;
96            $store.assert(
97                Type::from_owned(parse_quote!($tokens), 0)
98                    .with_generics::<TokenCmpWrapper<syn::Type>>(&$generics)
99                    .test::<TokenCmpWrapper<syn::Type>>($type),
100            );
101        }
102    };
103    ($store:ident | &$type:ident with $generics:ident == $tokens:tt) => {
104        {
105            internal_impl!(@internal imports);
106            use $crate::generatable::Type;
107            $store.assert(
108                Type::from_owned(parse_quote!($tokens), 0)
109                    .with_generics::<TokenCmpWrapper<syn::Type>>($generics)
110                    .test::<TokenCmpWrapper<syn::Type>>(&$type),
111            );
112        }
113    };
114    ($store:ident | &$type:ident with &$generics:ident == $tokens:tt) => {
115        {
116            internal_impl!(@internal imports);
117            use $crate::generatable::Type;
118            $store.assert(
119                Type::from_owned(parse_quote!($tokens), 0)
120                    .with_generics::<TokenCmpWrapper<syn::Type>>(&$generics)
121                    .test::<TokenCmpWrapper<syn::Type>>($type),
122            );
123        }
124    };
125
126    // ======================= Type Templates with generics =========================
127    ($store:ident | $type:ident == $tokens:tt<#$num:literal>) => {
128        {
129            internal_impl!(@internal imports);
130            use $crate::generatable::Type;
131            $store.assert(Type::from_owned(parse_quote!($tokens), $num).test::<TokenCmpWrapper<syn::Type>>($type));
132        }
133    };
134    ($store:ident | &$type:ident == $tokens:tt<#$num:literal>) => {
135        {
136            internal_impl!(@internal imports);
137            use $crate::generatable::Type;
138            $store.assert(Type::from_owned(parse_quote!($tokens), $num).test::<TokenCmpWrapper<syn::Type>>(&$type));
139        }
140    };
141    ($store:ident | $type:ident with $generics:ident == $tokens:tt<#$num:literal>) => {
142        {
143            internal_impl!(@internal imports);
144            use $crate::generatable::Type;
145            $store.assert(
146                Type::from_owned(parse_quote!($tokens), $num)
147                    .with_generics::<TokenCmpWrapper<syn::Type>>($generics)
148                    .test::<TokenCmpWrapper<syn::Type>>($type),
149            );
150        }
151    };
152    ($store:ident | $type:ident with &$generics:ident == $tokens:tt<#$num:literal>) => {
153        {
154            internal_impl!(@internal imports);
155            use $crate::generatable::Type;
156            $store.assert(
157                Type::from_owned(parse_quote!($tokens), $num)
158                    .with_generics::<TokenCmpWrapper<syn::Type>>(&$generics)
159                    .test::<TokenCmpWrapper<syn::Type>>($type),
160            );
161        }
162    };
163    ($store:ident | &$type:ident with $generics:ident == $tokens:tt<#$num:literal>) => {
164        {
165            internal_impl!(@internal imports);
166            use $crate::generatable::Type;
167            $store.assert(
168                Type::from_owned(parse_quote!($tokens), $num)
169                    .with_generics::<TokenCmpWrapper<syn::Type>>($generics)
170                    .test::<TokenCmpWrapper<syn::Type>>(&$type),
171            );
172        }
173    };
174    ($store:ident | &$type:ident with &$generics:ident == $tokens:tt<#$num:literal>) => {
175        {
176            internal_impl!(@internal imports);
177            use $crate::generatable::Type;
178            $store.assert(
179                Type::from_owned(parse_quote!($tokens), $num)
180                    .with_generics::<TokenCmpWrapper<syn::Type>>(&$generics)
181                    .test::<TokenCmpWrapper<syn::Type>>(&$type),
182            );
183        }
184    };
185
186    // helper methods
187    (@internal imports) => {
188        #[allow(unused_imports)]
189        use $crate::maybe_borrowed::FromMaybeBorrowed;
190        use $crate::add_generics::AttachGenericsWithAssert;
191        use $crate::assert::InsertIntoTemplate;
192        use $crate::token_cmp_wrapper::TokenCmpWrapper;
193        use syn::parse_quote;
194    };
195}
196
197/// A macro that makes it easier to generate assertions into an assertion store
198/// # Usage
199/// ```
200/// let store: proc_macro_assertions::store::Store = todo!();
201/// let assertable = todo!() // For example syn::Ident or syn::Type depending on Template
202///
203/// // for [template dependant] see below in Template docs
204/// assert_into!(store | assertable [template dependant]);
205/// ```
206/// There is also the option to pass `assertable` and `generics` (see below) by reference
207/// ```
208/// assert_into!(store | &assertable [template dependant]);
209/// ```
210/// # Generics
211/// In case there is a need for generics to use `assertable` (assertable may be a `T` from the struct declaration)
212/// you can pass generics using `with generics` in every macro kind.
213/// ```
214/// let generics: syn::Generics = todo!();
215/// assert_into!(store | &assertable with &generics [template dependant]);
216/// ```
217/// # Templates supported
218/// ## Trait (using `impl foo::Trait`)
219/// A template that ensures that some `syn::Type` implements some trait.
220/// ## Type (using `== foo::Type`)
221/// A template that ensures that some `syn::Type` equals some other type.
222/// ## Type with generics (using `== foo::Type<#[num]>` where `[num]` is the amount of Generics)
223/// A template that ensures that some `syn::Type` equals some other type that accepts some generics.
224/// # Examples
225/// ## Trait
226/// ```
227/// let store: proc_macro_assertions::store::Store = todo!();
228/// let assertable: syn::Type = todo!();
229/// let generics: syn::Generics = todo!();
230///
231/// assert_into!(store | &assertable with &generics impl ::std::default::Default);
232/// ```
233/// The macro invocation will expand to (excluding automatic imports of used items) to something like
234/// ```
235/// store.assert(
236///     Trait::from_owned(parse_quote!(::std::default::Default))
237///         .with_generics(&generics)
238///         .test(&assertable)
239/// );
240/// ```
241/// ## Type
242/// ```
243/// let store: proc_macro_assertions::store::Store = todo!();
244/// let assertable: syn::Type = todo!();
245/// let generics: syn::Generics = todo!();
246///
247/// assert_into!(store | &assertable with &generics == String);
248/// ```
249/// The macro invocation will expand to (excluding automatic imports of used items) to something like
250/// ```
251/// store.assert(
252///     Type::from_owned(parse_quote!(String), 0)
253///         .with_generics(&generics)
254///         .test(&assertable)
255/// );
256/// ```
257#[macro_export]
258macro_rules! assert_into {
259    ( $($hidden:tt)* ) => {
260        {
261            use $crate::internal_impl;
262            internal_impl!($($hidden)*);
263        }
264    };
265}