use crate::doc_parts::*;
use crate::util::syn_tools::*;
use crate::util::*;
use crate::*;
use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::Error;
use syn::parse::{Parse, ParseStream};
pub(crate) struct DocShareNode {
mod_id: Option<syn::Ident>,
syn_item: syn::Item,
}
impl DocShareNode {
pub fn translate(attr: TokenStream, body: TokenStream) -> TokenStream {
match Self::parse_all(attr, body) {
Err(x) => x,
Ok(x) => x.into_token_stream(),
}
}
pub fn parse_all(attr: TokenStream, body: TokenStream) -> Result<Self, TokenStream> {
let mod_id = syn_tools::parse::<syn::Ident>(attr);
let body = syn_tools::parse::<Self>(body);
let valid = body.as_ref().map_or_else(|_| Ok(()), Self::validate);
let errs = []
.iter()
.chain(mod_id.as_ref().err())
.chain(body.as_ref().err())
.chain(valid.as_ref().err())
.collect::<Vec<_>>();
if !errs.is_empty() {
return Err(quote::quote! { #(#errs)* });
}
let mut ret = body.unwrap();
ret.mod_id = Some(mod_id.unwrap());
Ok(ret)
}
pub fn mod_id(&self) -> &syn::Ident {
self.mod_id.as_ref().unwrap()
}
pub fn syn_item(&self) -> &syn::Item {
&self.syn_item
}
pub fn validate(&self) -> Result<(), TokenStream> {
if !(self.syn_item.as_ref() as &BaseItem).is_documentable() {
let item = SkipAttr::reparse(&self.syn_item);
let err = Error::new_spanned(item, msg::UNEXPECTED_ITEM);
let err = err.to_compile_error();
return Err(err);
}
Ok(())
}
}
impl Parse for DocShareNode {
fn parse(input: ParseStream) -> syn::Result<Self> {
let syn_item = input.parse::<syn::Item>()?;
Ok(Self {
mod_id: None,
syn_item,
})
}
}
impl ToTokens for DocShareNode {
fn to_tokens(&self, tokens: &mut TokenStream) {
let mod_id = self.mod_id();
let syn_item = &self.syn_item();
let doc_item = &DocShareMod::new(mod_id, syn_item);
tokens.extend(print::print_doc_share_item(syn_item));
tokens.extend(print::print_doc_share_mod(doc_item));
}
}