utoipauto_macro/
lib.rs

1use attribute_utils::update_openapi_macro_attributes;
2use proc_macro::TokenStream;
3
4use quote::quote;
5use string_utils::{discover, extract_paths};
6use syn::parse_macro_input;
7use token_utils::{check_macro_placement, extract_attributes, output_macro};
8use utoipauto_core::{attribute_utils, string_utils, token_utils};
9
10/// Macro to automatically discover all the functions with the #[utoipa] attribute
11/// And the struct deriving ToSchema and ToResponse
12#[proc_macro_attribute]
13pub fn utoipauto(
14    attributes: proc_macro::TokenStream, // #[utoipauto(paths = "(MODULE_TREE_PATH => MODULE_SRC_PATH) ;")]
15    item: proc_macro::TokenStream,       // #[openapi(paths = "")]
16) -> proc_macro::TokenStream {
17    // (MODULE_TREE_PATH => MODULE_SRC_PATH) ; (MODULE_TREE_PATH => MODULE_SRC_PATH) ; ...
18    let params = extract_attributes(attributes.into());
19    // [(MODULE_TREE_PATH, MODULE_SRC_PATH)]
20    let paths: Vec<String> = extract_paths(&params.paths);
21
22    // #[openapi(...)]
23    let mut openapi_macro = parse_macro_input!(item as syn::ItemStruct);
24
25    // Discover all the functions with the #[utoipa] attribute
26    let (uto_paths, uto_models, uto_responses): (String, String, String) = discover(paths, &params);
27
28    // extract the openapi macro attributes : #[openapi(openapi_macro_attibutes)]
29    let openapi_macro_attibutes = &mut openapi_macro.attrs;
30
31    // Check if the macro is placed before the #[derive] and #[openapi] attributes
32    check_macro_placement(openapi_macro_attibutes.clone());
33
34    // Update the openapi macro attributes with the newly discovered paths
35    update_openapi_macro_attributes(openapi_macro_attibutes, &uto_paths, &uto_models, &uto_responses);
36
37    // Output the macro back to the compiler
38    output_macro(openapi_macro)
39}
40
41/// Ignore the function from the auto discovery
42#[proc_macro_attribute]
43pub fn utoipa_ignore(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
44    let input = parse_macro_input!(item as syn::Item);
45    let code = quote!(
46          #input
47    );
48
49    TokenStream::from(code)
50}
51
52/// Useless macro to test custom function attributes
53#[proc_macro_attribute]
54pub fn test_handler(_attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream {
55    let input = parse_macro_input!(item as syn::ItemFn);
56
57    let code = quote!(
58        #[utoipa::path(get, path = "/")]
59        #input
60    );
61
62    TokenStream::from(code)
63}