@@ -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+
210302int 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