0.5.4
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Namespaces | Classes | Functions
clanguml::common::generators Namespace Reference

Namespaces

namespace  detail
 
namespace  json
 
namespace  mermaid
 
namespace  plantuml
 

Classes

class  diagram_action_visitor_factory
 Specialization of clang::ASTFrontendAction More...
 
class  diagram_ast_consumer
 Specialization of clang::ASTConsumer More...
 
class  diagram_fronted_action
 Specialization of clang::ASTFrontendAction More...
 
struct  diagram_generator_t
 
struct  diagram_generator_t< clanguml::config::class_diagram, json_generator_tag >
 
struct  diagram_generator_t< clanguml::config::class_diagram, mermaid_generator_tag >
 
struct  diagram_generator_t< clanguml::config::class_diagram, plantuml_generator_tag >
 
struct  diagram_generator_t< clanguml::config::include_diagram, json_generator_tag >
 
struct  diagram_generator_t< clanguml::config::include_diagram, mermaid_generator_tag >
 
struct  diagram_generator_t< clanguml::config::include_diagram, plantuml_generator_tag >
 
struct  diagram_generator_t< clanguml::config::package_diagram, json_generator_tag >
 
struct  diagram_generator_t< clanguml::config::package_diagram, mermaid_generator_tag >
 
struct  diagram_generator_t< clanguml::config::package_diagram, plantuml_generator_tag >
 
struct  diagram_generator_t< clanguml::config::sequence_diagram, json_generator_tag >
 
struct  diagram_generator_t< clanguml::config::sequence_diagram, mermaid_generator_tag >
 
struct  diagram_generator_t< clanguml::config::sequence_diagram, plantuml_generator_tag >
 
struct  diagram_model_t
 
struct  diagram_model_t< clanguml::config::class_diagram >
 
struct  diagram_model_t< clanguml::config::include_diagram >
 
struct  diagram_model_t< clanguml::config::package_diagram >
 
struct  diagram_model_t< clanguml::config::sequence_diagram >
 
struct  diagram_visitor_t
 
struct  diagram_visitor_t< clanguml::config::class_diagram >
 
struct  diagram_visitor_t< clanguml::config::include_diagram >
 
struct  diagram_visitor_t< clanguml::config::package_diagram >
 
struct  diagram_visitor_t< clanguml::config::sequence_diagram >
 
class  generator
 Common diagram generator interface. More...
 
struct  json_generator_tag
 
struct  mermaid_generator_tag
 
class  nested_element_stack
 
struct  plantuml_generator_tag
 
class  progress_indicator
 Container for diagram generation progress indicators. More...
 

Functions

void make_context_source_relative (inja::json &context, const std::string &prefix)
 
void find_translation_units_for_diagrams (const std::vector< std::string > &diagram_names, clanguml::config::config &config, const std::vector< std::string > &compilation_database_files, std::map< std::string, std::vector< std::string > > &translation_units_map)
 Assign translation units to diagrams.
 
void render_diagram (const clanguml::common::generator_type_t generator_type, std::shared_ptr< config::diagram > diagram_config)
 
void generate_diagram (const std::string &name, std::shared_ptr< clanguml::config::diagram > diagram, const common::compilation_database &db, const std::vector< std::string > &translation_units, const cli::runtime_config &runtime_config, std::function< void()> &&progress)
 Generate a single diagram.
 
void generate_diagrams (const std::vector< std::string > &diagram_names, clanguml::config::config &config, const common::compilation_database_ptr &db, const cli::runtime_config &runtime_config, const std::map< std::string, std::vector< std::string > > &translation_units_map)
 Generate diagrams.
 
indicators::Color diagram_type_to_color (model::diagram_t diagram_type)
 Return indicators progress bar color for diagram type.
 
template<typename DiagramModel , typename DiagramConfig , typename DiagramVisitor >
std::unique_ptr< DiagramModel > generate (const common::compilation_database &db, const std::string &name, DiagramConfig &config, const std::vector< std::string > &translation_units, bool=false, std::function< void()> progress={})
 Specialization of clang::ASTFrontendAction
 

Function Documentation

◆ diagram_type_to_color()

indicators::Color clanguml::common::generators::diagram_type_to_color ( model::diagram_t  diagram_type)

Return indicators progress bar color for diagram type.

Parameters
diagram_typeDiagram type
Returns
Progress bar color

Definition at line 307 of file generators.cc.

308{
309 switch (diagram_type) {
310 case model::diagram_t::kClass:
311 return indicators::Color::yellow;
312 case model::diagram_t::kSequence:
313 return indicators::Color::blue;
314 case model::diagram_t::kPackage:
315 return indicators::Color::cyan;
316 case model::diagram_t::kInclude:
317 return indicators::Color::magenta;
318 default:
319 return indicators::Color::unspecified;
320 }
321}

