term_rustdoc/tree/nodes/
item_inner.rs

1use super::{DEnum, DModule, DStruct, DTrait, DUnion};
2use crate::tree::{DocTree, IDMap, Show};
3use rustdoc_types::ItemEnum;
4
5/// Data-carrying items that provide extra tree layer on fields/variants/impls.
6#[derive(Debug, Clone, Copy)]
7pub enum DataItemKind {
8    Module,
9    Struct,
10    Enum,
11    Trait,
12    Union,
13}
14
15impl DataItemKind {
16    pub fn new(id: &str, map: &IDMap) -> Option<DataItemKind> {
17        map.get_item(id).and_then(|item| {
18            Some(match &item.inner {
19                ItemEnum::Module(_) => DataItemKind::Module,
20                ItemEnum::Struct(_) => DataItemKind::Struct,
21                ItemEnum::Enum(_) => DataItemKind::Enum,
22                ItemEnum::Trait(_) => DataItemKind::Trait,
23                ItemEnum::Union(_) => DataItemKind::Union,
24                ItemEnum::Import(reexport) => {
25                    let id = reexport.id.as_ref().map(|id| &*id.0)?;
26                    DataItemKind::new(id, map)?
27                }
28                _ => return None,
29            })
30        })
31    }
32}
33
34macro_rules! search {
35    () => {
36        search! {
37            search_for_struct structs DStruct,
38            search_for_enum   enums   DEnum,
39            search_for_trait  traits  DTrait,
40            search_for_union  unions  DUnion,
41        }
42    };
43    ($fname:ident $field:ident $typ:ident) => {
44        fn $fname<T>(
45            &self,
46            id: &str,
47            f: impl Copy + Fn(&$typ) -> T,
48        ) -> Option<T> {
49            for item in &self.$field {
50                if item.id.as_str() == id {
51                    return Some(f(item));
52                }
53            }
54            for m in &self.modules {
55                let tree = m.$fname(id, f);
56                if tree.is_some() {
57                    return tree;
58                }
59            }
60            None
61        }
62    };
63    ($($fname:ident $field:ident $typ:ident,)+) => {
64        impl DModule { $( search! { $fname $field $typ } )+ }
65    };
66}
67
68search! {}
69
70// Search after the kind is known to improve efficiency.
71impl DModule {
72    fn search_for_module<T>(&self, id: &str, f: impl Copy + Fn(&DModule) -> T) -> Option<T> {
73        if self.id.as_str() == id {
74            return Some(f(self));
75        }
76        for m in &self.modules {
77            let tree = m.search_for_module(id, f);
78            if tree.is_some() {
79                return tree;
80            }
81        }
82        None
83    }
84
85    pub fn item_inner_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
86        let kind = DataItemKind::new(id, map)?;
87        match kind {
88            DataItemKind::Struct => self.search_for_struct(id, |x| x.show_prettier(map)),
89            DataItemKind::Enum => self.search_for_enum(id, |x| x.show_prettier(map)),
90            DataItemKind::Trait => self.search_for_trait(id, |x| x.show_prettier(map)),
91            DataItemKind::Union => self.search_for_union(id, |x| x.show_prettier(map)),
92            DataItemKind::Module => self.search_for_module(id, |x| x.item_tree(map)),
93        }
94    }
95
96    pub fn impl_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
97        let kind = DataItemKind::new(id, map)?;
98        match kind {
99            DataItemKind::Struct => self.search_for_struct(id, |x| x.impls.show_prettier(map)),
100            DataItemKind::Enum => self.search_for_enum(id, |x| x.impls.show_prettier(map)),
101            DataItemKind::Trait => self.search_for_trait(id, |x| x.show_prettier(map)),
102            DataItemKind::Union => self.search_for_union(id, |x| x.impls.show_prettier(map)),
103            _ => None,
104        }
105    }
106
107    pub fn implementor_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
108        self.search_for_trait(id, |x| x.implementors(map))
109    }
110
111    pub fn associated_item_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
112        self.search_for_trait(id, |x| x.associated_items(map))
113    }
114
115    pub fn field_tree(&self, id: &str, map: &IDMap) -> Option<DocTree> {
116        let kind = DataItemKind::new(id, map)?;
117        match kind {
118            DataItemKind::Struct => self.search_for_struct(id, |x| x.fields_tree(map)),
119            DataItemKind::Enum => self.search_for_enum(id, |x| x.variants_tree(map)),
120            DataItemKind::Union => self.search_for_union(id, |x| x.fields_tree(map)),
121            _ => None,
122        }
123    }
124}