use super::{DEnum, DModule, DStruct, DTrait, DUnion};
use crate::tree::{DocTree, IDMap, Show};
use rustdoc_types::ItemEnum;
#[derive(Debug, Clone, Copy)]
pub enum DataItemKind {
Module,
Struct,
Enum,
Trait,
Union,
}
impl DataItemKind {
pub fn new(id: &str, map: &IDMap) -> Option<DataItemKind> {
map.get_item(id).and_then(|item| {
Some(match &item.inner {
ItemEnum::Module(_) => DataItemKind::Module,
ItemEnum::Struct(_) => DataItemKind::Struct,
ItemEnum::Enum(_) => DataItemKind::Enum,
ItemEnum::Trait(_) => DataItemKind::Trait,
ItemEnum::Union(_) => DataItemKind::Union,
ItemEnum::Import(reexport) => {
let id = reexport.id.as_ref().map(|id| &*id.0)?;
DataItemKind::new(id, map)?
}
_ => return None,
})
})
}
}
macro_rules! search {
() => {
search! {
search_for_struct structs DStruct,
search_for_enum enums DEnum,
search_for_trait traits DTrait,
search_for_union unions DUnion,
}
};
($fname:ident $field:ident $typ:ident) => {
fn $fname<T>(
&self,
id: &str,
f: impl Copy + Fn(&$typ) -> T,
) -> Option<T> {
for item in &self.$field {
if item.id.as_str() == id {
return Some(f(item));
}
}
for m in &self.modules {
let tree = m.$fname(id, f);
if tree.is_some() {
return tree;
}
}
None
}
};
($($fname:ident $field:ident $typ:ident,)+) => {
impl DModule { $( search! { $fname $field $typ } )+ }
};
}
search! {}
impl DModule {
fn search_for_module<T>(&self, id: &str, f: impl Copy + Fn(&DModule) -> T) -> Option<T> {
if self.id.as_str() == id {
return Some(f(self));
}
for m in &self.modules {
let tree = m.search_for_module(id, f);
if tree.is_some() {
return tree;
}
}
None
}
pub fn item_inner_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
let kind = DataItemKind::new(id, map)?;
match kind {
DataItemKind::Struct => self.search_for_struct(id, |x| x.show_prettier(map)),
DataItemKind::Enum => self.search_for_enum(id, |x| x.show_prettier(map)),
DataItemKind::Trait => self.search_for_trait(id, |x| x.show_prettier(map)),
DataItemKind::Union => self.search_for_union(id, |x| x.show_prettier(map)),
DataItemKind::Module => self.search_for_module(id, |x| x.item_tree(map)),
}
}
pub fn impl_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
let kind = DataItemKind::new(id, map)?;
match kind {
DataItemKind::Struct => self.search_for_struct(id, |x| x.impls.show_prettier(map)),
DataItemKind::Enum => self.search_for_enum(id, |x| x.impls.show_prettier(map)),
DataItemKind::Trait => self.search_for_trait(id, |x| x.show_prettier(map)),
DataItemKind::Union => self.search_for_union(id, |x| x.impls.show_prettier(map)),
_ => None,
}
}
pub fn implementor_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
self.search_for_trait(id, |x| x.implementors(map))
}
pub fn associated_item_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
self.search_for_trait(id, |x| x.associated_items(map))
}
pub fn field_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
let kind = DataItemKind::new(id, map)?;
match kind {
DataItemKind::Struct => self.search_for_struct(id, |x| x.fields_tree(map)),
DataItemKind::Enum => self.search_for_enum(id, |x| x.variants_tree(map)),
DataItemKind::Union => self.search_for_union(id, |x| x.fields_tree(map)),
_ => None,
}
}
}