0.5.4
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Public Member Functions | Private Types | Private Member Functions | Private Attributes | List of all members
clanguml::class_diagram::generators::mermaid::generator Class Reference

Class diagram MermaidJS generator. More...

Detailed Description

Class diagram MermaidJS generator.

Definition at line 64 of file class_diagram_generator.h.

#include <class_diagram_generator.h>

Public Member Functions

 generator (diagram_config &config, diagram_model &model)
 
void generate_diagram (std::ostream &ostr) const override
 Main generator method.
 
void generate_diagram_type (std::ostream &ostr) const override
 Generate the diagram type.
 
void generate_top_level_elements (std::ostream &ostr) const
 In a nested diagram, generate the top level elements.
 
void generate_alias (const common::model::element &e, std::ostream &ostr) const
 Generate MermaidJS alias for a class element.
 
void generate (const class_ &c, std::ostream &ostr) const
 Render class element to MermaidJS.
 
void generate_methods (const std::vector< class_method > &methods, std::ostream &ostr) const
 Render class methods to MermaidJS.
 
void generate_methods (const method_groups_t &methods, std::ostream &ostr) const
 Render class methods to MermaidJS in groups.
 
void generate_method (const class_method &m, std::ostream &ostr) const
 Render class method to MermaidJS.
 
void generate_member (const class_member &m, std::ostream &ostr) const
 Render class member to MermaidJS.
 
void generate_relationships (std::ostream &ostr) const
 Render all relationships in the diagram to MermaidJS.
 
void generate_relationships (const class_ &c, std::ostream &ostr) const
 Render all relationships originating from class element.
 
void generate_relationship (const relationship &r, std::set< std::string > &rendered_relations) const
 Render a specific relationship to MermaidJS.
 
void generate (const enum_ &e, std::ostream &ostr) const
 Render enum element to MermaidJS.
 
void generate_relationships (const enum_ &c, std::ostream &ostr) const
 Render all relationships originating from enum element.
 
void generate (const concept_ &c, std::ostream &ostr) const
 Render concept element to MermaidJS.
 
void generate_relationships (const concept_ &c, std::ostream &ostr) const
 Render all relationships originating from concept element.
 
void generate (const package &p, std::ostream &ostr) const
 Render package element to MermaidJS.
 
void generate_relationships (const package &p, std::ostream &ostr) const
 Render all relationships originating from package element.
 
void generate_member_notes (std::ostream &ostream, const class_element &member, const std::string &alias) const
 Generate any notes attached specifically to some class element.
 
void generate_groups (std::ostream &ostr) const
 Generate elements grouped together in together groups.
 
method_groups_t group_methods (const std::vector< class_method > &methods) const
 Group class methods based on method type.
 
- Public Member Functions inherited from clanguml::common::generators::mermaid::generator< ConfigType, DiagramType >
 generator (ConfigType &config, DiagramType &model)
 Constructor.
 
 ~generator () override=default
 
void generate (std::ostream &ostr) const override
 Generate diagram.
 
virtual void generate_diagram (std::ostream &ostr) const =0
 Generate diagram specific part.
 
void generate_mermaid_directives (std::ostream &ostr, const std::vector< std::string > &directives) const
 Generate MermaidJS directives from config file.
 
virtual void generate_diagram_type (std::ostream &ostr) const =0
 Generate the diagram type.
 
virtual void generate_notes (std::ostream &ostr, const model::diagram_element &element) const
 Generate diagram notes.
 
void generate_metadata (std::ostream &ostr) const
 Generate comment with diagram metadata.
 
void generate_title (std::ostream &ostr) const
 Generate diagram title.
 
template<typename E >
void generate_link (std::ostream &ostr, const E &e) const
 Generate hyper link to element.
 
void print_debug (const common::model::source_location &e, std::ostream &ostr) const
 Print debug information in diagram comments.
 
- Public Member Functions inherited from clanguml::common::generators::generator< ConfigType, DiagramType >
 generator (ConfigType &config, DiagramType &model)
 Constructor.
 
virtual ~generator ()=default
 
virtual void generate (std::ostream &ostr) const =0
 Generate diagram.
 
const ConfigType & config () const
 Get reference to diagram config.
 
const DiagramType & model () const
 Get reference to diagram model.
 
template<typename E >
inja::json element_context (const E &e) const
 
