sphinx_rustdocgen/directives/
enum_directive.rs1use syn::ItemEnum;
20
21use crate::directives::directive_options::{DirectiveOption, DirectiveVisibility, IndexEntryType};
22use crate::directives::struct_directive::StructDirective;
23use crate::directives::{extract_doc_from_attrs, Directive, ImplDirective};
24use crate::formats::{MdContent, MdDirective, RstContent, RstDirective};
25use crate::nodes::{nodes_for_generics, nodes_for_where_clause, Node};
26
27#[derive(Clone, Debug)]
29pub struct EnumDirective {
30 pub(crate) name: String,
32 pub(crate) ident: String,
34 pub(crate) options: Vec<DirectiveOption>,
36 pub(crate) content: Vec<String>,
38 pub(crate) variants: Vec<StructDirective>,
40 pub(crate) self_impls: Vec<ImplDirective>,
42 pub(crate) trait_impls: Vec<ImplDirective>,
44}
45
46impl EnumDirective {
47 const DIRECTIVE_NAME: &'static str = "enum";
48
49 pub(crate) fn from_item(parent_path: &str, item: &ItemEnum) -> Directive {
59 let name = format!("{}::{}", parent_path, item.ident);
60 let variants = item
61 .variants
62 .iter()
63 .map(|v| StructDirective::from_variant(&name, v, &Some(&item.vis)))
64 .collect();
65
66 let mut nodes = vec![
67 Node::Keyword(EnumDirective::DIRECTIVE_NAME),
68 Node::Space,
69 Node::Name(item.ident.to_string()),
70 ];
71 nodes.extend(nodes_for_generics(&item.generics));
72 if let Some(wc) = &item.generics.where_clause {
73 nodes.extend(nodes_for_where_clause(wc));
74 }
75
76 let options = vec![
77 DirectiveOption::Index(IndexEntryType::WithSubEntries),
78 DirectiveOption::Vis(DirectiveVisibility::from(&item.vis)),
79 DirectiveOption::Layout(nodes),
80 ];
81
82 Directive::Enum(EnumDirective {
83 name,
84 ident: item.ident.to_string(),
85 options,
86 content: extract_doc_from_attrs(&item.attrs),
87 variants,
88 self_impls: vec![],
89 trait_impls: vec![],
90 })
91 }
92
93 pub(crate) fn directive_visibility(&self) -> &DirectiveVisibility {
95 if let DirectiveOption::Vis(v) = &self.options[1] {
96 return v;
97 }
98 unreachable!("Enum: order of options changed")
99 }
100
101 pub(crate) fn change_parent(&mut self, new_parent: &str) {
103 self.name = format!("{new_parent}::{}", self.ident);
104 for variant in &mut self.variants {
105 variant.change_parent(&self.name);
106 }
107 for impl_ in &mut self.self_impls {
108 impl_.change_parent(new_parent);
109 }
110 for impl_ in &mut self.trait_impls {
111 impl_.change_parent(new_parent);
112 }
113 }
114
115 pub(crate) fn add_impl(&mut self, mut impl_: ImplDirective) {
124 impl_.change_parent(&self.name[0..self.name.rfind("::").unwrap()]);
126 impl_.set_directive_visibility(self.directive_visibility());
127 if impl_.trait_.is_some() {
128 self.trait_impls.push(impl_);
129 }
130 else {
131 self.self_impls.push(impl_);
132 }
133 }
134}
135
136impl RstDirective for EnumDirective {
137 fn get_rst_text(self, level: usize, max_visibility: &DirectiveVisibility) -> Vec<String> {
138 if self.directive_visibility() > max_visibility {
139 return vec![];
140 }
141 let content_indent = Self::make_indent(level + 1);
142
143 let mut text =
144 Self::make_rst_header(Self::DIRECTIVE_NAME, &self.name, &self.options, level);
145 text.extend(self.content.get_rst_text(&content_indent));
146
147 for variant in self.variants {
148 text.extend(variant.get_rst_text(level + 1, max_visibility));
149 }
150
151 text.extend(Self::make_rst_section(
152 "Implementations",
153 level,
154 self.self_impls.into_iter().map(Directive::Impl).collect(),
155 max_visibility,
156 ));
157
158 text.extend(Self::make_rst_section(
159 "Traits implemented",
160 level,
161 self.trait_impls.into_iter().map(Directive::Impl).collect(),
162 max_visibility,
163 ));
164
165 text
166 }
167}
168
169impl MdDirective for EnumDirective {
170 fn get_md_text(self, fence_size: usize, max_visibility: &DirectiveVisibility) -> Vec<String> {
171 if self.directive_visibility() > max_visibility {
172 return vec![];
173 }
174 let fence = Self::make_fence(fence_size);
175
176 let mut text =
177 Self::make_md_header(Self::DIRECTIVE_NAME, &self.name, &self.options, &fence);
178 text.extend(self.content.get_md_text());
179
180 for variant in self.variants {
181 text.extend(variant.get_md_text(fence_size - 1, max_visibility));
182 }
183
184 text.extend(Self::make_md_section(
185 "Implementations",
186 fence_size,
187 self.self_impls.into_iter().map(Directive::Impl).collect(),
188 max_visibility,
189 ));
190
191 text.extend(Self::make_md_section(
192 "Traits implemented",
193 fence_size,
194 self.trait_impls.into_iter().map(Directive::Impl).collect(),
195 max_visibility,
196 ));
197
198 text.push(fence);
199 text
200 }
201
202 fn fence_size(&self) -> usize {
203 [
204 match self.variants.iter().map(StructDirective::fence_size).max() {
205 Some(s) => s + 1,
206 None => 3,
207 },
208 match self.trait_impls.iter().map(ImplDirective::fence_size).max() {
209 Some(s) => s + 1,
210 None => 3,
211 },
212 match self.self_impls.iter().map(ImplDirective::fence_size).max() {
213 Some(s) => s + 1,
214 None => 3,
215 },
216 ]
217 .into_iter()
218 .max()
219 .unwrap()
220 }
221}