◆ find_translation_units_for_diagrams()

void clanguml::common::generators::find_translation_units_for_diagrams ( const std::vector< std::string > &  diagram_names,
clanguml::config::config config,
const std::vector< std::string > &  compilation_database_files,
std::map< std::string, std::vector< std::string > > &  translation_units_map 
)

Assign translation units to diagrams.

This function assigns for each diagram to be generated the list of translation units based on it's glob pattern if any.

If diagram_names is empty, this function processes all diagrams in config.

Parameters
diagram_namesList of diagram names, applies to all if empty
configReference to config instance
compilation_database_filesList of files found in compilation database
translation_units_mapResulting translation units map is stored here

Definition at line 46 of file generators.cc.

51{
52 for (const auto &[name, diagram] : config.diagrams) {
53 // If there are any specific diagram names provided on the command line,
54 // and this diagram is not in that list - skip it
55 if (!diagram_names.empty() && !util::contains(diagram_names, name))
56 continue;
57
58 translation_units_map[name] =
59 diagram->glob_translation_units(compilation_database_files);
60
61 LOG_DBG("Found {} translation units for diagram {}",
62 translation_units_map.at(name).size(), name);
63 }
64}

◆ generate()

template<typename DiagramModel , typename DiagramConfig , typename DiagramVisitor >
std::unique_ptr< DiagramModel > clanguml::common::generators::generate ( const common::compilation_database db,
const std::string &  name,
DiagramConfig &  config,
const std::vector< std::string > &  translation_units,
bool  = false,
std::function< void()>  progress = {} 
)

Specialization of clang::ASTFrontendAction

This is the entry point function to initiate AST frontend action for a specific diagram.

Template Parameters
DiagramModelType of diagram_model
DiagramConfigType of diagram_config
TranslationUnitVisitorType of translation_unit_visitor

Definition at line 362 of file generators.h.

365 {})
366{
367 LOG_INFO("Generating diagram {}", name);
368
369 auto diagram = std::make_unique<DiagramModel>();
370 diagram->set_name(name);
371 diagram->set_filter(
372 model::diagram_filter_factory::create(*diagram, config));
373
374 LOG_DBG("Found translation units for diagram {}: {}", name,
375 fmt::join(translation_units, ", "));
376
377 clang::tooling::ClangTool clang_tool(db, translation_units);
378 auto action_factory =
379 std::make_unique<diagram_action_visitor_factory<DiagramModel,
380 DiagramConfig, DiagramVisitor>>(
381 *diagram, config, std::move(progress));
382
383 auto res = clang_tool.run(action_factory.get());
384
385 if (res != 0) {
386 throw std::runtime_error("Diagram " + name + " generation failed");
387 }
388
389 diagram->set_complete(true);
390
391 diagram->finalize();
392
393 return diagram;
394}

◆ generate_diagram()

void clanguml::common::generators::generate_diagram ( const std::string &  name,
std::shared_ptr< clanguml::config::diagram diagram,
const common::compilation_database db,
const std::vector< std::string > &  translation_units,
const cli::runtime_config runtime_config,
std::function< void()> &&  progress 
)

Generate a single diagram.

Parameters
nameName of the diagram
diagramEffective diagram configuration
dbReference to compilation database
translation_unitsList of translation units for the diagram
generatorsList of generator types to be used for the diagram
verboseLog level
progressFunction to report translation unit progress

Definition at line 184 of file generators.cc.

189{
192
197
198 if (diagram->type() == diagram_t::kClass) {
199 detail::generate_diagram_impl<class_diagram>(name, diagram, db,
200 translation_units, runtime_config, std::move(progress));
201 }
202 else if (diagram->type() == diagram_t::kSequence) {
203 detail::generate_diagram_impl<sequence_diagram>(name, diagram, db,
204 translation_units, runtime_config, std::move(progress));
205 }
206 else if (diagram->type() == diagram_t::kPackage) {
207 detail::generate_diagram_impl<package_diagram>(name, diagram, db,
208 translation_units, runtime_config, std::move(progress));
209 }
210 else if (diagram->type() == diagram_t::kInclude) {
211 detail::generate_diagram_impl<include_diagram>(name, diagram, db,
212 translation_units, runtime_config, std::move(progress));
213 }
214}

◆ generate_diagrams()

void clanguml::common::generators::generate_diagrams ( const std::vector< std::string > &  diagram_names,
clanguml::config::config config,
const common::compilation_database_ptr db,
const cli::runtime_config runtime_config,
const std::map< std::string, std::vector< std::string > > &  translation_units_map 
)