std::optional< std::pair< std::string, std::string > > get_link_pattern (const common::model::source_location &sl) const
 
std::optional< std::pair< std::string, std::string > > get_tooltip_pattern (const common::model::source_location &sl) const
 
void init_context ()
 Initialize diagram Jinja context.
 
void update_context () const
 Update diagram Jinja context.
 
void init_env ()
 
const inja::json & context () const
 
inja::Environment & env () const
 

Private Types

using method_groups_t = std::map< std::string, std::vector< class_method > >
 

Private Member Functions

template<typename T >
void sort_class_elements (std::vector< T > &elements) const
 

Private Attributes

const std::vector< std::string > method_groups_
 
common::generators::nested_element_stack< common::model::elementtogether_group_stack_
 

Additional Inherited Members

- Protected Attributes inherited from clanguml::common::generators::mermaid::generator< ConfigType, DiagramType >
std::set< std::string > m_generated_aliases
 
- Protected Attributes inherited from clanguml::common::generators::generator< ConfigType, DiagramType >
inja::json m_context
 
inja::Environment m_env
 

Member Typedef Documentation

◆ method_groups_t

using clanguml::class_diagram::generators::mermaid::generator::method_groups_t = std::map<std::string, std::vector<class_method> >
private

Definition at line 65 of file class_diagram_generator.h.

Constructor & Destructor Documentation

◆ generator()

clanguml::class_diagram::generators::mermaid::generator::generator ( diagram_config config,
diagram_model model 
)

Definition at line 32 of file class_diagram_generator.cc.

33 : common_generator<diagram_config, diagram_model>{config, model}
35{
36}

Member Function Documentation

◆ generate() [1/4]

void clanguml::class_diagram::generators::mermaid::generator::generate ( const class_ c,
std::ostream &  ostr 
) const

Render class element to MermaidJS.

Parameters
cClass element
ostrOutput stream

Definition at line 61 of file class_diagram_generator.cc.

62{
63 std::string class_type{"class"};
64
65 ostr << indent(1) << "class " << c.alias();
66
67 ostr << " {" << '\n';
68
69 if (c.is_union())
70 ostr << indent(2) << "<<union>>\n";
71 else if (c.is_abstract())
72 ostr << indent(2) << "<<abstract>>\n";
73
74 //
75 // Process methods
76 //
77 if (config().group_methods()) {
78 generate_methods(group_methods(c.methods()), ostr);
79 }
80 else {
81 generate_methods(c.methods(), ostr);
82 }
83
84 //
85 // Process relationships - here only generate the set of
86 // rendered_relationships we'll generate them in a seperate method
87 //
88 std::set<std::string> rendered_relations;
89
90 std::stringstream all_relations_str;
91 for (const auto &r : c.relationships()) {
92 try {
93 generate_relationship(r, rendered_relations);
94 }
95 catch (error::uml_alias_missing &e) {
96 LOG_DBG("Skipping {} relation from {} to {} due "
97 "to: {}",
98 to_string(r.type()), c.full_name(), r.destination(), e.what());
99 }
100 }
101
102 //
103 // Process members
104 //
105 std::vector<clanguml::class_diagram::model::class_member> members{
106 c.members()};
107
108 sort_class_elements(members);
109
110 for (const auto &m : members) {
111 if (!config().include_relations_also_as_members() &&
112 rendered_relations.find(m.name()) != rendered_relations.end())
113 continue;
114
115 generate_member(m, ostr);
116
117 ostr << '\n';
118 }
119
120 ostr << indent(1) << "}" << '\n';
121
122 if (config().generate_links) {
124 }
125
126 generate_notes(ostr, c);
127
128 for (const auto &member : c.members())
129 generate_member_notes(ostr, member, c.alias());
130
131 for (const auto &method : c.methods())
132 generate_member_notes(ostr, method, c.alias());
133}

◆ generate() [2/4]

void clanguml::class_diagram::generators::mermaid::generator::generate ( const concept_ c,
std::ostream &  ostr 
) const

Render concept element to MermaidJS.

Parameters
cConcept element
ostrOutput stream

Definition at line 268 of file class_diagram_generator.cc.

