term_rustdoc/tree/nodes/
structs.rs

1use crate::tree::{
2    impls::show::{show_ids, show_names, DocTree, Show},
3    DImpl, IDMap, IDs, IdToID, SliceToIds, Tag, ID,
4};
5use rustdoc_types::{Struct, StructKind};
6
7#[derive(serde::Serialize, serde::Deserialize, Clone)]
8pub struct DStruct {
9    pub id: ID,
10    pub fields: IDs,
11    pub contain_private_fields: bool,
12    pub impls: DImpl,
13}
14
15impl DStruct {
16    pub fn new(id: ID, item: &Struct, map: &IDMap) -> Self {
17        let mut contain_private_fields = false;
18        let fields = match &item.kind {
19            StructKind::Unit => IDs::default(),
20            StructKind::Tuple(fields) => fields
21                .iter()
22                .filter_map(|f| {
23                    let id = f.as_ref().map(|id| id.to_ID());
24                    if id.is_none() {
25                        contain_private_fields = true;
26                    }
27                    id
28                })
29                .collect(),
30            StructKind::Plain {
31                fields,
32                fields_stripped,
33            } => {
34                contain_private_fields = *fields_stripped;
35                fields.to_ids()
36            }
37        };
38        let impls = DImpl::new(&item.impls, map);
39        DStruct {
40            id,
41            fields,
42            contain_private_fields,
43            impls,
44        }
45    }
46
47    /// External items need external crates compiled to know details,
48    /// and the ID here is for PathMap, not IndexMap.
49    pub fn new_external(id: ID) -> Self {
50        let (fields, impls) = Default::default();
51        DStruct {
52            id,
53            fields,
54            impls,
55            contain_private_fields: true,
56        }
57    }
58
59    pub fn fields_tree(&self, map: &IDMap) -> DocTree {
60        let mut root = node!(Struct: map, &self.id);
61        match (self.fields.len(), self.contain_private_fields) {
62            (0, true) => root.push(private_fields()),
63            (0, false) => root.push(Tag::NoFields.show()),
64            (_, true) => {
65                root.extend(show_names(&*self.fields, Tag::Field, map).chain([private_fields()]))
66            }
67            (_, false) => root.extend(show_names(&*self.fields, Tag::Field, map)),
68        };
69        root
70    }
71}
72
73fn private_fields() -> DocTree {
74    Tag::FieldsPrivate.show()
75}
76
77fn fields_root() -> DocTree {
78    Tag::Fields.show()
79}
80
81impl Show for DStruct {
82    fn show(&self) -> DocTree {
83        format!("[struct] {}", self.id).show().with_leaves([
84            "Fields".show().with_leaves(
85                show_ids(&self.fields).chain(self.contain_private_fields.then(private_fields)),
86            ),
87            self.impls.show(),
88        ])
89    }
90
91    fn show_prettier(&self, map: &IDMap) -> DocTree {
92        let mut root = node!(Struct: map, &self.id);
93        match (self.fields.len(), self.contain_private_fields) {
94            (0, true) => root.push(private_fields()),
95            (0, false) => root.push(Tag::NoFields.show()),
96            (_, true) => {
97                root.push(fields_root().with_leaves(
98                    show_names(&*self.fields, Tag::Field, map).chain([private_fields()]),
99                ))
100            }
101            (_, false) => {
102                root.push(fields_root().with_leaves(show_names(&*self.fields, Tag::Field, map)))
103            }
104        };
105        root.push(self.impls.show_prettier(map));
106        root
107    }
108}