sphinx_rustdocgen/directives/
variable_directive.rs1use syn::{
20 Fields,
21 ForeignItemStatic,
22 ImplItemConst,
23 ItemConst,
24 ItemStatic,
25 TraitItemConst,
26 Visibility,
27};
28
29use crate::directives::directive_options::{DirectiveOption, DirectiveVisibility, IndexEntryType};
30use crate::directives::{extract_doc_from_attrs, Directive};
31use crate::formats::{MdContent, MdDirective, RstContent, RstDirective};
32use crate::nodes::{nodes_for_type, Node};
33
34#[derive(Clone, Debug)]
36pub struct VariableDirective {
37 pub(crate) name: String,
39 pub(crate) ident: String,
41 pub(crate) options: Vec<DirectiveOption>,
43 pub(crate) content: Vec<String>,
45}
46
47macro_rules! var_from_item {
50 ($item:expr, $parent_path:expr, $vis:expr, $inherited:expr, $prefix:expr, $index:expr) => {{
51 let name = format!("{}::{}", $parent_path, &$item.ident);
52 let mut nodes = vec![
53 Node::Keyword($prefix),
54 Node::Space,
55 Node::Name($item.ident.to_string()),
56 Node::Punctuation(": "),
57 ];
58 nodes.extend(nodes_for_type(&$item.ty));
59
60 let options = vec![
61 DirectiveOption::Index($index),
62 DirectiveOption::Vis(DirectiveVisibility::effective_visibility(&$vis, $inherited)),
63 DirectiveOption::Toc(format!("{} {}", $prefix, &$item.ident)),
64 DirectiveOption::Layout(nodes),
65 ];
66
67 VariableDirective {
68 name,
69 ident: $item.ident.to_string(),
70 options,
71 content: extract_doc_from_attrs(&$item.attrs),
72 }
73 }};
74}
75
76impl VariableDirective {
77 const DIRECTIVE_NAME: &'static str = "variable";
78
79 pub(crate) fn from_fields(
81 parent_path: &str,
82 fields: &Fields,
83 inherited_visibility: &Option<&Visibility>,
84 index_entry_type: IndexEntryType,
85 ) -> Vec<Self> {
86 if let Fields::Named(named_fields) = fields {
87 named_fields
88 .named
89 .iter()
90 .map(|f| {
91 let mut nodes = vec![
92 Node::Name(f.ident.as_ref().unwrap().to_string()),
93 Node::Punctuation(": "),
94 ];
95 nodes.extend(nodes_for_type(&f.ty));
96 let options = vec![
97 DirectiveOption::Index(index_entry_type),
98 DirectiveOption::Vis(DirectiveVisibility::effective_visibility(
99 &f.vis,
100 inherited_visibility,
101 )),
102 DirectiveOption::Toc(format!("{}", f.ident.as_ref().unwrap())),
103 DirectiveOption::Layout(nodes),
104 ];
105
106 VariableDirective {
107 name: format!("{}::{}", parent_path, f.ident.as_ref().unwrap()),
108 ident: f.ident.as_ref().unwrap().to_string(),
109 options,
110 content: extract_doc_from_attrs(&f.attrs),
111 }
112 })
113 .collect()
114 }
115 else {
116 Vec::new()
117 }
118 }
119
120 pub(crate) fn from_static(parent_path: &str, item: &ItemStatic) -> Directive {
122 Directive::Variable(var_from_item!(
123 item,
124 parent_path,
125 item.vis,
126 &None,
127 "static",
128 IndexEntryType::Normal
129 ))
130 }
131
132 pub(crate) fn from_const(parent_path: &str, item: &ItemConst) -> Directive {
134 Directive::Variable(var_from_item!(
135 item,
136 parent_path,
137 item.vis,
138 &None,
139 "const",
140 IndexEntryType::Normal
141 ))
142 }
143
144 pub(crate) fn from_impl_const(
146 parent_path: &str,
147 item: &ImplItemConst,
148 inherited_visibility: &Option<&Visibility>,
149 ) -> Directive {
150 Directive::Variable(var_from_item!(
151 item,
152 parent_path,
153 item.vis,
154 inherited_visibility,
155 "const",
156 IndexEntryType::None
157 ))
158 }
159
160 pub(crate) fn from_trait_const(
163 parent_path: &str,
164 item: &TraitItemConst,
165 inherited_visibility: &Option<&Visibility>,
166 ) -> Directive {
167 Directive::Variable(var_from_item!(
168 item,
169 parent_path,
170 Visibility::Inherited,
171 inherited_visibility,
172 "const",
173 IndexEntryType::None
174 ))
175 }
176
177 pub(crate) fn from_extern_static(parent_path: &str, item: &ForeignItemStatic) -> Directive {
179 Directive::Variable(var_from_item!(
180 item,
181 parent_path,
182 item.vis,
183 &None,
184 "extern static",
185 IndexEntryType::Normal
186 ))
187 }
188
189 pub(crate) fn directive_visibility(&self) -> &DirectiveVisibility {
191 if let DirectiveOption::Vis(v) = &self.options[1] {
192 return v;
193 }
194 unreachable!("Variable: order of options changed")
195 }
196
197 pub(crate) fn change_parent(&mut self, new_parent: &str) {
199 self.name = format!("{new_parent}::{}", self.ident);
200 }
201}
202
203impl RstDirective for VariableDirective {
204 fn get_rst_text(self, level: usize, max_visibility: &DirectiveVisibility) -> Vec<String> {
206 if self.directive_visibility() > max_visibility {
207 return vec![];
208 }
209 let content_indent = Self::make_indent(level + 1);
210
211 let mut text =
212 Self::make_rst_header(Self::DIRECTIVE_NAME, &self.name, &self.options, level);
213 text.extend(self.content.get_rst_text(&content_indent));
214
215 text
216 }
217}
218
219impl MdDirective for VariableDirective {
220 fn get_md_text(self, fence_size: usize, max_visibility: &DirectiveVisibility) -> Vec<String> {
222 if self.directive_visibility() > max_visibility {
223 return vec![];
224 }
225 let fence = Self::make_fence(fence_size);
226
227 let mut text =
228 Self::make_md_header(Self::DIRECTIVE_NAME, &self.name, &self.options, &fence);
229 text.extend(self.content.get_md_text());
230
231 text.push(fence);
232 text
233 }
234}