0.5.4
C++ to UML diagram generator based on Clang
Loading...
Searching...
No Matches
Public Member Functions | Protected Attributes | Private Member Functions | List of all members
clanguml::common::generators::plantuml::generator< ConfigType, DiagramType > Class Template Referenceabstract

Base class for diagram generators. More...

Detailed Description

template<typename ConfigType, typename DiagramType>
class clanguml::common::generators::plantuml::generator< ConfigType, DiagramType >

Base class for diagram generators.

Template Parameters
ConfigTypeConfiguration type
DiagramTypeDiagram model type

Definition at line 52 of file generator.h.

#include <generator.h>

Public Member Functions

 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_config_layout_hints (std::ostream &ostr) const
 Generate diagram layout hints.
 
void generate_plantuml_directives (std::ostream &ostr, const std::vector< std::string > &directives) const
 Generate PlantUML directives from config file.
 
void generate_notes (std::ostream &ostr, const model::element &element) const
 Generate diagram notes.
 
void generate_style (std::ostream &ostr, const std::string &element_type, const model::stylable_element &el) const
 Generate diagram element PlantUML style.
 
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
 

Protected Attributes

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
 

Private Member Functions

void generate_row_column_hints (std::ostream &ostr, const std::string &entity_name, const config::layout_hint &hint) const
 
void generate_position_hints (std::ostream &ostr, const std::string &entity_name, const config::layout_hint &hint) const
 

Constructor & Destructor Documentation

◆ generator()

template<typename ConfigType , typename DiagramType >
clanguml::common::generators::plantuml::generator< ConfigType, DiagramType >::generator ( ConfigType &  config,
DiagramType &  model 
)
inline

Constructor.

Parameters
configReference to instance of model Reference to instance of clanguml::model::diagram

Definition at line 61 of file generator.h.

◆ ~generator()

template<typename ConfigType , typename DiagramType >
clanguml::common::generators::plantuml::generator< ConfigType, DiagramType >::~generator ( )
overridevirtualdefault

Member Function Documentation

◆ generate()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate ( std::ostream &  ostr) const
overridevirtual

Generate diagram.

This is the main diagram generation entrypoint. It is responsible for calling other methods in appropriate order to generate the diagram into the output stream. It generates diagram elements, that are common to all types of diagrams in a given generator.

Parameters
ostrOutput stream

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

Definition at line 190 of file generator.h.

191{
194
196
197 if (!config.allow_empty_diagrams() && model.is_empty() &&
198 config.puml().before.empty() && config.puml().after.empty()) {
200 "Diagram configuration resulted in empty diagram."};
201 }
202
203 ostr << "@startuml" << '\n';
204
205 generate_title(ostr);
206
207 // Generate PlantUML directives before auto generated content
208 generate_plantuml_directives(ostr, config.puml().before);
209
210 generate_diagram(ostr);
211
212 // Generate PlantUML directives after auto generated content
213 generate_plantuml_directives(ostr, config.puml().after);
214
215 generate_metadata(ostr);
216
217 ostr << "@enduml" << '\n';
218}

◆ generate_config_layout_hints()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate_config_layout_hints ( std::ostream &  ostr) const

Generate diagram layout hints.

This method adds to the diagram any layout hints that were provided in the configuration file.

Parameters
ostrOutput stream

Definition at line 221 of file generator.h.

222{
223 using namespace clanguml::util;
224
226
227 // Generate layout hints
228 for (const auto &[entity_name, hints] : config.layout()) {
229 for (const auto &hint : hints) {
230 try {
231 if (hint.hint == config::hint_t::together) {
232 // 'together' layout hint is handled separately
233 }
234 else if (hint.hint == config::hint_t::row ||
235 hint.hint == config::hint_t::column) {
236 generate_row_column_hints(ostr, entity_name, hint);
237 }
238 else {
239 generate_position_hints(ostr, entity_name, hint);
240 }
241 }
243 LOG_DBG("=== Skipping layout hint '{}' from {} due "
244 "to: {}",
245 to_string(hint.hint), entity_name, e.what());
246 }
247 }
248 }
249}

◆ generate_diagram()

template<typename ConfigType , typename DiagramType >
virtual void clanguml::common::generators::plantuml::generator< ConfigType, DiagramType >::generate_diagram ( std::ostream &  ostr) const
pure virtual

Generate diagram specific part.

This method must be implemented in subclasses for specific diagram types.

Parameters
ostrOutput stream

Implemented in clanguml::class_diagram::generators::plantuml::generator, clanguml::include_diagram::generators::plantuml::generator, clanguml::package_diagram::generators::plantuml::generator, and clanguml::sequence_diagram::generators::plantuml::generator.

◆ generate_link()

template<typename C , typename D >
template<typename E >
void clanguml::common::generators::plantuml::generator< C, D >::generate_link ( std::ostream &  ostr,
const E &  e 
) const

