1#![warn(missing_docs, clippy::all, clippy::pedantic, clippy::cargo)]
2#![deny(rustdoc::broken_intra_doc_links, missing_debug_implementations)]
3#![allow(clippy::module_name_repetitions)]
4#![feature(proc_macro_diagnostic)]
5
6mod attrs;
9mod bits;
10mod docs;
11mod inputs;
12mod opts;
13mod trie;
14
15use bits::{help::HelpParts, id::IdParts, parse::ParseParts, path::PathParts};
16use proc_macro::TokenStream;
17use proc_macro2::Span;
18use quote::quote_spanned;
19use syn::{parse_macro_input, spanned::Spanned, DeriveInput};
20
21pub(crate) type Error = (anyhow::Error, Span);
22pub(crate) type Result<T, E = Error> = std::result::Result<T, E>;
23
24#[proc_macro_derive(Docbot, attributes(docbot))]
26pub fn derive_docbot(input: TokenStream) -> TokenStream {
27 let input: DeriveInput = parse_macro_input!(input);
28
29 let inputs = match inputs::assemble(&input) {
30 Ok(s) => s,
31 Err((e, s)) => {
32 s.unwrap()
33 .error(format!("Macro execution failed:\n{:?}", e))
34 .emit();
35 return TokenStream::new();
36 },
37 };
38
39 let id_parts = bits::id::emit(&inputs);
40 let path_parts = bits::path::emit(&inputs, &id_parts);
41 let parse_parts = bits::parse::emit(&inputs, &id_parts, &path_parts);
42 let help_parts = bits::help::emit(&inputs, &path_parts);
43
44 let IdParts {
46 items: id_items, ..
47 } = id_parts;
48 let PathParts {
49 items: path_items, ..
50 } = path_parts;
51 let ParseParts { items: parse_items } = parse_parts;
52 let HelpParts { items: help_items } = help_parts;
53
54 let toks = quote_spanned! { input.span() =>
55 #id_items
56 #path_items
57 #parse_items
58 #help_items
59 };
60
61 toks.into()
64}