269{
270 ostr << indent(1) << "class"
271 << " " << c.alias();
272
273 ostr << " {" << '\n';
274 ostr << indent(2) << "<<concept>>\n";
275
276 if (config().generate_concept_requirements() &&
277 (c.requires_parameters().size() + c.requires_statements().size() > 0)) {
278 std::vector<std::string> parameters;
279 parameters.reserve(c.requires_parameters().size());
280 for (const auto &p : c.requires_parameters()) {
281 parameters.emplace_back(
282 escape_name(p.to_string(config().using_namespace())));
283 }
284
285 ostr << indent(2)
286 << fmt::format("\"({})\"\n", fmt::join(parameters, ","));
287
288 for (const auto &req : c.requires_statements()) {
289 ostr << indent(2)
290 << fmt::format("\"{}\"\n", escape_name(req, false));
291 }
292 }
293
294 ostr << indent(1) << "}" << '\n';
295
296 if (config().generate_links) {
298 }
299}

◆ generate() [3/4]

void clanguml::class_diagram::generators::mermaid::generator::generate ( const enum_ e,
std::ostream &  ostr 
) const

Render enum element to MermaidJS.

Parameters
eEnum element
ostrOutput stream

Definition at line 601 of file class_diagram_generator.cc.

602{
603 ostr << indent(1) << "class " << e.alias();
604
605 ostr << " {" << '\n';
606
607 ostr << indent(2) << "<<enumeration>>\n";
608
609 for (const auto &enum_constant : e.constants()) {
610 ostr << indent(2) << enum_constant << '\n';
611 }
612
613 ostr << indent(1) << "}" << '\n';
614
615 if (config().generate_links) {
617 }
618
619 generate_notes(ostr, e);
620}

◆ generate() [4/4]

void clanguml::class_diagram::generators::mermaid::generator::generate ( const package p,
std::ostream &  ostr 
) const

Render package element to MermaidJS.

Parameters
pPackage element
ostrOutput stream

Definition at line 622 of file class_diagram_generator.cc.

623{
624 for (const auto &subpackage : p) {
625 if (dynamic_cast<package *>(subpackage.get()) != nullptr) {
626 // TODO: add option - generate_empty_packages
627 const auto &sp = dynamic_cast<package &>(*subpackage);
628 if (!sp.is_empty()) {
629 together_group_stack_.enter();
630
631 generate(sp, ostr);
632
633 together_group_stack_.leave();
634 }
635 }
636 else if (auto *cls = dynamic_cast<class_ *>(subpackage.get()); cls) {
637 if (model().should_include(*subpackage)) {
638 auto together_group =
639 config().get_together_group(cls->full_name(false));
640 if (together_group) {
641 together_group_stack_.group_together(
642 together_group.value(), cls);
643 }
644 else {
645 generate_alias(*cls, ostr);
646 generate(*cls, ostr);
647 }
648 }
649 }
650 else if (auto *enm = dynamic_cast<enum_ *>(subpackage.get()); enm) {
651 if (model().should_include(*subpackage)) {
652 auto together_group =
653 config().get_together_group(subpackage->full_name(false));
654 if (together_group) {
655 together_group_stack_.group_together(
656 together_group.value(), enm);
657 }
658 else {
659 generate_alias(*enm, ostr);
660 generate(*enm, ostr);
661 }
662 }
663 }
664 else if (auto *cpt = dynamic_cast<concept_ *>(subpackage.get()); cpt) {
665 if (model().should_include(*subpackage)) {
666 auto together_group =
667 config().get_together_group(cpt->full_name(false));
668 if (together_group) {
669 together_group_stack_.group_together(
670 together_group.value(), cpt);
671 }
672 else {
673 generate_alias(*cpt, ostr);
674 generate(*cpt, ostr);
675 }
676 }
677 }
678 }
679}

◆ generate_alias()

void clanguml::class_diagram::generators::mermaid::generator::generate_alias ( const common::model::element e,
std::ostream &  ostr 
) const

Generate MermaidJS alias for a class element.

Parameters
cClass element
ostrOutput stream

Definition at line 43 of file class_diagram_generator.cc.

45{
46 const auto full_name = c.full_name(true);
47
48 assert(!full_name.empty());
49
50 print_debug(c, ostr);
51
52 auto class_label = config().simplify_template_type(render_name(full_name));
53
54 ostr << indent(1) << "class " << c.alias() << "[\""
55 << escape_name(class_label) << "\"]\n";
56
57 // Register the added alias
58 m_generated_aliases.emplace(c.alias());
59}

