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}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct DocTypeExpr {
112 pub display: String,
114 pub link_target: Option<LinkTarget>,
116 pub children: Vec<DocTypeExpr>,
118}
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
122#[serde(tag = "kind")]
123pub enum DocDefaultValue {
124 Simple { value: String },
126 Expression(DocDefaultExpression),
128}
129
130#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct DocDefaultExpression {
133 pub display: String,
135 pub type_refs: Vec<DocTypeRef>,
137}
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct DocTypeRef {
142 pub text: String,
144 pub offset: usize,
146 pub link_target: Option<LinkTarget>,
148}
149
150#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct LinkTarget {
153 pub fqn: String,
155 pub doc_module: String,
157 pub kind: ItemKind,
159 pub attribute: Option<String>,
161}
162
163#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
165pub enum ItemKind {
166 Class,
167 Function,
168 TypeAlias,
169 Variable,
170 Module,
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct DeprecatedInfo {
176 pub since: Option<String>,
177 pub note: Option<String>,
178}
179
180impl DocPackage {
181 pub fn normalize(&mut self) {
183 for module in self.modules.values_mut() {
184 module.normalize();
185 }
186 }
187}
188
189impl DocModule {
190 fn normalize(&mut self) {
191 self.items.sort_by(|a, b| {
193 use DocItem::*;
194 match (a, b) {
195 (Function(f1), Function(f2)) => f1.name.cmp(&f2.name),
196 (Class(c1), Class(c2)) => c1.name.cmp(&c2.name),
197 (TypeAlias(t1), TypeAlias(t2)) => t1.name.cmp(&t2.name),
198 (Variable(v1), Variable(v2)) => v1.name.cmp(&v2.name),
199 (Module(m1), Module(m2)) => m1.name.cmp(&m2.name),
200 _ => Self::item_type_priority(a)
202 .cmp(&Self::item_type_priority(b))
203 .then_with(|| Self::item_name(a).cmp(Self::item_name(b))),
204 }
205 });
206
207 self.submodules.sort();
209
210 for item in &mut self.items {
212 match item {
213 DocItem::Class(c) => c.normalize(),
214 DocItem::Function(f) => f.normalize(),
215 _ => {}
216 }
217 }
218 }
219
220 fn item_type_priority(item: &DocItem) -> u8 {
221 match item {
222 DocItem::Module(_) => 0,
223 DocItem::Class(_) => 1,
224 DocItem::Function(_) => 2,
225 DocItem::TypeAlias(_) => 3,
226 DocItem::Variable(_) => 4,
227 }
228 }
229
230 fn item_name(item: &DocItem) -> &str {
231 match item {
232 DocItem::Function(f) => &f.name,
233 DocItem::Class(c) => &c.name,
234 DocItem::TypeAlias(t) => &t.name,
235 DocItem::Variable(v) => &v.name,
236 DocItem::Module(m) => &m.name,
237 }
238 }
239}
240
241impl DocClass {
242 fn normalize(&mut self) {
243 self.methods.sort_by(|a, b| a.name.cmp(&b.name));
245
246 self.attributes.sort_by(|a, b| a.name.cmp(&b.name));
248
249 self.bases.sort_by(|a, b| a.display.cmp(&b.display));
251
252 for method in &mut self.methods {
254 method.normalize();
255 }
256 }
257}
258
259impl DocFunction {
260 fn normalize(&mut self) {
261 self.signatures.sort_by(|a, b| {
263 a.parameters.len().cmp(&b.parameters.len()).then_with(|| {
264 for (p1, p2) in a.parameters.iter().zip(b.parameters.iter()) {
266 match p1.name.cmp(&p2.name) {
267 std::cmp::Ordering::Equal => continue,
268 other => return other,
269 }
270 }
271 std::cmp::Ordering::Equal
272 })
273 });
274 }
275}