0.6.0
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
class_diagram_generator.cc
Go to the documentation of this file.
1/**
2 * @file rc/class_diagram/generators/json/class_diagram_generator.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
20
21#include "util/error.h"
22
24
27
30{
31}
32
33std::vector<std::pair<std::string, common::generators::graphml::property_type>>
35{
36 auto defaults =
38 defaults.emplace_back(
40 return defaults;
41}
42
43void generator::generate_top_level_elements(graphml_node_t &parent) const
44{
45 for (const auto &p : model()) {
46 if (auto *pkg = dynamic_cast<package *>(p.get()); pkg) {
47 if (!pkg->is_empty())
48 generate(*pkg, parent);
49 }
50 else {
51 model().dynamic_apply(
52 p.get(), [&](auto *el) { generate(*el, parent); });
53 }
54 }
55}
56
57void generator::generate(const package &p, graphml_node_t &parent) const
58{
59 const auto &uns = config().using_namespace();
60 using namespace common::generators::graphml;
61
62 pugi::xml_node package_node;
63 pugi::xml_node graph_node;
64
65 if (config().generate_packages()) {
66 // Don't generate packages from namespaces filtered out by
67 // using_namespace
68 if (!uns.starts_with({p.full_name(false)})) {
69 auto name = display_name_adapter(p).with_packages().name();
70 LOG_DBG("Generating package {}", name);
71
72 package_node = make_subgraph(
73 parent, p.alias(), name, to_string(config().package_type()));
74 graph_node = make_graph(package_node, p.alias());
75 }
76 }
77
78 for (const auto &subpackage : p) {
79 if (dynamic_cast<package *>(subpackage.get()) != nullptr) {
80 const auto &sp = dynamic_cast<package &>(*subpackage);
81 if (!sp.is_empty()) {
82 if (config().generate_packages()) {
83 generate(sp, graph_node);
84 }
85 else
86 generate(sp, parent);
87 }
88 }
89 else {
90 model().dynamic_apply(subpackage.get(), [&](auto *el) {
91 if (config().generate_packages()) {
92 generate(*el, graph_node);
93 }
94 else
95 generate(*el, parent);
96 });
97 }
98 }
99
100 // When generating packages as subgraphs, we want to render the note nodes
101 // and their relationship to their elements within the subgraph
102 if (config().generate_packages()) {
103 generate_notes(p, package_node);
104 }
105}
106
107void generator::generate(const class_ &c, graphml_node_t &parent) const
108{
109 using namespace common::generators::graphml;
110
111 std::string full_name;
112 if (!config().generate_fully_qualified_name())
113 full_name = display_name_adapter(c).with_packages().full_name_no_ns();
114 else
115 full_name = display_name_adapter(c).full_name(true);
116
117 auto class_node = make_node(parent, node_ids_.add(c.alias()));
118 add_data(class_node, "type", c.type_name());
119 add_cdata(class_node, "name", config().simplify_template_type(full_name));
120 if (c.is_abstract()) {
121 add_data(class_node, "stereotype", "abstract");
122 }
123 else if (c.is_union()) {
124 add_data(class_node, "stereotype", "union");
125 }
126 add_data(class_node, "is_template", to_string(c.is_template()));
127
128 generate_link(class_node, c);
129}
130
131void generator::generate(const enum_ &e, graphml_node_t &parent) const
132{
133 using namespace common::generators::graphml;
134
135 std::string full_name;
136 if (!config().generate_fully_qualified_name())
137 full_name = display_name_adapter(e).with_packages().name();
138 else
139 full_name = display_name_adapter(e).full_name(true);
140
141 auto node = make_node(parent, node_ids_.add(e.alias()));
142 add_data(node, "type", e.type_name());
143 add_cdata(node, "name", full_name);
144 generate_link(node, e);
145}
146
147void generator::generate(const concept_ &c, graphml_node_t &parent) const
148{
149 using namespace common::generators::graphml;
150
151 std::string full_name;
152 if (!config().generate_fully_qualified_name())
153 full_name = display_name_adapter(c).with_packages().full_name_no_ns();
154 else
155 full_name = display_name_adapter(c).full_name(true);
156
157 auto node = make_node(parent, node_ids_.add(c.alias()));
158 add_data(node, "type", c.type_name());
159 add_cdata(node, "name", full_name);
160 generate_link(node, c);
161}
162
163void generator::generate(const objc_interface &c, graphml_node_t &parent) const
164{
165 using namespace common::generators::graphml;
166
167 auto node = make_node(parent, node_ids_.add(c.alias()));
168 add_data(node, "type", c.type_name());
169 add_data(node, "name", display_name_adapter(c).full_name(true));
170 generate_link(node, c);
171}
172
173} // namespace clanguml::class_diagram::generators::graphml