◆ generate_diagram()

void clanguml::class_diagram::generators::mermaid::generator::generate_diagram ( std::ostream &  ostr) const
overridevirtual

Main generator method.

This method is called first and coordinates the entire diagram generation.

Parameters
ostrOutput stream.

Implements clanguml::common::generators::mermaid::generator< ConfigType, DiagramType >.

Definition at line 714 of file class_diagram_generator.cc.

715{
717
718 generate_groups(ostr);
719
721}

◆ generate_diagram_type()

void clanguml::class_diagram::generators::mermaid::generator::generate_diagram_type ( std::ostream &  ostr) const
overridevirtual

Generate the diagram type.

Parameters
ostrOutput stream

Implements clanguml::common::generators::mermaid::generator< ConfigType, DiagramType >.

Definition at line 38 of file class_diagram_generator.cc.

39{
40 ostr << "classDiagram\n";
41}

◆ generate_groups()

void clanguml::class_diagram::generators::mermaid::generator::generate_groups ( std::ostream &  ostr) const

Generate elements grouped together in together groups.

Parameters
ostrOutput stream

Definition at line 769 of file class_diagram_generator.cc.

770{
771 for (const auto &[group_name, group_elements] :
772 together_group_stack_.get_current_groups()) {
773
774 for (auto *e : group_elements) {
775 if (auto *cls = dynamic_cast<class_ *>(e); cls) {
776 generate_alias(*cls, ostr);
777 generate(*cls, ostr);
778 }
779 if (auto *enm = dynamic_cast<enum_ *>(e); enm) {
780 generate_alias(*enm, ostr);
781 generate(*enm, ostr);
782 }
783 if (auto *cpt = dynamic_cast<concept_ *>(e); cpt) {
784 generate_alias(*cpt, ostr);
785 generate(*cpt, ostr);
786 }
787 }
788 }
789}

◆ generate_member()

void clanguml::class_diagram::generators::mermaid::generator::generate_member ( const class_member m,
std::ostream &  ostr 
) const

Render class member to MermaidJS.

Parameters
mClass member
ostrOutput stream

Definition at line 254 of file class_diagram_generator.cc.

256{
257 namespace mermaid_common = clanguml::common::generators::mermaid;
258 const auto &uns = config().using_namespace();
259
260 print_debug(m, ostr);
261
262 ostr << indent(2) << mermaid_common::to_mermaid(m.access()) << m.name()
263 << " : "
264 << escape_name(uns.relative(
265 config().simplify_template_type(render_name(m.type()))));
266}

◆ generate_member_notes()

void clanguml::class_diagram::generators::mermaid::generator::generate_member_notes ( std::ostream &  ostream,
const class_element member,
const std::string &  alias 
) const

Generate any notes attached specifically to some class element.

Parameters
ostreamOutput stream
memberClass element (member or method)
aliasMermaidJS class alias

Definition at line 301 of file class_diagram_generator.cc.

303{
304 for (const auto &decorator : member.decorators()) {
305 auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
306 if (note && note->applies_to_diagram(config().name)) {
307 ostr << indent(1) << "note for " << alias << " \"" << note->text
308 << "\"" << '\n';
309 }
310 }
311}

◆ generate_method()

void clanguml::class_diagram::generators::mermaid::generator::generate_method ( const class_method m,
std::ostream &  ostr 
) const

Render class method to MermaidJS.

Parameters
mClass method
ostrOutput stream

Definition at line 185 of file class_diagram_generator.cc.

