syncdoc_core/
omnibus.rs

1use proc_macro2::TokenStream;
2use quote::quote;
3use unsynn::*;
4
5use crate::parse::{SyncDocArg, SyncDocInner};
6use crate::path_utils::apply_module_path;
7use crate::token_processors::TokenProcessor;
8
9pub fn inject_all_docs_impl(
10    args: TokenStream,
11    input: TokenStream,
12) -> core::result::Result<TokenStream, TokenStream> {
13    let (base_path, cfg_attr) = match parse_path_from_args(args) {
14        Ok(result) => result,
15        Err(e) => {
16            let error_msg = e.to_string();
17            return Ok(quote! {
18                compile_error!(#error_msg);
19                #input
20            });
21        }
22    };
23
24    Ok(TokenProcessor::new(input, base_path, cfg_attr).process())
25}
26
27fn parse_path_from_args(
28    args: TokenStream,
29) -> core::result::Result<(String, Option<String>), String> {
30    // If no args provided, try to get from config
31    if args.is_empty() {
32        let call_site = proc_macro2::Span::call_site();
33        if let Some(source_path) = call_site.local_file() {
34            let source_file = source_path.to_string_lossy().to_string();
35            let base_path = crate::config::get_docs_path(&source_file)
36                .map_err(|e| format!("Failed to get docs path from config: {}", e))?;
37            let cfg_attr = crate::config::get_cfg_attr(&source_file).ok().flatten();
38
39            let path = apply_module_path(base_path);
40
41            return Ok((path, cfg_attr));
42        } else {
43            return Err("omnidoc requires a path argument".to_string());
44        }
45    }
46
47    let mut args_iter = args.into_token_iter();
48    match args_iter.parse::<SyncDocInner>() {
49        Ok(parsed) => {
50            let mut path = None;
51            let mut cfg_attr = None;
52
53            if let Some(arg_list) = parsed.args {
54                for arg in arg_list.0 {
55                    match arg.value {
56                        SyncDocArg::Path(path_arg) => {
57                            path = Some(path_arg.value.as_str().to_string());
58                        }
59                        SyncDocArg::CfgAttr(cfg_arg) => {
60                            cfg_attr = Some(cfg_arg.value.as_str().to_string());
61                        }
62                        _ => {}
63                    }
64                }
65            }
66
67            let path = if let Some(p) = path {
68                apply_module_path(p)
69            } else {
70                // Try config
71                let call_site = proc_macro2::Span::call_site();
72                if let Some(source_path) = call_site.local_file() {
73                    let source_file = source_path.to_string_lossy().to_string();
74                    let base_path = crate::config::get_docs_path(&source_file)
75                        .map_err(|e| format!("Failed to get docs path from config: {}", e))?;
76                    apply_module_path(base_path)
77                } else {
78                    return Err("path argument not found".to_string());
79                }
80            };
81
82            // If cfg_attr still None, try config
83            if cfg_attr.is_none() {
84                let call_site = proc_macro2::Span::call_site();
85                if let Some(source_path) = call_site.local_file() {
86                    let source_file = source_path.to_string_lossy().to_string();
87                    cfg_attr = crate::config::get_cfg_attr(&source_file).ok().flatten();
88                }
89            }
90
91            Ok((path, cfg_attr))
92        }
93        Err(_e) => Err("Failed to parse arguments".to_string()),
94    }
95}