1use serde::{Deserialize, Serialize};
4use std::collections::BTreeMap;
5
6use crate::docgen::config::DocGenConfig;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct DocPackage {
11 pub name: String,
12 pub modules: BTreeMap<String, DocModule>,
13 pub export_map: BTreeMap<String, String>,
15 pub config: DocGenConfig,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
21pub struct DocModule {
22 pub name: String,
23 pub doc: String,
24 pub items: Vec<DocItem>,
25 pub submodules: Vec<String>,
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct DocSubmodule {
31 pub name: String,
32 pub doc: String,
33 pub fqn: String,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
38#[serde(tag = "kind")]
39pub enum DocItem {
40 Function(DocFunction),
41 Class(DocClass),
42 TypeAlias(DocTypeAlias),
43 Variable(DocVariable),
44 Module(DocSubmodule),
45}
46
47#[derive(Debug, Clone, Serialize, Deserialize)]
49pub struct DocFunction {
50 pub name: String,
51 pub doc: String,
53 pub signatures: Vec<DocSignature>,
55 pub is_async: bool,
56 pub deprecated: Option<DeprecatedInfo>,
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
61pub struct DocSignature {
62 pub parameters: Vec<DocParameter>,
63 pub return_type: Option<DocTypeExpr>,
64}
65
66#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct DocParameter {
69 pub name: String,
70 pub type_: DocTypeExpr,
71 pub default: Option<DocDefaultValue>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct DocTypeAlias {
77 pub name: String,
78 pub doc: String,
79 pub definition: DocTypeExpr,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
84pub struct DocVariable {
85 pub name: String,
86 pub doc: String,
87 pub type_: Option<DocTypeExpr>,
88}
89
90#[derive(Debug, Clone, Serialize, Deserialize)]
92pub struct DocClass {
93 pub name: String,
94 pub doc: String,
95 pub bases: Vec<DocTypeExpr>,
96 pub methods: Vec<DocFunction>,
97 pub attributes: Vec<DocAttribute>,
98 pub deprecated: Option<DeprecatedInfo>,
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct DocAttribute {
104 pub name: String,
105 pub doc: String,
106 pub type_: Option<DocTypeExpr>,
107 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
108 pub is_property: bool,
109 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
110 pub is_readonly: bool,
111 #[serde(default, skip_serializing_if = "Option::is_none")]
112 pub deprecated: Option<DeprecatedInfo>,
113}
114
115#[derive(Debug, Clone, Serialize, Deserialize)]
117pub struct DocTypeExpr {
118 pub display: String,
120 pub link_target: Option<LinkTarget>,
122 pub children: Vec<DocTypeExpr>,
124}
125
126#[derive(Debug, Clone, Serialize, Deserialize)]
128#[serde(tag = "kind")]
129pub enum DocDefaultValue {
130 Simple { value: String },
132 Expression(DocDefaultExpression),
134}
135
136#[derive(Debug, Clone, Serialize, Deserialize)]
138pub struct DocDefaultExpression {
139 pub display: String,
141 pub type_refs: Vec<DocTypeRef>,
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct DocTypeRef {
148 pub text: String,
150 pub offset: usize,
152 pub link_target: Option<LinkTarget>,
154}
155
156#[derive(Debug, Clone, Serialize, Deserialize)]
158pub struct LinkTarget {
159 pub fqn: String,
161 pub doc_module: String,
163 pub kind: ItemKind,
165 pub attribute: Option<String>,
167}
168
169#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
171pub enum ItemKind {
172 Class,
173 Function,
174 TypeAlias,
175 Variable,
176 Module,
177}
178
179#[derive(Debug, Clone, Serialize, Deserialize)]
181pub struct DeprecatedInfo {
182 pub since: Option<String>,
183 pub note: Option<String>,
184}
185
186impl DocPackage {
187 pub fn normalize(&mut self) {
189 for module in self.modules.values_mut() {
190 module.normalize();
191 }
192 }
193}
194
195impl DocModule {
196 fn normalize(&mut self) {
197 self.items.sort_by(|a, b| {
199 use DocItem::*;
200 match (a, b) {
201 (Function(f1), Function(f2)) => f1.name.cmp(&f2.name),
202 (Class(c1), Class(c2)) => c1.name.cmp(&c2.name),
203 (TypeAlias(t1), TypeAlias(t2)) => t1.name.cmp(&t2.name),
204 (Variable(v1), Variable(v2)) => v1.name.cmp(&v2.name),
205 (Module(m1), Module(m2)) => m1.name.cmp(&m2.name),
206 _ => Self::item_type_priority(a)
208 .cmp(&Self::item_type_priority(b))
209 .then_with(|| Self::item_name(a).cmp(Self::item_name(b))),
210 }
211 });
212
213 self.submodules.sort();
215
216 for item in &mut self.items {
218 match item {
219 DocItem::Class(c) => c.normalize(),
220 DocItem::Function(f) => f.normalize(),
221 _ => {}
222 }
223 }
224 }
225
226 fn item_type_priority(item: &DocItem) -> u8 {
227 match item {
228 DocItem::Module(_) => 0,
229 DocItem::Class(_) => 1,
230 DocItem::Function(_) => 2,
231 DocItem::TypeAlias(_) => 3,
232 DocItem::Variable(_) => 4,
233 }
234 }
235
236 fn item_name(item: &DocItem) -> &str {
237 match item {
238 DocItem::Function(f) => &f.name,
239 DocItem::Class(c) => &c.name,
240 DocItem::TypeAlias(t) => &t.name,
241 DocItem::Variable(v) => &v.name,
242 DocItem::Module(m) => &m.name,
243 }
244 }
245}
246
247impl DocClass {
248 fn normalize(&mut self) {
249 self.methods.sort_by(|a, b| a.name.cmp(&b.name));
251
252 self.attributes.sort_by(|a, b| a.name.cmp(&b.name));
254
255 self.bases.sort_by(|a, b| a.display.cmp(&b.display));
257
258 for method in &mut self.methods {
260 method.normalize();
261 }
262 }
263}
264
265impl DocFunction {
266 fn normalize(&mut self) {
267 self.signatures.sort_by(|a, b| {
269 a.parameters.len().cmp(&b.parameters.len()).then_with(|| {
270 for (p1, p2) in a.parameters.iter().zip(b.parameters.iter()) {
272 match p1.name.cmp(&p2.name) {
273 std::cmp::Ordering::Equal => continue,
274 other => return other,
275 }
276 }
277 std::cmp::Ordering::Equal
278 })
279 });
280 }
281}