187{
188 namespace mermaid_common = clanguml::common::generators::mermaid;
189 const auto &uns = config().using_namespace();
190
191 constexpr auto kAbbreviatedMethodArgumentsLength{15};
192
193 print_debug(m, ostr);
194
195 std::string type{uns.relative(config().simplify_template_type(m.type()))};
196
197 ostr << indent(2) << mermaid_common::to_mermaid(m.access()) << m.name();
198
199 if (!m.template_params().empty()) {
200 m.render_template_params(ostr, config().using_namespace(), false);
201 }
202
203 ostr << "(";
204 if (config().generate_method_arguments() !=
206 std::vector<std::string> params;
207 std::transform(m.parameters().cbegin(), m.parameters().cend(),
208 std::back_inserter(params), [this](const auto &mp) {
209 return config().simplify_template_type(
210 mp.to_string(config().using_namespace()));
211 });
212 auto args_string = fmt::format("{}", fmt::join(params, ", "));
213 if (config().generate_method_arguments() ==
215 args_string = clanguml::util::abbreviate(
216 args_string, kAbbreviatedMethodArgumentsLength);
217 }
218 ostr << args_string;
219 }
220 ostr << ")";
221
222 ostr << " : ";
223
224 std::vector<std::string> method_mods;
225 if (m.is_defaulted()) {
226 method_mods.emplace_back("default");
227 }
228 if (m.is_const()) {
229 method_mods.emplace_back("const");
230 }
231 if (m.is_constexpr()) {
232 method_mods.emplace_back("constexpr");
233 }
234 if (m.is_consteval()) {
235 method_mods.emplace_back("consteval");
236 }
237 if (m.is_coroutine()) {
238 method_mods.emplace_back("coroutine");
239 }
240
241 if (!method_mods.empty()) {
242 ostr << fmt::format("[{}] ", fmt::join(method_mods, ","));
243 }
244
245 ostr << escape_name(render_name(type));
246
247 if (m.is_pure_virtual())
248 ostr << "*";
249
250 if (m.is_static())
251 ostr << "$";
252}

◆ generate_methods() [1/2]

void clanguml::class_diagram::generators::mermaid::generator::generate_methods ( const method_groups_t methods,
std::ostream &  ostr 
) const

Render class methods to MermaidJS in groups.

Parameters
methodsMethods grouped by method type
ostrOutput stream

Definition at line 135 of file class_diagram_generator.cc.

137{
138 for (const auto &group : method_groups_) {
139 const auto &group_methods = methods.at(group);
140 if (!group_methods.empty()) {
142 }
143 }
144}

◆ generate_methods() [2/2]

void clanguml::class_diagram::generators::mermaid::generator::generate_methods ( const std::vector< class_method > &  methods,
std::ostream &  ostr 
) const

Render class methods to MermaidJS.

Parameters
methodsList of class methods
ostrOutput stream

Definition at line 146 of file class_diagram_generator.cc.

148{
149 auto sorted_methods = methods;
150 sort_class_elements(sorted_methods);
151
152 for (const auto &m : sorted_methods) {
153 generate_method(m, ostr);
154 ostr << '\n';
155 }
156}

◆ generate_relationship()

void clanguml::class_diagram::generators::mermaid::generator::generate_relationship ( const relationship r,
std::set< std::string > &  rendered_relations 
) const

Render a specific relationship to MermaidJS.

Parameters
rRelationship model
rendered_relationsSet of already rendered relationships, to ensure that there are no duplicate relationships

Definition at line 331 of file class_diagram_generator.cc.

333{
334 namespace mermaid_common = clanguml::common::generators::mermaid;
335
336 LOG_DBG("Processing relationship {}", to_string(r.type()));
337
338 std::string destination;
339
340 auto target_element = model().get(r.destination());
341 if (!target_element.has_value())
342 throw error::uml_alias_missing{fmt::format(
343 "Missing element in the model for ID: {}", r.destination())};
344
345 destination = target_element.value().full_name(false);
346
347 if (util::starts_with(destination, std::string{"::"}))
348 destination = destination.substr(2, destination.size());
349
350 std::string mmd_relation;
351 if (!r.multiplicity_source().empty())
352 mmd_relation += "\"" + r.multiplicity_source() + "\" ";
353
354 mmd_relation += mermaid_common::to_mermaid(r.type());
355
356 if (!r.multiplicity_destination().empty())
357 mmd_relation += " \"" + r.multiplicity_destination() + "\"";
358
359 if (!r.label().empty()) {
360 if (r.type() == relationship_t::kFriendship)
361 rendered_relations.emplace(fmt::format(
362 "{}[friend]", mermaid_common::to_mermaid(r.access())));
363 else
364 rendered_relations.emplace(r.label());
365 }
366}

◆ generate_relationships() [1/5]

void clanguml::class_diagram::generators::mermaid::generator::generate_relationships ( const class_ c,
std::ostream &  ostr 
) const

Render all relationships originating from class element.

Parameters
cClass element
ostrOutput stream

Definition at line 368 of file class_diagram_generator.cc.