Generate diagrams.

Parameters
diagram_namesList of diagram names to generate
configReference to config instance
output_directoryPath to output directory
dbReference to compilation database
verboseLog level
thread_countNumber of diagrams to be generated in parallel
progressWhether progress indicators should be displayed
generatorsList of generator types to use for each diagram
translation_units_mapMap of translation units for each file

Definition at line 216 of file generators.cc.

221{
222 util::thread_pool_executor generator_executor{runtime_config.thread_count};
223 std::vector<std::future<void>> futs;
224
225 std::unique_ptr<progress_indicator> indicator;
226
227 if (runtime_config.progress) {
228 std::cout << termcolor::white
229 << "Processing translation units and generating diagrams:\n";
230 indicator = std::make_unique<progress_indicator>();
231 }
232
233 for (const auto &[name, diagram] : config.diagrams) {
234 // If there are any specific diagram names provided on the command
235 // line, and this diagram is not in that list - skip it
236 if (!diagram_names.empty() && !util::contains(diagram_names, name))
237 continue;
238
239 const auto &valid_translation_units = translation_units_map.at(name);
240
241 LOG_DBG("Found {} valid translation units for diagram {}",
242 valid_translation_units.size(), name);
243
244 const auto matching_commands_count =
245 db->count_matching_commands(valid_translation_units);
246
247 if (matching_commands_count == 0) {
248 if (indicator) {
249 indicator->add_progress_bar(
250 name, 0, diagram_type_to_color(diagram->type()));
251 indicator->fail(name);
252 }
253 else {
254 LOG_ERROR(
255 "Diagram {} generation failed: no translation units "
256 "found. Please make sure that your 'glob' patterns match "
257 "at least 1 file in 'compile_commands.json'.",
258 name);
259 }
260 continue;
261 }
262
263 LOG_DBG("Found {} matching translation unit commands for diagram {}",
264 matching_commands_count, name);
265
266 auto generator = [&name = name, &diagram = diagram, &indicator,
267 db = std::ref(*db), matching_commands_count,
268 translation_units = valid_translation_units,
269 runtime_config]() mutable {
270 try {
271 if (indicator)
272 indicator->add_progress_bar(name, matching_commands_count,
273 diagram_type_to_color(diagram->type()));
274
275 generate_diagram(name, diagram, db, translation_units,
276 runtime_config, [&indicator, &name]() {
277 if (indicator)
278 indicator->increment(name);
279 });
280
281 if (indicator)
282 indicator->complete(name);
283 }
284 catch (const std::exception &e) {
285 if (indicator)
286 indicator->fail(name);
287
288 LOG_ERROR(
289 "ERROR: Failed to generate diagram {}: {}", name, e.what());
290 }
291 };
292
293 futs.emplace_back(generator_executor.add(std::move(generator)));
294 }
295
296 for (auto &fut : futs) {
297 fut.get();
298 }
299
300 if (runtime_config.progress) {
301 indicator->stop();
302 std::cout << termcolor::white << "Done\n";
303 std::cout << termcolor::reset;
304 }
305}

◆ make_context_source_relative()

void clanguml::common::generators::make_context_source_relative ( inja::json &  context,
const std::string &  prefix 
)

Definition at line 24 of file generators.cc.

26{
27 if (!context.contains("element"))
28 return;
29
30 if (!context["element"].contains("source"))
31 return;
32
33 auto &source = context["element"]["source"];
34
35 if (source.at("path").empty())
36 return;
37
38 auto path = std::filesystem::path{source.at("path")};
39 auto prefix_path = std::filesystem::path(prefix);
40 if (path.is_absolute() && util::is_relative_to(path, prefix_path)) {
41 source["path"] = relative(path, prefix_path);
42 return;
43 }
44}

◆ render_diagram()

void clanguml::common::generators::render_diagram ( const clanguml::common::generator_type_t  generator_type,
std::shared_ptr< config::diagram diagram_config 
)

Definition at line 66 of file generators.cc.

68{
69 std::string cmd;
70 switch (generator_type) {
72 cmd = diagram_config->puml().cmd;
73 break;
75 cmd = diagram_config->mermaid().cmd;
76 break;
77 default:
78 return;
79 };
80
81 if (cmd.empty())
82 throw std::runtime_error(
83 fmt::format("No render command template provided for {} diagrams",
84 to_string(diagram_config->type())));
85
86 util::replace_all(cmd, "{}", diagram_config->name);
87
88 LOG_INFO("Rendering diagram {} using {}", diagram_config->name,
89 to_string(generator_type));
90
91 util::check_process_output(cmd);
92}