syncdoc_core/
omnibus.rs

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