370{
371 namespace mermaid_common = clanguml::common::generators::mermaid;
372
373 //
374 // Process relationships
375 //
376 std::set<std::string> rendered_relations;
377
378 std::stringstream all_relations_str;
379 std::set<std::string> unique_relations;
380
381 for (const auto &r : c.relationships()) {
382 LOG_DBG("== Processing relationship {}", to_string(r.type()));
383
384 std::stringstream relstr;
385 eid_t destination{};
386 try {
387 destination = r.destination();
388
389 std::string relation_str;
390
391 if (!r.multiplicity_source().empty())
392 relation_str += "\"" + r.multiplicity_source() + "\" ";
393
394 relation_str += mermaid_common::to_mermaid(r.type());
395
396 if (!r.multiplicity_destination().empty())
397 relation_str += " \"" + r.multiplicity_destination() + "\"";
398
399 std::string target_alias;
400 try {
401 target_alias = model().to_alias(destination);
402 }
403 catch (...) {
404 LOG_DBG("Failed to find alias to {}", destination);
405 continue;
406 }
407
408 if (m_generated_aliases.find(target_alias) ==
410 continue;
411
412 if (r.type() == relationship_t::kContainment) {
413 relstr << indent(1) << target_alias << " " << relation_str
414 << " " << c.alias();
415 }
416 else {
417 relstr << indent(1) << c.alias() << " " << relation_str << " "
418 << target_alias;
419 }
420
421 relstr << " : ";
422
423 if (!r.label().empty()) {
424 auto lbl = r.label();
425 if (r.type() == relationship_t::kFriendship)
426 lbl = "[friend]";
427 relstr << mermaid_common::to_mermaid(r.access()) << lbl;
428 rendered_relations.emplace(r.label());
429 }
430
431 if (unique_relations.count(relstr.str()) == 0) {
432 unique_relations.emplace(relstr.str());
433
434 relstr << '\n';
435
436 LOG_DBG("=== Adding relation {}", relstr.str());
437
438 all_relations_str << relstr.str();
439 }
440 }
441 catch (error::uml_alias_missing &e) {
442 LOG_DBG("=== Skipping {} relation from {} to {} due "
443 "to: {}",
444 to_string(r.type()), c.full_name(), destination, e.what());
445 }
446 }
447
448 if (model().should_include(relationship_t::kExtension)) {
449 for (const auto &b : c.parents()) {
450 std::stringstream relstr;
451 try {
452 auto target_alias = model().to_alias(b.id());
453
454 if (m_generated_aliases.find(target_alias) ==
456 continue;
457
458 relstr << indent(1) << target_alias << " <|-- " << c.alias()
459 << '\n';
460 all_relations_str << relstr.str();
461 }
462 catch (error::uml_alias_missing &e) {
463 LOG_DBG("=== Skipping inheritance relation from {} to {} due "
464 "to: {}",
465 b.name(), c.name(), e.what());
466 }
467 }
468 }
469
470 ostr << all_relations_str.str();
471}

◆ generate_relationships() [2/5]

void clanguml::class_diagram::generators::mermaid::generator::generate_relationships ( const concept_ c,
std::ostream &  ostr 
) const

Render all relationships originating from concept element.

Parameters
cConcept element
ostrOutput stream

Definition at line 473 of file class_diagram_generator.cc.

475{
476 namespace mermaid_common = clanguml::common::generators::mermaid;
477
478 //
479 // Process relationships
480 //
481 std::set<std::string> rendered_relations;
482
483 std::stringstream all_relations_str;
484 std::set<std::string> unique_relations;
485
486 for (const auto &r : c.relationships()) {
487 LOG_DBG("== Processing relationship {}", to_string(r.type()));
488
489 std::stringstream relstr;
490 eid_t destination{};
491 try {
492 destination = r.destination();
493
494 std::string mmd_relation;
495 if (!r.multiplicity_source().empty())
496 mmd_relation += "\"" + r.multiplicity_source() + "\" ";
497
498 mmd_relation += mermaid_common::to_mermaid(r.type());
499
500 if (!r.multiplicity_destination().empty())
501 mmd_relation += " \"" + r.multiplicity_destination() + "\"";
502
503 std::string target_alias;
504 try {
505 target_alias = model().to_alias(destination);
506 }
507 catch (...) {
508 LOG_DBG("Failed to find alias to {}", destination);
509 continue;
510 }
511
512 if (m_generated_aliases.find(target_alias) ==
514 continue;
515
516 if (r.type() == relationship_t::kContainment) {
517 relstr << indent(1) << target_alias << " " << mmd_relation
518 << " " << c.alias();
519 }
520 else {
521 relstr << indent(1) << c.alias() << " " << mmd_relation << " "
522 << target_alias;
523 }
524
525 relstr << " : ";
526
527 if (!r.label().empty()) {
528 auto lbl = r.label();
529 if (r.type() == relationship_t::kFriendship)
530 lbl = "[friend]";
531 relstr << mermaid_common::to_mermaid(r.access()) << lbl;
532 rendered_relations.emplace(r.label());
533 }
534
535 if (unique_relations.count(relstr.str()) == 0) {
536 unique_relations.emplace(relstr.str());
537
538 relstr << '\n';
539
540 LOG_DBG("=== Adding relation {}", relstr.str());
541
542 all_relations_str << relstr.str();
543 }
544 }
545 catch (error::uml_alias_missing &e) {
546 LOG_DBG("=== Skipping {} relation from {} to {} due "
547 "to: {}",
548 to_string(r.type()), c.full_name(), destination, e.what());
549 }
550 }
551
552 ostr << all_relations_str.str();
553}

◆ generate_relationships() [3/5]

void clanguml::class_diagram::generators::mermaid::generator::generate_relationships ( const enum_ c,
std::ostream &  ostr 
) const

Render all relationships originating from enum element.

Parameters
cEnum element
ostrOutput stream

Definition at line 555 of file class_diagram_generator.cc.

556{
557 for (const auto &r : e.relationships()) {
558 eid_t destination{};
559 std::stringstream relstr;
560 try {
561 destination = r.destination();
562
563 auto target_alias = model().to_alias(destination);
564
565 if (m_generated_aliases.find(target_alias) ==
567 continue;
568
569 if (r.type() == relationship_t::kContainment) {
570 relstr << indent(1) << target_alias << " "
572 r.type())
573 << " " << e.alias();
574 }
575 else {
576 relstr << indent(1) << e.alias() << " "
578 r.type())
579 << " " << target_alias;
580 }
581
582 auto lbl = r.label();
583 if (r.type() == relationship_t::kFriendship)
584 lbl = "[friend]";
585
586 relstr << " : " << r.label();
587
588 relstr << '\n';
589
590 ostr << relstr.str();
591 }
592 catch (error::uml_alias_missing &ex) {
593 LOG_DBG("Skipping {} relation from {} to {} due "
594 "to: {}",
596 e.full_name(), destination, ex.what());
597 }
598 }
599}

◆ generate_relationships() [4/5]

void clanguml::class_diagram::generators::mermaid::generator::generate_relationships ( const package p,
std::ostream &  ostr 
) const

Render all relationships originating from package element.

Parameters
pPackage element
ostrOutput stream

Definition at line 681 of file class_diagram_generator.cc.

683{
684 for (const auto &subpackage : p) {
685 if (dynamic_cast<package *>(subpackage.get()) != nullptr) {
686 // TODO: add option - generate_empty_packages, currently
687 // packages which do not contain anything but other
688 // packages are skipped
689 const auto &sp = dynamic_cast<package &>(*subpackage);
690 if (!sp.is_empty())
691 generate_relationships(sp, ostr);
692 }
693 else if (dynamic_cast<class_ *>(subpackage.get()) != nullptr) {
694 if (model().should_include(*subpackage)) {
696 dynamic_cast<class_ &>(*subpackage), ostr);
697 }
698 }
699 else if (dynamic_cast<enum_ *>(subpackage.get()) != nullptr) {
700 if (model().should_include(*subpackage)) {
702 dynamic_cast<enum_ &>(*subpackage), ostr);
703 }
704 }
705 else if (dynamic_cast<concept_ *>(subpackage.get()) != nullptr) {
706 if (model().should_include(*subpackage)) {
708 dynamic_cast<concept_ &>(*subpackage), ostr);
709 }
710 }
711 }
712}

