1#![forbid(unsafe_code)]
9
10use proc_macro::TokenStream;
11use proc_macro2::TokenStream as TokenStream2;
12use proc_macro_error::{abort_call_site, proc_macro_error};
13use quote::quote;
14use syn::{parse_macro_input, visit_mut::VisitMut, File};
15
16use crate::pre_attr::PreAttrVisitor;
17
18mod call;
19mod call_handling;
20mod documentation;
21mod extern_crate;
22mod helpers;
23mod pre_attr;
24mod precondition;
25
26cfg_if::cfg_if! {
27 if #[cfg(nightly)] {
28 mod const_generics_impl;
29 pub(crate) use crate::const_generics_impl::{render_assure, render_pre};
30 } else {
31 mod struct_impl;
32 pub(crate) use crate::struct_impl::{render_assure, render_pre};
33 }
34}
35
36#[proc_macro_attribute]
37#[proc_macro_error]
38pub fn pre(attr: TokenStream, file: TokenStream) -> TokenStream {
39 let dummy_file: TokenStream2 = file.clone().into();
40 proc_macro_error::set_dummy(quote! {
41 #dummy_file
42 });
43
44 let mut file = parse_macro_input!(file as File);
45
46 PreAttrVisitor::new(attr.into()).visit_file_mut(&mut file);
47
48 let output = quote! {
49 #file
50 };
51
52 proc_macro_error::set_dummy(quote! {
55 #output
56 });
57
58 output.into()
59}
60
61#[proc_macro_attribute]
62#[proc_macro_error]
63pub fn assure(_: TokenStream, _: TokenStream) -> TokenStream {
64 abort_call_site!(
70 "this attribute by itself is currently non-functional";
71 help = "use it on an expression in an item wrapped by a `pre` attribute"
72 )
73}
74
75#[proc_macro_attribute]
76#[proc_macro_error]
77pub fn forward(_: TokenStream, _: TokenStream) -> TokenStream {
78 abort_call_site!(
84 "this attribute by itself is currently non-functional";
85 help = "use it on an expression in an item wrapped by a `pre` attribute"
86 )
87}
88
89#[proc_macro_attribute]
90#[proc_macro_error]
91pub fn extern_crate(attr: TokenStream, module: TokenStream) -> TokenStream {
92 let attr = parse_macro_input!(attr as extern_crate::ExternCrateAttr);
93 let module = parse_macro_input!(module as extern_crate::Module);
94
95 let output = module.render(attr);
96
97 proc_macro_error::set_dummy(quote! {
100 #output
101 });
102
103 output.into()
104}