0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
yaml_emitters.cc
Go to the documentation of this file.
1/**
2 * @file src/config/yaml_emitters.cc
3 *
4 * Copyright (c) 2021-2025 Bartek Kryza <bkryza@gmail.com>
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#include "config.h"
20
21namespace clanguml::common {
22
23YAML::Emitter &operator<<(YAML::Emitter &out, const string_or_regex &m)
24{
25 if (std::holds_alternative<std::string>(m.value())) {
26 out << std::get<std::string>(m.value());
27 }
28 else {
29 out << YAML::BeginMap;
30 out << YAML::Key << "r" << YAML::Value
31 << std::get<regex>(m.value()).pattern;
32 out << YAML::EndMap;
33 }
34
35 return out;
36}
37
38YAML::Emitter &operator<<(YAML::Emitter &out, const namespace_or_regex &m)
39{
40 if (std::holds_alternative<common::model::namespace_>(m.value())) {
41 out << std::get<common::model::namespace_>(m.value());
42 }
43 else {
44 out << YAML::BeginMap;
45 out << YAML::Key << "r" << YAML::Value
46 << std::get<regex>(m.value()).pattern;
47 out << YAML::EndMap;
48 }
49
50 return out;
51}
52
53namespace model {
54YAML::Emitter &operator<<(YAML::Emitter &out, const namespace_ &n)
55{
56 out << n.to_string();
57 return out;
58}
59
60YAML::Emitter &operator<<(YAML::Emitter &out, const relationship_t &r)
61{
62 out << to_string(r);
63 return out;
64}
65
66YAML::Emitter &operator<<(YAML::Emitter &out, const access_t &a)
67{
68 out << to_string(a);
69 return out;
70}
71
72YAML::Emitter &operator<<(YAML::Emitter &out, const module_access_t &a)
73{
74 out << to_string(a);
75 return out;
76}
77
78YAML::Emitter &operator<<(YAML::Emitter &out, const diagram_t &d)
79{
80 out << to_string(d);
81 return out;
82}
83
84} // namespace model
85} // namespace clanguml::common
86
87namespace clanguml::config {
88
89YAML::Emitter &operator<<(YAML::Emitter &out, const method_type &m)
90{
91 out << to_string(m);
92 return out;
93}
94
95YAML::Emitter &operator<<(YAML::Emitter &out, const callee_type &m)
96{
97 out << to_string(m);
98 return out;
99}
100
101YAML::Emitter &operator<<(YAML::Emitter &out, const member_order_t &r)
102{
103 out << to_string(r);
104 return out;
105}
106
107YAML::Emitter &operator<<(YAML::Emitter &out, const package_type_t &r)
108{
109 out << to_string(r);
110 return out;
111}
112
113YAML::Emitter &operator<<(YAML::Emitter &out, const context_config &c)
114{
115 out << YAML::BeginMap;
116 out << YAML::Key << "match";
117 out << YAML::BeginMap;
118 out << YAML::Key << "radius" << YAML::Value << c.radius;
119 out << YAML::Key << "pattern" << YAML::Value << c.pattern;
120 out << YAML::EndMap;
121 out << YAML::EndMap;
122
123 return out;
124}
125
126YAML::Emitter &operator<<(YAML::Emitter &out, const filter &f)
127{
128 out << YAML::BeginMap;
129 if (!f.namespaces.empty())
130 out << YAML::Key << "namespaces" << YAML::Value << f.namespaces;
131 if (!f.modules.empty())
132 out << YAML::Key << "modules" << YAML::Value << f.modules;
133 if (!f.module_access.empty())
134 out << YAML::Key << "module_access" << YAML::Value << f.module_access;
135 if (!f.access.empty())
136 out << YAML::Key << "access" << YAML::Value << f.access;
137 if (!f.context.empty())
138 out << YAML::Key << "context" << YAML::Value << f.context;
139 if (!f.dependants.empty())
140 out << YAML::Key << "dependants" << YAML::Value << f.dependants;
141 if (!f.dependencies.empty())
142 out << YAML::Key << "dependencies" << YAML::Value << f.dependencies;
143 if (!f.elements.empty())
144 out << YAML::Key << "elements" << YAML::Value << f.elements;
145 if (!f.element_types.empty())
146 out << YAML::Key << "element_types" << YAML::Value << f.element_types;
147 if (!f.method_types.empty())
148 out << YAML::Key << "method_types" << YAML::Value << f.method_types;
149 if (!f.paths.empty())
150 out << YAML::Key << "paths" << YAML::Value << f.paths;
151 if (!f.relationships.empty())
152 out << YAML::Key << "relationships" << YAML::Value << f.relationships;
153 if (!f.specializations.empty())
154 out << YAML::Key << "specializations" << YAML::Value
155 << f.specializations;
156 if (!f.subclasses.empty())
157 out << YAML::Key << "subclasses" << YAML::Value << f.subclasses;
158 if (!f.parents.empty())
159 out << YAML::Key << "parents" << YAML::Value << f.parents;
160 if (!f.method_types.empty())
161 out << YAML::Key << "callee_types" << YAML::Value << f.callee_types;
162 out << YAML::EndMap;
163 return out;
164}
165
166YAML::Emitter &operator<<(YAML::Emitter &out, const plantuml &p)
167{
168 if (is_null(p)) {
169 out << YAML::Null;
170 return out;
171 }
172
173 out << YAML::BeginMap;
174 if (!p.before.empty())
175 out << YAML::Key << "before" << YAML::Value << p.before;
176 if (!p.after.empty())
177 out << YAML::Key << "after" << YAML::Value << p.after;
178 if (!p.cmd.empty())
179 out << YAML::Key << "cmd" << YAML::Value << p.cmd;
180 if (!p.style.empty())
181 out << YAML::Key << "style" << YAML::Value << p.style;
182 out << YAML::EndMap;
183
184 return out;
185}
186
187YAML::Emitter &operator<<(YAML::Emitter &out, const mermaid &p)
188{
189 if (is_null(p)) {
190 out << YAML::Null;
191 return out;
192 }
193
194 out << YAML::BeginMap;
195 if (!p.before.empty())
196 out << YAML::Key << "before" << YAML::Value << p.before;
197 if (!p.after.empty())
198 out << YAML::Key << "after" << YAML::Value << p.after;
199 if (!p.cmd.empty())
200 out << YAML::Key << "cmd" << YAML::Value << p.cmd;
201 out << YAML::EndMap;
202
203 return out;
204}
205
206YAML::Emitter &operator<<(YAML::Emitter &out, const graphml &p)
207{
208 if (is_null(p)) {
209 out << YAML::Null;
210 return out;
211 }
212
213 out << YAML::BeginMap;
214 out << YAML::Key << "notes" << YAML::Value << p.notes;
215 out << YAML::EndMap;
216
217 return out;
218}
219
220YAML::Emitter &operator<<(YAML::Emitter &out, const method_arguments &ma)
221{
222 out << to_string(ma);
223 return out;
224}
225
226YAML::Emitter &operator<<(YAML::Emitter &out, const generate_links_config &glc)
227{
228 out << YAML::BeginMap;
229 out << YAML::Key << "link" << YAML::Value << glc.link;
230 out << YAML::Key << "tooltip" << YAML::Value << glc.tooltip;
231 out << YAML::EndMap;
232 return out;
233}
234
235YAML::Emitter &operator<<(YAML::Emitter &out, const git_config &gc)
236{
237 out << YAML::BeginMap;
238 out << YAML::Key << "branch" << YAML::Value << gc.branch;
239 out << YAML::Key << "revision" << YAML::Value << gc.revision;
240 out << YAML::Key << "commit" << YAML::Value << gc.commit;
241 out << YAML::Key << "toplevel" << YAML::Value << gc.toplevel;
242 out << YAML::EndMap;
243
244 return out;
245}
246
247YAML::Emitter &operator<<(YAML::Emitter &out, const relationship_hint_t &rh)
248{
249 out << YAML::BeginMap;
250 out << YAML::Key << "default" << YAML::Value << rh.default_hint;
251 for (const auto &[k, v] : rh.argument_hints)
252 out << YAML::Key << k << YAML::Value << v;
253 out << YAML::EndMap;
254 return out;
255}
256
257YAML::Emitter &operator<<(YAML::Emitter &out, const hint_t &h)
258{
259 out << to_string(h);
260 return out;
261}
262
263YAML::Emitter &operator<<(YAML::Emitter &out, const comment_parser_t &cp)
264{
265 out << to_string(cp);
266 return out;
267}
268
269#ifdef _MSC_VER
270YAML::Emitter &operator<<(YAML::Emitter &out, const std::filesystem::path &p)
271{
272 out << p.string();
273 return out;
274}
275
276YAML::Emitter &operator<<(
277 YAML::Emitter &out, const std::vector<std::filesystem::path> &paths)
278{
279 out << YAML::BeginSeq;
280 for (const auto &p : paths)
281 out << p;
282 out << YAML::EndSeq;
283 return out;
284}
285#endif
286
287YAML::Emitter &operator<<(YAML::Emitter &out, const layout_hint &c)
288{
289 out << YAML::BeginMap;
290
291 out << YAML::Key << c.hint << YAML::Value;
292 if (std::holds_alternative<std::string>(c.entity))
293 out << std::get<std::string>(c.entity);
294 else if (std::holds_alternative<std::vector<std::string>>(c.entity))
295 out << std::get<std::vector<std::string>>(c.entity);
296
297 out << YAML::EndMap;
298 return out;
299}
300
301YAML::Emitter &operator<<(YAML::Emitter &out, const source_location &sc)
302{
303 out << YAML::BeginMap;
304 out << YAML::Key << to_string(sc.location_type) << YAML::Value
305 << sc.location;
306 out << YAML::EndMap;
307 return out;
308}
309
310YAML::Emitter &operator<<(YAML::Emitter &out, const glob_t &g)
311{
312 out << YAML::BeginMap;
313 out << YAML::Key << "include" << YAML::Value << g.include;
314 out << YAML::Key << "exclude" << YAML::Value << g.exclude;
315 out << YAML::EndMap;
316 return out;
317}
318
319YAML::Emitter &operator<<(YAML::Emitter &out, const diagram_template &dt)
320{
321 out << YAML::BeginMap;
322 out << YAML::Key << "type" << YAML::Value << dt.type;
323 out << YAML::Key << "description" << YAML::Value << dt.description;
324 out << YAML::Key << "template" << YAML::Literal << dt.jinja_template;
325 out << YAML::EndMap;
326
327 return out;
328}
329
330YAML::Emitter &operator<<(YAML::Emitter &out, const inja::json &j)
331{
332 if (j.empty() || j.is_null()) {
333 out << YAML::Null;
334 }
335 else if (j.is_boolean()) {
336 out << j.get<bool>();
337 }
338 else if (j.is_number_integer()) {
339 out << j.get<long long>();
340 }
341 else if (j.is_number_unsigned()) {
342 out << j.get<unsigned long long>();
343 }
344 else if (j.is_number_float()) {
345 out << j.get<double>();
346 }
347 else if (j.is_string()) {
348 out << j.get<std::string>();
349 }
350 else if (j.is_array()) {
351 out << YAML::BeginSeq;
352 for (const auto &element : j) {
353 out << element;
354 }
355 out << YAML::EndSeq;
356 }
357 else if (j.is_object()) {
358 out << YAML::BeginMap;
359 for (auto it = j.begin(); it != j.end(); ++it) {
360 out << YAML::Key << it.key() << YAML::Value;
361 out << it.value();
362 }
363 out << YAML::EndMap;
364 }
365 else {
366 out << YAML::Null;
367 }
368 return out;
369}
370
371YAML::Emitter &operator<<(YAML::Emitter &out, const config &c)
372{
373 out << YAML::BeginMap;
374
376 out << c.output_directory;
377 out << c.query_driver;
378 out << c.add_compile_flags;
379 out << c.remove_compile_flags;
380 out << c.diagram_templates;
381
382 out << dynamic_cast<const inheritable_diagram_options &>(c);
383
384 if (!c.diagrams.empty()) {
385 out << YAML::Key << "diagrams";
386 out << YAML::BeginMap;
387
388 for (const auto &[k, v] : c.diagrams) {
389 out << YAML::Key << k;
390 if (v->type() == common::model::diagram_t::kClass) {
391 out << YAML::Value << dynamic_cast<class_diagram &>(*v);
392 }
393 else if (v->type() == common::model::diagram_t::kSequence) {
394 out << YAML::Value << dynamic_cast<sequence_diagram &>(*v);
395 }
396 else if (v->type() == common::model::diagram_t::kInclude) {
397 out << YAML::Value << dynamic_cast<include_diagram &>(*v);
398 }
399 else if (v->type() == common::model::diagram_t::kPackage) {
400 out << YAML::Value << dynamic_cast<package_diagram &>(*v);
401 }
402 }
403 }
404
405 out << YAML::EndMap;
406 out << YAML::EndMap;
407 return out;
408}
409
410YAML::Emitter &operator<<(
411 YAML::Emitter &out, const inheritable_diagram_options &c)
412{
413 // Common options
414 out << c.base_directory;
415 out << c.comment_parser;
416 out << c.debug_mode;
417 out << c.exclude;
418 out << c.generate_links;
419 out << c.git;
420 out << c.glob;
421 out << c.include;
422 out << c.puml;
423 out << c.mermaid;
424 out << c.graphml;
425 out << c.relative_to;
426 out << c.using_namespace;
427 out << c.using_module;
428 out << c.generate_metadata;
429 out << c.user_data;
430
431 if (const auto *cd = dynamic_cast<const class_diagram *>(&c);
432 cd != nullptr) {
433 out << cd->title;
436 out << c.generate_packages;
438 if (c.relationship_hints) {
439 out << YAML::Key << "relationship_hints" << YAML::Value
440 << c.relationship_hints();
441 }
442
443 if (c.type_aliases) {
444 out << YAML::Key << "type_aliases" << YAML::Value
445 << c.type_aliases();
446 }
447 out << c.member_order;
448 out << c.package_type;
451 }
452 else if (const auto *sd = dynamic_cast<const sequence_diagram *>(&c);
453 sd != nullptr) {
454 out << sd->title;
456 out << c.inline_lambda_messages;
459 out << c.generate_return_types;
460 out << c.participants_order;
463 out << c.message_comment_width;
464 }
465 else if (const auto *pd = dynamic_cast<const package_diagram *>(&c);
466 pd != nullptr) {
467 out << pd->title;
468 out << c.generate_packages;
469 out << c.package_type;
470 }
471 else if (const auto *id = dynamic_cast<const include_diagram *>(&c);
472 id != nullptr) {
473 out << id->title;
475 }
476
477 return out;
478}
479
480YAML::Emitter &operator<<(YAML::Emitter &out, const class_diagram &c)
481{
482 out << YAML::BeginMap;
483 out << YAML::Key << "type" << YAML::Value << c.type();
484 out << c.layout;
485 out << dynamic_cast<const inheritable_diagram_options &>(c);
486 out << YAML::EndMap;
487 return out;
488}
489
490YAML::Emitter &operator<<(YAML::Emitter &out, const sequence_diagram &c)
491{
492 out << YAML::BeginMap;
493 out << YAML::Key << "type" << YAML::Value << c.type();
494 out << c.from;
495 out << c.from_to;
496 out << c.to;
497 out << dynamic_cast<const inheritable_diagram_options &>(c);
498 out << YAML::EndMap;
499 return out;
500}
501
502YAML::Emitter &operator<<(YAML::Emitter &out, const include_diagram &c)
503{
504 out << YAML::BeginMap;
505 out << YAML::Key << "type" << YAML::Value << c.type();
506 out << c.layout;
507 out << dynamic_cast<const inheritable_diagram_options &>(c);
508 out << YAML::EndMap;
509 return out;
510}
511
512YAML::Emitter &operator<<(YAML::Emitter &out, const package_diagram &c)
513{
514 out << YAML::BeginMap;
515 out << YAML::Key << "type" << YAML::Value << c.type();
516 out << c.layout;
517 out << dynamic_cast<const inheritable_diagram_options &>(c);
518 out << YAML::EndMap;
519 return out;
520}
521
522YAML::Emitter &operator<<(YAML::Emitter &out, const element_filter_t &ef)
523{
524 out << YAML::BeginMap;
525 out << YAML::Key << "type" << YAML::Value << to_string(ef.type);
526 out << YAML::Key << "name" << YAML::Value << ef.name;
527 out << YAML::EndMap;
528
529 return out;
530}
531
532template <> bool is_null(const std::string &v) { return v.empty(); }
533
534template <> bool is_null(const glob_t &v)
535{
536 return v.include.empty() && v.exclude.empty();
537}
538
539template <> bool is_null(const plantuml &v)
540{
541 return v.before.empty() && v.after.empty() && v.cmd.empty() &&
542 v.style.empty();
543}
544
545template <> bool is_null(const mermaid &v)
546{
547 return v.before.empty() && v.after.empty() && v.cmd.empty();
548}
549
550template <> bool is_null(const graphml &v) { return v.notes.empty(); }
551
552template <> bool is_null(const inja::json &v) { return v.is_null(); }
553
554} // namespace clanguml::config