◆ generate_relationships() [5/5]

void clanguml::class_diagram::generators::mermaid::generator::generate_relationships ( std::ostream &  ostr) const

Render all relationships in the diagram to MermaidJS.

Parameters
ostrOutput stream

Definition at line 313 of file class_diagram_generator.cc.

314{
315 for (const auto &p : model()) {
316 if (auto *pkg = dynamic_cast<package *>(p.get()); pkg) {
317 generate_relationships(*pkg, ostr);
318 }
319 else if (auto *cls = dynamic_cast<class_ *>(p.get()); cls) {
320 generate_relationships(*cls, ostr);
321 }
322 else if (auto *enm = dynamic_cast<enum_ *>(p.get()); enm) {
323 generate_relationships(*enm, ostr);
324 }
325 else if (auto *cpt = dynamic_cast<concept_ *>(p.get()); cpt) {
326 generate_relationships(*cpt, ostr);
327 }
328 }
329}

◆ generate_top_level_elements()

void clanguml::class_diagram::generators::mermaid::generator::generate_top_level_elements ( std::ostream &  ostr) const

In a nested diagram, generate the top level elements.

This method iterates over the top level elements. In case the diagram is nested (i.e. includes packages), for each package it recursively call generation of elements contained in each package.

Parameters
parentJSON node

