1mod admin;
2mod api_response_enum;
3mod cache;
4mod dbtest;
5mod form;
6mod from_request;
7mod main_fn;
8mod model;
9mod query;
10mod select_as_form_field;
11mod select_choice;
12
13use darling::Error;
14use darling::ast::NestedMeta;
15use proc_macro::TokenStream;
16use proc_macro_crate::crate_name;
17use quote::quote;
18use syn::{DeriveInput, ItemFn, parse_macro_input};
19
20use crate::admin::impl_admin_model_for_struct;
21use crate::api_response_enum::{impl_api_operation_response_for_enum, impl_into_response_for_enum};
22use crate::dbtest::fn_to_dbtest;
23use crate::form::impl_form_for_struct;
24use crate::from_request::impl_from_request_head_for_struct;
25use crate::main_fn::{fn_to_cot_e2e_test, fn_to_cot_main, fn_to_cot_test};
26use crate::model::impl_model_for_struct;
27use crate::query::{Query, query_to_tokens};
28use crate::select_as_form_field::impl_select_as_form_field_for_enum;
29use crate::select_choice::impl_select_choice_for_enum;
30
31#[proc_macro_derive(Form, attributes(form))]
32pub fn derive_form(input: TokenStream) -> TokenStream {
33 let ast = parse_macro_input!(input as DeriveInput);
34 let token_stream = impl_form_for_struct(&ast);
35 token_stream.into()
36}
37
38#[proc_macro_derive(AdminModel)]
39pub fn derive_admin_model(input: TokenStream) -> TokenStream {
40 let ast = parse_macro_input!(input as DeriveInput);
41 let token_stream = impl_admin_model_for_struct(&ast);
42 token_stream.into()
43}
44
45#[proc_macro_attribute]
114pub fn model(args: TokenStream, input: TokenStream) -> TokenStream {
115 let attr_args = match NestedMeta::parse_meta_list(args.into()) {
116 Ok(v) => v,
117 Err(e) => {
118 return TokenStream::from(Error::from(e).write_errors());
119 }
120 };
121 let mut ast = parse_macro_input!(input as DeriveInput);
122 let token_stream = impl_model_for_struct(&attr_args, &mut ast);
123 token_stream.into()
124}
125
126#[proc_macro_derive(ModelHelper, attributes(model))]
136pub fn derive_model_helper(_item: TokenStream) -> TokenStream {
137 TokenStream::new()
138}
139
140#[proc_macro]
141pub fn query(input: TokenStream) -> TokenStream {
142 let query_input = parse_macro_input!(input as Query);
143 query_to_tokens(query_input).into()
144}
145
146#[proc_macro_attribute]
147pub fn dbtest(_args: TokenStream, input: TokenStream) -> TokenStream {
148 let fn_input = parse_macro_input!(input as ItemFn);
149 fn_to_dbtest(fn_input)
150 .unwrap_or_else(syn::Error::into_compile_error)
151 .into()
152}
153
154#[proc_macro_attribute]
155pub fn main(_args: TokenStream, input: TokenStream) -> TokenStream {
156 let fn_input = parse_macro_input!(input as ItemFn);
157 fn_to_cot_main(fn_input)
158 .unwrap_or_else(syn::Error::into_compile_error)
159 .into()
160}
161
162#[proc_macro_attribute]
163pub fn cachetest(_args: TokenStream, input: TokenStream) -> TokenStream {
164 let fn_input = parse_macro_input!(input as ItemFn);
165 cache::fn_to_cache_test(&fn_input).into()
166}
167
168#[proc_macro_attribute]
187pub fn test(_args: TokenStream, input: TokenStream) -> TokenStream {
188 let fn_input = parse_macro_input!(input as ItemFn);
189 fn_to_cot_test(&fn_input).into()
190}
191
192#[proc_macro_attribute]
193pub fn e2e_test(_args: TokenStream, input: TokenStream) -> TokenStream {
194 let fn_input = parse_macro_input!(input as ItemFn);
195 fn_to_cot_e2e_test(&fn_input).into()
196}
197
198pub(crate) fn cot_ident() -> proc_macro2::TokenStream {
199 let cot_crate = crate_name("cot").expect("cot is not present in `Cargo.toml`");
200 match cot_crate {
201 proc_macro_crate::FoundCrate::Itself => {
202 quote! { ::cot }
203 }
204 proc_macro_crate::FoundCrate::Name(name) => {
205 let ident = syn::Ident::new(&name, proc_macro2::Span::call_site());
206 quote! { ::#ident }
207 }
208 }
209}
210
211#[proc_macro_derive(FromRequestHead)]
212pub fn derive_from_request_head(input: TokenStream) -> TokenStream {
213 let ast = parse_macro_input!(input as DeriveInput);
214 let token_stream = impl_from_request_head_for_struct(&ast);
215 token_stream.into()
216}
217
218#[proc_macro_derive(SelectChoice, attributes(select_choice))]
219pub fn derive_select_choice(input: TokenStream) -> TokenStream {
220 let ast = syn::parse_macro_input!(input as DeriveInput);
221 let token_stream = impl_select_choice_for_enum(&ast);
222 token_stream.into()
223}
224
225#[proc_macro_derive(SelectAsFormField)]
226pub fn derive_select_as_form_field(input: TokenStream) -> TokenStream {
227 let ast = syn::parse_macro_input!(input as DeriveInput);
228 let token_stream = impl_select_as_form_field_for_enum(&ast);
229 token_stream.into()
230}
231
232#[proc_macro_derive(IntoResponse)]
233pub fn derive_into_response(input: TokenStream) -> TokenStream {
234 let ast = parse_macro_input!(input as DeriveInput);
235 impl_into_response_for_enum(&ast).into()
236}
237
238#[proc_macro_derive(ApiOperationResponse)]
239pub fn derive_api_operation_response(input: TokenStream) -> TokenStream {
240 let ast = parse_macro_input!(input as DeriveInput);
241 impl_api_operation_response_for_enum(&ast).into()
242}
243
244#[proc_macro_derive(Template, attributes(template))]
249pub fn derive_template(input: TokenStream) -> TokenStream {
250 askama_derive::derive_template(input.into(), import_askama).into()
251}
252
253#[proc_macro_attribute]
258pub fn filter_fn(attr: TokenStream, item: TokenStream) -> TokenStream {
259 askama_derive::derive_filter_fn(attr.into(), item.into(), import_askama).into()
260}
261
262fn import_askama() -> proc_macro2::TokenStream {
263 let cot = cot_ident();
264 quote!(use #cot::__private::askama;)
265}