Generate hyper link to element.

This method renders links to URL's based on templates provided in the configuration file (e.g. Git browser with specific line and column offset)

Parameters
ostrOutput stream
eReference to diagram element
Template Parameters
EDiagram element type

Definition at line 446 of file generator.h.

447{
448 if (e.file().empty() && e.file_relative().empty())
449 return;
450
451 auto maybe_link_pattern = generators::generator<C, D>::get_link_pattern(e);
452
453 if (!maybe_link_pattern) {
454 return;
455 }
456
457 const auto &[link_prefix, link_pattern] = *maybe_link_pattern;
458
459 ostr << " [[";
460 try {
461 if (!link_pattern.empty()) {
464 ostr << generators::generator<C, D>::env().render(
465 std::string_view{link_pattern}, ec);
466 }
467 }
468 catch (const inja::json::parse_error &e) {
469 LOG_ERROR("Failed to parse Jinja template: {}", link_pattern);
470 }
471 catch (const std::exception &e) {
472 LOG_ERROR("Failed to render PlantUML directive: \n{}\n due to: {}",
473 link_pattern, e.what());
474 }
475
476 auto maybe_tooltip_pattern =
478
479 if (maybe_tooltip_pattern) {
480 const auto &[tooltip_prefix, tooltip_pattern] = *maybe_tooltip_pattern;
481
482 ostr << "{";
483 try {
486 ec, tooltip_prefix);
487 if (!tooltip_pattern.empty()) {
488 ostr << generators::generator<C, D>::env().render(
489 std::string_view{tooltip_pattern}, ec);
490 }
491 }
492 catch (const inja::json::parse_error &e) {
493 LOG_ERROR("Failed to parse Jinja template: {}", tooltip_pattern);
494 }
495 catch (const std::exception &e) {
496 LOG_ERROR("Failed to render PlantUML directive: \n{}\n due to: {}",
497 tooltip_pattern, e.what());
498 }
499 ostr << "}";
500 }
501 ostr << "]]";
502}

◆ generate_metadata()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate_metadata ( std::ostream &  ostr) const

Generate comment with diagram metadata.

Parameters
ostrOutput stream

Definition at line 422 of file generator.h.

423{
425
426 if (config.generate_metadata()) {
427 ostr << '\n'
428 << "'Generated with clang-uml, version "
429 << clanguml::version::CLANG_UML_VERSION << '\n'
430 << "'LLVM version " << clang::getClangFullVersion() << '\n';
431 }
432}

◆ generate_notes()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate_notes ( std::ostream &  ostr,
const model::element element 
) const

Generate diagram notes.

This method adds any notes in the diagram, which were declared in the code using inline directives

Parameters
ostrOutput stream
elementElement to which the note should be attached

Definition at line 406 of file generator.h.

408{
410
411 for (const auto &decorator : e.decorators()) {
412 auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
413 if (note && note->applies_to_diagram(config.name)) {
414 ostr << "note " << note->position << " of " << e.alias() << '\n'
415 << note->text << '\n'
416 << "end note\n";
417 }
418 }
419}

◆ generate_plantuml_directives()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate_plantuml_directives ( std::ostream &  ostr,
const std::vector< std::string > &  directives 
) const

Generate PlantUML directives from config file.

This method renders the PlantUML directives provided in the configuration file, including resolving any element aliases and Jinja templates.

Parameters
ostrOutput stream
directivesList of directives from the configuration file

Definition at line 330 of file generator.h.

332{
335
337
338 for (const auto &d : directives) {
339 try {
340 // Render the directive with template engine first
341 std::string directive{generators::generator<C, D>::env().render(
342 std::string_view{d}, generators::generator<C, D>::context())};
343
344 // Now search for alias `@A()` directives in the text
345 // (this is deprecated)
346 std::tuple<std::string, size_t, size_t> alias_match;
347 while (util::find_element_alias(directive, alias_match)) {
348 const auto full_name =
349 config.using_namespace() | std::get<0>(alias_match);
350 auto element_opt = model.get(full_name.to_string());
351
352 if (element_opt)
353 directive.replace(std::get<1>(alias_match),
354 std::get<2>(alias_match), element_opt.value().alias());
355 else {
356 LOG_WARN("Cannot find clang-uml alias for element {}",
357 full_name.to_string());
358 directive.replace(std::get<1>(alias_match),
359 std::get<2>(alias_match), "UNKNOWN_ALIAS");
360 }
361 }
362
363 ostr << directive << '\n';
364 }
365 catch (const clanguml::error::uml_alias_missing &e) {
366 LOG_WARN("Failed to render PlantUML directive due to unresolvable "
367 "alias: {}",
368 e.what());
369 }
370 catch (const inja::json::parse_error &e) {
371 LOG_WARN("Failed to parse Jinja template: {}", d);
372 }
373 catch (const inja::json::exception &e) {
374 LOG_WARN("Failed to render PlantUML directive: \n{}\n due to: {}",
375 d, e.what());
376 }
377 catch (const std::regex_error &e) {
378 LOG_WARN("Failed to render PlantUML directive: \n{}\n due to "
379 "std::regex_error: {}",
380 d, e.what());
381 }
382 catch (const std::exception &e) {
383 LOG_WARN("Failed to render PlantUML directive: \n{}\n due to: {}",
384 d, e.what());
385 }
386 }
387}

◆ generate_position_hints()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate_position_hints ( std::ostream &  ostr,
const std::string &  entity_name,
const config::layout_hint hint 
) const
private

Definition at line 299 of file generator.h.

301{
304
305 const auto &uns = config.using_namespace();
306
307 const auto &hint_entity = std::get<std::string>(hint.entity);
308
309 auto element_opt = model.get(entity_name);
310 if (!element_opt)
311 element_opt = model.get((uns | entity_name).to_string());
312
313 auto hint_element_opt = model.get(hint_entity);
314 if (!hint_element_opt)
315 hint_element_opt = model.get((uns | hint_entity).to_string());
316
317 if (!element_opt || !hint_element_opt)
318 return;
319
320 std::stringstream hint_str;
321
322 hint_str << element_opt.value().alias() << " -[hidden]"
323 << clanguml::config::to_string(hint.hint) << "- "
324 << hint_element_opt.value().alias() << '\n';
325
326 ostr << hint_str.str();
327}

◆ generate_row_column_hints()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate_row_column_hints ( std::ostream &  ostr,
const std::string &  entity_name,
const config::layout_hint hint 
) const
private

Definition at line 252 of file generator.h.

254{
257
258 const auto &uns = config.using_namespace();
259
260 std::vector<std::string> group_elements;
261 std::vector<std::pair<std::string, std::string>> element_aliases_pairs;
262
263 group_elements.push_back(entity_name);
264 const auto &group_tail = std::get<std::vector<std::string>>(hint.entity);
265 std::copy(group_tail.begin(), group_tail.end(),
266 std::back_inserter(group_elements));
267
268 auto element_opt = model.get(entity_name);
269 if (!element_opt)
270 element_opt = model.get((uns | entity_name).to_string());
271
272 for (auto it = cbegin(group_elements);
273 it != cend(group_elements) && std::next(it) != cend(group_elements);
274 ++it) {
275 const auto &first = *it;
276 const auto &second = *std::next(it);
277
278 auto first_opt = model.get(first);
279 if (!first_opt)
280 first_opt = model.get((uns | first).to_string());
281
282 auto second_opt = model.get(second);
283 if (!second_opt)
284 second_opt = model.get((uns | second).to_string());
285
286 element_aliases_pairs.emplace_back(
287 first_opt.value().alias(), second_opt.value().alias());
288 }
289
290 std::string hint_direction =
291 hint.hint == clanguml::config::hint_t::row ? "right" : "down";
292
293 for (const auto &[f, s] : element_aliases_pairs) {
294 ostr << f << " -[hidden]" << hint_direction << "- " << s << '\n';
295 }
296}

◆ generate_style()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate_style ( std::ostream &  ostr,
const std::string &  element_type,
const model::stylable_element el 
) const

Generate diagram element PlantUML style.

This method renders a style for a specific el element if specified in the config file or inline comment directive.

Parameters
ostrOutput stream
element_typeName of the element type (e.g. "class")
elReference to a stylable diagram element

Definition at line 390 of file generator.h.

392{
394
395 if (el.style() && !el.style().value().empty()) // NOLINT
396 ostr << " " << *el.style(); // NOLINT
397 else if (config.puml) {
398 if (const auto config_style = config.puml().get_style(element_type);
399 config_style) {
400 ostr << " " << *config_style;
401 }
402 }
403}

◆ generate_title()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::generate_title ( std::ostream &  ostr) const

Generate diagram title.

Generates a PlantUML diagram title directive if diagram title is provided in the diagram configuration.

Parameters
ostrOutput stream

Definition at line 435 of file generator.h.

436{
438
439 if (config.title) {
440 ostr << "title " << config.title() << '\n';
441 }
442}

◆ print_debug()

template<typename C , typename D >
void clanguml::common::generators::plantuml::generator< C, D >::print_debug ( const common::model::source_location e,
std::ostream &  ostr 
) const

Print debug information in diagram comments.

Parameters
mDiagram element to describe
ostrOutput stream

Definition at line 505 of file generator.h.

507{
509
510 if (config.debug_mode())
511 ostr << "' " << e.file() << ":" << e.line() << '\n';
512}

Member Data Documentation

◆ m_generated_aliases

template<typename ConfigType , typename DiagramType >
std::set<std::string> clanguml::common::generators::plantuml::generator< ConfigType, DiagramType >::m_generated_aliases
mutableprotected

Definition at line 186 of file generator.h.


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