Definition at line 723 of file class_diagram_generator.cc.

724{
725 for (const auto &p : model()) {
726 if (auto *pkg = dynamic_cast<package *>(p.get()); pkg) {
727 if (!pkg->is_empty())
728 generate(*pkg, ostr);
729 }
730 else if (auto *cls = dynamic_cast<class_ *>(p.get()); cls) {
731 auto together_group =
732 config().get_together_group(cls->full_name(false));
733 if (together_group) {
734 together_group_stack_.group_together(
735 together_group.value(), cls);
736 }
737 else {
738 generate_alias(*cls, ostr);
739 generate(*cls, ostr);
740 }
741 }
742 else if (auto *enm = dynamic_cast<enum_ *>(p.get()); enm) {
743 auto together_group =
744 config().get_together_group(enm->full_name(false));
745 if (together_group) {
746 together_group_stack_.group_together(
747 together_group.value(), enm);
748 }
749 else {
750 generate_alias(*enm, ostr);
751 generate(*enm, ostr);
752 }
753 }
754 else if (auto *cpt = dynamic_cast<concept_ *>(p.get()); cpt) {
755 auto together_group =
756 config().get_together_group(cpt->full_name(false));
757 if (together_group) {
758 together_group_stack_.group_together(
759 together_group.value(), cpt);
760 }
761 else {
762 generate_alias(*cpt, ostr);
763 generate(*cpt, ostr);
764 }
765 }
766 }
767}

◆ group_methods()

generator::method_groups_t clanguml::class_diagram::generators::mermaid::generator::group_methods ( const std::vector< class_method > &  methods) const

Group class methods based on method type.

Parameters
methodsList of class methods.
Returns
Map of method groups.

Definition at line 158 of file class_diagram_generator.cc.

160{
161 std::map<std::string, std::vector<class_method>> result;
162
163 for (const auto &g : method_groups_) {
164 result[g] = {};
165 }
166
167 for (const auto &m : methods) {
168 if (m.is_constructor() || m.is_destructor()) {
169 result["constructors"].push_back(m);
170 }
171 else if (m.is_copy_assignment() || m.is_move_assignment()) {
172 result["assignment"].push_back(m);
173 }
174 else if (m.is_operator()) {
175 result["operators"].push_back(m);
176 }
177 else {
178 result["other"].push_back(m);
179 }
180 }
181
182 return result;
183}

◆ sort_class_elements()

template<typename T >
void clanguml::class_diagram::generators::mermaid::generator::sort_class_elements ( std::vector< T > &  elements) const
inlineprivate

Definition at line 257 of file class_diagram_generator.h.

258 {
259 if (config().member_order() == config::member_order_t::lexical) {
260 std::sort(elements.begin(), elements.end(),
261 [](const auto &m1, const auto &m2) {
262 return m1.name() < m2.name();
263 });
264 }
265 }

Member Data Documentation

◆ method_groups_

const std::vector<std::string> clanguml::class_diagram::generators::mermaid::generator::method_groups_
private
Initial value:
{
"constructors", "assignment", "operators", "other"}

Definition at line 253 of file class_diagram_generator.h.

◆ together_group_stack_

common::generators::nested_element_stack<common::model::element> clanguml::class_diagram::generators::mermaid::generator::together_group_stack_
mutableprivate

Definition at line 268 of file class_diagram_generator.h.


The documentation for this class was generated from the following files: