diff --git a/src/common/generators/generators.cc b/src/common/generators/generators.cc index b7b9dd1d..748460d4 100644 --- a/src/common/generators/generators.cc +++ b/src/common/generators/generators.cc @@ -55,6 +55,56 @@ void find_translation_units_for_diagrams( } } +namespace detail { + +template +void generate_diagram_select_generator(const std::string &od, + const std::string &name, std::shared_ptr diagram, + const DiagramModel &model) +{ + using diagram_generator = typename diagram_generator_t::type; + + auto path = std::filesystem::path{od} / + fmt::format("{}.{}", name, GeneratorTag::extension); + std::ofstream ofs; + ofs.open(path, std::ofstream::out | std::ofstream::trunc); + ofs << diagram_generator(dynamic_cast(*diagram), *model); + + ofs.close(); + + LOG_INFO("Written {} diagram to {}", name, path.string()); +} + +template +void generate_diagram_impl(const std::string &od, const std::string &name, + std::shared_ptr diagram, + const clang::tooling::CompilationDatabase &db, + const std::vector &translation_units, + const std::vector &generators, + bool verbose) +{ + using diagram_config = DiagramConfig; + using diagram_model = typename diagram_model_t::type; + using diagram_visitor = typename diagram_visitor_t::type; + + auto model = clanguml::common::generators::generate(db, diagram->name, + dynamic_cast(*diagram), translation_units, verbose); + + for (const auto generator_type : generators) { + if (generator_type == generator_type_t::plantuml) { + generate_diagram_select_generator(od, name, diagram, model); + } + else if (generator_type == generator_type_t::json) { + generate_diagram_select_generator(od, name, diagram, model); + } + } +} +} // namespace detail + void generate_diagram(const std::string &od, const std::string &name, std::shared_ptr diagram, const clang::tooling::CompilationDatabase &db, @@ -64,177 +114,27 @@ void generate_diagram(const std::string &od, const std::string &name, { using clanguml::common::generator_type_t; using clanguml::common::model::diagram_t; + using clanguml::config::class_diagram; using clanguml::config::include_diagram; using clanguml::config::package_diagram; using clanguml::config::sequence_diagram; if (diagram->type() == diagram_t::kClass) { - using diagram_config = class_diagram; - using diagram_model = clanguml::class_diagram::model::diagram; - using diagram_visitor = - clanguml::class_diagram::visitor::translation_unit_visitor; - - auto model = clanguml::common::generators::generate(db, diagram->name, - dynamic_cast(*diagram), translation_units, - verbose); - - for (const auto generator_type : generators) { - if (generator_type == generator_type_t::plantuml) { - auto path = - std::filesystem::path{od} / fmt::format("{}.puml", name); - std::ofstream ofs; - ofs.open(path, std::ofstream::out | std::ofstream::trunc); - ofs << clanguml::class_diagram::generators::plantuml::generator( - dynamic_cast(*diagram), *model); - - ofs.close(); - - LOG_INFO("Written {} diagram to {}", name, path.string()); - } - else if (generator_type == generator_type_t::json) { - auto path = - std::filesystem::path{od} / fmt::format("{}.json", name); - std::ofstream ofs; - ofs.open(path, std::ofstream::out | std::ofstream::trunc); - ofs << clanguml::class_diagram::generators::json::generator( - dynamic_cast(*diagram), *model); - - ofs.close(); - - LOG_INFO("Written {} diagram to {}", name, path.string()); - } - } + detail::generate_diagram_impl( + od, name, diagram, db, translation_units, generators, verbose); } else if (diagram->type() == diagram_t::kSequence) { - using diagram_config = sequence_diagram; - using diagram_model = clanguml::sequence_diagram::model::diagram; - using diagram_visitor = - clanguml::sequence_diagram::visitor::translation_unit_visitor; - - auto model = clanguml::common::generators::generate(db, diagram->name, - dynamic_cast(*diagram), translation_units, - verbose); - - for (const auto generator_type : generators) { - if (generator_type == generator_type_t::plantuml) { - auto path = - std::filesystem::path{od} / fmt::format("{}.puml", name); - std::ofstream ofs; - - ofs.open(path, std::ofstream::out | std::ofstream::trunc); - ofs << clanguml::sequence_diagram::generators::plantuml:: - generator( - dynamic_cast( - *diagram), - *model); - - ofs.close(); - - LOG_INFO("Written {} diagram to {}", name, path.string()); - } - else if (generator_type == generator_type_t::json) { - auto path = - std::filesystem::path{od} / fmt::format("{}.json", name); - std::ofstream ofs; - - ofs.open(path, std::ofstream::out | std::ofstream::trunc); - ofs << clanguml::sequence_diagram::generators::json::generator( - dynamic_cast( - *diagram), - *model); - - ofs.close(); - - LOG_INFO("Written {} diagram to {}", name, path.string()); - } - } + detail::generate_diagram_impl( + od, name, diagram, db, translation_units, generators, verbose); } else if (diagram->type() == diagram_t::kPackage) { - using diagram_config = package_diagram; - using diagram_model = clanguml::package_diagram::model::diagram; - using diagram_visitor = - clanguml::package_diagram::visitor::translation_unit_visitor; - - auto model = clanguml::common::generators::generate(db, diagram->name, - dynamic_cast(*diagram), translation_units, - verbose); - - for (const auto generator_type : generators) { - if (generator_type == generator_type_t::plantuml) { - auto path = - std::filesystem::path{od} / fmt::format("{}.puml", name); - std::ofstream ofs; - ofs.open(path, std::ofstream::out | std::ofstream::trunc); - - ofs << clanguml::package_diagram::generators::plantuml:: - generator( - dynamic_cast(*diagram), *model); - - ofs.close(); - - LOG_INFO("Written {} diagram to {}", name, path.string()); - } - else if (generator_type == generator_type_t::json) { - auto path = - std::filesystem::path{od} / fmt::format("{}.json", name); - std::ofstream ofs; - - ofs.open(path, std::ofstream::out | std::ofstream::trunc); - ofs << clanguml::package_diagram::generators::json::generator( - dynamic_cast(*diagram), - *model); - - ofs.close(); - - LOG_INFO("Written {} diagram to {}", name, path.string()); - } - } + detail::generate_diagram_impl( + od, name, diagram, db, translation_units, generators, verbose); } else if (diagram->type() == diagram_t::kInclude) { - using diagram_config = include_diagram; - using diagram_model = clanguml::include_diagram::model::diagram; - using diagram_visitor = - clanguml::include_diagram::visitor::translation_unit_visitor; - - auto model = clanguml::common::generators::generate(db, diagram->name, - dynamic_cast(*diagram), translation_units, - verbose); - - for (const auto generator_type : generators) { - if (generator_type == generator_type_t::plantuml) { - auto path = - std::filesystem::path{od} / fmt::format("{}.puml", name); - std::ofstream ofs; - ofs.open(path, std::ofstream::out | std::ofstream::trunc); - - ofs << clanguml::include_diagram::generators::plantuml:: - generator( - dynamic_cast(*diagram), *model); - - ofs.close(); - - LOG_INFO("Written {} diagram to {}", name, path.string()); - } - else if (generator_type == generator_type_t::json) { - auto path = - std::filesystem::path{od} / fmt::format("{}.json", name); - std::ofstream ofs; - - ofs.open(path, std::ofstream::out | std::ofstream::trunc); - ofs << clanguml::include_diagram::generators::json::generator( - dynamic_cast(*diagram), - *model); - - ofs.close(); - - LOG_INFO("Written {} diagram to {}", name, path.string()); - } - } + detail::generate_diagram_impl( + od, name, diagram, db, translation_units, generators, verbose); } } diff --git a/src/common/generators/generators.h b/src/common/generators/generators.h index e5e03803..c2a6e956 100644 --- a/src/common/generators/generators.h +++ b/src/common/generators/generators.h @@ -48,6 +48,91 @@ namespace clanguml::common::generators { +// template trait for selecting diagram model type based on diagram config +// type +template struct diagram_model_t; +template <> struct diagram_model_t { + using type = clanguml::class_diagram::model::diagram; +}; +template <> struct diagram_model_t { + using type = clanguml::sequence_diagram::model::diagram; +}; +template <> struct diagram_model_t { + using type = clanguml::package_diagram::model::diagram; +}; +template <> struct diagram_model_t { + using type = clanguml::include_diagram::model::diagram; +}; + +// template trait for selecting diagram visitor type based on diagram config +// type +template struct diagram_visitor_t; +template <> struct diagram_visitor_t { + using type = clanguml::class_diagram::visitor::translation_unit_visitor; +}; +template <> struct diagram_visitor_t { + using type = clanguml::sequence_diagram::visitor::translation_unit_visitor; +}; +template <> struct diagram_visitor_t { + using type = clanguml::package_diagram::visitor::translation_unit_visitor; +}; +template <> struct diagram_visitor_t { + using type = clanguml::include_diagram::visitor::translation_unit_visitor; +}; + +// template trait for selecting diagram generator type based on diagram config +// type +struct plantuml_generator_tag { + inline static const std::string extension = "puml"; +}; +struct json_generator_tag { + inline static const std::string extension = "json"; +}; + +template +struct diagram_generator_t; +template <> +struct diagram_generator_t { + using type = clanguml::class_diagram::generators::plantuml::generator; +}; +template <> +struct diagram_generator_t { + using type = clanguml::sequence_diagram::generators::plantuml::generator; +}; +template <> +struct diagram_generator_t { + using type = clanguml::package_diagram::generators::plantuml::generator; +}; +template <> +struct diagram_generator_t { + using type = clanguml::include_diagram::generators::plantuml::generator; +}; +template <> +struct diagram_generator_t { + using type = clanguml::class_diagram::generators::json::generator; +}; +template <> +struct diagram_generator_t { + using type = clanguml::sequence_diagram::generators::json::generator; +}; +template <> +struct diagram_generator_t { + using type = clanguml::package_diagram::generators::json::generator; +}; +template <> +struct diagram_generator_t { + using type = clanguml::include_diagram::generators::json::generator; +}; + +template struct diagram_visitor_t; void find_translation_units_for_diagrams( const std::vector &diagram_names, clanguml::config::config &config,