term_rustdoc/tree/nodes/
impls.rs1use crate::tree::{
2 impls::show::{show_ids, show_names, DocTree, Show},
3 IDMap, IDs, IdToID, Tag, ID,
4};
5use itertools::Itertools;
6use rustdoc_types::{Id, Impl, ItemEnum};
7use serde::{Deserialize, Serialize};
8
9#[derive(Clone, Default, Deserialize, Serialize)]
11pub struct DImpl {
12 pub inherent: Box<[DImplInner]>,
13 pub trait_: Box<[DImplInner]>,
14 pub auto: Box<[DImplInner]>,
15 pub blanket: Box<[DImplInner]>,
16 pub merged_inherent: Box<DImplInner>,
21}
22
23impl DImpl {
24 pub fn new(ids: &[Id], map: &IDMap) -> Self {
25 if ids.is_empty() {
26 return Default::default();
27 }
28 let [mut inherent, mut trait_, mut auto, mut blanket]: [Vec<_>; 4] = Default::default();
29 for Id(id) in ids {
30 let id = id.as_str();
31 if id.starts_with("a:") {
32 auto.push(DImplInner::new_with_no_details(id));
33 } else if id.starts_with("b:") {
34 blanket.push(DImplInner::new_with_no_details(id));
35 } else if let Some(item) = map.get_item(id) {
36 if let ItemEnum::Impl(impl_) = &item.inner {
37 if impl_.trait_.is_none() {
38 inherent.push(DImplInner::new(id, impl_, map));
39 } else {
40 trait_.push(DImplInner::new(id, impl_, map));
41 }
42 } else {
43 warn!("{id:?} in Crate's index doesn't refer to an impl item");
44 }
45 } else {
46 warn!("the impl with {id:?} not found in Crate's index");
47 }
48 }
49 inherent.sort_unstable_by_key(|x| map.name(&x.id));
50 trait_.sort_unstable_by_key(|x| map.name(&x.id));
51 auto.sort_unstable_by_key(|x| map.name(&x.id));
52 blanket.sort_unstable_by_key(|x| map.name(&x.id));
53 let merged_inherent = DImplInner::merge_inherent_impls(&inherent, map);
54 DImpl {
55 inherent: inherent.into(),
56 trait_: trait_.into(),
57 auto: auto.into(),
58 blanket: blanket.into(),
59 merged_inherent: Box::new(merged_inherent),
60 }
61 }
62 pub fn is_empty(&self) -> bool {
63 self.auto.is_empty()
64 && self.blanket.is_empty()
65 && self.inherent.is_empty()
66 && self.trait_.is_empty()
67 }
68}
69
70impl Show for DImpl {
71 fn show(&self) -> DocTree {
72 "Implementations".show().with_leaves([
73 "Inherent Impls"
74 .show()
75 .with_leaves(self.inherent.iter().map(|i| i.show())),
76 "Trait Impls"
77 .show()
78 .with_leaves(self.trait_.iter().map(|i| i.show())),
79 "Auto Impls"
80 .show()
81 .with_leaves(self.auto.iter().map(|i| i.show())),
82 "Blanket Impls"
83 .show()
84 .with_leaves(self.blanket.iter().map(|i| i.show())),
85 ])
86 }
87
88 fn show_prettier(&self, map: &IDMap) -> DocTree {
89 if self.is_empty() {
90 return Tag::NoImpls.show();
91 }
92 let mut root = Tag::Implementations.show();
93 if !self.merged_inherent.is_empty() {
94 let tree = Tag::InherentImpls.show();
95 root.push(tree.with_leaves(self.merged_inherent.show_prettier_iter(map)));
98 }
99 if !self.trait_.is_empty() {
100 let tree = Tag::TraitImpls.show();
101 let tag = Tag::ImplTrait;
102 root.push(tree.with_leaves(self.trait_.iter().map(|i| i.show_prettier(tag, map))));
103 }
104 if !self.auto.is_empty() {
105 let tree = Tag::AutoImpls.show();
106 let tag = Tag::ImplAuto;
107 root.push(tree.with_leaves(self.auto.iter().map(|i| i.show_prettier(tag, map))));
108 }
109 if !self.blanket.is_empty() {
110 let tree = Tag::BlanketImpls.show();
111 let tag = Tag::ImplBlanket;
112 root.push(tree.with_leaves(self.blanket.iter().map(|i| i.show_prettier(tag, map))));
113 }
114 root
115 }
116}
117
118#[derive(Clone, Default, Deserialize, Serialize)]
119pub struct DImplInner {
120 pub id: ID,
121 pub functions: IDs,
122 pub constants: IDs,
123 pub types: IDs,
124}
125
126impl DImplInner {
127 pub fn new(id: &str, imp: &Impl, map: &IDMap) -> Self {
128 let [mut functions, mut constants, mut types]: [Vec<ID>; 3] = Default::default();
129 for item in imp.items.iter().flat_map(|assc| map.get_item(&assc.0)) {
130 match &item.inner {
131 ItemEnum::Function(_) => functions.push(item.id.to_ID()),
132 ItemEnum::Constant(_) => constants.push(item.id.to_ID()),
133 ItemEnum::TypeAlias(_) => types.push(item.id.to_ID()),
134 _ => (),
135 };
136 }
137 functions.sort_unstable_by_key(|id| map.name(id));
138 constants.sort_unstable_by_key(|id| map.name(id));
139 types.sort_unstable_by_key(|id| map.name(id));
140 DImplInner {
141 id: id.to_ID(),
142 functions: functions.into(),
143 constants: constants.into(),
144 types: types.into(),
145 }
146 }
147
148 pub fn new_with_no_details(id: &str) -> Self {
149 DImplInner {
150 id: id.to_ID(),
151 ..Default::default()
152 }
153 }
154
155 fn show(&self) -> DocTree {
156 let mut root = self.id.show();
157 if !self.functions.is_empty() {
158 root.push("Functions".show().with_leaves(show_ids(&self.functions)));
159 }
160 if !self.constants.is_empty() {
161 root.push("Constants".show().with_leaves(show_ids(&self.constants)));
162 }
163 if !self.types.is_empty() {
164 root.push("Types".show().with_leaves(show_ids(&self.types)));
165 }
166 root
167 }
168
169 fn show_prettier(&self, tag: Tag, map: &IDMap) -> DocTree {
170 let root = DocTree::new(map.name(&self.id), tag, Some(self.id.as_str().into()));
171 root.with_leaves(self.show_prettier_iter(map))
179 }
180
181 fn show_prettier_iter<'s: 'ret, 'map: 'ret, 'ret>(
183 &'s self,
184 map: &'map IDMap,
185 ) -> impl 'ret + Iterator<Item = DocTree> {
186 show_names(&*self.constants, Tag::Constant, map)
187 .chain(show_names(&*self.types, Tag::TypeAlias, map))
188 .chain(show_names(&*self.functions, Tag::Function, map))
189 }
190
191 fn merge_inherent_impls(impls: &[Self], map: &IDMap) -> Self {
192 let iter = impls.iter();
193 Self {
194 id: ID::default(),
195 functions: iter
196 .clone()
197 .flat_map(|x| x.functions.iter())
198 .sorted_unstable_by_key(|id| map.name(id))
199 .cloned()
200 .collect(),
201 constants: iter
202 .clone()
203 .flat_map(|x| x.constants.iter())
204 .sorted_unstable_by_key(|id| map.name(id))
205 .cloned()
206 .collect(),
207 types: iter
208 .flat_map(|x| x.types.iter())
209 .sorted_unstable_by_key(|id| map.name(id))
210 .cloned()
211 .collect(),
212 }
213 }
214
215 fn is_empty(&self) -> bool {
216 self.functions.is_empty() && self.constants.is_empty() && self.types.is_empty()
217 }
218}