1use crate::{
7 builtin::Builtin,
8 symbol::{Symbol, SymbolDef},
9 syntax::*,
10};
11
12use microcad_lang_base::{Refer, SrcRef};
13
14pub trait Doc {
19 fn doc(&self) -> DocBlock {
21 DocBlock::merge(&self.outer_doc(), &self.inner_doc())
22 }
23
24 fn inner_doc(&self) -> DocBlock {
26 DocBlock::default()
27 }
28
29 fn outer_doc(&self) -> DocBlock {
31 DocBlock::default()
32 }
33}
34
35impl Doc for DocBlock {
36 fn doc(&self) -> DocBlock {
37 self.clone()
38 }
39}
40
41impl Doc for InitDefinition {
42 fn outer_doc(&self) -> DocBlock {
43 self.doc.as_ref().cloned().unwrap_or_default()
44 }
45
46 fn inner_doc(&self) -> DocBlock {
47 self.body.inner_doc()
48 }
49}
50
51impl Doc for StatementList {
52 fn inner_doc(&self) -> DocBlock {
53 if self.is_empty() {
54 DocBlock::default()
55 } else {
56 let src_ref = SrcRef::merge_all(self.iter());
57
58 DocBlock(Refer::new(
59 self.iter()
60 .filter_map(|s| match s {
61 Statement::InnerDocComment(doc) => Some(doc.0.value.clone()),
62 _ => None,
63 })
64 .collect::<Vec<_>>(),
65 src_ref,
66 ))
67 }
68 }
69}
70
71impl Doc for Body {
72 fn inner_doc(&self) -> DocBlock {
73 self.statements.inner_doc()
74 }
75}
76
77impl Doc for ModuleDefinition {
78 fn outer_doc(&self) -> DocBlock {
79 self.doc.as_ref().cloned().unwrap_or_default()
80 }
81
82 fn inner_doc(&self) -> DocBlock {
83 self.body
84 .as_ref()
85 .map(|body| body.inner_doc())
86 .unwrap_or_default()
87 }
88}
89
90impl Doc for FunctionDefinition {
91 fn outer_doc(&self) -> DocBlock {
92 self.doc.as_ref().cloned().unwrap_or_default()
93 }
94
95 fn inner_doc(&self) -> DocBlock {
96 self.body.inner_doc()
97 }
98}
99
100impl Doc for WorkbenchDefinition {
101 fn outer_doc(&self) -> DocBlock {
102 self.doc.as_ref().cloned().unwrap_or_default()
103 }
104
105 fn inner_doc(&self) -> DocBlock {
106 self.body.inner_doc()
107 }
108}
109
110impl Doc for SourceFile {
111 fn inner_doc(&self) -> DocBlock {
112 self.statements.inner_doc()
113 }
114}
115
116impl Doc for Assignment {
117 fn outer_doc(&self) -> DocBlock {
118 self.doc.as_ref().cloned().unwrap_or_default()
119 }
120}
121
122impl Doc for Builtin {
123 fn outer_doc(&self) -> DocBlock {
124 match self {
125 Builtin::Function(builtin_function) => builtin_function.doc.clone(),
126 Builtin::Workbench(builtin_workbench) => builtin_workbench.doc.clone(),
127 Builtin::Constant(builtin_constant) => builtin_constant.doc.clone(),
128 }
129 .unwrap_or_default()
130 }
131}
132
133impl Doc for SymbolDef {
134 fn inner_doc(&self) -> DocBlock {
135 match &self {
136 SymbolDef::SourceFile(source_file) => source_file.inner_doc(),
137 SymbolDef::Module(module_definition) => module_definition.inner_doc(),
138 SymbolDef::Workbench(workbench_definition) => workbench_definition.inner_doc(),
139 SymbolDef::Function(function_definition) => function_definition.inner_doc(),
140 _ => DocBlock::default(),
141 }
142 }
143
144 fn outer_doc(&self) -> DocBlock {
145 match &self {
146 SymbolDef::Module(module_definition) => module_definition.outer_doc(),
147 SymbolDef::Workbench(workbench_definition) => workbench_definition.outer_doc(),
148 SymbolDef::Function(function_definition) => function_definition.outer_doc(),
149 SymbolDef::Assignment(assignment) => assignment.outer_doc(),
150 SymbolDef::Builtin(builtin) => builtin.outer_doc(),
151 _ => DocBlock::default(),
154 }
155 }
156}
157
158impl Doc for Symbol {
159 fn inner_doc(&self) -> DocBlock {
160 self.with_def(|def| def.inner_doc())
161 }
162
163 fn outer_doc(&self) -> DocBlock {
164 self.with_def(|def| def.outer_doc())
165 }
166}