Skip to content

Commit 6dea41a

Browse files
committed
Added handling of different types of diagrams in generators (#415)
1 parent 2c25263 commit 6dea41a

File tree

1 file changed

+161
-133
lines changed

1 file changed

+161
-133
lines changed

src/common/generators/generators.cc

Lines changed: 161 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -207,21 +207,107 @@ bool is_diagram_supported_by_generators(
207207
});
208208
}
209209

210+
template <typename T>
211+
using diagram_model_future = std::future<std::unique_ptr<T>>;
212+
213+
template <typename T>
214+
using diagram_model_futures = std::vector<diagram_model_future<T>>;
215+
216+
using class_diagram_model_futures =
217+
diagram_model_futures<class_diagram::model::diagram>;
218+
using sequence_diagram_model_futures =
219+
diagram_model_futures<sequence_diagram::model::diagram>;
220+
using include_diagram_model_futures =
221+
diagram_model_futures<include_diagram::model::diagram>;
222+
using package_diagram_model_futures =
223+
diagram_model_futures<package_diagram::model::diagram>;
224+
using diagram_model_variant_collection = std::map<
225+
std::string /* diagram name */,
226+
std::variant<class_diagram_model_futures, sequence_diagram_model_futures,
227+
include_diagram_model_futures, package_diagram_model_futures>>;
228+
229+
template <typename DiagramConfig, typename DiagramModel>
230+
void create_model_future(util::thread_pool_executor &generator_executor,
231+
diagram_model_variant_collection &diagram_models, const std::string &name,
232+
const std::string &tu, const common::compilation_database_ptr &db,
233+
const std::shared_ptr<config::diagram> diagram,
234+
const cli::runtime_config &runtime_config,
235+
std::shared_ptr<progress_indicator_base> indicator)
236+
{
237+
std::function<std::unique_ptr<DiagramModel>()> generator =
238+
make_generator<DiagramConfig>(name, tu, db,
239+
dynamic_cast<DiagramConfig &>(*diagram), runtime_config, indicator);
240+
241+
auto fut = generator_executor.add<std::unique_ptr<DiagramModel>>(
242+
std::move(generator));
243+
244+
if (!std::holds_alternative<diagram_model_futures<DiagramModel>>(
245+
diagram_models[name]))
246+
diagram_models[name] = diagram_model_futures<DiagramModel>{};
247+
248+
std::get<diagram_model_futures<DiagramModel>>(diagram_models[name])
249+
.emplace_back(std::move(fut));
250+
}
251+
252+
template <typename T>
253+
std::unique_ptr<T> combine_partial_diagram_models(
254+
diagram_model_futures<T> &futs)
255+
{
256+
std::vector<std::unique_ptr<T>> models;
257+
for (auto &fut : futs) {
258+
models.emplace_back(fut.get());
259+
}
260+
261+
auto it = models.begin();
262+
auto &first = *it;
263+
it++;
264+
for (; it != models.end(); it++) {
265+
first->append(std::move(*it->get()));
266+
}
267+
first->finalize();
268+
first->apply_filter();
269+
270+
return std::move(first);
271+
}
272+
273+
template <typename DiagramConfig, typename DiagramModel>
274+
void generate_diagrams_by_type(std::shared_ptr<config::diagram> diagram_config,
275+
const DiagramModel &model, const std::string &name,
276+
const cli::runtime_config &runtime_config)
277+
{
278+
for (const auto generator_type : runtime_config.generators) {
279+
if (generator_type == generator_type_t::plantuml) {
280+
detail::generate_diagram_select_generator<DiagramConfig,
281+
plantuml_generator_tag>(
282+
runtime_config.output_directory, name, diagram_config, model);
283+
}
284+
else if (generator_type == generator_type_t::json) {
285+
detail::generate_diagram_select_generator<DiagramConfig,
286+
json_generator_tag>(
287+
runtime_config.output_directory, name, diagram_config, model);
288+
}
289+
else if (generator_type == generator_type_t::mermaid) {
290+
detail::generate_diagram_select_generator<DiagramConfig,
291+
mermaid_generator_tag>(
292+
runtime_config.output_directory, name, diagram_config, model);
293+
}
294+
else if (generator_type == generator_type_t::graphml) {
295+
detail::generate_diagram_select_generator<DiagramConfig,
296+
graphml_generator_tag>(
297+
runtime_config.output_directory, name, diagram_config, model);
298+
}
299+
}
300+
}
301+
210302
int generate_diagrams(const std::vector<std::string> &diagram_names,
211303
config::config &config, const common::compilation_database_ptr &db,
212304
const cli::runtime_config &runtime_config,
213305
const std::map<std::string, std::vector<std::string>>
214306
&translation_units_map)
215307
{
216308
util::thread_pool_executor generator_executor{runtime_config.thread_count};
217-
std::map<std::string /* diagram name */,
218-
std::vector<
219-
std::future<std::unique_ptr<package_diagram::model::diagram>>>>
220-
package_diagram_models;
221-
std::map<std::string /* diagram name */,
222-
std::vector<
223-
std::future<std::unique_ptr<include_diagram::model::diagram>>>>
224-
include_diagram_models;
309+
310+
diagram_model_variant_collection diagram_models;
225311

226312
std::shared_ptr<progress_indicator_base> indicator;
227313

@@ -296,146 +382,88 @@ int generate_diagrams(const std::vector<std::string> &diagram_names,
296382
}
297383

298384
for (const auto &tu : valid_translation_units) {
299-
300-
if (diagram->type() == model::diagram_t::kPackage) {
301-
std::function<
302-
std::unique_ptr<package_diagram::model::diagram>()>
303-
generator =
304-
make_generator<config::package_diagram>(name, tu, db,
305-
dynamic_cast<config::package_diagram &>(*diagram),
306-
runtime_config, indicator);
307-
308-
auto fut =
309-
generator_executor
310-
.add<std::unique_ptr<package_diagram::model::diagram>>(
311-
std::move(generator));
312-
313-
package_diagram_models[name].emplace_back(std::move(fut));
385+
if (diagram->type() == model::diagram_t::kClass) {
386+
create_model_future<config::class_diagram,
387+
class_diagram::model::diagram>(generator_executor,
388+
diagram_models, name, tu, db, diagram, runtime_config,
389+
indicator);
390+
}
391+
else if (diagram->type() == model::diagram_t::kSequence) {
392+
create_model_future<config::sequence_diagram,
393+
sequence_diagram::model::diagram>(generator_executor,
394+
diagram_models, name, tu, db, diagram, runtime_config,
395+
indicator);
396+
}
397+
else if (diagram->type() == model::diagram_t::kPackage) {
398+
create_model_future<config::package_diagram,
399+
package_diagram::model::diagram>(generator_executor,
400+
diagram_models, name, tu, db, diagram, runtime_config,
401+
indicator);
314402
}
315403
else if (diagram->type() == model::diagram_t::kInclude) {
316-
std::function<
317-
std::unique_ptr<include_diagram::model::diagram>()>
318-
generator =
319-
make_generator<config::include_diagram>(name, tu, db,
320-
dynamic_cast<config::include_diagram &>(*diagram),
321-
runtime_config, indicator);
322-
323-
auto fut =
324-
generator_executor
325-
.add<std::unique_ptr<include_diagram::model::diagram>>(
326-
std::move(generator));
327-
328-
include_diagram_models[name].emplace_back(std::move(fut));
404+
create_model_future<config::include_diagram,
405+
include_diagram::model::diagram>(generator_executor,
406+
diagram_models, name, tu, db, diagram, runtime_config,
407+
indicator);
329408
}
330409
}
331410
}
332411

333-
LOG_INFO("Collecting package diagram futures");
412+
LOG_INFO("Collecting diagram futures");
334413

335-
for (auto &[name, futs] : package_diagram_models) {
414+
for (auto &[name, futs] : diagram_models) {
336415
try {
337-
std::vector<std::unique_ptr<package_diagram::model::diagram>>
338-
models;
339-
for (auto &fut : futs) {
340-
models.emplace_back(fut.get());
416+
if (std::holds_alternative<class_diagram_model_futures>(futs)) {
417+
auto combined_model = combine_partial_diagram_models<
418+
class_diagram::model::diagram>(
419+
std::get<class_diagram_model_futures>(futs));
420+
421+
generate_diagrams_by_type<config::class_diagram,
422+
class_diagram::model::diagram>(config.diagrams.at(name),
423+
*combined_model, name, runtime_config);
341424
}
342-
343-
LOG_INFO("Collected package diagram futures for: {}", name);
344-
345-
auto it = models.begin();
346-
auto &first = *it;
347-
it++;
348-
for (; it != models.end(); it++) {
349-
first->append(std::move(*it->get()));
350-
}
351-
first->finalize();
352-
first->apply_filter();
353-
354-
LOG_INFO("Finalized diagram {}", name);
355-
356-
for (const auto generator_type : runtime_config.generators) {
357-
if (generator_type == generator_type_t::plantuml) {
358-
detail::generate_diagram_select_generator<
359-
config::package_diagram, plantuml_generator_tag>(
360-
runtime_config.output_directory, name,
361-
config.diagrams.at(first->name()), *first);
362-
}
363-
else if (generator_type == generator_type_t::json) {
364-
detail::generate_diagram_select_generator<
365-
config::package_diagram, json_generator_tag>(
366-
runtime_config.output_directory, name,
367-
config.diagrams.at(first->name()), *first);
368-
}
369-
else if (generator_type == generator_type_t::mermaid) {
370-
detail::generate_diagram_select_generator<
371-
config::package_diagram, mermaid_generator_tag>(
372-
runtime_config.output_directory, name,
373-
config.diagrams.at(first->name()), *first);
374-
}
375-
else if (generator_type == generator_type_t::graphml) {
376-
detail::generate_diagram_select_generator<
377-
config::package_diagram, graphml_generator_tag>(
378-
runtime_config.output_directory, name,
379-
config.diagrams.at(first->name()), *first);
380-
}
425+
else if (std::holds_alternative<sequence_diagram_model_futures>(
426+
futs)) {
427+
auto combined_model = combine_partial_diagram_models<
428+
sequence_diagram::model::diagram>(
429+
std::get<sequence_diagram_model_futures>(futs));
430+
431+
generate_diagrams_by_type<config::sequence_diagram,
432+
sequence_diagram::model::diagram>(config.diagrams.at(name),
433+
*combined_model, name, runtime_config);
381434
}
382-
}
383-
catch (std::exception &e) {
384-
errors.emplace_back(std::current_exception());
385-
}
386-
}
387-
388-
LOG_INFO("Collecting include diagram futures");
389-
390-
for (auto &[name, futs] : include_diagram_models) {
391-
try {
392-
std::vector<std::unique_ptr<include_diagram::model::diagram>>
393-
models;
394-
for (auto &fut : futs) {
395-
models.emplace_back(fut.get());
435+
else if (std::holds_alternative<include_diagram_model_futures>(
436+
futs)) {
437+
auto combined_model = combine_partial_diagram_models<
438+
include_diagram::model::diagram>(
439+
std::get<include_diagram_model_futures>(futs));
440+
441+
generate_diagrams_by_type<config::include_diagram,
442+
include_diagram::model::diagram>(config.diagrams.at(name),
443+
*combined_model, name, runtime_config);
396444
}
397-
398-
LOG_INFO("Collected include diagram futures for: {}", name);
399-
400-
auto it = models.begin();
401-
auto &first = *it;
402-
it++;
403-
for (; it != models.end(); it++) {
404-
first->append(std::move(*it->get()));
445+
else if (std::holds_alternative<package_diagram_model_futures>(
446+
futs)) {
447+
auto combined_model = combine_partial_diagram_models<
448+
package_diagram::model::diagram>(
449+
std::get<package_diagram_model_futures>(futs));
450+
451+
generate_diagrams_by_type<config::package_diagram,
452+
package_diagram::model::diagram>(config.diagrams.at(name),
453+
*combined_model, name, runtime_config);
405454
}
406-
first->finalize();
407-
first->apply_filter();
408-
409-
LOG_INFO("Finalized diagram {}", name);
410455

411-
for (const auto generator_type : runtime_config.generators) {
412-
if (generator_type == generator_type_t::plantuml) {
413-
detail::generate_diagram_select_generator<
414-
config::include_diagram, plantuml_generator_tag>(
415-
runtime_config.output_directory, name,
416-
config.diagrams.at(first->name()), *first);
417-
}
418-
else if (generator_type == generator_type_t::json) {
419-
detail::generate_diagram_select_generator<
420-
config::include_diagram, json_generator_tag>(
421-
runtime_config.output_directory, name,
422-
config.diagrams.at(first->name()), *first);
423-
}
424-
else if (generator_type == generator_type_t::mermaid) {
425-
detail::generate_diagram_select_generator<
426-
config::include_diagram, mermaid_generator_tag>(
427-
runtime_config.output_directory, name,
428-
config.diagrams.at(first->name()), *first);
429-
}
430-
else if (generator_type == generator_type_t::graphml) {
431-
detail::generate_diagram_select_generator<
432-
config::include_diagram, graphml_generator_tag>(
433-
runtime_config.output_directory, name,
434-
config.diagrams.at(first->name()), *first);
435-
}
436-
}
456+
if (indicator)
457+
indicator->complete(name);
458+
}
459+
catch (clanguml::generators::clang_tool_exception &e) {
460+
if (indicator)
461+
indicator->fail(name);
462+
throw std::move(e);
437463
}
438464
catch (std::exception &e) {
465+
if (indicator)
466+
indicator->fail(name);
439467
errors.emplace_back(std::current_exception());
440468
}
441469
}

0 commit comments

Comments
 (0)