From 251857e9c45285278c9c4ca0e9a2cbc169a98f43 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Thu, 8 Feb 2024 20:16:17 +0100 Subject: [PATCH 1/7] Added class translation unit visitor detailed diagram --- .clang-uml | 2 ++ uml/class/class_translation_unit_visitor.yml | 26 ++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 uml/class/class_translation_unit_visitor.yml diff --git a/.clang-uml b/.clang-uml index 53fed4a6..ec0124c5 100644 --- a/.clang-uml +++ b/.clang-uml @@ -15,6 +15,8 @@ generate_links: tooltip: "{% if existsIn(element, \"comment\") and existsIn(element.comment, \"brief\") %}{{ abbrv(trim(replace(element.comment.brief.0, \"\\n+\", \" \")), 256) }}{% else %}{{ element.name }}{% endif %}" diagrams: # Class diagrams + class_translation_unit_visitor: + include!: uml/class/class_translation_unit_visitor.yml architecture_visitors_class: include!: uml/class/architecture_visitors_class.yml config_class: diff --git a/uml/class/class_translation_unit_visitor.yml b/uml/class/class_translation_unit_visitor.yml new file mode 100644 index 00000000..2180a56b --- /dev/null +++ b/uml/class/class_translation_unit_visitor.yml @@ -0,0 +1,26 @@ +type: class +title: Class diagram TU visitor +include_relations_also_as_members: false +generate_method_arguments: none +generate_packages: false +glob: + - src/common/visitor/*.cc + - src/class_diagram/visitor/*.cc +include: + namespaces: + - clanguml + - clang + context: + - clanguml::class_diagram::visitor::translation_unit_visitor + - match: + radius: 2 + pattern: "clang::RecursiveASTVisitor" +exclude: + access: + - public + - protected + - private + relationships: + - dependency + element_types: + - enum \ No newline at end of file From 7f25fa58f556c0b3a7f4082e63ba09bcf7221fad Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Sun, 11 Feb 2024 19:33:03 +0100 Subject: [PATCH 2/7] Continued refactor of template building code to template_builder --- .../visitor/translation_unit_visitor.cc | 184 +-- .../visitor/translation_unit_visitor.h | 83 +- src/common/visitor/template_builder.cc | 1120 -------------- src/common/visitor/template_builder.h | 1342 ++++++++++++++++- .../visitor/translation_unit_visitor.cc | 168 --- src/common/visitor/translation_unit_visitor.h | 225 ++- .../visitor/translation_unit_visitor.cc | 16 +- .../visitor/translation_unit_visitor.h | 27 +- .../visitor/translation_unit_visitor.cc | 15 +- .../visitor/translation_unit_visitor.h | 26 +- .../visitor/translation_unit_visitor.cc | 685 +-------- .../visitor/translation_unit_visitor.h | 110 +- tests/t20040/.clang-uml | 11 + tests/t20040/t20040.cc | 32 + tests/t20040/test_case.h | 62 + tests/test_cases.cc | 1 + 16 files changed, 1738 insertions(+), 2369 deletions(-) create mode 100644 tests/t20040/.clang-uml create mode 100644 tests/t20040/t20040.cc create mode 100644 tests/t20040/test_case.h diff --git a/src/class_diagram/visitor/translation_unit_visitor.cc b/src/class_diagram/visitor/translation_unit_visitor.cc index e15d6d26..704abacf 100644 --- a/src/class_diagram/visitor/translation_unit_visitor.cc +++ b/src/class_diagram/visitor/translation_unit_visitor.cc @@ -29,32 +29,19 @@ namespace clanguml::class_diagram::visitor { translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm, clanguml::class_diagram::model::diagram &diagram, const clanguml::config::class_diagram &config) - : common::visitor::translation_unit_visitor{sm, config} - , diagram_{diagram} - , config_{config} - , template_builder_{diagram_, config_, *this, - [uns = config_.using_namespace()](const clang::NamedDecl *decl) { - auto cls = std::make_unique(uns); - cls->is_struct(common::is_struct(decl)); - return cls; - }, - [this](common::model::template_element &template_instantiation_base, - const std::string &full_name, common::id_t templated_decl_id) { - find_instantiation_relationships( - template_instantiation_base, full_name, templated_decl_id); - }, - [](clanguml::common::model::template_element &tinst, - clanguml::common::id_t id, const std::string &full_name) { - model::class_parent cp; - cp.set_access(common::model::access_t::kPublic); - cp.set_name(full_name); - cp.set_id(id); - - dynamic_cast(tinst).add_parent(std::move(cp)); - }} + : visitor_specialization_t{sm, diagram, config} + , template_builder_{diagram, config, *this} { } +std::unique_ptr translation_unit_visitor::create_element( + const clang::NamedDecl *decl) const +{ + auto cls = std::make_unique(config().using_namespace()); + cls->is_struct(common::is_struct(decl)); + return cls; +} + bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns) { assert(ns != nullptr); @@ -126,7 +113,7 @@ bool translation_unit_visitor::VisitEnumDecl(clang::EnumDecl *enm) enm->getQualifiedNameAsString(), enm->getLocation().printToString(source_manager())); - auto e_ptr = std::make_unique(config_.using_namespace()); + auto e_ptr = std::make_unique(config().using_namespace()); auto &e = *e_ptr; std::string qualified_name = common::get_qualified_name(*enm); @@ -274,7 +261,7 @@ bool translation_unit_visitor::VisitTypeAliasTemplateDecl( auto template_specialization_ptr = std::make_unique(config().using_namespace()); - tbuilder().build( + tbuilder().build_from_template_specialization_type( *template_specialization_ptr, cls, *template_type_specialization_ptr); if (diagram().should_include(*template_specialization_ptr)) { @@ -309,11 +296,10 @@ bool translation_unit_visitor::VisitClassTemplateDecl( add_processed_template_class(cls->getQualifiedNameAsString()); + tbuilder().build_from_template_declaration(*c_ptr, *cls, *c_ptr); + // Override the id with the template id, for now we don't care about the // underlying templated class id - - process_template_parameters(*cls, *c_ptr, *c_ptr); - const auto cls_full_name = c_ptr->full_name(false); const auto id = common::to_id(cls_full_name); @@ -420,7 +406,7 @@ bool translation_unit_visitor::TraverseConceptDecl(clang::ConceptDecl *cpt) id_mapper().add(cpt->getID(), concept_id); - process_template_parameters(*cpt, *concept_model); + tbuilder().build_from_template_declaration(*concept_model, *cpt); constexpr auto kMaxConstraintCount = 24U; llvm::SmallVector constraints{}; @@ -774,7 +760,7 @@ translation_unit_visitor::create_concept_declaration(clang::ConceptDecl *cpt) return {}; auto concept_ptr{ - std::make_unique(config_.using_namespace())}; + std::make_unique(config().using_namespace())}; auto &concept_model = *concept_ptr; auto ns = common::get_template_namespace(*cpt); @@ -803,7 +789,7 @@ std::unique_ptr translation_unit_visitor::create_record_declaration( if (!should_include(rec)) return {}; - auto record_ptr{std::make_unique(config_.using_namespace())}; + auto record_ptr{std::make_unique(config().using_namespace())}; auto &record = *record_ptr; process_record_parent(rec, record, namespace_{}); @@ -849,7 +835,7 @@ std::unique_ptr translation_unit_visitor::create_class_declaration( if (!should_include(cls)) return {}; - auto c_ptr{std::make_unique(config_.using_namespace())}; + auto c_ptr{std::make_unique(config().using_namespace())}; auto &c = *c_ptr; auto ns{common::get_tag_namespace(*cls)}; @@ -909,11 +895,11 @@ void translation_unit_visitor::process_record_parent( } } - if (id_opt && diagram_.find(*id_opt)) { + if (id_opt && diagram().find(*id_opt)) { // Here we have 2 options, either: // - the parent is a regular C++ class/struct // - the parent is a class template declaration/specialization - auto parent_class = diagram_.find(*id_opt); + auto parent_class = diagram().find(*id_opt); c.set_namespace(parent_ns); const auto cls_name = cls->getNameAsString(); @@ -963,102 +949,6 @@ void translation_unit_visitor::process_class_declaration( c.complete(true); } -bool translation_unit_visitor::process_template_parameters( - const clang::TemplateDecl &template_declaration, - common::model::template_trait &c, - common::optional_ref templated_element) -{ - LOG_DBG("Processing {} template parameters...", - common::get_qualified_name(template_declaration)); - - if (template_declaration.getTemplateParameters() == nullptr) - return false; - - for (const auto *parameter : - *template_declaration.getTemplateParameters()) { - if (clang::dyn_cast_or_null(parameter) != - nullptr) { - const auto *template_type_parameter = - clang::dyn_cast_or_null(parameter); - - std::optional default_arg; - if (template_type_parameter->hasDefaultArgument()) { - default_arg = - template_type_parameter->getDefaultArgument().getAsString(); - } - - auto parameter_name = template_type_parameter->getNameAsString(); - if (parameter_name.empty()) - parameter_name = "typename"; - - auto ct = template_parameter::make_template_type(parameter_name, - default_arg, template_type_parameter->isParameterPack()); - - if (template_type_parameter->getTypeConstraint() != nullptr) { - util::if_not_null(template_type_parameter->getTypeConstraint() - ->getNamedConcept(), - [this, &ct, &templated_element]( - const clang::ConceptDecl *named_concept) mutable { - ct.set_concept_constraint( - named_concept->getQualifiedNameAsString()); - if (templated_element && - should_include(named_concept)) { - templated_element.value().add_relationship( - {relationship_t::kConstraint, - id_mapper() - .get_global_id(named_concept->getID()) - .value(), - access_t::kNone, ct.name().value()}); - } - }); - } - - c.add_template(std::move(ct)); - } - else if (clang::dyn_cast_or_null( - parameter) != nullptr) { - const auto *template_nontype_parameter = - clang::dyn_cast_or_null( - parameter); - - std::optional default_arg; - - if (template_nontype_parameter->hasDefaultArgument()) - default_arg = common::to_string( - template_nontype_parameter->getDefaultArgument()); - - auto ct = template_parameter::make_non_type_template( - template_nontype_parameter->getType().getAsString(), - template_nontype_parameter->getNameAsString(), default_arg, - template_nontype_parameter->isParameterPack()); - - c.add_template(std::move(ct)); - } - else if (clang::dyn_cast_or_null( - parameter) != nullptr) { - const auto *template_template_parameter = - clang::dyn_cast_or_null( - parameter); - std::optional default_arg; - if (template_template_parameter->hasDefaultArgument()) { - default_arg = common::to_string( - template_template_parameter->getDefaultArgument() - .getArgument()); - } - auto ct = template_parameter::make_template_template_type( - template_template_parameter->getNameAsString(), default_arg, - template_template_parameter->isParameterPack()); - - c.add_template(std::move(ct)); - } - else { - // pass - } - } - - return false; -} - void translation_unit_visitor::process_class_bases( const clang::CXXRecordDecl *cls, class_ &c) { @@ -1074,7 +964,8 @@ void translation_unit_visitor::process_class_bases( tsp != nullptr) { auto template_specialization_ptr = std::make_unique(config().using_namespace()); - tbuilder().build(*template_specialization_ptr, cls, *tsp, {}); + tbuilder().build_from_template_specialization_type( + *template_specialization_ptr, cls, *tsp, {}); cp.set_id(template_specialization_ptr->id()); cp.set_name(template_specialization_ptr->full_name(false)); @@ -1330,7 +1221,8 @@ void translation_unit_visitor::process_method( if (unaliased_type != nullptr) { auto template_specialization_ptr = std::make_unique(config().using_namespace()); - tbuilder().build(*template_specialization_ptr, + tbuilder().build_from_template_specialization_type( + *template_specialization_ptr, unaliased_type->getTemplateName().getAsTemplateDecl(), *unaliased_type, &c); @@ -1476,14 +1368,13 @@ void translation_unit_visitor::process_template_method( // Is there a better way to do this? method_name = method_name.substr(0, method_name.find('<')); } - util::if_not_null( clang::dyn_cast(mf.getTemplatedDecl()), [&](const auto *decl) { process_method_properties(*decl, c, method_name, method); }); - process_template_parameters(mf, method); + tbuilder().build_from_template_declaration(method, mf); process_comment(mf, method); @@ -1705,7 +1596,8 @@ void translation_unit_visitor::process_function_parameter( templ != nullptr) { auto template_specialization_ptr = std::make_unique(config().using_namespace()); - tbuilder().build(*template_specialization_ptr, + tbuilder().build_from_template_specialization_type( + *template_specialization_ptr, templ->getTemplateName().getAsTemplateDecl(), *templ, &c); if (diagram().should_include(*template_specialization_ptr)) { @@ -1933,7 +1825,8 @@ void translation_unit_visitor::process_field( // Build the template instantiation for the field type auto template_specialization_ptr = std::make_unique(config().using_namespace()); - tbuilder().build(*template_specialization_ptr, + tbuilder().build_from_template_specialization_type( + *template_specialization_ptr, field_type->getAs() ->getTemplateName() .getAsTemplateDecl(), @@ -2100,25 +1993,6 @@ void translation_unit_visitor::extract_constrained_template_param_name( } } -bool translation_unit_visitor::should_include(const clang::NamedDecl *decl) -{ - if (decl == nullptr) - return false; - - if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin())) - return false; - - auto should_include_namespace = - diagram().should_include(namespace_{decl->getQualifiedNameAsString()}); - - const auto decl_file = decl->getLocation().printToString(source_manager()); - - const auto should_include_decl_file = - diagram().should_include(common::model::source_file{decl_file}); - - return should_include_namespace && should_include_decl_file; -} - void translation_unit_visitor::add_processed_template_class( std::string qualified_name) { diff --git a/src/class_diagram/visitor/translation_unit_visitor.h b/src/class_diagram/visitor/translation_unit_visitor.h index ac96229b..f7fbd525 100644 --- a/src/class_diagram/visitor/translation_unit_visitor.h +++ b/src/class_diagram/visitor/translation_unit_visitor.h @@ -54,6 +54,10 @@ using clanguml::common::model::template_trait; using clanguml::common::visitor::found_relationships_t; using clanguml::common::visitor::template_builder; +using visitor_specialization_t = + common::visitor::translation_unit_visitor; + /** * @brief Class diagram translation unit visitor * @@ -62,8 +66,13 @@ using clanguml::common::visitor::template_builder; */ class translation_unit_visitor : public clang::RecursiveASTVisitor, - public common::visitor::translation_unit_visitor { + public visitor_specialization_t { public: + using visitor_specialization_t::config_t; + using visitor_specialization_t::diagram_t; + + using template_builder_t = template_builder; + /** * @brief Constructor. * @@ -102,30 +111,6 @@ public: virtual bool TraverseConceptDecl(clang::ConceptDecl *cpt); /** @} */ - /** - * @brief Get diagram model reference - * - * @return Reference to diagram model created by the visitor - */ - clanguml::class_diagram::model::diagram &diagram() { return diagram_; } - - /** - * @brief Get diagram model reference - * - * @return Reference to diagram model created by the visitor - */ - const clanguml::class_diagram::model::diagram &diagram() const - { - return diagram_; - } - - /** - * @brief Get diagram config instance - * - * @return Reference to config instance - */ - const clanguml::config::class_diagram &config() const { return config_; } - /** * @brief Finalize diagram model * @@ -157,15 +142,16 @@ public: */ void add_concept(std::unique_ptr &&c); -private: - /** - * @brief Check if the diagram should include a declaration. - * - * @param decl Clang declaration. - * @return True, if the entity should be included in the diagram. - */ - bool should_include(const clang::NamedDecl *decl); + void add_diagram_element( + std::unique_ptr element) override; + std::unique_ptr create_element(const clang::NamedDecl *decl) const; + + void find_instantiation_relationships( + common::model::template_element &template_instantiation_base, + const std::string &full_name, common::id_t templated_decl_id); + +private: /** * @brief Create class element model from class declaration * @@ -244,20 +230,6 @@ private: void process_template_specialization_children( const clang::ClassTemplateSpecializationDecl *cls, class_ &c); - /** - * @brief Process template parameters - * - * @param template_declaration Template declaration - * @param t `template_trait` instance to which the parameters should be - * added - * @param templated_element Optional templated diagram element (e.g. class_) - * @return Ignored - */ - bool process_template_parameters( - const clang::TemplateDecl &template_declaration, - clanguml::common::model::template_trait &t, - common::optional_ref templated_element = {}); - /** * @brief Process class method * @@ -451,27 +423,14 @@ private: */ bool has_processed_template_class(const std::string &qualified_name) const; - void add_diagram_element( - std::unique_ptr element) override; - - void find_instantiation_relationships( - common::model::template_element &template_instantiation_base, - const std::string &full_name, common::id_t templated_decl_id); - /** * @brief Get template builder reference * * @return Reference to 'template_builder' instance */ - template_builder &tbuilder() { return template_builder_; } + template_builder_t &tbuilder() { return template_builder_; } - // Reference to the output diagram model - clanguml::class_diagram::model::diagram &diagram_; - - // Reference to class diagram config - const clanguml::config::class_diagram &config_; - - template_builder template_builder_; + template_builder_t template_builder_; std::map> diff --git a/src/common/visitor/template_builder.cc b/src/common/visitor/template_builder.cc index eee5ed7c..1b232357 100644 --- a/src/common/visitor/template_builder.cc +++ b/src/common/visitor/template_builder.cc @@ -18,535 +18,9 @@ #include "template_builder.h" #include "common/clang_utils.h" -#include "translation_unit_visitor.h" #include namespace clanguml::common::visitor { - -template_builder::template_builder(clanguml::common::model::diagram &diagram_, - const clanguml::config::diagram &config_, - clanguml::common::visitor::translation_unit_visitor &visitor, - element_factory_t element_factory, - find_instantiation_relationships_t find_instantiation_relationships, - on_argument_base_found_t on_argument_base_found) - : diagram_{diagram_} - , config_{config_} - , id_mapper_{visitor.id_mapper()} - , source_manager_{visitor.source_manager()} - , visitor_{visitor} - , element_factory_{std::move(element_factory)} - , find_instantiation_relationships_{std::move( - find_instantiation_relationships)} - , on_argument_base_found_{std::move(on_argument_base_found)} -{ -} - -common::model::diagram &template_builder::diagram() { return diagram_; } - -const config::diagram &template_builder::config() const { return config_; } - -const namespace_ &template_builder::using_namespace() const -{ - return config_.using_namespace(); -} - -common::visitor::ast_id_mapper &template_builder::id_mapper() -{ - return id_mapper_; -} - -clang::SourceManager &template_builder::source_manager() const -{ - return source_manager_; -} - -bool template_builder::simplify_system_template( - template_parameter &ct, const std::string &full_name) const -{ - auto simplified = config().simplify_template_type(full_name); - - if (simplified != full_name) { - ct.set_type(simplified); - ct.set_id(common::to_id(simplified)); - ct.clear_params(); - return true; - } - - return false; -} - -void template_builder::build( - clanguml::common::model::template_element &template_instantiation, - const clang::NamedDecl *cls, - const clang::TemplateSpecializationType &template_type_decl, - std::optional parent) -{ - // - // Here we'll hold the template base class params to replace with the - // instantiated values - // - std::deque> - template_base_params{}; - - const auto *template_type_ptr = &template_type_decl; - - if (template_type_decl.isTypeAlias()) { - if (const auto *tsp = - template_type_decl.getAliasedType() - ->template getAs(); - tsp != nullptr) - template_type_ptr = tsp; - } - - const auto &template_type = *template_type_ptr; - - template_instantiation.is_template(true); - - std::string full_template_specialization_name = common::to_string( - template_type.desugar(), - template_type.getTemplateName().getAsTemplateDecl()->getASTContext()); - - auto *template_decl{template_type.getTemplateName().getAsTemplateDecl()}; - - auto template_decl_qualified_name = - template_decl->getQualifiedNameAsString(); - - auto *class_template_decl{ - clang::dyn_cast(template_decl)}; - - if ((class_template_decl != nullptr) && - (class_template_decl->getTemplatedDecl() != nullptr) && - (class_template_decl->getTemplatedDecl()->getParent() != nullptr) && - class_template_decl->getTemplatedDecl()->getParent()->isRecord()) { - - namespace_ ns{ - common::get_tag_namespace(*class_template_decl->getTemplatedDecl() - ->getParent() - ->getOuterLexicalRecordContext())}; - - std::string ns_str = ns.to_string(); - std::string name = template_decl->getQualifiedNameAsString(); - if (!ns_str.empty()) { - name = name.substr(ns_str.size() + 2); - } - - util::replace_all(name, "::", "##"); - template_instantiation.set_name(name); - - template_instantiation.set_namespace(ns); - } - else { - namespace_ ns{template_decl_qualified_name}; - ns.pop_back(); - template_instantiation.set_name(template_decl->getNameAsString()); - template_instantiation.set_namespace(ns); - } - - // TODO: Refactor handling of base parameters to a separate method - - // We need this to match any possible base classes coming from template - // arguments - std::vector< - std::pair> - template_parameter_names{}; - - for (const auto *parameter : *template_decl->getTemplateParameters()) { - if (parameter->isTemplateParameter() && - (parameter->isTemplateParameterPack() || - parameter->isParameterPack())) { - template_parameter_names.emplace_back( - parameter->getNameAsString(), true); - } - else - template_parameter_names.emplace_back( - parameter->getNameAsString(), false); - } - - // Check if the primary template has any base classes - int base_index = 0; - - const auto *templated_class_decl = - clang::dyn_cast_or_null( - template_decl->getTemplatedDecl()); - - if ((templated_class_decl != nullptr) && - templated_class_decl->hasDefinition()) - for (const auto &base : templated_class_decl->bases()) { - const auto base_class_name = common::to_string( - base.getType(), templated_class_decl->getASTContext(), false); - - LOG_DBG("Found template instantiation base: {}, {}", - base_class_name, base_index); - - // Check if any of the primary template arguments has a - // parameter equal to this type - auto it = std::find_if(template_parameter_names.begin(), - template_parameter_names.end(), - [&base_class_name]( - const auto &p) { return p.first == base_class_name; }); - - if (it != template_parameter_names.end()) { - const auto ¶meter_name = it->first; - const bool is_variadic = it->second; - // Found base class which is a template parameter - LOG_DBG("Found base class which is a template parameter " - "{}, {}, {}", - parameter_name, is_variadic, - std::distance(template_parameter_names.begin(), it)); - - template_base_params.emplace_back(parameter_name, - std::distance(template_parameter_names.begin(), it), - is_variadic); - } - else { - // This is a regular base class - it is handled by - // process_template - } - base_index++; - } - - process_template_arguments(parent, cls, template_base_params, - template_type.template_arguments(), template_instantiation, - template_decl); - - find_instantiation_relationships(template_instantiation, - template_type.getTemplateName().getAsTemplateDecl()->getID(), - full_template_specialization_name); - - template_instantiation.set_id( - common::to_id(template_instantiation.full_name(false))); - - visitor_.set_source_location(*cls, template_instantiation); -} - -void template_builder::build_from_class_template_specialization( - clanguml::common::model::template_element &template_instantiation, - const clang::ClassTemplateSpecializationDecl &template_specialization, - std::optional parent) -{ - // - // Here we'll hold the template base params to replace with the - // instantiated values - // - std::deque> - template_base_params{}; - - const clang::ClassTemplateDecl *template_decl = - template_specialization.getSpecializedTemplate(); - - auto qualified_name = template_decl->getQualifiedNameAsString(); - - namespace_ ns{qualified_name}; - ns.pop_back(); - template_instantiation.set_name(template_decl->getNameAsString()); - template_instantiation.set_namespace(ns); - - process_template_arguments(parent, &template_specialization, - template_base_params, - template_specialization.getTemplateArgs().asArray(), - template_instantiation, template_decl); - - // Update the id after the template parameters are processed - template_instantiation.set_id( - common::to_id(template_instantiation.full_name(false))); - - find_instantiation_relationships(template_instantiation, - template_specialization.getID(), qualified_name); - - visitor_.set_source_location(*template_decl, template_instantiation); -} - -void template_builder::find_instantiation_relationships( - common::model::template_element &template_instantiation, common::id_t id, - const std::string &qualified_name) const -{ - if (find_instantiation_relationships_) { - find_instantiation_relationships_( - template_instantiation, qualified_name, id); - } -} - -void template_builder::process_template_arguments( - std::optional &parent, - const clang::NamedDecl *cls, - std::deque> &template_base_params, - const clang::ArrayRef &template_args, - clanguml::common::model::template_element &template_instantiation, - const clang::TemplateDecl *template_decl) -{ - auto arg_index{0}; - - for (const auto &arg : template_args) { - // Argument can be a parameter pack in which case it gives multiple - // arguments - std::vector arguments; - - // For now ignore the default template arguments of templates which - // do not match the inclusion filters, to make the system - // templates 'nicer' - i.e. skipping the allocators and comparators - // TODO: Change this to ignore only when the arguments are set to - // default values, and add them when they are specifically - // overridden - if (!diagram().should_include( - namespace_{template_decl->getQualifiedNameAsString()})) { - const auto *maybe_type_parm_decl = - clang::dyn_cast( - template_decl->getTemplateParameters()->getParam( - std::min(arg_index, - static_cast( - template_decl->getTemplateParameters() - ->size()) - - 1))); - if (maybe_type_parm_decl != nullptr && - maybe_type_parm_decl->hasDefaultArgument()) { - continue; - } - } - - // - // Handle the template parameter/argument based on its kind - // - argument_process_dispatch(parent, cls, template_instantiation, - template_decl, arg, arg_index, arguments); - - if (arguments.empty()) { - arg_index++; - continue; - } - - // We can figure this only when we encounter variadic param in - // the list of template params, from then this variable is true - // and we can process following template parameters as belonging - // to the variadic tuple - [[maybe_unused]] auto variadic_params{false}; - - // In case any of the template arguments are base classes, add - // them as parents of the current template instantiation class - if (!template_base_params.empty()) { - variadic_params = - add_base_classes(template_instantiation, template_base_params, - arg_index, variadic_params, arguments.front()); - } - - for (auto &argument : arguments) { - simplify_system_template( - argument, argument.to_string(using_namespace(), false, true)); - - LOG_DBG("Adding template argument {} to template " - "specialization/instantiation {}", - argument.to_string(using_namespace(), false), - template_instantiation.name()); - - template_instantiation.add_template(std::move(argument)); - } - - arg_index++; - } - - // Update id - template_instantiation.set_id( - common::to_id(template_instantiation.full_name(false))); -} - -void template_builder::argument_process_dispatch( - std::optional &parent, - const clang::NamedDecl *cls, - clanguml::common::model::template_element &template_instantiation, - const clang::TemplateDecl *template_decl, - const clang::TemplateArgument &arg, size_t argument_index, - std::vector &argument) -{ - LOG_DBG("Processing argument {} in template class: {}", argument_index, - cls->getQualifiedNameAsString()); - - switch (arg.getKind()) { - case clang::TemplateArgument::Null: - argument.push_back(process_null_argument(arg)); - break; - case clang::TemplateArgument::Template: - argument.push_back(process_template_argument(arg)); - break; - case clang::TemplateArgument::Type: { - argument.push_back(process_type_argument(parent, cls, template_decl, - arg.getAsType(), template_instantiation, argument_index)); - break; - } - case clang::TemplateArgument::Declaration: - break; - case clang::TemplateArgument::NullPtr: - argument.push_back(process_nullptr_argument(arg)); - break; - case clang::TemplateArgument::Integral: - argument.push_back(process_integral_argument(arg)); - break; - case clang::TemplateArgument::TemplateExpansion: - argument.push_back(process_template_expansion(arg)); - break; - case clang::TemplateArgument::Expression: - argument.push_back(process_expression_argument(arg)); - break; - case clang::TemplateArgument::Pack: - for (auto &a : - process_pack_argument(parent, cls, template_instantiation, - template_decl, arg, argument_index, argument)) { - argument.push_back(a); - } - break; - } -} - -template_parameter template_builder::process_template_argument( - const clang::TemplateArgument &arg) -{ - auto arg_name = common::to_string(arg); - - LOG_DBG("Processing template argument: {}", arg_name); - - return template_parameter::make_template_type(arg_name); -} - -template_parameter template_builder::process_template_expansion( - const clang::TemplateArgument &arg) -{ - auto arg_name = common::to_string(arg); - - LOG_DBG("Processing template expansion argument: {}", arg_name); - - util::if_not_null( - arg.getAsTemplate().getAsTemplateDecl(), [&arg_name](const auto *decl) { - arg_name = decl->getQualifiedNameAsString(); - }); - - auto param = template_parameter::make_template_type(arg_name); - param.is_variadic(true); - - return param; -} - -clang::QualType template_builder::consume_context( - clang::QualType type, template_parameter &tp) const -{ - auto [unqualified_type, context] = common::consume_type_context(type); - - tp.deduced_context(std::move(context)); - - return unqualified_type; -} - -template_parameter template_builder::process_type_argument( - std::optional &parent, - const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, - clang::QualType type, - clanguml::common::model::template_element &template_instantiation, - size_t argument_index) -{ - std::optional argument; - - if (type->getAs() != nullptr) { - type = type->getAs()->getNamedType(); // NOLINT - } - - auto type_name = common::to_string(type, &cls->getASTContext()); - - LOG_DBG("Processing template {} type argument {}: {}, {}, {}", - template_decl->getQualifiedNameAsString(), argument_index, type_name, - type->getTypeClassName(), - common::to_string(type, cls->getASTContext())); - - argument = try_as_function_prototype(parent, cls, template_decl, type, - template_instantiation, argument_index); - if (argument) - return *argument; - - argument = try_as_member_pointer(parent, cls, template_decl, type, - template_instantiation, argument_index); - if (argument) - return *argument; - - argument = try_as_array(parent, cls, template_decl, type, - template_instantiation, argument_index); - if (argument) - return *argument; - - argument = try_as_template_parm_type(cls, template_decl, type); - if (argument) - return *argument; - - argument = try_as_template_specialization_type(parent, cls, template_decl, - type, template_instantiation, argument_index); - if (argument) - return *argument; - - argument = try_as_decl_type(parent, cls, template_decl, type, - template_instantiation, argument_index); - if (argument) - return *argument; - - argument = try_as_typedef_type(parent, cls, template_decl, type, - template_instantiation, argument_index); - if (argument) - return *argument; - - argument = try_as_lambda(cls, template_decl, type); - if (argument) - return *argument; - - argument = try_as_record_type(parent, cls, template_decl, type, - template_instantiation, argument_index); - if (argument) - return *argument; - - argument = try_as_enum_type( - parent, cls, template_decl, type, template_instantiation); - if (argument) - return *argument; - - argument = try_as_builtin_type(parent, type, template_decl); - if (argument) - return *argument; - - // fallback - return template_parameter::make_argument(type_name); -} - -bool template_builder::find_relationships_in_unexposed_template_params( - const template_parameter &ct, found_relationships_t &relationships) -{ - const auto &type = ct.type(); - - if (!type) - return false; - - bool found{false}; - LOG_DBG("Finding relationships in user defined type: {}", - ct.to_string(config().using_namespace(), false)); - - auto type_with_namespace = - std::make_optional(type.value()); - - if (!type_with_namespace.has_value()) { - // Couldn't find declaration of this type - type_with_namespace = common::model::namespace_{type.value()}; - } - - auto element_opt = diagram().get(type_with_namespace.value().to_string()); - if (config_.generate_template_argument_dependencies() && element_opt) { - relationships.emplace_back( - element_opt.value().id(), relationship_t::kDependency); - found = true; - } - - for (const auto &nested_template_params : ct.template_params()) { - found = find_relationships_in_unexposed_template_params( - nested_template_params, relationships) || - found; - } - - return found; -} - namespace detail { std::string map_type_parameter_to_template_parameter( @@ -609,598 +83,4 @@ std::string map_type_parameter_to_template_parameter_name( return type_parameter; } -template_parameter template_builder::process_integral_argument( - const clang::TemplateArgument &arg) -{ - assert(arg.getKind() == clang::TemplateArgument::Integral); - - std::string result; - llvm::raw_string_ostream ostream(result); - arg.dump(ostream); - - return template_parameter::make_argument(result); -} - -template_parameter template_builder::process_null_argument( - const clang::TemplateArgument &arg) -{ - assert(arg.getKind() == clang::TemplateArgument::Null); - - return template_parameter::make_argument(""); -} - -template_parameter template_builder::process_nullptr_argument( - const clang::TemplateArgument &arg) -{ - assert(arg.getKind() == clang::TemplateArgument::NullPtr); - - LOG_DBG("Processing nullptr argument: {}", common::to_string(arg)); - - return template_parameter::make_argument("nullptr"); -} - -template_parameter template_builder::process_expression_argument( - const clang::TemplateArgument &arg) -{ - assert(arg.getKind() == clang::TemplateArgument::Expression); - return template_parameter::make_argument(common::get_source_text( - arg.getAsExpr()->getSourceRange(), source_manager())); -} - -std::vector template_builder::process_pack_argument( - std::optional &parent, - const clang::NamedDecl *cls, - clanguml::common::model::template_element &template_instantiation, - const clang::TemplateDecl *base_template_decl, - const clang::TemplateArgument &arg, size_t argument_index, - std::vector & /*argument*/) -{ - assert(arg.getKind() == clang::TemplateArgument::Pack); - - std::vector res; - - auto pack_argument_index = argument_index; - - for (const auto &a : arg.getPackAsArray()) { - argument_process_dispatch(parent, cls, template_instantiation, - base_template_decl, a, pack_argument_index++, res); - } - - return res; -} - -std::optional template_builder::try_as_member_pointer( - std::optional &parent, - const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, - clang::QualType &type, - clanguml::common::model::template_element &template_instantiation, - size_t argument_index) -{ - const auto *mp_type = - common::dereference(type)->getAs(); - if (mp_type == nullptr) - return {}; - - auto argument = template_parameter::make_template_type(""); - type = consume_context(type, argument); - - // Handle a pointer to a data member of a class - if (mp_type->isMemberDataPointer()) { - argument.is_member_pointer(false); - argument.is_data_pointer(true); - - auto pointee_arg = process_type_argument(parent, cls, template_decl, - mp_type->getPointeeType(), template_instantiation, argument_index); - - argument.add_template_param(std::move(pointee_arg)); - - const auto *member_class_type = mp_type->getClass(); - - if (member_class_type == nullptr) - return {}; - - auto class_type_arg = process_type_argument(parent, cls, template_decl, - mp_type->getClass()->getCanonicalTypeUnqualified(), - template_instantiation, argument_index); - - argument.add_template_param(std::move(class_type_arg)); - } - // Handle pointer to class method member - else { - argument.is_member_pointer(true); - argument.is_data_pointer(false); - - const auto *function_type = - mp_type->getPointeeType()->getAs(); - - assert(function_type != nullptr); - - auto return_type_arg = process_type_argument(parent, cls, template_decl, - function_type->getReturnType(), template_instantiation, - argument_index); - - // Add return type argument - argument.add_template_param(std::move(return_type_arg)); - - const auto *member_class_type = mp_type->getClass(); - - if (member_class_type == nullptr) - return {}; - - auto class_type_arg = process_type_argument(parent, cls, template_decl, - mp_type->getClass()->getCanonicalTypeUnqualified(), - template_instantiation, argument_index); - - // Add class type argument - argument.add_template_param(std::move(class_type_arg)); - - // Add argument types - for (const auto ¶m_type : function_type->param_types()) { - argument.add_template_param( - process_type_argument(parent, cls, template_decl, param_type, - template_instantiation, argument_index)); - } - } - - return argument; -} - -std::optional template_builder::try_as_array( - std::optional &parent, - const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, - clang::QualType &type, - clanguml::common::model::template_element &template_instantiation, - size_t argument_index) -{ - const auto *array_type = common::dereference(type)->getAsArrayTypeUnsafe(); - if (array_type == nullptr) - return {}; - - auto argument = template_parameter::make_template_type(""); - - type = consume_context(type, argument); - - argument.is_array(true); - - // Set function template return type - auto element_type = process_type_argument(parent, cls, template_decl, - array_type->getElementType(), template_instantiation, argument_index); - - argument.add_template_param(element_type); - - if (array_type->isDependentSizedArrayType() && - array_type->getDependence() == - clang::TypeDependence::DependentInstantiation) { - argument.add_template_param( - template_parameter::make_template_type(common::to_string( - ((clang::DependentSizedArrayType *)array_type) // NOLINT - ->getSizeExpr()))); - } - else if (array_type->isConstantArrayType()) { - argument.add_template_param(template_parameter::make_argument( - std::to_string(((clang::ConstantArrayType *)array_type) // NOLINT - ->getSize() - .getLimitedValue()))); - } - - // TODO: Handle variable sized arrays - - return argument; -} - -std::optional template_builder::try_as_function_prototype( - std::optional &parent, - const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, - clang::QualType &type, - clanguml::common::model::template_element &template_instantiation, - size_t argument_index) -{ - const auto *function_type = type->getAs(); - - if (function_type == nullptr && type->isFunctionPointerType()) { - function_type = - type->getPointeeType()->getAs(); - if (function_type == nullptr) - return {}; - } - - if (function_type == nullptr) - return {}; - - LOG_DBG("Template argument is a function prototype"); - - auto argument = template_parameter::make_template_type(""); - - type = consume_context(type, argument); - - argument.is_function_template(true); - - // Set function template return type - auto return_arg = process_type_argument(parent, cls, template_decl, - function_type->getReturnType(), template_instantiation, argument_index); - - argument.add_template_param(return_arg); - - // Set function template argument types - if (function_type->isVariadic() && function_type->param_types().empty()) { - auto fallback_arg = template_parameter::make_argument({}); - fallback_arg.is_ellipsis(true); - argument.add_template_param(std::move(fallback_arg)); - } - else { - for (const auto ¶m_type : function_type->param_types()) { - argument.add_template_param( - process_type_argument(parent, cls, template_decl, param_type, - template_instantiation, argument_index)); - } - } - - return argument; -} - -std::optional template_builder::try_as_decl_type( - std::optional & /*parent*/, - const clang::NamedDecl * /*cls*/, - const clang::TemplateDecl * /*template_decl*/, clang::QualType &type, - clanguml::common::model::template_element & /*template_instantiation*/, - size_t /*argument_index*/) -{ - const auto *decl_type = - common::dereference(type)->getAs(); - if (decl_type == nullptr) { - return {}; - } - - LOG_DBG("Template argument is a decltype()"); - - // TODO - return {}; -} - -std::optional template_builder::try_as_typedef_type( - std::optional &parent, - const clang::NamedDecl * /*cls*/, - const clang::TemplateDecl * /*template_decl*/, clang::QualType &type, - clanguml::common::model::template_element & /*template_instantiation*/, - size_t /*argument_index*/) -{ - const auto *typedef_type = - common::dereference(type)->getAs(); - if (typedef_type == nullptr) { - return {}; - } - - LOG_DBG("Template argument is a typedef/using"); - - // If this is a typedef/using alias to a decltype - we're not able - // to figure out anything out of it probably - if (typedef_type->getAs() != nullptr) { - // Here we need to figure out the parent context of this alias, - // it can be a: - // - class/struct - if (typedef_type->getDecl()->isCXXClassMember() && parent) { - return template_parameter::make_argument( - fmt::format("{}::{}", parent.value()->full_name(false), - typedef_type->getDecl()->getNameAsString())); - } - // - namespace - return template_parameter::make_argument( - typedef_type->getDecl()->getQualifiedNameAsString()); - } - - return {}; -} - -std::optional -template_builder::try_as_template_specialization_type( - std::optional &parent, - const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, - clang::QualType &type, - clanguml::common::model::template_element &template_instantiation, - size_t argument_index) -{ - const auto *nested_template_type = - common::dereference(type)->getAs(); - if (nested_template_type == nullptr) { - return {}; - } - - LOG_DBG("Template argument is a template specialization type"); - - auto argument = template_parameter::make_argument(""); - type = consume_context(type, argument); - - auto nested_type_name = nested_template_type->getTemplateName() - .getAsTemplateDecl() - ->getQualifiedNameAsString(); - - if (clang::dyn_cast( - nested_template_type->getTemplateName().getAsTemplateDecl()) != - nullptr) { - if (const auto *template_specialization_decl = - clang::dyn_cast(cls); - template_specialization_decl != nullptr) { - nested_type_name = - template_specialization_decl->getDescribedTemplateParams() - ->getParam(argument_index) - ->getNameAsString(); - } - else { - // fallback - nested_type_name = "template"; - } - - argument.is_template_template_parameter(true); - } - - argument.set_type(nested_type_name); - - auto nested_template_instantiation = - element_factory_(nested_template_type->getTemplateName() - .getAsTemplateDecl() - ->getTemplatedDecl()); - build(*nested_template_instantiation, cls, *nested_template_type, - diagram().should_include( - namespace_{template_decl->getQualifiedNameAsString()}) - ? std::make_optional(&template_instantiation) - : parent); - - argument.set_id(nested_template_instantiation->id()); - - for (const auto &t : nested_template_instantiation->template_params()) - argument.add_template_param(t); - - // Check if this template should be simplified (e.g. system - // template aliases such as 'std:basic_string' should - // be simply 'std::string') - simplify_system_template( - argument, argument.to_string(using_namespace(), false)); - - argument.set_id( - common::to_id(argument.to_string(using_namespace(), false))); - - const auto nested_template_instantiation_full_name = - nested_template_instantiation->full_name(false); - - if (nested_template_instantiation && - diagram().should_include( - namespace_{nested_template_instantiation_full_name})) { - if (config_.generate_template_argument_dependencies()) { - if (diagram().should_include( - namespace_{template_decl->getQualifiedNameAsString()})) { - template_instantiation.add_relationship( - {relationship_t::kDependency, - nested_template_instantiation->id()}); - } - else { - if (parent.has_value()) - parent.value()->add_relationship( - {relationship_t::kDependency, - nested_template_instantiation->id()}); - } - } - } - - if (diagram().should_include( - namespace_{nested_template_instantiation_full_name})) { - visitor_.set_source_location(*cls, *nested_template_instantiation); - visitor_.add_diagram_element(std::move(nested_template_instantiation)); - } - - return argument; -} - -std::optional template_builder::try_as_template_parm_type( - const clang::NamedDecl *cls, const clang::TemplateDecl * /*template_decl*/, - clang::QualType &type) -{ - auto is_variadic{false}; - - const auto *type_parameter = - common::dereference(type)->getAs(); - - auto type_name = common::to_string(type, &cls->getASTContext()); - - if (type_parameter == nullptr) { - if (const auto *pet = - common::dereference(type)->getAs(); - pet != nullptr) { - is_variadic = true; - type_parameter = - pet->getPattern()->getAs(); - } - } - - if (type_parameter == nullptr) - return {}; - - LOG_DBG("Template argument is a template parameter type"); - - auto argument = template_parameter::make_template_type(""); - type = consume_context(type, argument); - - auto type_parameter_name = common::to_string(type, cls->getASTContext()); - if (type_parameter_name.empty()) - type_parameter_name = "typename"; - - argument.set_name(map_type_parameter_to_template_parameter_name( - cls, type_parameter_name)); - - argument.is_variadic(is_variadic); - - common::ensure_lambda_type_is_relative(config(), type_parameter_name); - - return argument; -} - -std::optional template_builder::try_as_lambda( - const clang::NamedDecl *cls, const clang::TemplateDecl * /*template_decl*/, - clang::QualType &type) -{ - auto type_name = common::to_string(type, &cls->getASTContext()); - - if (type_name.find("(lambda at ") != 0) - return {}; - - LOG_DBG("Template argument is a lambda"); - - auto argument = template_parameter::make_argument(""); - type = consume_context(type, argument); - - common::ensure_lambda_type_is_relative(config(), type_name); - argument.set_type(type_name); - - return argument; -} - -std::optional template_builder::try_as_record_type( - std::optional &parent, - const clang::NamedDecl * /*cls*/, const clang::TemplateDecl *template_decl, - clang::QualType &type, - clanguml::common::model::template_element &template_instantiation, - size_t /*argument_index*/) -{ - const auto *record_type = - common::dereference(type)->getAs(); - if (record_type == nullptr) - return {}; - - LOG_DBG("Template argument is a c++ record"); - - auto argument = template_parameter::make_argument({}); - type = consume_context(type, argument); - - const auto type_name = config().simplify_template_type( - common::to_string(type, template_decl->getASTContext())); - - argument.set_type(type_name); - const auto type_id = common::to_id(type_name); - - argument.set_id(type_id); - - const auto *class_template_specialization = - clang::dyn_cast( - record_type->getAsRecordDecl()); - - if (class_template_specialization != nullptr) { - auto tag_argument = element_factory_(class_template_specialization); - - build_from_class_template_specialization( - *tag_argument, *class_template_specialization); - - if (tag_argument) { - argument.set_type(tag_argument->name_and_ns()); - for (const auto &p : tag_argument->template_params()) - argument.add_template_param(p); - for (auto &r : tag_argument->relationships()) { - template_instantiation.add_relationship(std::move(r)); - } - - if (config_.generate_template_argument_dependencies() && - diagram().should_include(tag_argument->get_namespace())) { - if (parent.has_value()) - parent.value()->add_relationship( - {relationship_t::kDependency, tag_argument->id()}); - visitor_.set_source_location(*template_decl, *tag_argument); - visitor_.add_diagram_element(std::move(tag_argument)); - } - } - } - else if (const auto *record_type_decl = record_type->getAsRecordDecl(); - record_type_decl != nullptr) { - if (config_.generate_template_argument_dependencies() && - diagram().should_include(namespace_{type_name})) { - // Add dependency relationship to the parent - // template - template_instantiation.add_relationship( - {relationship_t::kDependency, type_id}); - } - } - - return argument; -} - -std::optional template_builder::try_as_enum_type( - std::optional & /*parent*/, - const clang::NamedDecl * /*cls*/, const clang::TemplateDecl *template_decl, - clang::QualType &type, - clanguml::common::model::template_element &template_instantiation) -{ - const auto *enum_type = type->getAs(); - if (enum_type == nullptr) - return {}; - - LOG_DBG("Template argument is a an enum"); - - auto argument = template_parameter::make_argument({}); - type = consume_context(type, argument); - - auto type_name = common::to_string(type, template_decl->getASTContext()); - argument.set_type(type_name); - const auto type_id = common::to_id(type_name); - argument.set_id(type_id); - - if (enum_type->getAsTagDecl() != nullptr && - config_.generate_template_argument_dependencies()) { - template_instantiation.add_relationship( - {relationship_t::kDependency, type_id}); - } - - return argument; -} - -std::optional template_builder::try_as_builtin_type( - std::optional & /*parent*/, - clang::QualType &type, const clang::TemplateDecl *template_decl) -{ - const auto *builtin_type = type->getAs(); - if (builtin_type == nullptr) - return {}; - - LOG_DBG("Template argument is a builtin type"); - - auto type_name = common::to_string(type, template_decl->getASTContext()); - auto argument = template_parameter::make_argument(type_name); - - type = consume_context(type, argument); - argument.set_type(type_name); - - return argument; -} - -bool template_builder::add_base_classes( - clanguml::common::model::template_element &tinst, - std::deque> &template_base_params, - int arg_index, bool variadic_params, const template_parameter &ct) -{ - bool add_template_argument_as_base_class = false; - - if (variadic_params) { - add_template_argument_as_base_class = true; - } - else { - auto [arg_name, index, is_variadic] = template_base_params.front(); - - variadic_params = is_variadic; - if ((arg_index == index) || (is_variadic && arg_index >= index)) { - add_template_argument_as_base_class = true; - if (!is_variadic) { - // Don't remove the remaining variadic parameter - template_base_params.pop_front(); - } - } - } - - const auto maybe_id = ct.id(); - if (add_template_argument_as_base_class && maybe_id) { - LOG_DBG("Adding template argument as base class '{}'", - ct.to_string({}, false)); - if (on_argument_base_found_) - on_argument_base_found_( - tinst, maybe_id.value(), ct.to_string({}, false)); - } - - return variadic_params; -} - } // namespace clanguml::class_diagram::visitor diff --git a/src/common/visitor/template_builder.h b/src/common/visitor/template_builder.h index 25b00df9..a8f0f118 100644 --- a/src/common/visitor/template_builder.h +++ b/src/common/visitor/template_builder.h @@ -17,6 +17,7 @@ */ #pragma once +#include "class_diagram/model/diagram.h" #include "common/model/diagram.h" #include "common/model/template_element.h" #include "common/visitor/ast_id_mapper.h" @@ -32,35 +33,31 @@ using common::model::template_parameter; using found_relationships_t = std::vector< std::pair>; -class translation_unit_visitor; +namespace detail { + +std::string map_type_parameter_to_template_parameter( + const clang::ClassTemplateSpecializationDecl *decl, const std::string &tp); + +std::string map_type_parameter_to_template_parameter( + const clang::TypeAliasTemplateDecl *decl, const std::string &tp); + +} // namespace detail + +std::string map_type_parameter_to_template_parameter_name( + const clang::Decl *decl, const std::string &type_parameter); /** * @brief Class responsible for building all kinds of templates from Clang AST. */ -class template_builder { +template class template_builder { public: - using element_factory_t = - std::function( - const clang::NamedDecl *)>; - - using find_instantiation_relationships_t = std::function; - - using on_argument_base_found_t = - std::function; /** * @brief Constructor. * * @param visitor Reference to class diagram translation_unit_visitor */ template_builder(clanguml::common::model::diagram &diagram_, - const clanguml::config::diagram &config_, - clanguml::common::visitor::translation_unit_visitor &visitor, - element_factory_t element_factory, - find_instantiation_relationships_t find_instantiation_relationships = - {}, - on_argument_base_found_t on_argument_base_found = {}); + const clanguml::config::diagram &config_, VisitorT &visitor); /** * @brief Get reference to the current diagram model @@ -100,6 +97,11 @@ public: bool simplify_system_template( template_parameter &ct, const std::string &full_name) const; + void build_from_template_declaration( + clanguml::common::model::template_trait &template_model, + const clang::TemplateDecl &template_declaration, + common::optional_ref templated_element = {}); + /** * @brief Basic template class build method * @@ -108,12 +110,19 @@ public: * @param parent Optional class in which this template is contained * @return Created template class model */ - void build( + void build_from_template_specialization_type( clanguml::common::model::template_element &template_instantiation, const clang::NamedDecl *cls, const clang::TemplateSpecializationType &template_type_decl, std::optional parent = {}); + void build( + clanguml::common::model::template_element &template_instantiation, + const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, + const clang::ArrayRef template_arguments, + std::string full_template_specialization_name, + std::optional parent = {}); + /** * @brief Build template class from class template specialization decl * @@ -528,15 +537,1292 @@ private: clang::SourceManager &source_manager_; - clanguml::common::visitor::translation_unit_visitor &visitor_; - - element_factory_t element_factory_; - - find_instantiation_relationships_t find_instantiation_relationships_; - - // Callback to call when a template instantiation has arguments which are - // base classes, i.e. when template class inherits from template params - on_argument_base_found_t on_argument_base_found_; + VisitorT &visitor_; }; +template +template_builder::template_builder( + clanguml::common::model::diagram &diagram_, + const clanguml::config::diagram &config_, VisitorT &visitor) + : diagram_{diagram_} + , config_{config_} + , id_mapper_{visitor.id_mapper()} + , source_manager_{visitor.source_manager()} + , visitor_{visitor} +{ +} + +template +common::model::diagram &template_builder::diagram() +{ + return diagram_; +} + +template +const config::diagram &template_builder::config() const +{ + return config_; +} + +template +const namespace_ &template_builder::using_namespace() const +{ + return config_.using_namespace(); +} + +template +common::visitor::ast_id_mapper &template_builder::id_mapper() +{ + return id_mapper_; +} + +template +clang::SourceManager &template_builder::source_manager() const +{ + return source_manager_; +} + +template +bool template_builder::simplify_system_template( + template_parameter &ct, const std::string &full_name) const +{ + auto simplified = config().simplify_template_type(full_name); + + if (simplified != full_name) { + ct.set_type(simplified); + ct.set_id(common::to_id(simplified)); + ct.clear_params(); + return true; + } + + return false; +} + +template +void template_builder::build_from_template_declaration( + clanguml::common::model::template_trait &template_model, + const clang::TemplateDecl &template_declaration, + common::optional_ref templated_element) +{ + + LOG_DBG("Processing {} template parameters...", + common::get_qualified_name(template_declaration)); + + if (template_declaration.getTemplateParameters() == nullptr) + return; + + for (const auto *parameter : + *template_declaration.getTemplateParameters()) { + if (clang::dyn_cast_or_null(parameter) != + nullptr) { + const auto *template_type_parameter = + clang::dyn_cast_or_null(parameter); + + std::optional default_arg; + if (template_type_parameter->hasDefaultArgument()) { + default_arg = + template_type_parameter->getDefaultArgument().getAsString(); + } + + auto parameter_name = template_type_parameter->getNameAsString(); + if (parameter_name.empty()) + parameter_name = "typename"; + + auto ct = template_parameter::make_template_type(parameter_name, + default_arg, template_type_parameter->isParameterPack()); + + if constexpr (std::is_same_v) { + if (template_type_parameter->getTypeConstraint() != nullptr) { + util::if_not_null( + template_type_parameter->getTypeConstraint() + ->getNamedConcept(), + [this, &ct, &templated_element]( + const clang::ConceptDecl *named_concept) mutable { + ct.set_concept_constraint( + named_concept->getQualifiedNameAsString()); + if (templated_element && + visitor_.should_include(named_concept)) { + templated_element.value().add_relationship( + {relationship_t::kConstraint, + id_mapper() + .get_global_id( + named_concept->getID()) + .value(), + model::access_t::kNone, + ct.name().value()}); + } + }); + } + } + + template_model.add_template(std::move(ct)); + } + else if (clang::dyn_cast_or_null( + parameter) != nullptr) { + const auto *template_nontype_parameter = + clang::dyn_cast_or_null( + parameter); + + std::optional default_arg; + + if (template_nontype_parameter->hasDefaultArgument()) + default_arg = common::to_string( + template_nontype_parameter->getDefaultArgument()); + + auto ct = template_parameter::make_non_type_template( + template_nontype_parameter->getType().getAsString(), + template_nontype_parameter->getNameAsString(), default_arg, + template_nontype_parameter->isParameterPack()); + + template_model.add_template(std::move(ct)); + } + else if (clang::dyn_cast_or_null( + parameter) != nullptr) { + const auto *template_template_parameter = + clang::dyn_cast_or_null( + parameter); + std::optional default_arg; + if (template_template_parameter->hasDefaultArgument()) { + default_arg = common::to_string( + template_template_parameter->getDefaultArgument() + .getArgument()); + } + auto ct = template_parameter::make_template_template_type( + template_template_parameter->getNameAsString(), default_arg, + template_template_parameter->isParameterPack()); + + template_model.add_template(std::move(ct)); + } + else { + // pass + } + } +} + +template +void template_builder::build_from_template_specialization_type( + clanguml::common::model::template_element &template_instantiation, + const clang::NamedDecl *cls, + const clang::TemplateSpecializationType &template_type_decl, + std::optional parent) +{ + const auto *template_type_ptr = &template_type_decl; + + if (template_type_decl.isTypeAlias()) { + if (const auto *tsp = + template_type_decl.getAliasedType() + ->template getAs(); + tsp != nullptr) + template_type_ptr = tsp; + } + + const auto &template_type = *template_type_ptr; + + template_instantiation.is_template(true); + + std::string full_template_specialization_name = common::to_string( + template_type.desugar(), + template_type.getTemplateName().getAsTemplateDecl()->getASTContext()); + + auto *template_decl{template_type.getTemplateName().getAsTemplateDecl()}; + + build(template_instantiation, cls, template_decl, + template_type.template_arguments(), full_template_specialization_name, + parent); +} + +template +void template_builder::build( + clanguml::common::model::template_element &template_instantiation, + const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, + const clang::ArrayRef template_arguments, + std::string full_template_specialization_name, + std::optional parent) +{ + // + // Here we'll hold the template base class params to replace with the + // instantiated values + // + std::deque> + template_base_params{}; + + auto template_decl_qualified_name = + template_decl->getQualifiedNameAsString(); + + if (const auto *class_template_decl = + clang::dyn_cast(template_decl); + (class_template_decl != nullptr) && + (class_template_decl->getTemplatedDecl() != nullptr) && + (class_template_decl->getTemplatedDecl()->getParent() != nullptr) && + class_template_decl->getTemplatedDecl()->getParent()->isRecord()) { + + namespace_ ns{ + common::get_tag_namespace(*class_template_decl->getTemplatedDecl() + ->getParent() + ->getOuterLexicalRecordContext())}; + + std::string ns_str = ns.to_string(); + std::string name = template_decl->getQualifiedNameAsString(); + if (!ns_str.empty()) { + name = name.substr(ns_str.size() + 2); + } + + util::replace_all(name, "::", "##"); + template_instantiation.set_name(name); + + template_instantiation.set_namespace(ns); + } + else { + namespace_ ns{template_decl_qualified_name}; + ns.pop_back(); + template_instantiation.set_name(template_decl->getNameAsString()); + template_instantiation.set_namespace(ns); + } + + // TODO: Refactor handling of base parameters to a separate method + + // We need this to match any possible base classes coming from template + // arguments + std::vector< + std::pair> + template_parameter_names{}; + + for (const auto *parameter : *template_decl->getTemplateParameters()) { + if (parameter->isTemplateParameter() && + (parameter->isTemplateParameterPack() || + parameter->isParameterPack())) { + template_parameter_names.emplace_back( + parameter->getNameAsString(), true); + } + else + template_parameter_names.emplace_back( + parameter->getNameAsString(), false); + } + + // Check if the primary template has any base classes + int base_index = 0; + + const auto *templated_class_decl = + clang::dyn_cast_or_null( + template_decl->getTemplatedDecl()); + + if ((templated_class_decl != nullptr) && + templated_class_decl->hasDefinition()) + for (const auto &base : templated_class_decl->bases()) { + const auto base_class_name = common::to_string( + base.getType(), templated_class_decl->getASTContext(), false); + + LOG_DBG("Found template instantiation base: {}, {}", + base_class_name, base_index); + + // Check if any of the primary template arguments has a + // parameter equal to this type + auto it = std::find_if(template_parameter_names.begin(), + template_parameter_names.end(), + [&base_class_name]( + const auto &p) { return p.first == base_class_name; }); + + if (it != template_parameter_names.end()) { + const auto ¶meter_name = it->first; + const bool is_variadic = it->second; + // Found base class which is a template parameter + LOG_DBG("Found base class which is a template parameter " + "{}, {}, {}", + parameter_name, is_variadic, + std::distance(template_parameter_names.begin(), it)); + + template_base_params.emplace_back(parameter_name, + std::distance(template_parameter_names.begin(), it), + is_variadic); + } + else { + // This is a regular base class - it is handled by + // process_template + } + base_index++; + } + + process_template_arguments(parent, cls, template_base_params, + template_arguments, template_instantiation, template_decl); + + if constexpr (std::is_same_v) { + find_instantiation_relationships(template_instantiation, + template_decl->getID(), full_template_specialization_name); + } + + template_instantiation.set_id( + common::to_id(template_instantiation.full_name(false))); + + visitor_.set_source_location(*cls, template_instantiation); +} + +template +void template_builder::build_from_class_template_specialization( + clanguml::common::model::template_element &template_instantiation, + const clang::ClassTemplateSpecializationDecl &template_specialization, + std::optional parent) +{ + // + // Here we'll hold the template base params to replace with the + // instantiated values + // + std::deque> + template_base_params{}; + + const clang::ClassTemplateDecl *template_decl = + template_specialization.getSpecializedTemplate(); + + auto qualified_name = template_decl->getQualifiedNameAsString(); + + namespace_ ns{qualified_name}; + ns.pop_back(); + template_instantiation.set_name(template_decl->getNameAsString()); + template_instantiation.set_namespace(ns); + + process_template_arguments(parent, &template_specialization, + template_base_params, + template_specialization.getTemplateArgs().asArray(), + template_instantiation, template_decl); + + // Update the id after the template parameters are processed + template_instantiation.set_id( + common::to_id(template_instantiation.full_name(false))); + + if constexpr (std::is_same_v) { + find_instantiation_relationships(template_instantiation, + template_specialization.getID(), qualified_name); + } + + visitor_.set_source_location(*template_decl, template_instantiation); +} + +template +void template_builder::find_instantiation_relationships( + common::model::template_element &template_instantiation, common::id_t id, + const std::string &qualified_name) const +{ + visitor_.find_instantiation_relationships( + template_instantiation, qualified_name, id); +} + +template +void template_builder::process_template_arguments( + std::optional &parent, + const clang::NamedDecl *cls, + std::deque> &template_base_params, + const clang::ArrayRef &template_args, + clanguml::common::model::template_element &template_instantiation, + const clang::TemplateDecl *template_decl) +{ + auto arg_index{0}; + + for (const auto &arg : template_args) { + // Argument can be a parameter pack in which case it gives multiple + // arguments + std::vector arguments; + + // For now ignore the default template arguments of templates which + // do not match the inclusion filters, to make the system + // templates 'nicer' - i.e. skipping the allocators and comparators + // TODO: Change this to ignore only when the arguments are set to + // default values, and add them when they are specifically + // overridden + if (!diagram().should_include( + namespace_{template_decl->getQualifiedNameAsString()})) { + const auto *maybe_type_parm_decl = + clang::dyn_cast( + template_decl->getTemplateParameters()->getParam( + std::min(arg_index, + static_cast( + template_decl->getTemplateParameters() + ->size()) - + 1))); + if (maybe_type_parm_decl != nullptr && + maybe_type_parm_decl->hasDefaultArgument()) { + continue; + } + } + + // + // Handle the template parameter/argument based on its kind + // + argument_process_dispatch(parent, cls, template_instantiation, + template_decl, arg, arg_index, arguments); + + if (arguments.empty()) { + arg_index++; + continue; + } + + // We can figure this only when we encounter variadic param in + // the list of template params, from then this variable is true + // and we can process following template parameters as belonging + // to the variadic tuple + [[maybe_unused]] auto variadic_params{false}; + + if constexpr (std::is_same_v) { + // In case any of the template arguments are base classes, add + // them as parents of the current template instantiation class + if (!template_base_params.empty()) { + variadic_params = add_base_classes(template_instantiation, + template_base_params, arg_index, variadic_params, + arguments.front()); + } + } + + for (auto &argument : arguments) { + simplify_system_template( + argument, argument.to_string(using_namespace(), false, true)); + + LOG_DBG("Adding template argument {} to template " + "specialization/instantiation {}", + argument.to_string(using_namespace(), false), + template_instantiation.name()); + + template_instantiation.add_template(std::move(argument)); + } + + arg_index++; + } + + // Update id + template_instantiation.set_id( + common::to_id(template_instantiation.full_name(false))); +} + +template +void template_builder::argument_process_dispatch( + std::optional &parent, + const clang::NamedDecl *cls, + clanguml::common::model::template_element &template_instantiation, + const clang::TemplateDecl *template_decl, + const clang::TemplateArgument &arg, size_t argument_index, + std::vector &argument) +{ + LOG_DBG("Processing argument {} in template class: {}", argument_index, + cls->getQualifiedNameAsString()); + + switch (arg.getKind()) { + case clang::TemplateArgument::Null: + argument.push_back(process_null_argument(arg)); + break; + case clang::TemplateArgument::Template: + argument.push_back(process_template_argument(arg)); + break; + case clang::TemplateArgument::Type: { + argument.push_back(process_type_argument(parent, cls, template_decl, + arg.getAsType(), template_instantiation, argument_index)); + break; + } + case clang::TemplateArgument::Declaration: + break; + case clang::TemplateArgument::NullPtr: + argument.push_back(process_nullptr_argument(arg)); + break; + case clang::TemplateArgument::Integral: + argument.push_back(process_integral_argument(arg)); + break; + case clang::TemplateArgument::TemplateExpansion: + argument.push_back(process_template_expansion(arg)); + break; + case clang::TemplateArgument::Expression: + argument.push_back(process_expression_argument(arg)); + break; + case clang::TemplateArgument::Pack: + for (auto &a : + process_pack_argument(parent, cls, template_instantiation, + template_decl, arg, argument_index, argument)) { + argument.push_back(a); + } + break; + } +} + +template +template_parameter template_builder::process_template_argument( + const clang::TemplateArgument &arg) +{ + auto arg_name = common::to_string(arg); + + LOG_DBG("Processing template argument: {}", arg_name); + + return template_parameter::make_template_type(arg_name); +} + +template +template_parameter template_builder::process_template_expansion( + const clang::TemplateArgument &arg) +{ + auto arg_name = common::to_string(arg); + + LOG_DBG("Processing template expansion argument: {}", arg_name); + + util::if_not_null( + arg.getAsTemplate().getAsTemplateDecl(), [&arg_name](const auto *decl) { + arg_name = decl->getQualifiedNameAsString(); + }); + + auto param = template_parameter::make_template_type(arg_name); + param.is_variadic(true); + + return param; +} + +template +clang::QualType template_builder::consume_context( + clang::QualType type, template_parameter &tp) const +{ + auto [unqualified_type, context] = common::consume_type_context(type); + + tp.deduced_context(std::move(context)); + + return unqualified_type; +} + +template +template_parameter template_builder::process_type_argument( + std::optional &parent, + const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, + clang::QualType type, + clanguml::common::model::template_element &template_instantiation, + size_t argument_index) +{ + std::optional argument; + + if (type->getAs() != nullptr) { + type = type->getAs()->getNamedType(); // NOLINT + } + + auto type_name = common::to_string(type, &cls->getASTContext()); + + LOG_DBG("Processing template {} type argument {}: {}, {}, {}", + template_decl->getQualifiedNameAsString(), argument_index, type_name, + type->getTypeClassName(), + common::to_string(type, cls->getASTContext())); + + argument = try_as_function_prototype(parent, cls, template_decl, type, + template_instantiation, argument_index); + if (argument) + return *argument; + + argument = try_as_member_pointer(parent, cls, template_decl, type, + template_instantiation, argument_index); + if (argument) + return *argument; + + argument = try_as_array(parent, cls, template_decl, type, + template_instantiation, argument_index); + if (argument) + return *argument; + + argument = try_as_template_parm_type(cls, template_decl, type); + if (argument) + return *argument; + + argument = try_as_template_specialization_type(parent, cls, template_decl, + type, template_instantiation, argument_index); + if (argument) + return *argument; + + argument = try_as_decl_type(parent, cls, template_decl, type, + template_instantiation, argument_index); + if (argument) + return *argument; + + argument = try_as_typedef_type(parent, cls, template_decl, type, + template_instantiation, argument_index); + if (argument) + return *argument; + + argument = try_as_lambda(cls, template_decl, type); + if (argument) + return *argument; + + argument = try_as_record_type(parent, cls, template_decl, type, + template_instantiation, argument_index); + if (argument) + return *argument; + + argument = try_as_enum_type( + parent, cls, template_decl, type, template_instantiation); + if (argument) + return *argument; + + argument = try_as_builtin_type(parent, type, template_decl); + if (argument) + return *argument; + + // fallback + return template_parameter::make_argument(type_name); +} + +template +bool template_builder:: + find_relationships_in_unexposed_template_params( + const template_parameter &ct, found_relationships_t &relationships) +{ + const auto &type = ct.type(); + + if (!type) + return false; + + bool found{false}; + LOG_DBG("Finding relationships in user defined type: {}", + ct.to_string(config().using_namespace(), false)); + + auto type_with_namespace = + std::make_optional(type.value()); + + if (!type_with_namespace.has_value()) { + // Couldn't find declaration of this type + type_with_namespace = common::model::namespace_{type.value()}; + } + + auto element_opt = diagram().get(type_with_namespace.value().to_string()); + if (config_.generate_template_argument_dependencies() && element_opt) { + relationships.emplace_back( + element_opt.value().id(), relationship_t::kDependency); + found = true; + } + + for (const auto &nested_template_params : ct.template_params()) { + found = find_relationships_in_unexposed_template_params( + nested_template_params, relationships) || + found; + } + + return found; +} + +template +template_parameter template_builder::process_integral_argument( + const clang::TemplateArgument &arg) +{ + assert(arg.getKind() == clang::TemplateArgument::Integral); + + std::string result; + llvm::raw_string_ostream ostream(result); + arg.dump(ostream); + + return template_parameter::make_argument(result); +} + +template +template_parameter template_builder::process_null_argument( + const clang::TemplateArgument &arg) +{ + assert(arg.getKind() == clang::TemplateArgument::Null); + + return template_parameter::make_argument(""); +} + +template +template_parameter template_builder::process_nullptr_argument( + const clang::TemplateArgument &arg) +{ + assert(arg.getKind() == clang::TemplateArgument::NullPtr); + + LOG_DBG("Processing nullptr argument: {}", common::to_string(arg)); + + return template_parameter::make_argument("nullptr"); +} + +template +template_parameter template_builder::process_expression_argument( + const clang::TemplateArgument &arg) +{ + assert(arg.getKind() == clang::TemplateArgument::Expression); + return template_parameter::make_argument(common::get_source_text( + arg.getAsExpr()->getSourceRange(), source_manager())); +} + +template +std::vector +template_builder::process_pack_argument( + std::optional &parent, + const clang::NamedDecl *cls, + clanguml::common::model::template_element &template_instantiation, + const clang::TemplateDecl *base_template_decl, + const clang::TemplateArgument &arg, size_t argument_index, + std::vector & /*argument*/) +{ + assert(arg.getKind() == clang::TemplateArgument::Pack); + + std::vector res; + + auto pack_argument_index = argument_index; + + for (const auto &a : arg.getPackAsArray()) { + argument_process_dispatch(parent, cls, template_instantiation, + base_template_decl, a, pack_argument_index++, res); + } + + return res; +} + +template +std::optional +template_builder::try_as_member_pointer( + std::optional &parent, + const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, + clang::QualType &type, + clanguml::common::model::template_element &template_instantiation, + size_t argument_index) +{ + const auto *mp_type = + common::dereference(type)->getAs(); + if (mp_type == nullptr) + return {}; + + auto argument = template_parameter::make_template_type(""); + type = consume_context(type, argument); + + // Handle a pointer to a data member of a class + if (mp_type->isMemberDataPointer()) { + argument.is_member_pointer(false); + argument.is_data_pointer(true); + + auto pointee_arg = process_type_argument(parent, cls, template_decl, + mp_type->getPointeeType(), template_instantiation, argument_index); + + argument.add_template_param(std::move(pointee_arg)); + + const auto *member_class_type = mp_type->getClass(); + + if (member_class_type == nullptr) + return {}; + + auto class_type_arg = process_type_argument(parent, cls, template_decl, + mp_type->getClass()->getCanonicalTypeUnqualified(), + template_instantiation, argument_index); + + argument.add_template_param(std::move(class_type_arg)); + } + // Handle pointer to class method member + else { + argument.is_member_pointer(true); + argument.is_data_pointer(false); + + const auto *function_type = + mp_type->getPointeeType()->getAs(); + + assert(function_type != nullptr); + + auto return_type_arg = process_type_argument(parent, cls, template_decl, + function_type->getReturnType(), template_instantiation, + argument_index); + + // Add return type argument + argument.add_template_param(std::move(return_type_arg)); + + const auto *member_class_type = mp_type->getClass(); + + if (member_class_type == nullptr) + return {}; + + auto class_type_arg = process_type_argument(parent, cls, template_decl, + mp_type->getClass()->getCanonicalTypeUnqualified(), + template_instantiation, argument_index); + + // Add class type argument + argument.add_template_param(std::move(class_type_arg)); + + // Add argument types + for (const auto ¶m_type : function_type->param_types()) { + argument.add_template_param( + process_type_argument(parent, cls, template_decl, param_type, + template_instantiation, argument_index)); + } + } + + return argument; +} + +template +std::optional template_builder::try_as_array( + std::optional &parent, + const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, + clang::QualType &type, + clanguml::common::model::template_element &template_instantiation, + size_t argument_index) +{ + const auto *array_type = common::dereference(type)->getAsArrayTypeUnsafe(); + if (array_type == nullptr) + return {}; + + auto argument = template_parameter::make_template_type(""); + + type = consume_context(type, argument); + + argument.is_array(true); + + // Set function template return type + auto element_type = process_type_argument(parent, cls, template_decl, + array_type->getElementType(), template_instantiation, argument_index); + + argument.add_template_param(element_type); + + if (array_type->isDependentSizedArrayType() && + array_type->getDependence() == + clang::TypeDependence::DependentInstantiation) { + argument.add_template_param( + template_parameter::make_template_type(common::to_string( + ((clang::DependentSizedArrayType *)array_type) // NOLINT + ->getSizeExpr()))); + } + else if (array_type->isConstantArrayType()) { + argument.add_template_param(template_parameter::make_argument( + std::to_string(((clang::ConstantArrayType *)array_type) // NOLINT + ->getSize() + .getLimitedValue()))); + } + + // TODO: Handle variable sized arrays + + return argument; +} + +template +std::optional +template_builder::try_as_function_prototype( + std::optional &parent, + const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, + clang::QualType &type, + clanguml::common::model::template_element &template_instantiation, + size_t argument_index) +{ + const auto *function_type = type->getAs(); + + if (function_type == nullptr && type->isFunctionPointerType()) { + function_type = + type->getPointeeType()->getAs(); + if (function_type == nullptr) + return {}; + } + + if (function_type == nullptr) + return {}; + + LOG_DBG("Template argument is a function prototype"); + + auto argument = template_parameter::make_template_type(""); + + type = consume_context(type, argument); + + argument.is_function_template(true); + + // Set function template return type + auto return_arg = process_type_argument(parent, cls, template_decl, + function_type->getReturnType(), template_instantiation, argument_index); + + argument.add_template_param(return_arg); + + // Set function template argument types + if (function_type->isVariadic() && function_type->param_types().empty()) { + auto fallback_arg = template_parameter::make_argument({}); + fallback_arg.is_ellipsis(true); + argument.add_template_param(std::move(fallback_arg)); + } + else { + for (const auto ¶m_type : function_type->param_types()) { + argument.add_template_param( + process_type_argument(parent, cls, template_decl, param_type, + template_instantiation, argument_index)); + } + } + + return argument; +} + +template +std::optional template_builder::try_as_decl_type( + std::optional & /*parent*/, + const clang::NamedDecl * /*cls*/, + const clang::TemplateDecl * /*template_decl*/, clang::QualType &type, + clanguml::common::model::template_element & /*template_instantiation*/, + size_t /*argument_index*/) +{ + const auto *decl_type = + common::dereference(type)->getAs(); + if (decl_type == nullptr) { + return {}; + } + + LOG_DBG("Template argument is a decltype()"); + + // TODO + return {}; +} + +template +std::optional +template_builder::try_as_typedef_type( + std::optional &parent, + const clang::NamedDecl * /*cls*/, + const clang::TemplateDecl * /*template_decl*/, clang::QualType &type, + clanguml::common::model::template_element & /*template_instantiation*/, + size_t /*argument_index*/) +{ + const auto *typedef_type = + common::dereference(type)->getAs(); + if (typedef_type == nullptr) { + return {}; + } + + LOG_DBG("Template argument is a typedef/using"); + + // If this is a typedef/using alias to a decltype - we're not able + // to figure out anything out of it probably + if (typedef_type->getAs() != nullptr) { + // Here we need to figure out the parent context of this alias, + // it can be a: + // - class/struct + if (typedef_type->getDecl()->isCXXClassMember() && parent) { + return template_parameter::make_argument( + fmt::format("{}::{}", parent.value()->full_name(false), + typedef_type->getDecl()->getNameAsString())); + } + // - namespace + return template_parameter::make_argument( + typedef_type->getDecl()->getQualifiedNameAsString()); + } + + return {}; +} + +template +std::optional +template_builder::try_as_template_specialization_type( + std::optional &parent, + const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, + clang::QualType &type, + clanguml::common::model::template_element &template_instantiation, + size_t argument_index) +{ + const auto *nested_template_type = + common::dereference(type)->getAs(); + if (nested_template_type == nullptr) { + return {}; + } + + LOG_DBG("Template argument is a template specialization type"); + + auto argument = template_parameter::make_argument(""); + type = consume_context(type, argument); + + auto nested_type_name = nested_template_type->getTemplateName() + .getAsTemplateDecl() + ->getQualifiedNameAsString(); + + if (clang::dyn_cast( + nested_template_type->getTemplateName().getAsTemplateDecl()) != + nullptr) { + if (const auto *template_specialization_decl = + clang::dyn_cast(cls); + template_specialization_decl != nullptr) { + nested_type_name = + template_specialization_decl->getDescribedTemplateParams() + ->getParam(argument_index) + ->getNameAsString(); + } + else { + // fallback + nested_type_name = "template"; + } + + argument.is_template_template_parameter(true); + } + + argument.set_type(nested_type_name); + + auto nested_template_instantiation = + visitor_.create_element(nested_template_type->getTemplateName() + .getAsTemplateDecl() + ->getTemplatedDecl()); + build_from_template_specialization_type(*nested_template_instantiation, cls, + *nested_template_type, + diagram().should_include( + namespace_{template_decl->getQualifiedNameAsString()}) + ? std::make_optional(&template_instantiation) + : parent); + + argument.set_id(nested_template_instantiation->id()); + + for (const auto &t : nested_template_instantiation->template_params()) + argument.add_template_param(t); + + // Check if this template should be simplified (e.g. system + // template aliases such as 'std:basic_string' should + // be simply 'std::string') + simplify_system_template( + argument, argument.to_string(using_namespace(), false)); + + argument.set_id( + common::to_id(argument.to_string(using_namespace(), false))); + + const auto nested_template_instantiation_full_name = + nested_template_instantiation->full_name(false); + + if (nested_template_instantiation && + diagram().should_include( + namespace_{nested_template_instantiation_full_name})) { + if (config_.generate_template_argument_dependencies()) { + if (diagram().should_include( + namespace_{template_decl->getQualifiedNameAsString()})) { + template_instantiation.add_relationship( + {relationship_t::kDependency, + nested_template_instantiation->id()}); + } + else { + if (parent.has_value()) + parent.value()->add_relationship( + {relationship_t::kDependency, + nested_template_instantiation->id()}); + } + } + } + + if (diagram().should_include( + namespace_{nested_template_instantiation_full_name})) { + visitor_.set_source_location(*cls, *nested_template_instantiation); + visitor_.add_diagram_element(std::move(nested_template_instantiation)); + } + + return argument; +} + +template +std::optional +template_builder::try_as_template_parm_type( + const clang::NamedDecl *cls, const clang::TemplateDecl * /*template_decl*/, + clang::QualType &type) +{ + auto is_variadic{false}; + + const auto *type_parameter = + common::dereference(type)->getAs(); + + auto type_name = common::to_string(type, &cls->getASTContext()); + + if (type_parameter == nullptr) { + if (const auto *pet = + common::dereference(type)->getAs(); + pet != nullptr) { + is_variadic = true; + type_parameter = + pet->getPattern()->getAs(); + } + } + + if (type_parameter == nullptr) + return {}; + + LOG_DBG("Template argument is a template parameter type"); + + auto argument = template_parameter::make_template_type(""); + type = consume_context(type, argument); + + auto type_parameter_name = common::to_string(type, cls->getASTContext()); + if (type_parameter_name.empty()) + type_parameter_name = "typename"; + + argument.set_name(map_type_parameter_to_template_parameter_name( + cls, type_parameter_name)); + + argument.is_variadic(is_variadic); + + common::ensure_lambda_type_is_relative(config(), type_parameter_name); + + return argument; +} + +template +std::optional template_builder::try_as_lambda( + const clang::NamedDecl *cls, const clang::TemplateDecl * /*template_decl*/, + clang::QualType &type) +{ + auto type_name = common::to_string(type, &cls->getASTContext()); + + if (type_name.find("(lambda at ") != 0) + return {}; + + LOG_DBG("Template argument is a lambda"); + + auto argument = template_parameter::make_argument(""); + type = consume_context(type, argument); + + common::ensure_lambda_type_is_relative(config(), type_name); + argument.set_type(type_name); + + return argument; +} + +template +std::optional +template_builder::try_as_record_type( + std::optional &parent, + const clang::NamedDecl * /*cls*/, const clang::TemplateDecl *template_decl, + clang::QualType &type, + clanguml::common::model::template_element &template_instantiation, + size_t /*argument_index*/) +{ + const auto *record_type = + common::dereference(type)->getAs(); + if (record_type == nullptr) + return {}; + + LOG_DBG("Template argument is a c++ record"); + + auto argument = template_parameter::make_argument({}); + type = consume_context(type, argument); + + const auto type_name = config().simplify_template_type( + common::to_string(type, template_decl->getASTContext())); + + argument.set_type(type_name); + const auto type_id = common::to_id(type_name); + + argument.set_id(type_id); + + const auto *class_template_specialization = + clang::dyn_cast( + record_type->getAsRecordDecl()); + + if (class_template_specialization != nullptr) { + auto tag_argument = + visitor_.create_element(class_template_specialization); + + build_from_class_template_specialization( + *tag_argument, *class_template_specialization); + + if (tag_argument) { + argument.set_type(tag_argument->name_and_ns()); + for (const auto &p : tag_argument->template_params()) + argument.add_template_param(p); + for (auto &r : tag_argument->relationships()) { + template_instantiation.add_relationship(std::move(r)); + } + + if (config_.generate_template_argument_dependencies() && + diagram().should_include(tag_argument->get_namespace())) { + if (parent.has_value()) + parent.value()->add_relationship( + {relationship_t::kDependency, tag_argument->id()}); + visitor_.set_source_location(*template_decl, *tag_argument); + visitor_.add_diagram_element(std::move(tag_argument)); + } + } + } + else if (const auto *record_type_decl = record_type->getAsRecordDecl(); + record_type_decl != nullptr) { + if (config_.generate_template_argument_dependencies() && + diagram().should_include(namespace_{type_name})) { + // Add dependency relationship to the parent + // template + template_instantiation.add_relationship( + {relationship_t::kDependency, type_id}); + } + } + + return argument; +} + +template +std::optional template_builder::try_as_enum_type( + std::optional & /*parent*/, + const clang::NamedDecl * /*cls*/, const clang::TemplateDecl *template_decl, + clang::QualType &type, + clanguml::common::model::template_element &template_instantiation) +{ + const auto *enum_type = type->getAs(); + if (enum_type == nullptr) + return {}; + + LOG_DBG("Template argument is a an enum"); + + auto argument = template_parameter::make_argument({}); + type = consume_context(type, argument); + + auto type_name = common::to_string(type, template_decl->getASTContext()); + argument.set_type(type_name); + const auto type_id = common::to_id(type_name); + argument.set_id(type_id); + + if (enum_type->getAsTagDecl() != nullptr && + config_.generate_template_argument_dependencies()) { + template_instantiation.add_relationship( + {relationship_t::kDependency, type_id}); + } + + return argument; +} + +template +std::optional +template_builder::try_as_builtin_type( + std::optional & /*parent*/, + clang::QualType &type, const clang::TemplateDecl *template_decl) +{ + const auto *builtin_type = type->getAs(); + if (builtin_type == nullptr) + return {}; + + LOG_DBG("Template argument is a builtin type"); + + auto type_name = common::to_string(type, template_decl->getASTContext()); + auto argument = template_parameter::make_argument(type_name); + + type = consume_context(type, argument); + argument.set_type(type_name); + + return argument; +} + +template +bool template_builder::add_base_classes( + clanguml::common::model::template_element &tinst, + std::deque> &template_base_params, + int arg_index, bool variadic_params, const template_parameter &ct) +{ + bool add_template_argument_as_base_class = false; + + if (variadic_params) { + add_template_argument_as_base_class = true; + } + else { + auto [arg_name, index, is_variadic] = template_base_params.front(); + + variadic_params = is_variadic; + if ((arg_index == index) || (is_variadic && arg_index >= index)) { + add_template_argument_as_base_class = true; + if (!is_variadic) { + // Don't remove the remaining variadic parameter + template_base_params.pop_front(); + } + } + } + + const auto maybe_id = ct.id(); + if (add_template_argument_as_base_class && maybe_id) { + LOG_DBG("Adding template argument as base class '{}'", + ct.to_string({}, false)); + + class_diagram::model::class_parent cp; + cp.set_access(common::model::access_t::kPublic); + cp.set_name(ct.to_string({}, false)); + cp.set_id(maybe_id.value()); + + dynamic_cast(tinst).add_parent( + std::move(cp)); + } + + return variadic_params; +} + } // namespace clanguml::common::visitor \ No newline at end of file diff --git a/src/common/visitor/translation_unit_visitor.cc b/src/common/visitor/translation_unit_visitor.cc index 4ac9973b..0e774dcc 100644 --- a/src/common/visitor/translation_unit_visitor.cc +++ b/src/common/visitor/translation_unit_visitor.cc @@ -16,174 +16,6 @@ * limitations under the License. */ -#include "translation_unit_visitor.h" - -#include "comment/clang_visitor.h" -#include "comment/plain_visitor.h" -#include "common/clang_utils.h" - -#include -#include - namespace clanguml::common::visitor { -translation_unit_visitor::translation_unit_visitor( - clang::SourceManager &sm, const clanguml::config::diagram &config) - : source_manager_{sm} - , relative_to_path_{config.root_directory()} -{ - if (config.comment_parser() == config::comment_parser_t::plain) { - comment_visitor_ = - std::make_unique(source_manager_); - } - else if (config.comment_parser() == config::comment_parser_t::clang) { - comment_visitor_ = - std::make_unique(source_manager_); - } -} - -void translation_unit_visitor::set_tu_path( - const std::string &translation_unit_path) -{ - translation_unit_path_ = relative( - std::filesystem::path{translation_unit_path}, relative_to_path_); - translation_unit_path_.make_preferred(); -} - -const std::filesystem::path &translation_unit_visitor::tu_path() const -{ - return translation_unit_path_; -} - -clang::SourceManager &translation_unit_visitor::source_manager() const -{ - return source_manager_; -} - -void translation_unit_visitor::process_comment( - const clang::NamedDecl &decl, clanguml::common::model::decorated_element &e) -{ - assert(comment_visitor_.get() != nullptr); - - comment_visitor_->visit(decl, e); - - const auto *comment = - decl.getASTContext().getRawCommentForDeclNoCache(&decl); - - process_comment(comment, decl.getASTContext().getDiagnostics(), e); -} - -void translation_unit_visitor::process_comment(const clang::RawComment *comment, - clang::DiagnosticsEngine &de, clanguml::common::model::decorated_element &e) -{ - if (comment != nullptr) { - auto [it, inserted] = processed_comments_.emplace(comment); - - if (!inserted) - return; - - // Process clang-uml decorators in the comments - // TODO: Refactor to use standard block comments processable by clang - // comments - e.add_decorators( - decorators::parse(comment->getFormattedText(source_manager_, de))); - } -} - -void translation_unit_visitor::set_source_location( - const clang::Decl &decl, clanguml::common::model::source_location &element) -{ - set_source_location(decl.getLocation(), element); -} - -void translation_unit_visitor::set_source_location( - const clang::Expr &expr, clanguml::common::model::source_location &element) -{ - set_source_location(expr.getBeginLoc(), element); -} - -void translation_unit_visitor::set_source_location( - const clang::Stmt &stmt, clanguml::common::model::source_location &element) -{ - set_source_location(stmt.getBeginLoc(), element); -} - -void translation_unit_visitor::set_source_location( - const clang::SourceLocation &location, - clanguml::common::model::source_location &element) -{ - namespace fs = std::filesystem; - - std::string file; - unsigned line{}; - unsigned column{}; - - if (location.isValid()) { - file = source_manager_.getFilename(location).str(); - line = source_manager_.getSpellingLineNumber(location); - column = source_manager_.getSpellingColumnNumber(location); - - if (file.empty()) { - // Why do I have to do this? - parse_source_location( - location.printToString(source_manager()), file, line, column); - } - } - else { - auto success = parse_source_location( - location.printToString(source_manager()), file, line, column); - if (!success) { - LOG_DBG("Failed to extract source location for element from {}", - location.printToString(source_manager_)); - return; - } - } - - // ensure the path is absolute - fs::path file_path{file}; - if (!file_path.is_absolute()) { - file_path = fs::absolute(file_path); - } - - file_path = fs::weakly_canonical(file_path); - - file = file_path.string(); - - element.set_file(file); - - if (util::is_relative_to(file_path, relative_to_path_)) { - element.set_file_relative(util::path_to_url( - fs::relative(element.file(), relative_to_path_).string())); - } - else { - element.set_file_relative(""); - } - - element.set_translation_unit(tu_path().string()); - element.set_line(line); - element.set_column(column); - element.set_location_id(location.getHashValue()); -} - -void translation_unit_visitor::set_owning_module( - const clang::Decl &decl, clanguml::common::model::element &element) -{ - if (const clang::Module *module = decl.getOwningModule(); - module != nullptr) { - std::string module_name = module->Name; - bool is_private{false}; -#if LLVM_VERSION_MAJOR < 15 - is_private = - module->Kind == clang::Module::ModuleKind::PrivateModuleFragment; -#else - is_private = module->isPrivateModule(); -#endif - if (is_private) { - // Clang just maps private modules names to "" - module_name = module->getTopLevelModule()->Name; - } - element.set_module(module_name); - element.set_module_private(is_private); - } -} } // namespace clanguml::common::visitor \ No newline at end of file diff --git a/src/common/visitor/translation_unit_visitor.h b/src/common/visitor/translation_unit_visitor.h index 71408ed5..6f271832 100644 --- a/src/common/visitor/translation_unit_visitor.h +++ b/src/common/visitor/translation_unit_visitor.h @@ -17,14 +17,21 @@ */ #pragma once +#include "comment/clang_visitor.h" #include "comment/comment_visitor.h" +#include "comment/plain_visitor.h" +#include "common/clang_utils.h" +#include "common/model/namespace.h" +#include "common/model/source_file.h" #include "common/model/source_location.h" #include "common/model/template_element.h" #include "common/visitor/ast_id_mapper.h" #include "config/config.h" #include +#include #include +#include #include #include @@ -44,8 +51,11 @@ using found_relationships_t = std::vector< * This class provides common interface for diagram translation unit * visitors. */ -class translation_unit_visitor { +template class translation_unit_visitor { public: + using config_t = ConfigT; + using diagram_t = DiagramT; + /** * @brief Constructor * @@ -54,17 +64,39 @@ public: * instance */ explicit translation_unit_visitor( - clang::SourceManager &sm, const clanguml::config::diagram &config); + clang::SourceManager &sm, DiagramT &diagram, const ConfigT &config) + : diagram_{diagram} + , config_{config} + , source_manager_{sm} + , relative_to_path_{config.root_directory()} + { + if (config.comment_parser() == config::comment_parser_t::plain) { + comment_visitor_ = + std::make_unique(source_manager_); + } + else if (config.comment_parser() == config::comment_parser_t::clang) { + comment_visitor_ = + std::make_unique(source_manager_); + } + } virtual ~translation_unit_visitor() = default; - void set_tu_path(const std::string &translation_unit_path); + void set_tu_path(const std::string &translation_unit_path) + { + translation_unit_path_ = relative( + std::filesystem::path{translation_unit_path}, relative_to_path_); + translation_unit_path_.make_preferred(); + } /** * @brief Return relative path to current translation unit * @return Current translation unit path */ - const std::filesystem::path &tu_path() const; + const std::filesystem::path &tu_path() const + { + return translation_unit_path_; + } /** * @brief Get reference to Clang AST to clang-uml id mapper @@ -78,7 +110,7 @@ public: * @return Reference to @ref clang::SourceManager used by this translation * unit visitor */ - clang::SourceManager &source_manager() const; + clang::SourceManager &source_manager() const { return source_manager_; } /** * @brief Set source location in diagram element @@ -87,7 +119,10 @@ public: * @param element Reference to element to be updated */ void set_source_location(const clang::Decl &decl, - clanguml::common::model::source_location &element); + clanguml::common::model::source_location &element) + { + set_source_location(decl.getLocation(), element); + } /** * @brief Set source location in diagram element @@ -96,10 +131,25 @@ public: * @param element Reference to element to be updated */ void set_source_location(const clang::Expr &expr, - clanguml::common::model::source_location &element); + clanguml::common::model::source_location &element) + { + set_source_location(expr.getBeginLoc(), element); + } void set_source_location(const clang::Stmt &stmt, - clanguml::common::model::source_location &element); + clanguml::common::model::source_location &element) + { + set_source_location(stmt.getBeginLoc(), element); + } + + void set_qualified_name( + const clang::NamedDecl &decl, clanguml::common::model::element &element) + { + common::model::namespace_ ns{decl.getQualifiedNameAsString()}; + element.set_name(ns.name()); + ns.pop_back(); + element.set_namespace(ns); + } /** * @brief Set source location in diagram element @@ -108,17 +158,88 @@ public: * @param element Reference to element to be updated */ void set_source_location(const clang::SourceLocation &location, - clanguml::common::model::source_location &element); + clanguml::common::model::source_location &element) + { + namespace fs = std::filesystem; + + std::string file; + unsigned line{}; + unsigned column{}; + + if (location.isValid()) { + file = source_manager_.getFilename(location).str(); + line = source_manager_.getSpellingLineNumber(location); + column = source_manager_.getSpellingColumnNumber(location); + + if (file.empty()) { + // Why do I have to do this? + parse_source_location(location.printToString(source_manager()), + file, line, column); + } + } + else { + auto success = parse_source_location( + location.printToString(source_manager()), file, line, column); + if (!success) { + LOG_DBG("Failed to extract source location for element from {}", + location.printToString(source_manager_)); + return; + } + } + + // ensure the path is absolute + fs::path file_path{file}; + if (!file_path.is_absolute()) { + file_path = fs::absolute(file_path); + } + + file_path = fs::weakly_canonical(file_path); + + file = file_path.string(); + + element.set_file(file); + + if (util::is_relative_to(file_path, relative_to_path_)) { + element.set_file_relative(util::path_to_url( + fs::relative(element.file(), relative_to_path_).string())); + } + else { + element.set_file_relative(""); + } + + element.set_translation_unit(tu_path().string()); + element.set_line(line); + element.set_column(column); + element.set_location_id(location.getHashValue()); + } void set_owning_module( - const clang::Decl &decl, clanguml::common::model::element &element); + const clang::Decl &decl, clanguml::common::model::element &element) + { + if (const clang::Module *module = decl.getOwningModule(); + module != nullptr) { + std::string module_name = module->Name; + bool is_private{false}; +#if LLVM_VERSION_MAJOR < 15 + is_private = module->Kind == + clang::Module::ModuleKind::PrivateModuleFragment; +#else + is_private = module->isPrivateModule(); +#endif + if (is_private) { + // Clang just maps private modules names to "" + module_name = module->getTopLevelModule()->Name; + } + element.set_module(module_name); + element.set_module_private(is_private); + } + } virtual void add_diagram_element( std::unique_ptr element) { } -protected: /** * @brief Process comment directives in comment attached to a declaration * @@ -126,7 +247,17 @@ protected: * @param element Reference to element to be updated */ void process_comment(const clang::NamedDecl &decl, - clanguml::common::model::decorated_element &e); + clanguml::common::model::decorated_element &e) + { + assert(comment_visitor_.get() != nullptr); + + comment_visitor_->visit(decl, e); + + const auto *comment = + decl.getASTContext().getRawCommentForDeclNoCache(&decl); + + process_comment(comment, decl.getASTContext().getDiagnostics(), e); + } /** * @brief Process comment directives in raw comment @@ -137,9 +268,77 @@ protected: */ void process_comment(const clang::RawComment *comment, clang::DiagnosticsEngine &de, - clanguml::common::model::decorated_element &e); + clanguml::common::model::decorated_element &e) + { + if (comment != nullptr) { + auto [it, inserted] = processed_comments_.emplace(comment); + + if (!inserted) + return; + + // Process clang-uml decorators in the comments + // TODO: Refactor to use standard block comments processable by + // clang comments + e.add_decorators(decorators::parse( + comment->getFormattedText(source_manager_, de))); + } + } + + /** + * @brief Check if the diagram should include a declaration. + * + * @param decl Clang declaration. + * @return True, if the entity should be included in the diagram. + */ + bool should_include(const clang::NamedDecl *decl) + { + if (decl == nullptr) + return false; + + if (source_manager().isInSystemHeader( + decl->getSourceRange().getBegin())) + return false; + + auto should_include_namespace = diagram().should_include( + common::model::namespace_{decl->getQualifiedNameAsString()}); + + const auto decl_file = + decl->getLocation().printToString(source_manager()); + + const auto should_include_decl_file = + diagram().should_include(common::model::source_file{decl_file}); + + return should_include_namespace && should_include_decl_file; + } + + /** + * @brief Get diagram model reference + * + * @return Reference to diagram model created by the visitor + */ + DiagramT &diagram() { return diagram_; } + + /** + * @brief Get diagram model reference + * + * @return Reference to diagram model created by the visitor + */ + const DiagramT &diagram() const { return diagram_; } + + /** + * @brief Get diagram config instance + * + * @return Reference to config instance + */ + const ConfigT &config() const { return config_; } private: + // Reference to the output diagram model + DiagramT &diagram_; + + // Reference to class diagram config + const ConfigT &config_; + clang::SourceManager &source_manager_; std::unique_ptr comment_visitor_; diff --git a/src/include_diagram/visitor/translation_unit_visitor.cc b/src/include_diagram/visitor/translation_unit_visitor.cc index 000c213b..c6158291 100644 --- a/src/include_diagram/visitor/translation_unit_visitor.cc +++ b/src/include_diagram/visitor/translation_unit_visitor.cc @@ -37,9 +37,7 @@ translation_unit_visitor::include_visitor::include_visitor( clang::SourceManager &sm, clanguml::include_diagram::model::diagram &diagram, const clanguml::config::include_diagram &config) - : common::visitor::translation_unit_visitor{sm, config} - , diagram_{diagram} - , config_{config} + : visitor_specialization_t{sm, diagram, config} { } @@ -112,18 +110,6 @@ void translation_unit_visitor::include_visitor::InclusionDirective( } } -clanguml::include_diagram::model::diagram & -translation_unit_visitor::include_visitor::diagram() -{ - return diagram_; -} - -const clanguml::config::include_diagram & -translation_unit_visitor::include_visitor::config() const -{ - return config_; -} - void translation_unit_visitor::include_visitor::process_internal_header( const std::filesystem::path &include_path, bool is_system, const common::id_t current_file_id) diff --git a/src/include_diagram/visitor/translation_unit_visitor.h b/src/include_diagram/visitor/translation_unit_visitor.h index d59f258b..872c9709 100644 --- a/src/include_diagram/visitor/translation_unit_visitor.h +++ b/src/include_diagram/visitor/translation_unit_visitor.h @@ -35,6 +35,10 @@ namespace clanguml::include_diagram::visitor { +using visitor_specialization_t = + common::visitor::translation_unit_visitor; + /** * @brief Include diagram translation unit visitor wrapper * @@ -53,7 +57,7 @@ public: * include_visitor type from translation_unit_visitor type */ class include_visitor : public clang::PPCallbacks, - public common::visitor::translation_unit_visitor { + public visitor_specialization_t { public: /** * @brief Constructor. @@ -123,27 +127,6 @@ public: */ std::optional process_source_file( const std::filesystem::path &file); - - /** - * @brief Get reference to the include diagram model - * - * @return Reference to the include diagram model - */ - clanguml::include_diagram::model::diagram &diagram(); - - /** - * @brief Get reference to the diagram configuration - * - * @return Reference to the diagram configuration - */ - const clanguml::config::include_diagram &config() const; - - private: - // Reference to the output diagram model - clanguml::include_diagram::model::diagram &diagram_; - - // Reference to class diagram config - const clanguml::config::include_diagram &config_; }; /** diff --git a/src/package_diagram/visitor/translation_unit_visitor.cc b/src/package_diagram/visitor/translation_unit_visitor.cc index 1794bee2..15ea040a 100644 --- a/src/package_diagram/visitor/translation_unit_visitor.cc +++ b/src/package_diagram/visitor/translation_unit_visitor.cc @@ -37,9 +37,7 @@ using clanguml::common::model::relationship_t; translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm, clanguml::package_diagram::model::diagram &diagram, const clanguml::config::package_diagram &config) - : common::visitor::translation_unit_visitor{sm, config} - , diagram_{diagram} - , config_{config} + : visitor_specialization_t{sm, diagram, config} { } @@ -676,17 +674,6 @@ bool translation_unit_visitor::find_relationships(const clang::QualType &type, return result; } -clanguml::package_diagram::model::diagram &translation_unit_visitor::diagram() -{ - return diagram_; -} - -const clanguml::config::package_diagram & -translation_unit_visitor::config() const -{ - return config_; -} - void translation_unit_visitor::finalize() { } std::vector translation_unit_visitor::get_parent_package_ids( diff --git a/src/package_diagram/visitor/translation_unit_visitor.h b/src/package_diagram/visitor/translation_unit_visitor.h index 11d8dc14..5aeb2657 100644 --- a/src/package_diagram/visitor/translation_unit_visitor.h +++ b/src/package_diagram/visitor/translation_unit_visitor.h @@ -36,6 +36,10 @@ namespace clanguml::package_diagram::visitor { using found_relationships_t = std::vector< std::pair>; +using visitor_specialization_t = + common::visitor::translation_unit_visitor; + /** * @brief Package diagram translation unit visitor * @@ -44,7 +48,7 @@ using found_relationships_t = std::vector< */ class translation_unit_visitor : public clang::RecursiveASTVisitor, - public common::visitor::translation_unit_visitor { + public visitor_specialization_t { public: /** * @brief Constructor. @@ -76,20 +80,6 @@ public: virtual bool VisitFunctionDecl(clang::FunctionDecl *function_declaration); /** @} */ - /** - * @brief Get diagram model reference - * - * @return Reference to diagram model created by the visitor - */ - clanguml::package_diagram::model::diagram &diagram(); - - /** - * @brief Get diagram model reference - * - * @return Reference to diagram model created by the visitor - */ - const clanguml::config::package_diagram &config() const; - /** * @brief Finalize diagram model */ @@ -214,11 +204,5 @@ private: clang::Decl *cls, found_relationships_t &relationships); std::vector get_parent_package_ids(common::id_t id); - - // Reference to the output diagram model - clanguml::package_diagram::model::diagram &diagram_; - - // Reference to class diagram config - const clanguml::config::package_diagram &config_; }; } // namespace clanguml::package_diagram::visitor diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.cc b/src/sequence_diagram/visitor/translation_unit_visitor.cc index dffaa1f4..fe8f491b 100644 --- a/src/sequence_diagram/visitor/translation_unit_visitor.cc +++ b/src/sequence_diagram/visitor/translation_unit_visitor.cc @@ -27,16 +27,18 @@ namespace clanguml::sequence_diagram::visitor { translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm, clanguml::sequence_diagram::model::diagram &diagram, const clanguml::config::sequence_diagram &config) - : common::visitor::translation_unit_visitor{sm, config} - , diagram_{diagram} - , config_{config} - , template_builder_{diagram_, config_, *this, - [uns = config_.using_namespace()](const clang::NamedDecl * /*decl*/) { - return std::make_unique(uns); - }} + : visitor_specialization_t{sm, diagram, config} + , template_builder_{diagram, config, *this} { } +std::unique_ptr +translation_unit_visitor::create_element(const clang::NamedDecl *decl) const +{ + return std::make_unique( + config().using_namespace()); +} + bool translation_unit_visitor::shouldVisitTemplateInstantiations() { return true; @@ -52,23 +54,6 @@ const call_expression_context &translation_unit_visitor::context() const return call_expression_context_; } -clanguml::sequence_diagram::model::diagram &translation_unit_visitor::diagram() -{ - return diagram_; -} - -const clanguml::sequence_diagram::model::diagram & -translation_unit_visitor::diagram() const -{ - return diagram_; -} - -const clanguml::config::sequence_diagram & -translation_unit_visitor::config() const -{ - return config_; -} - bool translation_unit_visitor::VisitCXXRecordDecl( clang::CXXRecordDecl *declaration) { @@ -153,13 +138,13 @@ bool translation_unit_visitor::VisitClassTemplateDecl( if (!class_model_ptr) return true; - // Override the id with the template id, for now we don't care about the - // underlying templated class id - process_template_parameters(*declaration, *class_model_ptr); + tbuilder().build_from_template_declaration(*class_model_ptr, *declaration); const auto class_full_name = class_model_ptr->full_name(false); const auto id = common::to_id(class_full_name); + // Override the id with the template id, for now we don't care about the + // underlying templated class id class_model_ptr->set_id(id); set_unique_id(declaration->getID(), id); @@ -198,7 +183,7 @@ bool translation_unit_visitor::VisitClassTemplateSpecializationDecl( return true; auto template_specialization_ptr = - process_template_specialization(declaration); + process_class_template_specialization(declaration); if (!template_specialization_ptr) return true; @@ -1486,8 +1471,9 @@ translation_unit_visitor::create_class_model(clang::CXXRecordDecl *cls) return {}; auto parent_class = - diagram_.get_participant( - *id_opt); + diagram() + .get_participant( + *id_opt); assert(parent_class); @@ -1555,84 +1541,6 @@ translation_unit_visitor::create_class_model(clang::CXXRecordDecl *cls) return c_ptr; } -bool translation_unit_visitor::process_template_parameters( - const clang::TemplateDecl &template_declaration, - sequence_diagram::model::template_trait &c) -{ - using common::model::template_parameter; - - LOG_TRACE("Processing class {} template parameters...", - common::get_qualified_name(template_declaration)); - - if (template_declaration.getTemplateParameters() == nullptr) - return false; - - for (const auto *parameter : - *template_declaration.getTemplateParameters()) { - if (clang::dyn_cast_or_null(parameter) != - nullptr) { - const auto *template_type_parameter = - clang::dyn_cast_or_null(parameter); - std::optional default_arg; - if (template_type_parameter->hasDefaultArgument()) { - default_arg = - template_type_parameter->getDefaultArgument().getAsString(); - } - auto ct = template_parameter::make_template_type( - template_type_parameter->getNameAsString(), default_arg, - template_type_parameter->isParameterPack()); - - c.add_template(std::move(ct)); - } - else if (clang::dyn_cast_or_null( - parameter) != nullptr) { - const auto *template_nontype_parameter = - clang::dyn_cast_or_null( - parameter); - std::optional default_arg; - if (template_nontype_parameter->hasDefaultArgument()) - default_arg = common::to_string( - template_nontype_parameter->getDefaultArgument()); - auto ct = template_parameter::make_non_type_template( - template_nontype_parameter->getType().getAsString(), - template_nontype_parameter->getNameAsString(), default_arg); - - c.add_template(std::move(ct)); - } - else if (clang::dyn_cast_or_null( - parameter) != nullptr) { - const auto *template_template_parameter = - clang::dyn_cast_or_null( - parameter); - std::optional default_arg; - if (template_template_parameter->hasDefaultArgument()) { - const auto &def_arg = - template_template_parameter->getDefaultArgument() - .getArgument(); - if (def_arg.getKind() == - clang::TemplateArgument::ArgKind::Expression) { - default_arg = common::to_string(def_arg.getAsExpr()); - } - else if (def_arg.getKind() == - clang::TemplateArgument::ArgKind::Declaration) { - default_arg = common::to_string(def_arg.getAsDecl()); - } - } - - auto ct = template_parameter::make_template_template_type( - template_template_parameter->getNameAsString(), default_arg, - template_template_parameter->isParameterPack()); - - c.add_template(std::move(ct)); - } - else { - // pass - } - } - - return false; -} - void translation_unit_visitor::set_unique_id( int64_t local_id, common::id_t global_id) { @@ -1658,12 +1566,10 @@ translation_unit_visitor::build_function_template( std::make_unique( config().using_namespace()); - common::model::namespace_ ns{declaration.getQualifiedNameAsString()}; - function_template_model_ptr->set_name(ns.name()); - ns.pop_back(); - function_template_model_ptr->set_namespace(ns); + set_qualified_name(declaration, *function_template_model_ptr); - process_template_parameters(declaration, *function_template_model_ptr); + tbuilder().build_from_template_declaration( + *function_template_model_ptr, declaration); function_template_model_ptr->return_type( common::to_string(declaration.getAsFunction()->getReturnType(), @@ -1682,35 +1588,17 @@ std::unique_ptr translation_unit_visitor::build_function_template_instantiation( const clang::FunctionDecl &decl) { - // - // Here we'll hold the template base params to replace with the - // instantiated values - // - std::deque> - template_base_params{}; - auto template_instantiation_ptr = - std::make_unique(config_.using_namespace()); + std::make_unique(config().using_namespace()); auto &template_instantiation = *template_instantiation_ptr; - // - // Set function template instantiation name - // - auto template_decl_qualified_name = decl.getQualifiedNameAsString(); - common::model::namespace_ ns{template_decl_qualified_name}; - ns.pop_back(); - template_instantiation.set_name(decl.getNameAsString()); - template_instantiation.set_namespace(ns); + set_qualified_name(decl, template_instantiation); - // - // Instantiate the template arguments - // - model::template_trait *parent{nullptr}; - build_template_instantiation_process_template_arguments(parent, - template_base_params, decl.getTemplateSpecializationArgs()->asArray(), - template_instantiation, "", decl.getPrimaryTemplate()); + tbuilder().build(template_instantiation, &decl, decl.getPrimaryTemplate(), + decl.getTemplateSpecializationArgs()->asArray(), + common::to_string(&decl)); + // Handle function parameters for (const auto *param : decl.parameters()) { template_instantiation_ptr->add_parameter( common::to_string(param->getType(), decl.getASTContext())); @@ -1743,150 +1631,11 @@ std::unique_ptr translation_unit_visitor::build_function_model( return function_model_ptr; } -void translation_unit_visitor:: - build_template_instantiation_process_template_arguments( - model::template_trait *parent, - std::deque> - & /*template_base_params*/, - const clang::ArrayRef &template_args, - model::template_trait &template_instantiation, - const std::string &full_template_specialization_name, - const clang::TemplateDecl *template_decl) -{ - for (const auto &arg : template_args) { - const auto argument_kind = arg.getKind(); - std::optional argument; - if (argument_kind == clang::TemplateArgument::Template) { - argument = - build_template_instantiation_process_template_argument(arg); - } - else if (argument_kind == clang::TemplateArgument::Type) { - argument = build_template_instantiation_process_type_argument( - parent, full_template_specialization_name, template_decl, arg, - template_instantiation); - } - else if (argument_kind == clang::TemplateArgument::Integral) { - argument = - build_template_instantiation_process_integral_argument(arg); - } - else if (argument_kind == clang::TemplateArgument::Expression) { - argument = - build_template_instantiation_process_expression_argument(arg); - } - else { - LOG_INFO("Unsupported argument type {}", arg.getKind()); - continue; - } - - simplify_system_template(argument.value(), - argument.value().to_string(config().using_namespace(), false)); - - template_instantiation.add_template(std::move(argument.value())); - } -} - -template_parameter translation_unit_visitor:: - build_template_instantiation_process_template_argument( - const clang::TemplateArgument &arg) const -{ - auto arg_name = - arg.getAsTemplate().getAsTemplateDecl()->getQualifiedNameAsString(); - return template_parameter::make_template_type(arg_name); -} - -template_parameter translation_unit_visitor:: - build_template_instantiation_process_integral_argument( - const clang::TemplateArgument &arg) const -{ - assert(arg.getKind() == clang::TemplateArgument::Integral); - - return template_parameter::make_argument( - std::to_string(arg.getAsIntegral().getExtValue())); -} - -template_parameter translation_unit_visitor:: - build_template_instantiation_process_expression_argument( - const clang::TemplateArgument &arg) const -{ - assert(arg.getKind() == clang::TemplateArgument::Expression); - return template_parameter::make_argument(common::get_source_text( - arg.getAsExpr()->getSourceRange(), source_manager())); -} - -void translation_unit_visitor:: - build_template_instantiation_process_tag_argument( - model::template_trait & /*template_instantiation*/, - const std::string & /*full_template_specialization_name*/, - const clang::TemplateDecl *template_decl, - const clang::TemplateArgument &arg, - common::model::template_parameter &argument) const -{ - assert(arg.getKind() == clang::TemplateArgument::Type); - - argument.is_template_parameter(false); - argument.set_type( - common::to_string(arg.getAsType(), template_decl->getASTContext())); -} - -common::model::template_parameter -translation_unit_visitor::build_template_instantiation_process_type_argument( - model::template_trait * /*parent*/, - const std::string &full_template_specialization_name, - const clang::TemplateDecl *template_decl, - const clang::TemplateArgument &arg, - model::template_trait &template_instantiation) -{ - assert(arg.getKind() == clang::TemplateArgument::Type); - - std::optional argument; - - // If this is a nested template type - add nested templates as - // template arguments - if (const auto *function_template_type = - arg.getAsType()->getAs(); - function_template_type != nullptr) { - // TODO - argument = template_parameter::make_argument( - common::to_string(function_template_type->getReturnType(), - template_decl->getASTContext())); - } - else if (const auto *nested_template_type = - arg.getAsType()->getAs(); - nested_template_type != nullptr) { - - const auto nested_template_name = - nested_template_type->getTemplateName() - .getAsTemplateDecl() - ->getQualifiedNameAsString(); - - argument = template_parameter::make_argument(nested_template_name); - - // Check if this template should be simplified (e.g. system - // template aliases such as 'std:basic_string' should - // be simply 'std::string') - simplify_system_template(*argument, - argument.value().to_string(config().using_namespace(), false)); - } - else if (arg.getAsType()->getAs() != nullptr) { - argument = template_parameter::make_template_type( - common::to_string(arg.getAsType(), template_decl->getASTContext())); - } - else { - argument = template_parameter::make_argument({}); - // This is just a regular record type - build_template_instantiation_process_tag_argument( - template_instantiation, full_template_specialization_name, - template_decl, arg, *argument); - } - - return *argument; -} - std::unique_ptr -translation_unit_visitor::process_template_specialization( +translation_unit_visitor::process_class_template_specialization( clang::ClassTemplateSpecializationDecl *cls) { - auto c_ptr{std::make_unique(config_.using_namespace())}; + auto c_ptr{std::make_unique(config().using_namespace())}; tbuilder().build_from_class_template_specialization(*c_ptr, *cls); @@ -1919,386 +1668,6 @@ translation_unit_visitor::process_template_specialization( return c_ptr; } -void translation_unit_visitor::process_template_specialization_argument( - const clang::ClassTemplateSpecializationDecl *cls, - model::class_ &template_instantiation, const clang::TemplateArgument &arg, - size_t argument_index, bool /*in_parameter_pack*/) -{ - const auto argument_kind = arg.getKind(); - - if (argument_kind == clang::TemplateArgument::Type) { - auto argument = template_parameter::make_argument({}); - argument.is_template_parameter(false); - - // If this is a nested template type - add nested templates as - // template arguments - if (const auto *nested_template_type = - arg.getAsType()->getAs(); - nested_template_type != nullptr) { - - const auto nested_template_name = - nested_template_type->getTemplateName() - .getAsTemplateDecl() - ->getQualifiedNameAsString(); - - argument.set_type(nested_template_name); - - auto nested_template_instantiation = build_template_instantiation( - *nested_template_type, &template_instantiation); - - argument.set_id(nested_template_instantiation->id()); - - for (const auto &t : - nested_template_instantiation->template_params()) - argument.add_template_param(t); - - // Check if this template should be simplified (e.g. system - // template aliases such as 'std:basic_string' should be - // simply 'std::string') - simplify_system_template(argument, - argument.to_string(config().using_namespace(), false)); - } - else if (arg.getAsType()->getAs() != - nullptr) { - auto type_name = - common::to_string(arg.getAsType(), cls->getASTContext()); - - // clang does not provide declared template parameter/argument - // names in template specializations - so we have to extract - // them from raw source code... - if (type_name.find("type-parameter-") == 0) { - auto declaration_text = common::get_source_text_raw( - cls->getSourceRange(), source_manager()); - - declaration_text = declaration_text.substr( - declaration_text.find(cls->getNameAsString()) + - cls->getNameAsString().size() + 1); - - auto template_params = common::parse_unexposed_template_params( - declaration_text, [](const auto &t) { return t; }); - - if (template_params.size() > argument_index) - type_name = template_params[argument_index].to_string( - config().using_namespace(), false); - else { - LOG_DBG("Failed to find type specialization for argument " - "{} at index {} in declaration \n===\n{}\n===\n", - type_name, argument_index, declaration_text); - } - } - - argument.set_type(type_name); - } - else if ((arg.getAsType()->getAsCXXRecordDecl() != nullptr) && - arg.getAsType()->getAsCXXRecordDecl()->isLambda()) { - const auto maybe_id = - get_unique_id(arg.getAsType()->getAsCXXRecordDecl()->getID()); - if (maybe_id.has_value()) { - argument.set_type( - get_participant(maybe_id.value()).value().full_name(false)); - } - else { - const auto type_name = - make_lambda_name(arg.getAsType()->getAsCXXRecordDecl()); - argument.set_type(type_name); - } - } - else { - auto type_name = - common::to_string(arg.getAsType(), cls->getASTContext()); - if (type_name.find('<') != std::string::npos) { - // Sometimes template instantiation is reported as - // RecordType in the AST and getAs to - // TemplateSpecializationType returns null pointer so we - // have to at least make sure it's properly formatted - // (e.g. std:integral_constant, or any template - // specialization which contains it - see t00038) - process_unexposed_template_specialization_parameters( - type_name.substr(type_name.find('<') + 1, - type_name.size() - (type_name.find('<') + 2)), - argument, template_instantiation); - - argument.set_type(type_name.substr(0, type_name.find('<'))); - } - else if (type_name.find("type-parameter-") == 0) { - auto declaration_text = common::get_source_text_raw( - cls->getSourceRange(), source_manager()); - - declaration_text = declaration_text.substr( - declaration_text.find(cls->getNameAsString()) + - cls->getNameAsString().size() + 1); - - auto template_params = common::parse_unexposed_template_params( - declaration_text, [](const auto &t) { return t; }); - - if (template_params.size() > argument_index) - type_name = template_params[argument_index].to_string( - config().using_namespace(), false); - else { - LOG_DBG("Failed to find type specialization for argument " - "{} at index {} in declaration \n===\n{}\n===\n", - type_name, argument_index, declaration_text); - } - - // Otherwise just set the name for the template argument to - // whatever clang says - if (template_params.size() > argument_index && - template_params[argument_index].type()) - argument.set_type(type_name); - else - argument.set_name(type_name); - } - else - argument.set_type(type_name); - } - - simplify_system_template( - argument, argument.to_string(config().using_namespace(), false)); - - LOG_TRACE("Adding template instantiation argument {}", - argument.to_string(config().using_namespace(), false)); - - template_instantiation.add_template(std::move(argument)); - } - else if (argument_kind == clang::TemplateArgument::Integral) { - auto argument = template_parameter::make_argument( - std::to_string(arg.getAsIntegral().getExtValue())); - template_instantiation.add_template(std::move(argument)); - } - else if (argument_kind == clang::TemplateArgument::Expression) { - auto argument = - template_parameter::make_argument(common::get_source_text( - arg.getAsExpr()->getSourceRange(), source_manager())); - template_instantiation.add_template(std::move(argument)); - } - else if (argument_kind == clang::TemplateArgument::TemplateExpansion) { - // TODO - } - else if (argument_kind == clang::TemplateArgument::Pack) { - // This will only work for now if pack is at the end - size_t argument_pack_index{argument_index}; - for (const auto &template_argument : arg.getPackAsArray()) { - process_template_specialization_argument(cls, - template_instantiation, template_argument, - argument_pack_index++, true); - } - } - else { - LOG_INFO("Unsupported template argument kind {} [{}]", arg.getKind(), - cls->getLocation().printToString(source_manager())); - } -} - -std::unique_ptr -translation_unit_visitor::build_template_instantiation( - const clang::TemplateSpecializationType &template_type_decl, - model::class_ *parent) -{ - // TODO: Make sure we only build instantiation once - - // - // Here we'll hold the template base params to replace with the - // instantiated values - // - std::deque> - template_base_params{}; - - const auto *template_type_ptr = &template_type_decl; - if (template_type_decl.isTypeAlias() && - (template_type_decl.getAliasedType() - ->getAs() != nullptr)) - template_type_ptr = template_type_decl.getAliasedType() - ->getAs(); - - const auto &template_type = *template_type_ptr; - - // - // Create class_ instance to hold the template instantiation - // - auto template_instantiation_ptr = - std::make_unique(config_.using_namespace()); - auto &template_instantiation = *template_instantiation_ptr; - std::string full_template_specialization_name = common::to_string( - template_type.desugar(), - template_type.getTemplateName().getAsTemplateDecl()->getASTContext()); - - auto *template_decl{template_type.getTemplateName().getAsTemplateDecl()}; - - auto template_decl_qualified_name = - template_decl->getQualifiedNameAsString(); - - auto *class_template_decl{ - clang::dyn_cast(template_decl)}; - - if ((class_template_decl != nullptr) && - (class_template_decl->getTemplatedDecl() != nullptr) && - (class_template_decl->getTemplatedDecl()->getParent() != nullptr) && - class_template_decl->getTemplatedDecl()->getParent()->isRecord()) { - - common::model::namespace_ ns{ - common::get_tag_namespace(*class_template_decl->getTemplatedDecl() - ->getParent() - ->getOuterLexicalRecordContext())}; - - std::string ns_str = ns.to_string(); - std::string name = template_decl->getQualifiedNameAsString(); - if (!ns_str.empty()) { - name = name.substr(ns_str.size() + 2); - } - - util::replace_all(name, "::", "##"); - template_instantiation.set_name(name); - - template_instantiation.set_namespace(ns); - } - else { - common::model::namespace_ ns{template_decl_qualified_name}; - ns.pop_back(); - template_instantiation.set_name(template_decl->getNameAsString()); - template_instantiation.set_namespace(ns); - } - - // TODO: Refactor handling of base parameters to a separate method - - // We need this to match any possible base classes coming from template - // arguments - std::vector< - std::pair> - template_parameter_names{}; - - for (const auto *parameter : *template_decl->getTemplateParameters()) { - if (parameter->isTemplateParameter() && - (parameter->isTemplateParameterPack() || - parameter->isParameterPack())) { - template_parameter_names.emplace_back( - parameter->getNameAsString(), true); - } - else - template_parameter_names.emplace_back( - parameter->getNameAsString(), false); - } - - // Check if the primary template has any base classes - int base_index = 0; - - const auto *templated_class_decl = - clang::dyn_cast_or_null( - template_decl->getTemplatedDecl()); - - if ((templated_class_decl != nullptr) && - templated_class_decl->hasDefinition()) - for (const auto &base : templated_class_decl->bases()) { - const auto base_class_name = common::to_string( - base.getType(), templated_class_decl->getASTContext(), false); - - LOG_DBG("Found template instantiation base: {}, {}", - base_class_name, base_index); - - // Check if any of the primary template arguments has a - // parameter equal to this type - auto it = std::find_if(template_parameter_names.begin(), - template_parameter_names.end(), - [&base_class_name]( - const auto &p) { return p.first == base_class_name; }); - - if (it != template_parameter_names.end()) { - const auto ¶meter_name = it->first; - const bool is_variadic = it->second; - // Found base class which is a template parameter - LOG_DBG("Found base class which is a template parameter " - "{}, {}, {}", - parameter_name, is_variadic, - std::distance(template_parameter_names.begin(), it)); - - template_base_params.emplace_back(parameter_name, - std::distance(template_parameter_names.begin(), it), - is_variadic); - } - else { - // This is a regular base class - it is handled by - // process_template - } - base_index++; - } - - build_template_instantiation_process_template_arguments(parent, - template_base_params, template_type.template_arguments(), - template_instantiation, full_template_specialization_name, - template_decl); - - // First try to find the best match for this template in partially - // specialized templates - std::string destination{}; - std::string best_match_full_name{}; - auto full_template_name = template_instantiation.full_name(false); - int best_match{}; - common::id_t best_match_id{0}; - - for (const auto &[id, c] : diagram().participants()) { - const auto *participant_as_class = - dynamic_cast(c.get()); - if (participant_as_class == nullptr) - continue; - - if ((participant_as_class != nullptr) && - (*participant_as_class == template_instantiation)) - continue; - - auto c_full_name = participant_as_class->full_name(false); - auto match = - template_instantiation.calculate_template_specialization_match( - *participant_as_class); - - if (match > best_match) { - best_match = match; - best_match_full_name = c_full_name; - best_match_id = participant_as_class->id(); - } - } - - auto templated_decl_id = - template_type.getTemplateName().getAsTemplateDecl()->getID(); - - if (best_match_id > 0) { - destination = best_match_full_name; - } - else { - LOG_DBG("Cannot determine global id for specialization template {} " - "- delaying until the translation unit is complete ", - templated_decl_id); - } - - template_instantiation.set_id( - common::to_id(template_instantiation_ptr->full_name(false))); - - return template_instantiation_ptr; -} - -void translation_unit_visitor:: - process_unexposed_template_specialization_parameters( - const std::string &type_name, common::model::template_parameter &tp, - model::class_ & /*c*/) const -{ - auto template_params = common::parse_unexposed_template_params( - type_name, [](const std::string &t) { return t; }); - - for (auto ¶m : template_params) { - tp.add_template_param(param); - } -} - -bool translation_unit_visitor::simplify_system_template( - common::model::template_parameter &ct, const std::string &full_name) const -{ - if (config().type_aliases().count(full_name) > 0) { - ct.set_type(config().type_aliases().at(full_name)); - ct.clear_params(); - return true; - } - return false; -} - std::string translation_unit_visitor::simplify_system_template( const std::string &full_name) const { diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.h b/src/sequence_diagram/visitor/translation_unit_visitor.h index 109cf779..11e4aae3 100644 --- a/src/sequence_diagram/visitor/translation_unit_visitor.h +++ b/src/sequence_diagram/visitor/translation_unit_visitor.h @@ -36,6 +36,10 @@ using common::model::template_parameter; std::string to_string(const clang::FunctionTemplateDecl *decl); +using visitor_specialization_t = common::visitor::translation_unit_visitor< + clanguml::config::sequence_diagram, + clanguml::sequence_diagram::model::diagram>; + /** * @brief Sequence diagram translation unit visitor * @@ -44,8 +48,14 @@ std::string to_string(const clang::FunctionTemplateDecl *decl); */ class translation_unit_visitor : public clang::RecursiveASTVisitor, - public common::visitor::translation_unit_visitor { + public visitor_specialization_t { public: + using visitor_specialization_t::config_t; + using visitor_specialization_t::diagram_t; + + using template_builder_t = + common::visitor::template_builder; + /** * @brief Constructor. * @@ -124,27 +134,6 @@ public: bool TraverseConditionalOperator(clang::ConditionalOperator *stmt); /** @} */ - /** - * @brief Get diagram model reference - * - * @return Reference to diagram model created by the visitor - */ - clanguml::sequence_diagram::model::diagram &diagram(); - - /** - * @brief Get diagram model reference - * - * @return Reference to diagram model created by the visitor - */ - const clanguml::sequence_diagram::model::diagram &diagram() const; - - /** - * @brief Get diagram config instance - * - * @return Reference to config instance - */ - const clanguml::config::sequence_diagram &config() const; - /** * @brief Get current call expression context reference * @@ -255,6 +244,9 @@ public: */ void finalize(); + std::unique_ptr create_element( + const clang::NamedDecl *decl) const; + private: /** * @brief Check if the diagram should include a declaration. @@ -312,21 +304,12 @@ private: */ bool should_include(const clang::ClassTemplateDecl *decl) const; - /** - * @todo #227 Refactor this group of methods to @ref template_builder - * - * @{ - */ std::unique_ptr create_class_model(clang::CXXRecordDecl *cls); std::unique_ptr create_method_model(clang::CXXMethodDecl *cls); - bool process_template_parameters( - const clang::TemplateDecl &template_declaration, - common::model::template_trait &c); - std::unique_ptr build_function_template_instantiation(const clang::FunctionDecl &pDecl); @@ -336,63 +319,10 @@ private: std::unique_ptr build_function_template( const clang::FunctionTemplateDecl &declaration); - void build_template_instantiation_process_template_arguments( - model::template_trait *parent, - std::deque> &template_base_params, - const clang::ArrayRef &template_args, - model::template_trait &template_instantiation, - const std::string &full_template_specialization_name, - const clang::TemplateDecl *template_decl); - - common::model::template_parameter - build_template_instantiation_process_template_argument( - const clang::TemplateArgument &arg) const; - - common::model::template_parameter - build_template_instantiation_process_integral_argument( - const clang::TemplateArgument &arg) const; - - common::model::template_parameter - build_template_instantiation_process_expression_argument( - const clang::TemplateArgument &arg) const; - - void build_template_instantiation_process_tag_argument( - model::template_trait &template_instantiation, - const std::string &full_template_specialization_name, - const clang::TemplateDecl *template_decl, - const clang::TemplateArgument &arg, - common::model::template_parameter &argument) const; - - common::model::template_parameter - build_template_instantiation_process_type_argument( - model::template_trait *parent, - const std::string &full_template_specialization_name, - const clang::TemplateDecl *template_decl, - const clang::TemplateArgument &arg, - model::template_trait &template_instantiation); - - std::unique_ptr process_template_specialization( + std::unique_ptr process_class_template_specialization( clang::ClassTemplateSpecializationDecl *cls); - void process_template_specialization_argument( - const clang::ClassTemplateSpecializationDecl *cls, - model::class_ &template_instantiation, - const clang::TemplateArgument &arg, size_t argument_index, - bool in_parameter_pack = false); - - void process_unexposed_template_specialization_parameters( - const std::string &type_name, common::model::template_parameter &tp, - model::class_ &c) const; - - std::unique_ptr build_template_instantiation( - const clang::TemplateSpecializationType &template_type_decl, - model::class_ *parent); - - bool simplify_system_template(common::model::template_parameter &ct, - const std::string &full_name) const; - std::string simplify_system_template(const std::string &full_name) const; - /** }@ */ /** * @brief Assuming `cls` is a lambda, create it's full name. @@ -516,13 +446,7 @@ private: * * @return Reference to 'template_builder' instance */ - common::visitor::template_builder &tbuilder() { return template_builder_; } - - // Reference to the output diagram model - clanguml::sequence_diagram::model::diagram &diagram_; - - // Reference to class diagram config - const clanguml::config::sequence_diagram &config_; + template_builder_t &tbuilder() { return template_builder_; } call_expression_context call_expression_context_; @@ -558,6 +482,6 @@ private: mutable std::set> processed_comments_; - common::visitor::template_builder template_builder_; + template_builder_t template_builder_; }; } // namespace clanguml::sequence_diagram::visitor diff --git a/tests/t20040/.clang-uml b/tests/t20040/.clang-uml new file mode 100644 index 00000000..0e2bcb05 --- /dev/null +++ b/tests/t20040/.clang-uml @@ -0,0 +1,11 @@ +diagrams: + t20040_sequence: + type: sequence + glob: + - t20040.cc + include: + namespaces: + - clanguml::t20040 + using_namespace: clanguml::t20040 + from: + - function: "clanguml::t20040::tmain()" \ No newline at end of file diff --git a/tests/t20040/t20040.cc b/tests/t20040/t20040.cc new file mode 100644 index 00000000..58d452ae --- /dev/null +++ b/tests/t20040/t20040.cc @@ -0,0 +1,32 @@ +#include +#include + +namespace clanguml { +namespace t20040 { +void print() { } + +template void print(T head, Ts... tail) +{ + std::cout << head << std::endl; + print(tail...); +} + +template void doublePrint(Ts... args) +{ + print(args + args...); +} + +void tmain() +{ + using namespace std::literals::string_literals; + + print(1, 3.14, "test"s); + + doublePrint("test"s, 2024 / 2); + + // TODO: Add separate test case for variadic class template sequence diagram + + // TODO: Add overload pattern test case +} +} +} \ No newline at end of file diff --git a/tests/t20040/test_case.h b/tests/t20040/test_case.h new file mode 100644 index 00000000..ffb4998b --- /dev/null +++ b/tests/t20040/test_case.h @@ -0,0 +1,62 @@ +/** + * tests/t20040/test_case.h + * + * Copyright (c) 2021-2024 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +TEST_CASE("t20040", "[test-case][sequence]") +{ + auto [config, db] = load_config("t20040"); + + auto diagram = config.diagrams["t20040_sequence"]; + + REQUIRE(diagram->name == "t20040_sequence"); + + auto model = generate_sequence_diagram(*db, diagram); + + REQUIRE(model->name() == "t20040_sequence"); + + { + auto src = generate_sequence_puml(diagram, *model); + AliasMatcher _A(src); + + REQUIRE_THAT(src, StartsWith("@startuml")); + REQUIRE_THAT(src, EndsWith("@enduml\n")); + + REQUIRE_THAT(src, + HasCall(_A("tmain()"), + _A("print(int,double,std::string)"), + "")); + + save_puml(config.output_directory(), diagram->name + ".puml", src); + } + + { + auto j = generate_sequence_json(diagram, *model); + + using namespace json; + + save_json(config.output_directory(), diagram->name + ".json", j); + } + + { + auto src = generate_sequence_mermaid(diagram, *model); + + mermaid::AliasMatcher _A(src); + using mermaid::IsClass; + + save_mermaid(config.output_directory(), diagram->name + ".mmd", src); + } +} \ No newline at end of file diff --git a/tests/test_cases.cc b/tests/test_cases.cc index 93a02baa..d74a9283 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -461,6 +461,7 @@ using namespace clanguml::test::matchers; #include "t20037/test_case.h" #include "t20038/test_case.h" #include "t20039/test_case.h" +#include "t20040/test_case.h" /// /// Package diagram tests From 3af55f1e78c31756db6b206017f831f375d74d5c Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Sun, 11 Feb 2024 23:52:32 +0100 Subject: [PATCH 3/7] Added variadic class template recursive call sequence diagram --- tests/t20039/test_case.h | 13 +++++- tests/t20040/test_case.h | 31 +++++++++++++- tests/t20041/.clang-uml | 11 +++++ tests/t20041/t20041.cc | 31 ++++++++++++++ tests/t20041/test_case.h | 89 ++++++++++++++++++++++++++++++++++++++++ tests/test_cases.cc | 1 + tests/test_cases.yaml | 6 +++ 7 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 tests/t20041/.clang-uml create mode 100644 tests/t20041/t20041.cc create mode 100644 tests/t20041/test_case.h diff --git a/tests/t20039/test_case.h b/tests/t20039/test_case.h index b6f1d976..316d20e0 100644 --- a/tests/t20039/test_case.h +++ b/tests/t20039/test_case.h @@ -59,8 +59,17 @@ TEST_CASE("t20039", "[test-case][sequence]") { auto src = generate_sequence_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; + mermaid::SequenceDiagramAliasMatcher _A(src); + using mermaid::HasCall; + + REQUIRE_THAT(src, HasCall(_A("tmain()"), _A("R"), "run()")); + REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int)")); + REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int_vec_t)")); + REQUIRE_THAT( + src, HasCall(_A("R"), _A("A"), "a(string_vec_t)")); + REQUIRE_THAT(src, HasCall(_A("R"), _A("A"), "a(int_map_t)")); + REQUIRE_THAT( + src, HasCall(_A("R"), _A("A"), "a(string_map_t)")); save_mermaid(config.output_directory(), diagram->name + ".mmd", src); } diff --git a/tests/t20040/test_case.h b/tests/t20040/test_case.h index ffb4998b..9ff98228 100644 --- a/tests/t20040/test_case.h +++ b/tests/t20040/test_case.h @@ -40,6 +40,17 @@ TEST_CASE("t20040", "[test-case][sequence]") _A("print(int,double,std::string)"), "")); + REQUIRE_THAT(src, + HasCall(_A("print(int,double,std::string)"), + _A("print(double,std::string)"), "")); + + REQUIRE_THAT(src, + HasCall(_A("print(double,std::string)"), + _A("print(std::string)"), "")); + + REQUIRE_THAT(src, + HasCall(_A("print(std::string)"), _A("print()"), "")); + save_puml(config.output_directory(), diagram->name + ".puml", src); } @@ -54,8 +65,24 @@ TEST_CASE("t20040", "[test-case][sequence]") { auto src = generate_sequence_mermaid(diagram, *model); - mermaid::AliasMatcher _A(src); - using mermaid::IsClass; + mermaid::SequenceDiagramAliasMatcher _A(src); + using mermaid::HasCall; + + REQUIRE_THAT(src, + HasCall(_A("tmain()"), + _A("print(int,double,std::string)"), + "")); + + REQUIRE_THAT(src, + HasCall(_A("print(int,double,std::string)"), + _A("print(double,std::string)"), "")); + + REQUIRE_THAT(src, + HasCall(_A("print(double,std::string)"), + _A("print(std::string)"), "")); + + REQUIRE_THAT(src, + HasCall(_A("print(std::string)"), _A("print()"), "")); save_mermaid(config.output_directory(), diagram->name + ".mmd", src); } diff --git a/tests/t20041/.clang-uml b/tests/t20041/.clang-uml new file mode 100644 index 00000000..f711b899 --- /dev/null +++ b/tests/t20041/.clang-uml @@ -0,0 +1,11 @@ +diagrams: + t20041_sequence: + type: sequence + glob: + - t20041.cc + include: + namespaces: + - clanguml::t20041 + using_namespace: clanguml::t20041 + from: + - function: "clanguml::t20041::tmain()" \ No newline at end of file diff --git a/tests/t20041/t20041.cc b/tests/t20041/t20041.cc new file mode 100644 index 00000000..03dffe9f --- /dev/null +++ b/tests/t20041/t20041.cc @@ -0,0 +1,31 @@ +#include +#include + +namespace clanguml { +namespace t20041 { + +template struct A; + +template struct A { + void print(First first, Rest... rest) + { + std::cout << first << std::endl; + + A a; + a.print(rest...); + } +}; + +template <> struct A<> { + void print() { } +}; + +void tmain() +{ + using namespace std::literals::string_literals; + + A a; + a.print(1, 3.14, "test"s); +} +} +} \ No newline at end of file diff --git a/tests/t20041/test_case.h b/tests/t20041/test_case.h new file mode 100644 index 00000000..c3198068 --- /dev/null +++ b/tests/t20041/test_case.h @@ -0,0 +1,89 @@ +/** + * tests/t20041/test_case.h + * + * Copyright (c) 2021-2024 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +TEST_CASE("t20041", "[test-case][sequence]") +{ + auto [config, db] = load_config("t20041"); + + auto diagram = config.diagrams["t20041_sequence"]; + + REQUIRE(diagram->name == "t20041_sequence"); + + auto model = generate_sequence_diagram(*db, diagram); + + REQUIRE(model->name() == "t20041_sequence"); + + { + auto src = generate_sequence_puml(diagram, *model); + AliasMatcher _A(src); + + REQUIRE_THAT(src, StartsWith("@startuml")); + REQUIRE_THAT(src, EndsWith("@enduml\n")); + + REQUIRE_THAT(src, + HasCall(_A("tmain()"), _A("A"), + "print(int,double,std::string)")); + REQUIRE_THAT(src, + HasCall(_A("A"), + _A("A"), "print(double,std::string)")); + REQUIRE_THAT(src, + HasCall(_A("A"), _A("A"), + "print(std::string)")); + REQUIRE_THAT(src, HasCall(_A("A"), _A("A"), "print()")); + + save_puml(config.output_directory(), diagram->name + ".puml", src); + } + + { + auto j = generate_sequence_json(diagram, *model); + + using namespace json; + + std::vector messages = { + FindMessage(j, "tmain()", "A", + "print(int,double,std::string)"), + FindMessage(j, "A", "A", + "print(double,std::string)"), + FindMessage(j, "A", "A", + "print(std::string)"), + FindMessage(j, "A", "A", "print()")}; + + REQUIRE(std::is_sorted(messages.begin(), messages.end())); + + save_json(config.output_directory(), diagram->name + ".json", j); + } + + { + auto src = generate_sequence_mermaid(diagram, *model); + + mermaid::SequenceDiagramAliasMatcher _A(src); + using mermaid::HasCall; + + REQUIRE_THAT(src, + HasCall(_A("tmain()"), _A("A"), + "print(int,double,std::string)")); + REQUIRE_THAT(src, + HasCall(_A("A"), + _A("A"), "print(double,std::string)")); + REQUIRE_THAT(src, + HasCall(_A("A"), _A("A"), + "print(std::string)")); + + save_mermaid(config.output_directory(), diagram->name + ".mmd", src); + } +} \ No newline at end of file diff --git a/tests/test_cases.cc b/tests/test_cases.cc index d74a9283..b851f1fb 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -462,6 +462,7 @@ using namespace clanguml::test::matchers; #include "t20038/test_case.h" #include "t20039/test_case.h" #include "t20040/test_case.h" +#include "t20041/test_case.h" /// /// Package diagram tests diff --git a/tests/test_cases.yaml b/tests/test_cases.yaml index 5bc0fba0..ce5f9cec 100644 --- a/tests/test_cases.yaml +++ b/tests/test_cases.yaml @@ -331,6 +331,12 @@ test_cases: - name: t20039 title: Test case for type aliases config option in sequence diagrams description: + - name: t20040 + title: Test case for recursive variadic template function call + description: + - name: t20041 + title: Test case for recursive variadic template class call + description: Package diagrams: - name: t30001 title: Basic package diagram test case From 09e18125095f13dd8e32dfa3fe351057d4af8054 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Mon, 12 Feb 2024 00:23:54 +0100 Subject: [PATCH 4/7] Added variable template base class overload pattern sequence diagram test case --- tests/t20040/t20040.cc | 4 --- tests/t20042/.clang-uml | 11 ++++++ tests/t20042/t20042.cc | 30 ++++++++++++++++ tests/t20042/test_case.h | 75 ++++++++++++++++++++++++++++++++++++++++ tests/test_cases.cc | 1 + tests/test_cases.yaml | 3 ++ 6 files changed, 120 insertions(+), 4 deletions(-) create mode 100644 tests/t20042/.clang-uml create mode 100644 tests/t20042/t20042.cc create mode 100644 tests/t20042/test_case.h diff --git a/tests/t20040/t20040.cc b/tests/t20040/t20040.cc index 58d452ae..cffd74f1 100644 --- a/tests/t20040/t20040.cc +++ b/tests/t20040/t20040.cc @@ -23,10 +23,6 @@ void tmain() print(1, 3.14, "test"s); doublePrint("test"s, 2024 / 2); - - // TODO: Add separate test case for variadic class template sequence diagram - - // TODO: Add overload pattern test case } } } \ No newline at end of file diff --git a/tests/t20042/.clang-uml b/tests/t20042/.clang-uml new file mode 100644 index 00000000..a278f580 --- /dev/null +++ b/tests/t20042/.clang-uml @@ -0,0 +1,11 @@ +diagrams: + t20042_sequence: + type: sequence + glob: + - t20042.cc + include: + namespaces: + - clanguml::t20042 + using_namespace: clanguml::t20042 + from: + - function: "clanguml::t20042::tmain()" \ No newline at end of file diff --git a/tests/t20042/t20042.cc b/tests/t20042/t20042.cc new file mode 100644 index 00000000..57dca400 --- /dev/null +++ b/tests/t20042/t20042.cc @@ -0,0 +1,30 @@ +namespace clanguml { +namespace t20042 { +struct A { }; +struct AHandler { + void handle(A &a) const { } + void operator()(A &a) const { handle(a); } +}; + +struct B { }; +struct BHandler { + void handle(B &b) const { } + void operator()(B &b) const { handle(b); } +}; + +template struct Overload : public Bases... { + using Bases::operator()...; +}; +template Overload(Bases...) -> Overload; + +void tmain() +{ + Overload dispatch; + A a; + B b; + + dispatch(a); + dispatch(b); +} +} +} \ No newline at end of file diff --git a/tests/t20042/test_case.h b/tests/t20042/test_case.h new file mode 100644 index 00000000..3e2276d8 --- /dev/null +++ b/tests/t20042/test_case.h @@ -0,0 +1,75 @@ +/** + * tests/t20042/test_case.h + * + * Copyright (c) 2021-2024 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +TEST_CASE("t20042", "[test-case][sequence]") +{ + auto [config, db] = load_config("t20042"); + + auto diagram = config.diagrams["t20042_sequence"]; + + REQUIRE(diagram->name == "t20042_sequence"); + + auto model = generate_sequence_diagram(*db, diagram); + + REQUIRE(model->name() == "t20042_sequence"); + + { + auto src = generate_sequence_puml(diagram, *model); + AliasMatcher _A(src); + + REQUIRE_THAT(src, StartsWith("@startuml")); + REQUIRE_THAT(src, EndsWith("@enduml\n")); + + REQUIRE_THAT(src, + HasCall(_A("tmain()"), _A("AHandler"), "operator()(A &) const")); + REQUIRE_THAT( + src, HasCall(_A("AHandler"), _A("AHandler"), "handle(A &) const")); + REQUIRE_THAT(src, + HasCall(_A("tmain()"), _A("BHandler"), "operator()(B &) const")); + REQUIRE_THAT( + src, HasCall(_A("BHandler"), _A("BHandler"), "handle(B &) const")); + + save_puml(config.output_directory(), diagram->name + ".puml", src); + } + + { + auto j = generate_sequence_json(diagram, *model); + + using namespace json; + + save_json(config.output_directory(), diagram->name + ".json", j); + } + + { + auto src = generate_sequence_mermaid(diagram, *model); + + mermaid::SequenceDiagramAliasMatcher _A(src); + using mermaid::HasCall; + + REQUIRE_THAT(src, + HasCall(_A("tmain()"), _A("AHandler"), "operator()(A &) const")); + REQUIRE_THAT( + src, HasCall(_A("AHandler"), _A("AHandler"), "handle(A &) const")); + REQUIRE_THAT(src, + HasCall(_A("tmain()"), _A("BHandler"), "operator()(B &) const")); + REQUIRE_THAT( + src, HasCall(_A("BHandler"), _A("BHandler"), "handle(B &) const")); + + save_mermaid(config.output_directory(), diagram->name + ".mmd", src); + } +} \ No newline at end of file diff --git a/tests/test_cases.cc b/tests/test_cases.cc index b851f1fb..1afcb86d 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -463,6 +463,7 @@ using namespace clanguml::test::matchers; #include "t20039/test_case.h" #include "t20040/test_case.h" #include "t20041/test_case.h" +#include "t20042/test_case.h" /// /// Package diagram tests diff --git a/tests/test_cases.yaml b/tests/test_cases.yaml index ce5f9cec..a2cde08f 100644 --- a/tests/test_cases.yaml +++ b/tests/test_cases.yaml @@ -337,6 +337,9 @@ test_cases: - name: t20041 title: Test case for recursive variadic template class call description: + - name: t20042 + title: Test case for template overload pattern + description: Package diagrams: - name: t30001 title: Basic package diagram test case From d305902e3c2ee940f2e92d286f9c838c548d3856 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Tue, 13 Feb 2024 00:05:07 +0100 Subject: [PATCH 5/7] Added variable template base class overload pattern class diagram test case --- tests/t00073/.clang-uml | 9 ++++ tests/t00073/t00073.cc | 24 ++++++++++ tests/t00073/test_case.h | 96 ++++++++++++++++++++++++++++++++++++++++ tests/test_cases.cc | 1 + tests/test_cases.yaml | 3 ++ 5 files changed, 133 insertions(+) create mode 100644 tests/t00073/.clang-uml create mode 100644 tests/t00073/t00073.cc create mode 100644 tests/t00073/test_case.h diff --git a/tests/t00073/.clang-uml b/tests/t00073/.clang-uml new file mode 100644 index 00000000..2e0a42d9 --- /dev/null +++ b/tests/t00073/.clang-uml @@ -0,0 +1,9 @@ +diagrams: + t00073_class: + type: class + glob: + - t00073.cc + include: + namespaces: + - clanguml::t00073 + using_namespace: clanguml::t00073 \ No newline at end of file diff --git a/tests/t00073/t00073.cc b/tests/t00073/t00073.cc new file mode 100644 index 00000000..f16faad0 --- /dev/null +++ b/tests/t00073/t00073.cc @@ -0,0 +1,24 @@ +namespace clanguml { +namespace t00073 { +struct A { }; +struct AHandler { + void handle(A &a) const { } + void operator()(A &a) const { handle(a); } +}; + +struct B { }; +struct BHandler { + void handle(B &b) const { } + void operator()(B &b) const { handle(b); } +}; + +template struct Overload : public Bases... { + using Bases::operator()...; +}; +template Overload(Bases...) -> Overload; + +struct R { + Overload dispatch; +}; +} +} \ No newline at end of file diff --git a/tests/t00073/test_case.h b/tests/t00073/test_case.h new file mode 100644 index 00000000..68af72fd --- /dev/null +++ b/tests/t00073/test_case.h @@ -0,0 +1,96 @@ +/** + * tests/t00073/test_case.h + * + * Copyright (c) 2021-2024 Bartek Kryza + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +TEST_CASE("t00073", "[test-case][class]") +{ + auto [config, db] = load_config("t00073"); + + auto diagram = config.diagrams["t00073_class"]; + + REQUIRE(diagram->name == "t00073_class"); + + auto model = generate_class_diagram(*db, diagram); + + REQUIRE(model->name() == "t00073_class"); + + { + auto src = generate_class_puml(diagram, *model); + AliasMatcher _A(src); + + REQUIRE_THAT(src, StartsWith("@startuml")); + REQUIRE_THAT(src, EndsWith("@enduml\n")); + + REQUIRE_THAT(src, IsClass(_A("A"))); + REQUIRE_THAT(src, IsClass(_A("B"))); + REQUIRE_THAT(src, IsClass(_A("AHandler"))); + REQUIRE_THAT(src, IsClass(_A("BHandler"))); + REQUIRE_THAT(src, IsClassTemplate("Overload", "Bases...")); + REQUIRE_THAT(src, IsClassTemplate("Overload", "AHandler,BHandler")); + + REQUIRE_THAT(src, IsDependency(_A("AHandler"), _A("A"))); + REQUIRE_THAT(src, IsDependency(_A("BHandler"), _A("B"))); + REQUIRE_THAT(src, + IsInstantiation( + _A("Overload"), _A("Overload"))); + REQUIRE_THAT(src, + IsAggregation( + _A("R"), _A("Overload"), "+dispatch")); + + save_puml(config.output_directory(), diagram->name + ".puml", src); + } + + { + auto j = generate_class_json(diagram, *model); + + using namespace json; + + REQUIRE(IsClassTemplate(j, "Overload")); + REQUIRE(IsClass(j, "A")); + REQUIRE(IsClass(j, "B")); + REQUIRE(IsClass(j, "AHandler")); + REQUIRE(IsClass(j, "BHandler")); + REQUIRE(IsClass(j, "Overload")); + + save_json(config.output_directory(), diagram->name + ".json", j); + } + + { + auto src = generate_class_mermaid(diagram, *model); + + mermaid::AliasMatcher _A(src); + using mermaid::IsClass; + + REQUIRE_THAT(src, IsClass(_A("A"))); + REQUIRE_THAT(src, IsClass(_A("B"))); + REQUIRE_THAT(src, IsClass(_A("AHandler"))); + REQUIRE_THAT(src, IsClass(_A("BHandler"))); + REQUIRE_THAT(src, IsClass(_A("Overload"))); + REQUIRE_THAT(src, IsClass(_A("Overload"))); + + REQUIRE_THAT(src, IsDependency(_A("AHandler"), _A("A"))); + REQUIRE_THAT(src, IsDependency(_A("BHandler"), _A("B"))); + REQUIRE_THAT(src, + IsInstantiation( + _A("Overload"), _A("Overload"))); + REQUIRE_THAT(src, + IsAggregation( + _A("R"), _A("Overload"), "+dispatch")); + + save_mermaid(config.output_directory(), diagram->name + ".mmd", src); + } +} \ No newline at end of file diff --git a/tests/test_cases.cc b/tests/test_cases.cc index 1afcb86d..931c71ce 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -414,6 +414,7 @@ using namespace clanguml::test::matchers; #include "t00071/test_case.h" #include "t00072/test_case.h" #endif +#include "t00073/test_case.h" /// /// Sequence diagram tests diff --git a/tests/test_cases.yaml b/tests/test_cases.yaml index a2cde08f..f4471719 100644 --- a/tests/test_cases.yaml +++ b/tests/test_cases.yaml @@ -213,6 +213,9 @@ test_cases: - name: t00072 title: Class diagram with C++20 module partitions generated as packages description: + - name: t00073 + title: Class diagram for template overload pattern + description: Sequence diagrams: - name: t20001 title: Basic sequence diagram test case From 563014901639bc5a0152a82d6567fd340dc5f5a5 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Tue, 13 Feb 2024 23:42:27 +0100 Subject: [PATCH 6/7] Fixed clang-tidy warnings --- src/common/generators/progress_indicator.cc | 9 ++++++--- src/common/visitor/template_builder.cc | 2 +- src/common/visitor/template_builder.h | 2 +- src/package_diagram/visitor/translation_unit_visitor.cc | 3 ++- src/sequence_diagram/visitor/translation_unit_visitor.cc | 3 ++- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/common/generators/progress_indicator.cc b/src/common/generators/progress_indicator.cc index 5db13a71..ce019d87 100644 --- a/src/common/generators/progress_indicator.cc +++ b/src/common/generators/progress_indicator.cc @@ -72,12 +72,13 @@ void progress_indicator::increment(const std::string &name) auto &p = progress_bar_index_.at(name); auto &bar = progress_bars_[p.index]; - progress_bars_mutex_.unlock(); p.progress++; + bar.set_progress((p.progress * kASTTraverseProgressPercent) / p.max); bar.set_option(indicators::option::PostfixText{ fmt::format("{}/{}", p.progress, p.max)}); + progress_bars_mutex_.unlock(); } void progress_indicator::stop() @@ -104,7 +105,6 @@ void progress_indicator::complete(const std::string &name) auto &p = progress_bar_index_.at(name); auto &bar = progress_bars_[p.index]; - progress_bars_mutex_.unlock(); bar.set_progress(kCompleteProgressPercent); @@ -117,6 +117,8 @@ void progress_indicator::complete(const std::string &name) bar.set_option( indicators::option::ForegroundColor{indicators::Color::green}); bar.mark_as_completed(); + + progress_bars_mutex_.unlock(); } void progress_indicator::fail(const std::string &name) @@ -124,7 +126,6 @@ void progress_indicator::fail(const std::string &name) progress_bars_mutex_.lock(); auto &p = progress_bar_index_.at(name); auto &bar = progress_bars_[p.index]; - progress_bars_mutex_.unlock(); #if _MSC_VER const auto postfix_text = fmt::format("{}/{} FAILED", p.progress, p.max); @@ -134,6 +135,8 @@ void progress_indicator::fail(const std::string &name) bar.set_option(indicators::option::ForegroundColor{indicators::Color::red}); bar.set_option(indicators::option::PostfixText{postfix_text}); bar.mark_as_completed(); + + progress_bars_mutex_.unlock(); } } // namespace clanguml::common::generators \ No newline at end of file diff --git a/src/common/visitor/template_builder.cc b/src/common/visitor/template_builder.cc index 1b232357..f8aaf021 100644 --- a/src/common/visitor/template_builder.cc +++ b/src/common/visitor/template_builder.cc @@ -83,4 +83,4 @@ std::string map_type_parameter_to_template_parameter_name( return type_parameter; } -} // namespace clanguml::class_diagram::visitor +} // namespace clanguml::common::visitor diff --git a/src/common/visitor/template_builder.h b/src/common/visitor/template_builder.h index a8f0f118..ebae7ecc 100644 --- a/src/common/visitor/template_builder.h +++ b/src/common/visitor/template_builder.h @@ -119,7 +119,7 @@ public: void build( clanguml::common::model::template_element &template_instantiation, const clang::NamedDecl *cls, const clang::TemplateDecl *template_decl, - const clang::ArrayRef template_arguments, + clang::ArrayRef template_arguments, std::string full_template_specialization_name, std::optional parent = {}); diff --git a/src/package_diagram/visitor/translation_unit_visitor.cc b/src/package_diagram/visitor/translation_unit_visitor.cc index 15ea040a..850e1aec 100644 --- a/src/package_diagram/visitor/translation_unit_visitor.cc +++ b/src/package_diagram/visitor/translation_unit_visitor.cc @@ -325,7 +325,8 @@ common::id_t translation_unit_visitor::get_package_id(const clang::Decl *cls) return {}; } - else if (config().package_type() == config::package_type_t::kModule) { + + if (config().package_type() == config::package_type_t::kModule) { const auto *module = cls->getOwningModule(); if (module != nullptr) { std::string module_path = module->Name; diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.cc b/src/sequence_diagram/visitor/translation_unit_visitor.cc index fe8f491b..33b5d558 100644 --- a/src/sequence_diagram/visitor/translation_unit_visitor.cc +++ b/src/sequence_diagram/visitor/translation_unit_visitor.cc @@ -33,7 +33,8 @@ translation_unit_visitor::translation_unit_visitor(clang::SourceManager &sm, } std::unique_ptr -translation_unit_visitor::create_element(const clang::NamedDecl *decl) const +translation_unit_visitor::create_element( + const clang::NamedDecl * /*decl*/) const { return std::make_unique( config().using_namespace()); From eedf594c7a20a4de2da0a8b4747ebfbdb8b2c18c Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Wed, 14 Feb 2024 00:17:47 +0100 Subject: [PATCH 7/7] Updated test cases documentation --- docs/test_cases.md | 4 + docs/test_cases/t00002_class.svg | 68 ++-- docs/test_cases/t00002_class_mermaid.svg | 10 +- docs/test_cases/t00003_class.svg | 126 +++--- docs/test_cases/t00003_class_mermaid.svg | 2 +- docs/test_cases/t00004_class.svg | 86 ++-- docs/test_cases/t00004_class_mermaid.svg | 32 +- docs/test_cases/t00005_class.svg | 110 ++--- docs/test_cases/t00005_class_mermaid.svg | 24 +- docs/test_cases/t00006_class.svg | 134 +++---- docs/test_cases/t00006_class_mermaid.svg | 38 +- docs/test_cases/t00007_class.svg | 30 +- docs/test_cases/t00007_class_mermaid.svg | 8 +- docs/test_cases/t00008_class.svg | 82 ++-- docs/test_cases/t00008_class_mermaid.svg | 16 +- docs/test_cases/t00009_class.svg | 38 +- docs/test_cases/t00009_class_mermaid.svg | 10 +- docs/test_cases/t00010_class.svg | 38 +- docs/test_cases/t00010_class_mermaid.svg | 10 +- docs/test_cases/t00011_class.svg | 30 +- docs/test_cases/t00011_class_mermaid.svg | 6 +- docs/test_cases/t00012_class.svg | 76 ++-- docs/test_cases/t00012_class_mermaid.svg | 18 +- docs/test_cases/t00013_class.svg | 130 +++--- docs/test_cases/t00013_class_mermaid.svg | 24 +- docs/test_cases/t00014_class.svg | 146 +++---- docs/test_cases/t00014_class_mermaid.svg | 36 +- docs/test_cases/t00015_class.svg | 22 +- docs/test_cases/t00015_class_mermaid.svg | 10 +- docs/test_cases/t00016_class.svg | 26 +- docs/test_cases/t00016_class_mermaid.svg | 12 +- docs/test_cases/t00017_class.svg | 70 ++-- docs/test_cases/t00017_class_mermaid.svg | 24 +- docs/test_cases/t00018_class.svg | 66 +-- docs/test_cases/t00018_class_mermaid.svg | 4 +- docs/test_cases/t00019_class.svg | 84 ++-- docs/test_cases/t00019_class_mermaid.svg | 16 +- docs/test_cases/t00020_class.svg | 94 ++--- docs/test_cases/t00020_class_mermaid.svg | 18 +- docs/test_cases/t00021_class.svg | 82 ++-- docs/test_cases/t00021_class_mermaid.svg | 14 +- docs/test_cases/t00022_class.svg | 42 +- docs/test_cases/t00022_class_mermaid.svg | 6 +- docs/test_cases/t00023_class.svg | 54 +-- docs/test_cases/t00023_class_mermaid.svg | 10 +- docs/test_cases/t00024_class.svg | 62 +-- docs/test_cases/t00024_class_mermaid.svg | 8 +- docs/test_cases/t00025_class.svg | 66 +-- docs/test_cases/t00025_class_mermaid.svg | 12 +- docs/test_cases/t00026_class.svg | 82 ++-- docs/test_cases/t00026_class_mermaid.svg | 12 +- docs/test_cases/t00027_class.svg | 98 ++--- docs/test_cases/t00027_class_mermaid.svg | 26 +- docs/test_cases/t00028_class.svg | 88 ++-- docs/test_cases/t00028_class_mermaid.svg | 18 +- docs/test_cases/t00029_class.svg | 58 +-- docs/test_cases/t00029_class_mermaid.svg | 18 +- docs/test_cases/t00030_class.svg | 46 +-- docs/test_cases/t00030_class_mermaid.svg | 12 +- docs/test_cases/t00031_class.svg | 56 +-- docs/test_cases/t00031_class_mermaid.svg | 12 +- docs/test_cases/t00032_class.svg | 54 +-- docs/test_cases/t00032_class_mermaid.svg | 16 +- docs/test_cases/t00033_class.svg | 54 +-- docs/test_cases/t00033_class_mermaid.svg | 16 +- docs/test_cases/t00034_class.svg | 46 +-- docs/test_cases/t00034_class_mermaid.svg | 14 +- docs/test_cases/t00035_class.svg | 22 +- docs/test_cases/t00035_class_mermaid.svg | 10 +- docs/test_cases/t00036_class.svg | 40 +- docs/test_cases/t00036_class_mermaid.svg | 10 +- docs/test_cases/t00037_class.svg | 58 +-- docs/test_cases/t00037_class_mermaid.svg | 8 +- docs/test_cases/t00038_class.svg | 54 +-- docs/test_cases/t00038_class_mermaid.svg | 24 +- docs/test_cases/t00039_class.svg | 78 ++-- docs/test_cases/t00039_class_mermaid.svg | 28 +- docs/test_cases/t00040_class.svg | 38 +- docs/test_cases/t00040_class_mermaid.svg | 8 +- docs/test_cases/t00041_class.svg | 58 +-- docs/test_cases/t00041_class_mermaid.svg | 18 +- docs/test_cases/t00042_class.svg | 42 +- docs/test_cases/t00042_class_mermaid.svg | 12 +- docs/test_cases/t00043_class.svg | 90 ++--- docs/test_cases/t00043_class_mermaid.svg | 22 +- docs/test_cases/t00044_class.svg | 42 +- docs/test_cases/t00044_class_mermaid.svg | 14 +- docs/test_cases/t00045_class.svg | 74 ++-- docs/test_cases/t00045_class_mermaid.svg | 24 +- docs/test_cases/t00046_class.svg | 66 +-- docs/test_cases/t00046_class_mermaid.svg | 18 +- docs/test_cases/t00047_class.svg | 18 +- docs/test_cases/t00047_class_mermaid.svg | 8 +- docs/test_cases/t00048_class.svg | 74 ++-- docs/test_cases/t00048_class_mermaid.svg | 12 +- docs/test_cases/t00049_class.svg | 50 +-- docs/test_cases/t00049_class_mermaid.svg | 10 +- docs/test_cases/t00050_class.svg | 70 ++-- docs/test_cases/t00050_class_mermaid.svg | 16 +- docs/test_cases/t00051_class.svg | 82 ++-- docs/test_cases/t00051_class_mermaid.svg | 10 +- docs/test_cases/t00052_class.svg | 42 +- docs/test_cases/t00052_class_mermaid.svg | 12 +- docs/test_cases/t00053_class.svg | 70 ++-- docs/test_cases/t00053_class_mermaid.svg | 34 +- docs/test_cases/t00054_class.svg | 78 ++-- docs/test_cases/t00054_class_mermaid.svg | 34 +- docs/test_cases/t00055_class.svg | 42 +- docs/test_cases/t00055_class_mermaid.svg | 20 +- docs/test_cases/t00056_class.svg | 94 ++--- docs/test_cases/t00056_class_mermaid.svg | 28 +- docs/test_cases/t00057_class.svg | 126 +++--- docs/test_cases/t00057_class_mermaid.svg | 20 +- docs/test_cases/t00058_class.svg | 54 +-- docs/test_cases/t00058_class_mermaid.svg | 16 +- docs/test_cases/t00059_class.svg | 94 ++--- docs/test_cases/t00059_class_mermaid.svg | 22 +- docs/test_cases/t00060_class.svg | 38 +- docs/test_cases/t00060_class_mermaid.svg | 12 +- docs/test_cases/t00061_class.svg | 6 +- docs/test_cases/t00061_class_mermaid.svg | 2 +- docs/test_cases/t00062_class.svg | 198 ++++----- docs/test_cases/t00062_class_mermaid.svg | 44 +- docs/test_cases/t00063_class.svg | 6 +- docs/test_cases/t00063_class_mermaid.svg | 2 +- docs/test_cases/t00064_class.svg | 118 +++--- docs/test_cases/t00064_class_mermaid.svg | 46 +-- docs/test_cases/t00065_class.svg | 102 ++--- docs/test_cases/t00065_class_mermaid.svg | 24 +- docs/test_cases/t00066_class.svg | 126 +++--- docs/test_cases/t00066_class_mermaid.svg | 2 +- docs/test_cases/t00067_class.svg | 86 ++-- docs/test_cases/t00067_class_mermaid.svg | 2 +- docs/test_cases/t00068_r0_class.svg | 14 +- docs/test_cases/t00068_r0_class_mermaid.svg | 2 +- docs/test_cases/t00068_r1_class.svg | 38 +- docs/test_cases/t00068_r1_class_mermaid.svg | 10 +- docs/test_cases/t00068_r2_class.svg | 54 +-- docs/test_cases/t00068_r2_class_mermaid.svg | 16 +- docs/test_cases/t00069_class.svg | 74 ++-- docs/test_cases/t00069_class_mermaid.svg | 8 +- docs/test_cases/t00070_class.svg | 30 +- docs/test_cases/t00070_class_mermaid.svg | 8 +- docs/test_cases/t00071_class.svg | 80 ++-- docs/test_cases/t00071_class_mermaid.svg | 20 +- docs/test_cases/t00072_class.svg | 64 +-- docs/test_cases/t00072_class_mermaid.svg | 18 +- docs/test_cases/t00073.md | 421 ++++++++++++++++++++ docs/test_cases/t00073_class.svg | 124 ++++++ docs/test_cases/t00073_class_mermaid.svg | 286 +++++++++++++ docs/test_cases/t20001_sequence.svg | 78 ++-- docs/test_cases/t20002_sequence.svg | 48 +-- docs/test_cases/t20003_sequence.svg | 48 +-- docs/test_cases/t20004_sequence.svg | 120 +++--- docs/test_cases/t20005_sequence.svg | 36 +- docs/test_cases/t20006_sequence.svg | 162 ++++---- docs/test_cases/t20007_sequence.svg | 48 +-- docs/test_cases/t20008_sequence.svg | 84 ++-- docs/test_cases/t20009_sequence.svg | 84 ++-- docs/test_cases/t20010_sequence.svg | 72 ++-- docs/test_cases/t20011_sequence.svg | 72 ++-- docs/test_cases/t20012_sequence.svg | 198 ++++----- docs/test_cases/t20013_sequence.svg | 60 +-- docs/test_cases/t20014_sequence.svg | 72 ++-- docs/test_cases/t20015_sequence.svg | 24 +- docs/test_cases/t20016_sequence.svg | 48 +-- docs/test_cases/t20017_sequence.svg | 48 +-- docs/test_cases/t20018_sequence.svg | 96 ++--- docs/test_cases/t20019_sequence.svg | 84 ++-- docs/test_cases/t20020_sequence.svg | 124 +++--- docs/test_cases/t20021_sequence.svg | 106 ++--- docs/test_cases/t20022_sequence.svg | 42 +- docs/test_cases/t20023_sequence.svg | 50 +-- docs/test_cases/t20024_sequence.svg | 88 ++-- docs/test_cases/t20025_sequence.svg | 36 +- docs/test_cases/t20026_sequence.svg | 24 +- docs/test_cases/t20027_sequence.svg | 24 +- docs/test_cases/t20028_sequence.svg | 44 +- docs/test_cases/t20029_sequence.svg | 88 ++-- docs/test_cases/t20030_sequence.svg | 112 +++--- docs/test_cases/t20031_sequence.svg | 58 +-- docs/test_cases/t20032_sequence.svg | 60 +-- docs/test_cases/t20033_sequence.svg | 128 +++--- docs/test_cases/t20034_sequence.svg | 76 ++-- docs/test_cases/t20035_sequence.svg | 32 +- docs/test_cases/t20036_sequence.svg | 64 +-- docs/test_cases/t20037_sequence.svg | 108 ++--- docs/test_cases/t20038_sequence.svg | 174 ++++---- docs/test_cases/t20039_sequence.svg | 84 ++-- docs/test_cases/t20040.md | 335 ++++++++++++++++ docs/test_cases/t20040_sequence.svg | 119 ++++++ docs/test_cases/t20040_sequence_mermaid.svg | 203 ++++++++++ docs/test_cases/t20041.md | 279 +++++++++++++ docs/test_cases/t20041_sequence.svg | 78 ++++ docs/test_cases/t20041_sequence_mermaid.svg | 138 +++++++ docs/test_cases/t20042.md | 248 ++++++++++++ docs/test_cases/t20042_sequence.svg | 68 ++++ docs/test_cases/t20042_sequence_mermaid.svg | 108 +++++ docs/test_cases/t30001_package.svg | 54 +-- docs/test_cases/t30002_package.svg | 94 ++--- docs/test_cases/t30003_package.svg | 26 +- docs/test_cases/t30004_package.svg | 38 +- docs/test_cases/t30005_package.svg | 38 +- docs/test_cases/t30006_package.svg | 18 +- docs/test_cases/t30007_package.svg | 22 +- docs/test_cases/t30008_package.svg | 34 +- docs/test_cases/t30009_package.svg | 42 +- docs/test_cases/t30010_package.svg | 24 +- docs/test_cases/t30011_package.svg | 24 +- docs/test_cases/t30012_package.svg | 20 +- docs/test_cases/t30013_package.svg | 78 ++-- docs/test_cases/t30014_package.svg | 16 +- docs/test_cases/t30015_package.svg | 80 ++-- docs/test_cases/t40001_include.svg | 32 +- docs/test_cases/t40001_include_mermaid.svg | 6 +- docs/test_cases/t40002_include.svg | 34 +- docs/test_cases/t40002_include_mermaid.svg | 10 +- docs/test_cases/t40003_include.svg | 46 +-- docs/test_cases/t40003_include_mermaid.svg | 18 +- 219 files changed, 7340 insertions(+), 4929 deletions(-) create mode 100644 docs/test_cases/t00073.md create mode 100644 docs/test_cases/t00073_class.svg create mode 100644 docs/test_cases/t00073_class_mermaid.svg create mode 100644 docs/test_cases/t20040.md create mode 100644 docs/test_cases/t20040_sequence.svg create mode 100644 docs/test_cases/t20040_sequence_mermaid.svg create mode 100644 docs/test_cases/t20041.md create mode 100644 docs/test_cases/t20041_sequence.svg create mode 100644 docs/test_cases/t20041_sequence_mermaid.svg create mode 100644 docs/test_cases/t20042.md create mode 100644 docs/test_cases/t20042_sequence.svg create mode 100644 docs/test_cases/t20042_sequence_mermaid.svg diff --git a/docs/test_cases.md b/docs/test_cases.md index 5252dd93..9ade30ca 100644 --- a/docs/test_cases.md +++ b/docs/test_cases.md @@ -77,6 +77,7 @@ * [t00070](./test_cases/t00070.md) - Diagram filter based on C++20 modules * [t00071](./test_cases/t00071.md) - Class diagram with C++20 modules generated as packages * [t00072](./test_cases/t00072.md) - Class diagram with C++20 module partitions generated as packages + * [t00073](./test_cases/t00073.md) - Class diagram for template overload pattern ## Sequence diagrams * [t20001](./test_cases/t20001.md) - Basic sequence diagram test case * [t20002](./test_cases/t20002.md) - Free function sequence diagram test case @@ -117,6 +118,9 @@ * [t20037](./test_cases/t20037.md) - Test case checking if activities in static variable declarations appear only once * [t20038](./test_cases/t20038.md) - Sequence diagram comment decorator test case * [t20039](./test_cases/t20039.md) - Test case for type aliases config option in sequence diagrams + * [t20040](./test_cases/t20040.md) - Test case for recursive variadic template function call + * [t20041](./test_cases/t20041.md) - Test case for recursive variadic template class call + * [t20042](./test_cases/t20042.md) - Test case for template overload pattern ## Package diagrams * [t30001](./test_cases/t30001.md) - Basic package diagram test case * [t30002](./test_cases/t30002.md) - Package dependency test case diff --git a/docs/test_cases/t00002_class.svg b/docs/test_cases/t00002_class.svg index 1b8a7de5..9ca360ca 100644 --- a/docs/test_cases/t00002_class.svg +++ b/docs/test_cases/t00002_class.svg @@ -1,6 +1,6 @@ - + @@ -10,123 +10,123 @@ Basic class diagram example - - + + A - + - + foo_a() = 0 : void - + - + foo_c() = 0 : void - - + + B - + - + foo_a() : void - - + + C - + - + foo_c() : void - - + + D - + - + foo_a() : void - + - + foo_c() : void - + - + as : std::vector<A *> - - + + E - + - + foo_a() : void - + - + foo_c() : void - + - + as : std::vector<A *> - + This is class A - + This is class B - + This is class D diff --git a/docs/test_cases/t00002_class_mermaid.svg b/docs/test_cases/t00002_class_mermaid.svg index 81d978cd..4b591fc3 100644 --- a/docs/test_cases/t00002_class_mermaid.svg +++ b/docs/test_cases/t00002_class_mermaid.svg @@ -169,7 +169,7 @@ - + @@ -198,7 +198,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -246,7 +246,7 @@ - + @@ -280,7 +280,7 @@ - + diff --git a/docs/test_cases/t00003_class.svg b/docs/test_cases/t00003_class.svg index 37270ca2..1a454ba7 100644 --- a/docs/test_cases/t00003_class.svg +++ b/docs/test_cases/t00003_class.svg @@ -1,6 +1,6 @@ - + @@ -9,227 +9,227 @@ - - + + A - + - + A() = default : void - + - + A(int i) : void - + - + A(A &&) = default : void - + - + A(const A &) = deleted : void A<T>(T t) : void - + - + ~A() = default : void - + - + operator=(A && other) noexcept : A & - + - + operator=(A & other) noexcept : A & - + - + operator++() : A & - + - + auto_method() : int - + - + basic_method() : void - + - + const_method() const : void - + - + create_from_int(int i) : A - + - + default_int(int i = 12) : int - + - + default_string(int i, std::string s = "abc") : std::string - + - + double_int(const int i) : int - + - + private_method() : void - + - + protected_method() : void - + - + size() constexpr const : std::size_t - + - + static_method() : int - + - + sum(const double a, const double b) : int - + - + a_ : int - + - + auto_member : const unsigned long - + - + b_ : int - + - + c_ : int - + - + compare : std::function<bool (const int)> - + - + private_member : int - + - + protected_member : int - + - + public_member : int - + - + static_const_int : const int - + - + static_int : int diff --git a/docs/test_cases/t00003_class_mermaid.svg b/docs/test_cases/t00003_class_mermaid.svg index cd8fd47f..beafd662 100644 --- a/docs/test_cases/t00003_class_mermaid.svg +++ b/docs/test_cases/t00003_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00004_class.svg b/docs/test_cases/t00004_class.svg index 4e08cddb..8369e661 100644 --- a/docs/test_cases/t00004_class.svg +++ b/docs/test_cases/t00004_class.svg @@ -1,6 +1,6 @@ - + @@ -9,16 +9,16 @@ - - + + B - - + + B::AA @@ -28,38 +28,38 @@ AA_3 - - + + A - + - + foo() const : void - + - + foo2() const : void - - + + A::AA - - + + A::AA::Lights @@ -69,16 +69,16 @@ Red - - + + A::AA::AAA - - + + C::B @@ -87,8 +87,8 @@ - - + + C @@ -97,38 +97,38 @@ - + - + b_int : B<int> - + - + t : T - - + + C::AA - - + + C::AA::AAA - - + + C::AA::CCC @@ -137,8 +137,8 @@ CCC_2 - - + + C::B @@ -147,15 +147,15 @@ - + - + b : V - - + + C::CC @@ -164,16 +164,16 @@ CC_2 - - + + detail::D - - + + detail::D::AA @@ -183,8 +183,8 @@ AA_3 - - + + detail::D::DD diff --git a/docs/test_cases/t00004_class_mermaid.svg b/docs/test_cases/t00004_class_mermaid.svg index 8cdb3554..2280f5b0 100644 --- a/docs/test_cases/t00004_class_mermaid.svg +++ b/docs/test_cases/t00004_class_mermaid.svg @@ -210,7 +210,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -292,7 +292,7 @@ - + @@ -311,7 +311,7 @@ - + @@ -345,7 +345,7 @@ - + @@ -364,7 +364,7 @@ - + @@ -383,7 +383,7 @@ - + @@ -412,7 +412,7 @@ - + @@ -431,7 +431,7 @@ - + @@ -450,7 +450,7 @@ - + @@ -479,7 +479,7 @@ - + @@ -503,7 +503,7 @@ - + @@ -532,7 +532,7 @@ - + @@ -551,7 +551,7 @@ - + @@ -585,7 +585,7 @@ - + diff --git a/docs/test_cases/t00005_class.svg b/docs/test_cases/t00005_class.svg index ba3c4dd3..b5695b5d 100644 --- a/docs/test_cases/t00005_class.svg +++ b/docs/test_cases/t00005_class.svg @@ -1,6 +1,6 @@ - + @@ -9,205 +9,205 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F - - + + G - - + + H - - + + I - - + + J - - + + K - - + + R - + - + a : A - + - + b : B * - + - + c : C & - + - + d : const D * - + - + e : const E & - + - + f : F && - + - + g : G ** - + - + h : H *** - + - + i : I *& - + - + j : volatile J * - + - + k : K * - + - + some_int : int - + - + some_int_pointer : int * - + - + some_int_pointer_pointer : int ** - + - + some_int_reference : int & diff --git a/docs/test_cases/t00005_class_mermaid.svg b/docs/test_cases/t00005_class_mermaid.svg index 7090e6c4..667fc8d9 100644 --- a/docs/test_cases/t00005_class_mermaid.svg +++ b/docs/test_cases/t00005_class_mermaid.svg @@ -186,7 +186,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -224,7 +224,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + @@ -300,7 +300,7 @@ - + @@ -319,7 +319,7 @@ - + @@ -338,7 +338,7 @@ - + @@ -357,7 +357,7 @@ - + @@ -376,7 +376,7 @@ - + @@ -395,7 +395,7 @@ - + diff --git a/docs/test_cases/t00006_class.svg b/docs/test_cases/t00006_class.svg index 94ab5eb1..9d470a85 100644 --- a/docs/test_cases/t00006_class.svg +++ b/docs/test_cases/t00006_class.svg @@ -1,6 +1,6 @@ - + @@ -9,136 +9,136 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F - - + + G - - + + H - - + + I - - + + J - - + + K - - + + L - - + + M - - + + N - - + + NN - - + + NNN - - + + custom_container @@ -147,15 +147,15 @@ - + - + data : std::vector<T> - - + + custom_container @@ -164,103 +164,103 @@ - - + + R - + - + a : std::vector<A> - + - + b : std::vector<B *> - + - + c : std::map<int,C> - + - + d : std::map<int,D *> - + - + e : custom_container<E> - + - + f : std::vector<std::vector<F>> - + - + g : std::map<int,std::vector<G *>> - + - + h : std::array<H,10> - + - + i : std::array<I *,5> - + - + j : J[10] - + - + k : K *[20] - + - + lm : std::vector<std::pair<L,M>> - + - + ns : std::tuple<N,NN,NNN> diff --git a/docs/test_cases/t00006_class_mermaid.svg b/docs/test_cases/t00006_class_mermaid.svg index 2258977c..c9ce3e53 100644 --- a/docs/test_cases/t00006_class_mermaid.svg +++ b/docs/test_cases/t00006_class_mermaid.svg @@ -270,7 +270,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -308,7 +308,7 @@ - + @@ -327,7 +327,7 @@ - + @@ -346,7 +346,7 @@ - + @@ -365,7 +365,7 @@ - + @@ -384,7 +384,7 @@ - + @@ -403,7 +403,7 @@ - + @@ -422,7 +422,7 @@ - + @@ -441,7 +441,7 @@ - + @@ -460,7 +460,7 @@ - + @@ -479,7 +479,7 @@ - + @@ -498,7 +498,7 @@ - + @@ -517,7 +517,7 @@ - + @@ -536,7 +536,7 @@ - + @@ -555,7 +555,7 @@ - + @@ -574,7 +574,7 @@ - + @@ -598,7 +598,7 @@ - + @@ -617,7 +617,7 @@ - + diff --git a/docs/test_cases/t00007_class.svg b/docs/test_cases/t00007_class.svg index 5cbdbc01..fcf509df 100644 --- a/docs/test_cases/t00007_class.svg +++ b/docs/test_cases/t00007_class.svg @@ -1,6 +1,6 @@ - + @@ -9,57 +9,57 @@ - - + + A - - + + B - - + + C - - + + R - + - + a : std::unique_ptr<A> - + - + b : std::shared_ptr<B> - + - + c : std::weak_ptr<C> diff --git a/docs/test_cases/t00007_class_mermaid.svg b/docs/test_cases/t00007_class_mermaid.svg index 13ad029a..c1e8572f 100644 --- a/docs/test_cases/t00007_class_mermaid.svg +++ b/docs/test_cases/t00007_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + diff --git a/docs/test_cases/t00008_class.svg b/docs/test_cases/t00008_class.svg index 7e3d6b0e..7fc4c12a 100644 --- a/docs/test_cases/t00008_class.svg +++ b/docs/test_cases/t00008_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,50 +19,50 @@ - + - + comparator : CMP - + - + ints : std::array<int,N> - + - + pointer : T * - + - + reference : T & - + - + value : T - + - + values : std::vector<P> - - + + Vector @@ -71,15 +71,15 @@ - + - + values : std::vector<T> - - + + B @@ -88,15 +88,15 @@ - + - + template_template : C<T> - - + + B @@ -105,8 +105,8 @@ - - + + D @@ -115,31 +115,31 @@ D<Items...>(std::tuple<Items...> *) : void - + - + add(int i) : void - + - + ints : B<int,Vector> - - + + E - - + + E::nested_template @@ -147,16 +147,16 @@ ET - + - + get(ET * d) : DT * - - + + E::nested_template @@ -164,11 +164,11 @@ char - + - + getDecl(char * c) : DeclType * diff --git a/docs/test_cases/t00008_class_mermaid.svg b/docs/test_cases/t00008_class_mermaid.svg index 615a410a..f15786f3 100644 --- a/docs/test_cases/t00008_class_mermaid.svg +++ b/docs/test_cases/t00008_class_mermaid.svg @@ -114,7 +114,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -187,7 +187,7 @@ - + @@ -211,7 +211,7 @@ - + @@ -230,7 +230,7 @@ - + @@ -264,7 +264,7 @@ - + @@ -283,7 +283,7 @@ - + @@ -307,7 +307,7 @@ - + diff --git a/docs/test_cases/t00009_class.svg b/docs/test_cases/t00009_class.svg index 5bd84efe..900d4e24 100644 --- a/docs/test_cases/t00009_class.svg +++ b/docs/test_cases/t00009_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,15 +19,15 @@ - + - + value : T - - + + A @@ -36,8 +36,8 @@ - - + + A @@ -46,8 +46,8 @@ - - + + A @@ -56,33 +56,33 @@ - - + + B - + - + aint : A<int> - + - + astring : A<std::string> * - + - + avector : A<std::vector<std::string>> & diff --git a/docs/test_cases/t00009_class_mermaid.svg b/docs/test_cases/t00009_class_mermaid.svg index 1a57803a..0e6575ae 100644 --- a/docs/test_cases/t00009_class_mermaid.svg +++ b/docs/test_cases/t00009_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -169,7 +169,7 @@ - + @@ -188,7 +188,7 @@ - + @@ -207,7 +207,7 @@ - + diff --git a/docs/test_cases/t00010_class.svg b/docs/test_cases/t00010_class.svg index dba37f90..5baca45d 100644 --- a/docs/test_cases/t00010_class.svg +++ b/docs/test_cases/t00010_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,22 +19,22 @@ - + - + first : T - + - + second : P - - + + A @@ -43,8 +43,8 @@ - - + + B @@ -53,15 +53,15 @@ - + - + astring : A<T,std::string> - - + + B @@ -70,19 +70,19 @@ - - + + C - + - + aintstring : B<int> diff --git a/docs/test_cases/t00010_class_mermaid.svg b/docs/test_cases/t00010_class_mermaid.svg index 6ca8634b..d3062a31 100644 --- a/docs/test_cases/t00010_class_mermaid.svg +++ b/docs/test_cases/t00010_class_mermaid.svg @@ -102,7 +102,7 @@ - + @@ -131,7 +131,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -174,7 +174,7 @@ - + @@ -193,7 +193,7 @@ - + diff --git a/docs/test_cases/t00011_class.svg b/docs/test_cases/t00011_class.svg index 90392f08..dd927549 100644 --- a/docs/test_cases/t00011_class.svg +++ b/docs/test_cases/t00011_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + D @@ -19,48 +19,48 @@ - + - + value : T - - + + A - + - + foo() : void - - + + B - + - + foo() : void - + - + m_a : A * diff --git a/docs/test_cases/t00011_class_mermaid.svg b/docs/test_cases/t00011_class_mermaid.svg index 729264fe..4a4fcdf4 100644 --- a/docs/test_cases/t00011_class_mermaid.svg +++ b/docs/test_cases/t00011_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -102,7 +102,7 @@ - + @@ -126,7 +126,7 @@ - + diff --git a/docs/test_cases/t00012_class.svg b/docs/test_cases/t00012_class.svg index ef9256f5..c9141133 100644 --- a/docs/test_cases/t00012_class.svg +++ b/docs/test_cases/t00012_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,22 +19,22 @@ - + - + value : T - + - + values : std::variant<Ts...> - - + + B @@ -43,15 +43,15 @@ - + - + ints : std::array<int,sizeof...(Is)> - - + + C @@ -60,15 +60,15 @@ - + - + ints : std::array<T,sizeof...(Is)> - - + + A @@ -77,8 +77,8 @@ - - + + A @@ -87,8 +87,8 @@ - - + + B @@ -97,8 +97,8 @@ - - + + B @@ -107,8 +107,8 @@ - - + + C @@ -117,50 +117,50 @@ - - + + R - + - + a1 : A<int,std::string,float> - + - + a2 : A<int,std::string,bool> - + - + b1 : B<3,2,1> - + - + b2 : B<1,1,1,1> - + - + c1 : C<std::map<int,std::vector<std::vector<std::vector<std::string>>>>,3,3,3> - + Long template annotation diff --git a/docs/test_cases/t00012_class_mermaid.svg b/docs/test_cases/t00012_class_mermaid.svg index 8d554f86..2a3a91b9 100644 --- a/docs/test_cases/t00012_class_mermaid.svg +++ b/docs/test_cases/t00012_class_mermaid.svg @@ -174,7 +174,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -227,7 +227,7 @@ - + @@ -251,7 +251,7 @@ - + @@ -270,7 +270,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -308,7 +308,7 @@ - + @@ -327,7 +327,7 @@ - + @@ -346,7 +346,7 @@ - + diff --git a/docs/test_cases/t00013_class.svg b/docs/test_cases/t00013_class.svg index a6040852..f7212e99 100644 --- a/docs/test_cases/t00013_class.svg +++ b/docs/test_cases/t00013_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + ABCD::F @@ -19,15 +19,15 @@ - + - + f : T - - + + ABCD::F @@ -36,75 +36,75 @@ - - + + A - + - + a : int - - + + B - + - + b : int - - + + C - + - + c : int - - + + D - + - + print(R * r) : void - + - + d : int - - + + E @@ -113,15 +113,15 @@ - + - + e : T - - + + G @@ -130,22 +130,22 @@ - + - + args : std::tuple<Args...> - + - + g : T - - + + E @@ -154,8 +154,8 @@ - - + + G @@ -164,8 +164,8 @@ - - + + E @@ -174,93 +174,93 @@ - - + + R - + - + get_a(A * a) : int - + - + get_b(B & b) : int - + - + get_c(C c) : int - + - + get_const_b(const B & b) : int - + - + get_d(D && d) : int - + - + get_d2(D && d) : int get_e<T>(E<T> e) : T get_f<T>(const F<T> & f) : T - + - + get_int_e(const E<int> & e) : int - + - + get_int_e2(E<int> & e) : int - + - + get_int_f(const ABCD::F<int> & f) : int - + - + estring : E<std::string> - + - + gintstring : G<int,float,std::string> diff --git a/docs/test_cases/t00013_class_mermaid.svg b/docs/test_cases/t00013_class_mermaid.svg index 966fc889..c964c8ca 100644 --- a/docs/test_cases/t00013_class_mermaid.svg +++ b/docs/test_cases/t00013_class_mermaid.svg @@ -234,7 +234,7 @@ - + @@ -258,7 +258,7 @@ - + @@ -277,7 +277,7 @@ - + @@ -301,7 +301,7 @@ - + @@ -325,7 +325,7 @@ - + @@ -349,7 +349,7 @@ - + @@ -378,7 +378,7 @@ - + @@ -402,7 +402,7 @@ - + @@ -431,7 +431,7 @@ - + @@ -450,7 +450,7 @@ - + @@ -469,7 +469,7 @@ - + @@ -488,7 +488,7 @@ - + diff --git a/docs/test_cases/t00014_class.svg b/docs/test_cases/t00014_class.svg index 8a0bfa47..e1f0e020 100644 --- a/docs/test_cases/t00014_class.svg +++ b/docs/test_cases/t00014_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,37 +19,37 @@ - + - + p : P - + - + t : T - - + + B - + - + value : std::string - - + + A @@ -58,8 +58,8 @@ - - + + A @@ -68,8 +68,8 @@ - - + + A @@ -78,8 +78,8 @@ - - + + A @@ -88,8 +88,8 @@ - - + + A @@ -98,8 +98,8 @@ - - + + A @@ -108,8 +108,8 @@ - - + + A @@ -118,8 +118,8 @@ - - + + A @@ -128,8 +128,8 @@ - - + + A @@ -138,8 +138,8 @@ - - + + A @@ -148,8 +148,8 @@ - - + + A @@ -158,8 +158,8 @@ - - + + A @@ -168,8 +168,8 @@ - - + + A @@ -178,7 +178,7 @@ - + A @@ -186,7 +186,7 @@ char,std::string - + A @@ -194,8 +194,8 @@ wchar_t,std::string - - + + R @@ -204,116 +204,116 @@ - + - + abool : APtr<bool> - + - + aboolfloat : AAPtr<bool,float> - + - + afloat : ASharedPtr<float> - + - + atfloat : AAPtr<T,float> - + - + bapair : PairPairBA<bool> - + - + boolstring : A<bool,std::string> - + - + bs : BVector - + - + bs2 : BVector2 - + - + bstringstring : BStringString - + - + cb : SimpleCallback<ACharString> - + - + floatstring : AStringPtr<float> - + - + gcb : GenericCallback<AWCharString> - + - + intstring : AIntString - + - + stringstring : AStringString - + - + vcb : VoidCallback - + - + vps : VectorPtr<B> diff --git a/docs/test_cases/t00014_class_mermaid.svg b/docs/test_cases/t00014_class_mermaid.svg index ae07b388..24b16d0f 100644 --- a/docs/test_cases/t00014_class_mermaid.svg +++ b/docs/test_cases/t00014_class_mermaid.svg @@ -474,7 +474,7 @@ - + @@ -503,7 +503,7 @@ - + @@ -527,7 +527,7 @@ - + @@ -546,7 +546,7 @@ - + @@ -565,7 +565,7 @@ - + @@ -584,7 +584,7 @@ - + @@ -603,7 +603,7 @@ - + @@ -622,7 +622,7 @@ - + @@ -641,7 +641,7 @@ - + @@ -660,7 +660,7 @@ - + @@ -679,7 +679,7 @@ - + @@ -698,7 +698,7 @@ - + @@ -717,7 +717,7 @@ - + @@ -736,7 +736,7 @@ - + @@ -755,7 +755,7 @@ - + @@ -774,7 +774,7 @@ - + @@ -793,7 +793,7 @@ - + @@ -812,7 +812,7 @@ - + diff --git a/docs/test_cases/t00015_class.svg b/docs/test_cases/t00015_class.svg index 2b1379de..be9fda09 100644 --- a/docs/test_cases/t00015_class.svg +++ b/docs/test_cases/t00015_class.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + ns1::A - - + + ns1::ns2_v0_9_0::A - - + + ns1::Anon - - + + ns3::ns1::ns2::Anon - - + + ns3::B diff --git a/docs/test_cases/t00015_class_mermaid.svg b/docs/test_cases/t00015_class_mermaid.svg index b336e26a..57635eb7 100644 --- a/docs/test_cases/t00015_class_mermaid.svg +++ b/docs/test_cases/t00015_class_mermaid.svg @@ -84,7 +84,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -122,7 +122,7 @@ - + @@ -141,7 +141,7 @@ - + @@ -160,7 +160,7 @@ - + diff --git a/docs/test_cases/t00016_class.svg b/docs/test_cases/t00016_class.svg index 2b9bce13..631ad51d 100644 --- a/docs/test_cases/t00016_class.svg +++ b/docs/test_cases/t00016_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + is_numeric @@ -21,8 +21,8 @@ value : enum - - + + is_numeric @@ -33,8 +33,8 @@ value : enum - - + + is_numeric @@ -45,8 +45,8 @@ value : enum - - + + is_numeric @@ -57,8 +57,8 @@ value : enum - - + + is_numeric @@ -69,8 +69,8 @@ value : enum - - + + is_numeric diff --git a/docs/test_cases/t00016_class_mermaid.svg b/docs/test_cases/t00016_class_mermaid.svg index 183b1648..629d1e5e 100644 --- a/docs/test_cases/t00016_class_mermaid.svg +++ b/docs/test_cases/t00016_class_mermaid.svg @@ -114,7 +114,7 @@ - + @@ -138,7 +138,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -186,7 +186,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -234,7 +234,7 @@ - + diff --git a/docs/test_cases/t00017_class.svg b/docs/test_cases/t00017_class.svg index cbe080ee..0f500bdb 100644 --- a/docs/test_cases/t00017_class.svg +++ b/docs/test_cases/t00017_class.svg @@ -1,6 +1,6 @@ - + @@ -9,135 +9,135 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F - - + + G - - + + H - - + + I - - + + J - - + + K - - + + R - + - + R(int & some_int, C & cc, const E & ee, F && ff, I *& ii) : void - + - + some_int : int - + - + some_int_pointer : int * - + - + some_int_pointer_pointer : int ** - + - + some_int_reference : int & diff --git a/docs/test_cases/t00017_class_mermaid.svg b/docs/test_cases/t00017_class_mermaid.svg index 371fec0a..2c94a4e9 100644 --- a/docs/test_cases/t00017_class_mermaid.svg +++ b/docs/test_cases/t00017_class_mermaid.svg @@ -186,7 +186,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -224,7 +224,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + @@ -300,7 +300,7 @@ - + @@ -319,7 +319,7 @@ - + @@ -338,7 +338,7 @@ - + @@ -357,7 +357,7 @@ - + @@ -376,7 +376,7 @@ - + @@ -395,7 +395,7 @@ - + diff --git a/docs/test_cases/t00018_class.svg b/docs/test_cases/t00018_class.svg index f5516ab7..fbee599f 100644 --- a/docs/test_cases/t00018_class.svg +++ b/docs/test_cases/t00018_class.svg @@ -1,6 +1,6 @@ - + @@ -9,121 +9,121 @@ - - + + impl::widget - + - + widget(int n) : void - + - + draw(const widget & w) const : void - + - + draw(const widget & w) : void - + - + n : int - - + + widget - + - + widget(int) : void - + - + widget(widget &&) : void - + - + widget(const widget &) = deleted : void - + - + ~widget() : void - + - + operator=(widget &&) : widget & - + - + operator=(const widget &) = deleted : widget & - + - + draw() const : void - + - + draw() : void - + - + shown() const : bool - + - + pImpl : std::unique_ptr<impl::widget> diff --git a/docs/test_cases/t00018_class_mermaid.svg b/docs/test_cases/t00018_class_mermaid.svg index 22ab3470..16e9cf74 100644 --- a/docs/test_cases/t00018_class_mermaid.svg +++ b/docs/test_cases/t00018_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -117,7 +117,7 @@ - + diff --git a/docs/test_cases/t00019_class.svg b/docs/test_cases/t00019_class.svg index 4e65a2c1..966d7e2e 100644 --- a/docs/test_cases/t00019_class.svg +++ b/docs/test_cases/t00019_class.svg @@ -1,6 +1,6 @@ - + @@ -9,45 +9,45 @@ - - + + Base - + - + Base() = default : void - + - + ~Base() constexpr = default : void - + - + m1() : int - + - + m2() : std::string - - + + Layer1 @@ -55,23 +55,23 @@ LowerLayer - + - + m1() : int - + - + m2() : std::string - - + + Layer2 @@ -79,16 +79,16 @@ LowerLayer - + - + all_calls_count() const : int - - + + Layer3 @@ -96,50 +96,50 @@ LowerLayer - + - + m1() : int - + - + m1_calls() const : int - + - + m2() : std::string - + - + m2_calls() const : int - + - + m_m1_calls : int - + - + m_m2_calls : int - + Layer3 @@ -147,7 +147,7 @@ Base - + Layer2 @@ -155,7 +155,7 @@ Layer3<Base> - + Layer1 @@ -163,19 +163,19 @@ Layer2<Layer3<Base>> - - + + A - + - + layers : std::unique_ptr<Layer1<Layer2<Layer3<Base>>>> diff --git a/docs/test_cases/t00019_class_mermaid.svg b/docs/test_cases/t00019_class_mermaid.svg index d2e6791c..eae904dd 100644 --- a/docs/test_cases/t00019_class_mermaid.svg +++ b/docs/test_cases/t00019_class_mermaid.svg @@ -132,7 +132,7 @@ - + @@ -171,7 +171,7 @@ - + @@ -200,7 +200,7 @@ - + @@ -224,7 +224,7 @@ - + @@ -273,7 +273,7 @@ - + @@ -292,7 +292,7 @@ - + @@ -311,7 +311,7 @@ - + @@ -330,7 +330,7 @@ - + diff --git a/docs/test_cases/t00020_class.svg b/docs/test_cases/t00020_class.svg index 7e3ee4bb..d11d1e04 100644 --- a/docs/test_cases/t00020_class.svg +++ b/docs/test_cases/t00020_class.svg @@ -1,6 +1,6 @@ - + @@ -9,175 +9,175 @@ - - + + ProductA - + - + ~ProductA() constexpr = default : void - + - + sell(int price) const = 0 : bool - - + + ProductA1 - + - + sell(int price) const : bool - - + + ProductA2 - + - + sell(int price) const : bool - - + + ProductB - + - + ~ProductB() constexpr = default : void - + - + buy(int price) const = 0 : bool - - + + ProductB1 - + - + buy(int price) const : bool - - + + ProductB2 - + - + buy(int price) const : bool - - + + AbstractFactory - + - + make_a() const = 0 : std::unique_ptr<ProductA> - + - + make_b() const = 0 : std::unique_ptr<ProductB> - - + + Factory1 - + - + make_a() const : std::unique_ptr<ProductA> - + - + make_b() const : std::unique_ptr<ProductB> - - + + Factory2 - + - + make_a() const : std::unique_ptr<ProductA> - + - + make_b() const : std::unique_ptr<ProductB> diff --git a/docs/test_cases/t00020_class_mermaid.svg b/docs/test_cases/t00020_class_mermaid.svg index 1cef13c3..9ef2b26b 100644 --- a/docs/test_cases/t00020_class_mermaid.svg +++ b/docs/test_cases/t00020_class_mermaid.svg @@ -186,7 +186,7 @@ - + @@ -215,7 +215,7 @@ - + @@ -239,7 +239,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -292,7 +292,7 @@ - + @@ -316,7 +316,7 @@ - + @@ -340,7 +340,7 @@ - + @@ -369,7 +369,7 @@ - + @@ -398,7 +398,7 @@ - + diff --git a/docs/test_cases/t00021_class.svg b/docs/test_cases/t00021_class.svg index 129f2808..e605f992 100644 --- a/docs/test_cases/t00021_class.svg +++ b/docs/test_cases/t00021_class.svg @@ -1,6 +1,6 @@ - + @@ -9,152 +9,152 @@ - - + + Visitor - + - + ~Visitor() constexpr = default : void - + - + visit_A(const A & item) const = 0 : void - + - + visit_B(const B & item) const = 0 : void - - + + Visitor1 - + - + visit_A(const A & item) const : void - + - + visit_B(const B & item) const : void - - + + Visitor2 - + - + visit_A(const A & item) const : void - + - + visit_B(const B & item) const : void - - + + Visitor3 - + - + visit_A(const A & item) const : void - + - + visit_B(const B & item) const : void - - + + Item - + - + ~Item() constexpr = default : void - + - + accept(const Visitor & visitor) const = 0 : void - - + + A - + - + accept(const Visitor & visitor) const : void - - + + B - + - + accept(const Visitor & visitor) const : void diff --git a/docs/test_cases/t00021_class_mermaid.svg b/docs/test_cases/t00021_class_mermaid.svg index 75d3cfee..f2e76cbf 100644 --- a/docs/test_cases/t00021_class_mermaid.svg +++ b/docs/test_cases/t00021_class_mermaid.svg @@ -236,7 +236,7 @@ - + @@ -270,7 +270,7 @@ - + @@ -299,7 +299,7 @@ - + @@ -328,7 +328,7 @@ - + @@ -357,7 +357,7 @@ - + @@ -386,7 +386,7 @@ - + @@ -410,7 +410,7 @@ - + diff --git a/docs/test_cases/t00022_class.svg b/docs/test_cases/t00022_class.svg index 2c0fc0b2..15205fc8 100644 --- a/docs/test_cases/t00022_class.svg +++ b/docs/test_cases/t00022_class.svg @@ -1,6 +1,6 @@ - + @@ -9,76 +9,76 @@ - - + + A - + - + method1() = 0 : void - + - + method2() = 0 : void - + - + template_method() : void - - + + A1 - + - + method1() : void - + - + method2() : void - - + + A2 - + - + method1() : void - + - + method2() : void diff --git a/docs/test_cases/t00022_class_mermaid.svg b/docs/test_cases/t00022_class_mermaid.svg index cbaa5f6a..48a995de 100644 --- a/docs/test_cases/t00022_class_mermaid.svg +++ b/docs/test_cases/t00022_class_mermaid.svg @@ -74,7 +74,7 @@ - + @@ -108,7 +108,7 @@ - + @@ -137,7 +137,7 @@ - + diff --git a/docs/test_cases/t00023_class.svg b/docs/test_cases/t00023_class.svg index 3c706e34..315b71bb 100644 --- a/docs/test_cases/t00023_class.svg +++ b/docs/test_cases/t00023_class.svg @@ -1,6 +1,6 @@ - + @@ -9,102 +9,102 @@ - - + + Strategy - + - + ~Strategy() constexpr = default : void - + - + algorithm() = 0 : void - - + + StrategyA - + - + algorithm() : void - - + + StrategyB - + - + algorithm() : void - - + + StrategyC - + - + algorithm() : void - - + + Context - + - + Context(std::unique_ptr<Strategy> strategy) : void - + - + apply() : void - + - + m_strategy : std::unique_ptr<Strategy> diff --git a/docs/test_cases/t00023_class_mermaid.svg b/docs/test_cases/t00023_class_mermaid.svg index d75681c2..2defcbd6 100644 --- a/docs/test_cases/t00023_class_mermaid.svg +++ b/docs/test_cases/t00023_class_mermaid.svg @@ -96,7 +96,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -149,7 +149,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -197,7 +197,7 @@ - + diff --git a/docs/test_cases/t00024_class.svg b/docs/test_cases/t00024_class.svg index a715f2ab..caf24c70 100644 --- a/docs/test_cases/t00024_class.svg +++ b/docs/test_cases/t00024_class.svg @@ -1,6 +1,6 @@ - + @@ -9,115 +9,115 @@ - - + + Target - + - + ~Target() = 0 : void - + - + m1() = 0 : void - + - + m2() = 0 : void - - + + Target1 - + - + m1() : void - + - + m2() : void - - + + Target2 - + - + m1() : void - + - + m2() : void - - + + Proxy - + - + Proxy(std::shared_ptr<Target> target) : void - + - + m1() : void - + - + m2() : void - + - + m_target : std::shared_ptr<Target> diff --git a/docs/test_cases/t00024_class_mermaid.svg b/docs/test_cases/t00024_class_mermaid.svg index 56836ea3..88763564 100644 --- a/docs/test_cases/t00024_class_mermaid.svg +++ b/docs/test_cases/t00024_class_mermaid.svg @@ -96,7 +96,7 @@ - + @@ -130,7 +130,7 @@ - + @@ -159,7 +159,7 @@ - + @@ -188,7 +188,7 @@ - + diff --git a/docs/test_cases/t00025_class.svg b/docs/test_cases/t00025_class.svg index a5c82ae0..02f357ff 100644 --- a/docs/test_cases/t00025_class.svg +++ b/docs/test_cases/t00025_class.svg @@ -1,6 +1,6 @@ - + @@ -9,52 +9,52 @@ - - + + Target1 - + - + m1() : void - + - + m2() : void - - + + Target2 - + - + m1() : void - + - + m2() : void - - + + Proxy @@ -62,38 +62,38 @@ T - + - + Proxy(std::shared_ptr<T> target) : void - + - + m1() : void - + - + m2() : void - + - + m_target : std::shared_ptr<T> - - + + Proxy @@ -102,8 +102,8 @@ - - + + Proxy @@ -112,26 +112,26 @@ - - + + ProxyHolder - + - + proxy1 : Proxy<Target1> - + - + proxy2 : Proxy<Target2> diff --git a/docs/test_cases/t00025_class_mermaid.svg b/docs/test_cases/t00025_class_mermaid.svg index fb6f2717..3affc00b 100644 --- a/docs/test_cases/t00025_class_mermaid.svg +++ b/docs/test_cases/t00025_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -184,7 +184,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -242,7 +242,7 @@ - + @@ -261,7 +261,7 @@ - + diff --git a/docs/test_cases/t00026_class.svg b/docs/test_cases/t00026_class.svg index e4f172d9..24a73ef1 100644 --- a/docs/test_cases/t00026_class.svg +++ b/docs/test_cases/t00026_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + Memento @@ -18,31 +18,31 @@ T - + - + Memento(T && v) : void - + - + value() const : T - + - + m_value : T - - + + Originator @@ -50,52 +50,52 @@ T - + - + Originator(T && v) : void - + - + load(const Memento<T> & m) : void - + - + memoize_value() const : Memento<T> - + - + print() const : void - + - + set(T && v) : void - + - + m_value : T - - + + Caretaker @@ -103,30 +103,30 @@ T - + - + set_state(const std::string & s, Memento<T> && m) : void - + - + state(const std::string & n) : Memento<T> & - + - + m_mementos : std::unordered_map<std::string,Memento<T>> - - + + Caretaker @@ -135,8 +135,8 @@ - - + + Originator @@ -145,26 +145,26 @@ - - + + StringMemento - + - + caretaker : Caretaker<std::string> - + - + originator : Originator<std::string> diff --git a/docs/test_cases/t00026_class_mermaid.svg b/docs/test_cases/t00026_class_mermaid.svg index 368c7d2f..e581b3b5 100644 --- a/docs/test_cases/t00026_class_mermaid.svg +++ b/docs/test_cases/t00026_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -160,7 +160,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + diff --git a/docs/test_cases/t00027_class.svg b/docs/test_cases/t00027_class.svg index 0cbbc143..fd1eb24d 100644 --- a/docs/test_cases/t00027_class.svg +++ b/docs/test_cases/t00027_class.svg @@ -1,6 +1,6 @@ - + @@ -9,39 +9,39 @@ - - + + Shape - + - + ~Shape() constexpr = default : void - + - + display() = 0 : void - - + + Line - - + + Line @@ -49,24 +49,24 @@ T<>... - + - + display() : void - - + + Text - - + + Text @@ -74,31 +74,31 @@ T<>... - + - + display() : void - - + + ShapeDecorator - + - + display() = 0 : void - - + + Color @@ -106,16 +106,16 @@ T - + - + display() : void - - + + Weight @@ -123,16 +123,16 @@ T - + - + display() : void - - + + Line @@ -141,8 +141,8 @@ - - + + Line @@ -151,8 +151,8 @@ - - + + Text @@ -161,8 +161,8 @@ - - + + Text @@ -171,40 +171,40 @@ - - + + Window - + - + border : Line<Color,Weight> - + - + description : Text<Color> - + - + divider : Line<Color> - + - + title : Text<Color,Weight> diff --git a/docs/test_cases/t00027_class_mermaid.svg b/docs/test_cases/t00027_class_mermaid.svg index 966e5dc4..add990e0 100644 --- a/docs/test_cases/t00027_class_mermaid.svg +++ b/docs/test_cases/t00027_class_mermaid.svg @@ -190,7 +190,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -238,7 +238,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + @@ -305,7 +305,7 @@ - + @@ -329,7 +329,7 @@ - + @@ -353,7 +353,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -396,7 +396,7 @@ - + @@ -415,7 +415,7 @@ - + @@ -434,7 +434,7 @@ - + @@ -453,7 +453,7 @@ - + diff --git a/docs/test_cases/t00028_class.svg b/docs/test_cases/t00028_class.svg index dfd396ef..522a5c4e 100644 --- a/docs/test_cases/t00028_class.svg +++ b/docs/test_cases/t00028_class.svg @@ -1,6 +1,6 @@ - + @@ -9,54 +9,54 @@ - - + + A - + A class note. - - + + B - + B class note. - - + + C - + C class note. - - + + D - + D class note. - - + + E @@ -65,26 +65,26 @@ - + - + param : T - + E template class note. - - + + G - - + + F @@ -94,11 +94,11 @@ three - + F enum note. - - + + E @@ -107,70 +107,70 @@ - - + + R - + - + R(C & c) : void - + - + aaa : A - + - + bbb : B * - + - + ccc : C & - + - + ddd : std::vector<std::shared_ptr<D>> - + - + eee : E<int> - + - + ggg : G ** - + R class note. - + R contains an instance of A. - + Reference to C. diff --git a/docs/test_cases/t00028_class_mermaid.svg b/docs/test_cases/t00028_class_mermaid.svg index 62090bd2..6e1b93f5 100644 --- a/docs/test_cases/t00028_class_mermaid.svg +++ b/docs/test_cases/t00028_class_mermaid.svg @@ -218,7 +218,7 @@ - + @@ -237,7 +237,7 @@ - + @@ -256,7 +256,7 @@ - + @@ -275,7 +275,7 @@ - + @@ -294,7 +294,7 @@ - + @@ -318,7 +318,7 @@ - + @@ -337,7 +337,7 @@ - + @@ -371,7 +371,7 @@ - + @@ -390,7 +390,7 @@ - + diff --git a/docs/test_cases/t00029_class.svg b/docs/test_cases/t00029_class.svg index 76d3e068..880174aa 100644 --- a/docs/test_cases/t00029_class.svg +++ b/docs/test_cases/t00029_class.svg @@ -1,6 +1,6 @@ - + @@ -9,16 +9,16 @@ - - + + A - - + + C @@ -27,30 +27,30 @@ - + - + param : T - - + + D - + - + param : T - - + + E @@ -60,65 +60,65 @@ three - - + + G1 - - + + G2 - - + + G3 - - + + G4 - - + + R - + - + g1 : G1 - + - + g3 : G3 & - + - + g4 : std::shared_ptr<G4> diff --git a/docs/test_cases/t00029_class_mermaid.svg b/docs/test_cases/t00029_class_mermaid.svg index a7c5416f..e389cb03 100644 --- a/docs/test_cases/t00029_class_mermaid.svg +++ b/docs/test_cases/t00029_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -97,7 +97,7 @@ - + @@ -121,7 +121,7 @@ - + @@ -145,7 +145,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -198,7 +198,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -236,7 +236,7 @@ - + @@ -255,7 +255,7 @@ - + diff --git a/docs/test_cases/t00030_class.svg b/docs/test_cases/t00030_class.svg index 86441188..8ebd95c0 100644 --- a/docs/test_cases/t00030_class.svg +++ b/docs/test_cases/t00030_class.svg @@ -1,6 +1,6 @@ - + @@ -9,87 +9,87 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + R - + - + aaa : A - + - + bbb : std::vector<B> - + - + ccc : std::vector<C> - + - + ddd : D - + - + eee : E * diff --git a/docs/test_cases/t00030_class_mermaid.svg b/docs/test_cases/t00030_class_mermaid.svg index 74b84c49..ad291b18 100644 --- a/docs/test_cases/t00030_class_mermaid.svg +++ b/docs/test_cases/t00030_class_mermaid.svg @@ -164,7 +164,7 @@ - + @@ -183,7 +183,7 @@ - + @@ -202,7 +202,7 @@ - + @@ -221,7 +221,7 @@ - + @@ -240,7 +240,7 @@ - + @@ -259,7 +259,7 @@ - + diff --git a/docs/test_cases/t00031_class.svg b/docs/test_cases/t00031_class.svg index dfec6885..af6efe29 100644 --- a/docs/test_cases/t00031_class.svg +++ b/docs/test_cases/t00031_class.svg @@ -1,33 +1,33 @@ - + - + - + - - - + + + A - - + + B @@ -37,8 +37,8 @@ three - - + + @@ -48,23 +48,23 @@ - + - + ttt : T - - + + D - - + + C @@ -73,47 +73,47 @@ - - + + R - + - + add_b(B b) : void - + - + aaa : A * - + - + bbb : std::vector<B> - + - + ccc : C<int> - + - + ddd : D * diff --git a/docs/test_cases/t00031_class_mermaid.svg b/docs/test_cases/t00031_class_mermaid.svg index 02a3e15d..9f1464f4 100644 --- a/docs/test_cases/t00031_class_mermaid.svg +++ b/docs/test_cases/t00031_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -145,7 +145,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -241,7 +241,7 @@ - + diff --git a/docs/test_cases/t00032_class.svg b/docs/test_cases/t00032_class.svg index 47ffb367..8eed1e5c 100644 --- a/docs/test_cases/t00032_class.svg +++ b/docs/test_cases/t00032_class.svg @@ -1,6 +1,6 @@ - + @@ -9,69 +9,69 @@ - - + + Base - - + + TBase - - + + A - + - + operator()() : void - - + + B - + - + operator()() : void - - + + C - + - + operator()() : void - - + + Overload @@ -80,15 +80,15 @@ - + - + counter : L - - + + Overload @@ -97,19 +97,19 @@ - - + + R - + - + overload : Overload<TBase,int,A,B,C> diff --git a/docs/test_cases/t00032_class_mermaid.svg b/docs/test_cases/t00032_class_mermaid.svg index 4f81bd87..481cf4ea 100644 --- a/docs/test_cases/t00032_class_mermaid.svg +++ b/docs/test_cases/t00032_class_mermaid.svg @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -190,7 +190,7 @@ - + @@ -214,7 +214,7 @@ - + @@ -238,7 +238,7 @@ - + @@ -262,7 +262,7 @@ - + @@ -281,7 +281,7 @@ - + diff --git a/docs/test_cases/t00033_class.svg b/docs/test_cases/t00033_class.svg index 9e34d479..50b8ae8b 100644 --- a/docs/test_cases/t00033_class.svg +++ b/docs/test_cases/t00033_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,15 +19,15 @@ - + - + aaa : T - - + + B @@ -36,15 +36,15 @@ - + - + bbb : T - - + + C @@ -53,30 +53,30 @@ - + - + ccc : T - - + + D - + - + ddd : int - - + + C @@ -85,8 +85,8 @@ - - + + B @@ -95,8 +95,8 @@ - - + + A @@ -105,19 +105,19 @@ - - + + R - + - + abc : A<B<std::unique_ptr<C<D>>>> diff --git a/docs/test_cases/t00033_class_mermaid.svg b/docs/test_cases/t00033_class_mermaid.svg index 49a68c1d..1ec4129a 100644 --- a/docs/test_cases/t00033_class_mermaid.svg +++ b/docs/test_cases/t00033_class_mermaid.svg @@ -138,7 +138,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -186,7 +186,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -234,7 +234,7 @@ - + @@ -253,7 +253,7 @@ - + @@ -272,7 +272,7 @@ - + @@ -291,7 +291,7 @@ - + diff --git a/docs/test_cases/t00034_class.svg b/docs/test_cases/t00034_class.svg index 5bdf4b5f..5992e6d7 100644 --- a/docs/test_cases/t00034_class.svg +++ b/docs/test_cases/t00034_class.svg @@ -1,6 +1,6 @@ - + @@ -9,30 +9,30 @@ - - + + Void - + - + operator!=(const Void &) constexpr const : bool - + - + operator==(const Void &) constexpr const : bool - - + + lift_void @@ -41,8 +41,8 @@ - - + + lift_void @@ -51,8 +51,8 @@ - - + + drop_void @@ -61,8 +61,8 @@ - - + + drop_void @@ -71,34 +71,34 @@ - - + + A - - + + R - + - + la : lift_void_t<A> * - + - + lv : lift_void_t<void> * diff --git a/docs/test_cases/t00034_class_mermaid.svg b/docs/test_cases/t00034_class_mermaid.svg index 585b3b0d..ec70f833 100644 --- a/docs/test_cases/t00034_class_mermaid.svg +++ b/docs/test_cases/t00034_class_mermaid.svg @@ -102,7 +102,7 @@ - + @@ -131,7 +131,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -169,7 +169,7 @@ - + @@ -188,7 +188,7 @@ - + @@ -207,7 +207,7 @@ - + @@ -226,7 +226,7 @@ - + diff --git a/docs/test_cases/t00035_class.svg b/docs/test_cases/t00035_class.svg index 0023eddb..a0d8d775 100644 --- a/docs/test_cases/t00035_class.svg +++ b/docs/test_cases/t00035_class.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + Top - - + + Left - - + + Center - - + + Bottom - - + + Right diff --git a/docs/test_cases/t00035_class_mermaid.svg b/docs/test_cases/t00035_class_mermaid.svg index 45caa7e1..238e1199 100644 --- a/docs/test_cases/t00035_class_mermaid.svg +++ b/docs/test_cases/t00035_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + diff --git a/docs/test_cases/t00036_class.svg b/docs/test_cases/t00036_class.svg index 4fbda689..a0002c9b 100644 --- a/docs/test_cases/t00036_class.svg +++ b/docs/test_cases/t00036_class.svg @@ -1,6 +1,6 @@ - + @@ -9,23 +9,23 @@ - + ns1 - + ns11 - + ns111 - + ns2 - + ns22 - - + + E @@ -34,8 +34,8 @@ yellow - - + + A @@ -44,15 +44,15 @@ - + - + a : T - - + + A @@ -61,23 +61,23 @@ - - + + B - + - + a_int : A<int> - - + + C diff --git a/docs/test_cases/t00036_class_mermaid.svg b/docs/test_cases/t00036_class_mermaid.svg index 022f7a78..e6910710 100644 --- a/docs/test_cases/t00036_class_mermaid.svg +++ b/docs/test_cases/t00036_class_mermaid.svg @@ -78,7 +78,7 @@ - + @@ -107,7 +107,7 @@ - + @@ -131,7 +131,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -174,7 +174,7 @@ - + diff --git a/docs/test_cases/t00037_class.svg b/docs/test_cases/t00037_class.svg index f967f4f8..a5e800cf 100644 --- a/docs/test_cases/t00037_class.svg +++ b/docs/test_cases/t00037_class.svg @@ -1,6 +1,6 @@ - + @@ -9,106 +9,106 @@ - - + + ST - + - + dimensions : ST::(anonymous_662) - + - + units : ST::(anonymous_792) - - + + ST::(dimensions) - + - + t : double - + - + x : double - + - + y : double - + - + z : double - - + + ST::(units) - + - + c : double - + - + h : double - - + + A - + - + A() : void - + - + st : ST diff --git a/docs/test_cases/t00037_class_mermaid.svg b/docs/test_cases/t00037_class_mermaid.svg index 3514c1f3..dbcaff64 100644 --- a/docs/test_cases/t00037_class_mermaid.svg +++ b/docs/test_cases/t00037_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -119,7 +119,7 @@ - + @@ -158,7 +158,7 @@ - + @@ -187,7 +187,7 @@ - + diff --git a/docs/test_cases/t00038_class.svg b/docs/test_cases/t00038_class.svg index 5bec6b63..4a4617f4 100644 --- a/docs/test_cases/t00038_class.svg +++ b/docs/test_cases/t00038_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + thirdparty::ns1::color_t @@ -20,16 +20,16 @@ blue - - + + thirdparty::ns1::E - - + + property_t @@ -39,47 +39,47 @@ property_c - - + + A - - + + B - - + + C - - + + key_t - + - + key : std::string - - + + map @@ -88,8 +88,8 @@ - - + + map @@ -98,8 +98,8 @@ - - + + map @@ -108,8 +108,8 @@ - - + + map @@ -118,8 +118,8 @@ - - + + map diff --git a/docs/test_cases/t00038_class_mermaid.svg b/docs/test_cases/t00038_class_mermaid.svg index be356b65..6c5aa82a 100644 --- a/docs/test_cases/t00038_class_mermaid.svg +++ b/docs/test_cases/t00038_class_mermaid.svg @@ -202,7 +202,7 @@ - + @@ -236,7 +236,7 @@ - + @@ -255,7 +255,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -308,7 +308,7 @@ - + @@ -327,7 +327,7 @@ - + @@ -346,7 +346,7 @@ - + @@ -370,7 +370,7 @@ - + @@ -389,7 +389,7 @@ - + @@ -408,7 +408,7 @@ - + @@ -427,7 +427,7 @@ - + @@ -446,7 +446,7 @@ - + diff --git a/docs/test_cases/t00039_class.svg b/docs/test_cases/t00039_class.svg index 6c461468..23a56efd 100644 --- a/docs/test_cases/t00039_class.svg +++ b/docs/test_cases/t00039_class.svg @@ -1,6 +1,6 @@ - + @@ -9,95 +9,95 @@ - - + + C - - + + D - - + + E - - + + CD - - + + DE - - + + CDE - - + + A - - + + AA - - + + AAA - + - + b : B * - - + + ns2::AAAA - - + + ns3::F @@ -106,15 +106,15 @@ - + - + t : T * - - + + ns3::FF @@ -123,15 +123,15 @@ - + - + m : M * - - + + ns3::FE @@ -140,15 +140,15 @@ - + - + m : M * - - + + ns3::FFF @@ -157,11 +157,11 @@ - + - + n : N * diff --git a/docs/test_cases/t00039_class_mermaid.svg b/docs/test_cases/t00039_class_mermaid.svg index 4a01c7a1..b1a404ad 100644 --- a/docs/test_cases/t00039_class_mermaid.svg +++ b/docs/test_cases/t00039_class_mermaid.svg @@ -184,7 +184,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -260,7 +260,7 @@ - + @@ -279,7 +279,7 @@ - + @@ -298,7 +298,7 @@ - + @@ -317,7 +317,7 @@ - + @@ -336,7 +336,7 @@ - + @@ -360,7 +360,7 @@ - + @@ -379,7 +379,7 @@ - + @@ -403,7 +403,7 @@ - + @@ -427,7 +427,7 @@ - + @@ -451,7 +451,7 @@ - + diff --git a/docs/test_cases/t00040_class.svg b/docs/test_cases/t00040_class.svg index 6335fe64..1ee6665f 100644 --- a/docs/test_cases/t00040_class.svg +++ b/docs/test_cases/t00040_class.svg @@ -1,6 +1,6 @@ - + @@ -9,70 +9,70 @@ - - + + A - + - + get_a() : int - + - + ii_ : int - - + + AA - - + + AAA - + - + get_aaa() : int - + - + b : B * - - + + R - + - + foo(A * a) : void diff --git a/docs/test_cases/t00040_class_mermaid.svg b/docs/test_cases/t00040_class_mermaid.svg index 871ae22a..a2ed1af5 100644 --- a/docs/test_cases/t00040_class_mermaid.svg +++ b/docs/test_cases/t00040_class_mermaid.svg @@ -74,7 +74,7 @@ - + @@ -103,7 +103,7 @@ - + @@ -122,7 +122,7 @@ - + @@ -151,7 +151,7 @@ - + diff --git a/docs/test_cases/t00041_class.svg b/docs/test_cases/t00041_class.svg index 62e3a2aa..6943951e 100644 --- a/docs/test_cases/t00041_class.svg +++ b/docs/test_cases/t00041_class.svg @@ -1,6 +1,6 @@ - + @@ -9,107 +9,107 @@ - - + + R - - + + D - + - + rr : RR * - - + + E - - + + F - - + + RR - + - + foo(H * h) : void - + - + e : E * - + - + f : F * - + - + g : detail::G * - - + + RRR - - + + ns1::N - - + + ns1::NN - - + + ns1::NM diff --git a/docs/test_cases/t00041_class_mermaid.svg b/docs/test_cases/t00041_class_mermaid.svg index 29ef0b8d..ea02f770 100644 --- a/docs/test_cases/t00041_class_mermaid.svg +++ b/docs/test_cases/t00041_class_mermaid.svg @@ -130,7 +130,7 @@ - + @@ -149,7 +149,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -192,7 +192,7 @@ - + @@ -211,7 +211,7 @@ - + @@ -250,7 +250,7 @@ - + @@ -269,7 +269,7 @@ - + @@ -288,7 +288,7 @@ - + @@ -307,7 +307,7 @@ - + diff --git a/docs/test_cases/t00042_class.svg b/docs/test_cases/t00042_class.svg index ead042cf..41442637 100644 --- a/docs/test_cases/t00042_class.svg +++ b/docs/test_cases/t00042_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,15 +19,15 @@ - + - + a : T - - + + A @@ -36,15 +36,15 @@ - + - + a : void * - - + + B @@ -53,22 +53,22 @@ - + - + b : T - + - + bb : K - - + + A @@ -77,8 +77,8 @@ - - + + A @@ -87,8 +87,8 @@ - - + + B diff --git a/docs/test_cases/t00042_class_mermaid.svg b/docs/test_cases/t00042_class_mermaid.svg index b10f3f2a..cb1e01f6 100644 --- a/docs/test_cases/t00042_class_mermaid.svg +++ b/docs/test_cases/t00042_class_mermaid.svg @@ -102,7 +102,7 @@ - + @@ -126,7 +126,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -179,7 +179,7 @@ - + @@ -198,7 +198,7 @@ - + @@ -217,7 +217,7 @@ - + diff --git a/docs/test_cases/t00043_class.svg b/docs/test_cases/t00043_class.svg index 3f8c664c..936d6c26 100644 --- a/docs/test_cases/t00043_class.svg +++ b/docs/test_cases/t00043_class.svg @@ -1,6 +1,6 @@ - + @@ -9,167 +9,167 @@ - + dependants - + dependencies - - + + A - - + + B - + - + b(A * a) : void - - + + BB - + - + bb(A * a) : void - - + + C - + - + c(B * b) : void - - + + D - + - + d(C * c) : void - + - + dd(BB * bb) : void - - + + E - + - + e(D * d) : void - - + + G - - + + GG - - + + H - + - + h(G * g) : void - + - + hh(GG * gg) : void - - + + I - + - + i(H * h) : void - - + + J - + - + i(I * i) : void diff --git a/docs/test_cases/t00043_class_mermaid.svg b/docs/test_cases/t00043_class_mermaid.svg index 6eff05af..c787959a 100644 --- a/docs/test_cases/t00043_class_mermaid.svg +++ b/docs/test_cases/t00043_class_mermaid.svg @@ -174,7 +174,7 @@ - + @@ -193,7 +193,7 @@ - + @@ -217,7 +217,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -265,7 +265,7 @@ - + @@ -294,7 +294,7 @@ - + @@ -318,7 +318,7 @@ - + @@ -337,7 +337,7 @@ - + @@ -356,7 +356,7 @@ - + @@ -385,7 +385,7 @@ - + @@ -409,7 +409,7 @@ - + diff --git a/docs/test_cases/t00044_class.svg b/docs/test_cases/t00044_class.svg index 5c7e8f20..ddb57da9 100644 --- a/docs/test_cases/t00044_class.svg +++ b/docs/test_cases/t00044_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + signal_handler @@ -19,8 +19,8 @@ - - + + sink @@ -28,26 +28,26 @@ signal_handler<Ret(Args...),A> - + - + sink(signal_t & sh) : void get_signal<CastTo>() : CastTo * - + - + signal : signal_t * - - + + signal_handler @@ -56,8 +56,8 @@ - - + + sink @@ -66,23 +66,23 @@ - - + + R - + - + sink1 : sink<signal_handler<void (int),bool>> - - + + signal_handler @@ -91,8 +91,8 @@ - - + + sink diff --git a/docs/test_cases/t00044_class_mermaid.svg b/docs/test_cases/t00044_class_mermaid.svg index a1b147c5..ea5e4e9e 100644 --- a/docs/test_cases/t00044_class_mermaid.svg +++ b/docs/test_cases/t00044_class_mermaid.svg @@ -138,7 +138,7 @@ - + @@ -157,7 +157,7 @@ - + @@ -191,7 +191,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -253,7 +253,7 @@ - + @@ -272,7 +272,7 @@ - + diff --git a/docs/test_cases/t00045_class.svg b/docs/test_cases/t00045_class.svg index f45ec475..a4881801 100644 --- a/docs/test_cases/t00045_class.svg +++ b/docs/test_cases/t00045_class.svg @@ -1,6 +1,6 @@ - + @@ -9,32 +9,32 @@ - - + + A - - + + AA - - + + AAA - - + + AAAA @@ -43,110 +43,110 @@ - + - + t : T - - + + ns1::A - - + + ns1::ns2::A - - + + ns1::ns2::B - - + + ns1::ns2::C - - + + ns1::ns2::D - - + + ns1::ns2::E - - + + ns1::ns2::AAA - - + + ns1::ns2::R - + - + foo(AA & aa) : void - + - + a : A * - + - + ns1_a : ns1::A * - + - + ns1_ns2_a : ns1::ns2::A * - + - + root_a : ::A * diff --git a/docs/test_cases/t00045_class_mermaid.svg b/docs/test_cases/t00045_class_mermaid.svg index 06564c82..f9912438 100644 --- a/docs/test_cases/t00045_class_mermaid.svg +++ b/docs/test_cases/t00045_class_mermaid.svg @@ -166,7 +166,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -247,7 +247,7 @@ - + @@ -266,7 +266,7 @@ - + @@ -285,7 +285,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -342,7 +342,7 @@ - + @@ -361,7 +361,7 @@ - + @@ -380,7 +380,7 @@ - + diff --git a/docs/test_cases/t00046_class.svg b/docs/test_cases/t00046_class.svg index 5802c472..21d80b18 100644 --- a/docs/test_cases/t00046_class.svg +++ b/docs/test_cases/t00046_class.svg @@ -1,6 +1,6 @@ - + @@ -9,120 +9,120 @@ - + ns1 - + ns2 - - + + A - - + + A - - + + B - - + + C - - + + D - - + + E - - + + R - + - + foo(AA & aa) : void - + - + a : A * - + - + i : std::vector<std::uint8_t> - + - + ns1_a : ns1::A * - + - + ns1_ns2_a : ns1::ns2::A * - + - + root_a : ::A * - - + + A - - + + AA diff --git a/docs/test_cases/t00046_class_mermaid.svg b/docs/test_cases/t00046_class_mermaid.svg index 42fa8b8c..a7d79e1a 100644 --- a/docs/test_cases/t00046_class_mermaid.svg +++ b/docs/test_cases/t00046_class_mermaid.svg @@ -154,7 +154,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -192,7 +192,7 @@ - + @@ -211,7 +211,7 @@ - + @@ -230,7 +230,7 @@ - + @@ -249,7 +249,7 @@ - + @@ -268,7 +268,7 @@ - + @@ -287,7 +287,7 @@ - + @@ -306,7 +306,7 @@ - + diff --git a/docs/test_cases/t00047_class.svg b/docs/test_cases/t00047_class.svg index ff962603..4258ea04 100644 --- a/docs/test_cases/t00047_class.svg +++ b/docs/test_cases/t00047_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + conditional_t @@ -19,8 +19,8 @@ - - + + conditional_t @@ -29,8 +29,8 @@ - - + + conditional_t @@ -39,8 +39,8 @@ - - + + conditional_t diff --git a/docs/test_cases/t00047_class_mermaid.svg b/docs/test_cases/t00047_class_mermaid.svg index dd7828bd..213b9b52 100644 --- a/docs/test_cases/t00047_class_mermaid.svg +++ b/docs/test_cases/t00047_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + diff --git a/docs/test_cases/t00048_class.svg b/docs/test_cases/t00048_class.svg index 8296eaef..34f694ec 100644 --- a/docs/test_cases/t00048_class.svg +++ b/docs/test_cases/t00048_class.svg @@ -1,6 +1,6 @@ - + @@ -9,30 +9,30 @@ - - + + Base - + - + foo() = 0 : void - + - + base : int - - + + BaseTemplate @@ -40,45 +40,45 @@ T - + - + foo() = 0 : void - + - + base : T - - + + B - + - + foo() : void - + - + b : int - - + + BTemplate @@ -86,45 +86,45 @@ T - + - + foo() : void - + - + b : T - - + + A - + - + foo() : void - + - + a : int - - + + ATemplate @@ -132,19 +132,19 @@ T - + - + foo() : void - + - + a : T diff --git a/docs/test_cases/t00048_class_mermaid.svg b/docs/test_cases/t00048_class_mermaid.svg index e1ee0151..e0b2424e 100644 --- a/docs/test_cases/t00048_class_mermaid.svg +++ b/docs/test_cases/t00048_class_mermaid.svg @@ -94,7 +94,7 @@ - + @@ -123,7 +123,7 @@ - + @@ -152,7 +152,7 @@ - + @@ -181,7 +181,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -239,7 +239,7 @@ - + diff --git a/docs/test_cases/t00049_class.svg b/docs/test_cases/t00049_class.svg index 105eebab..44093226 100644 --- a/docs/test_cases/t00049_class.svg +++ b/docs/test_cases/t00049_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -18,23 +18,23 @@ T - + - + get_a() : T & - + - + a : T - - + + A @@ -43,8 +43,8 @@ - - + + A @@ -53,8 +53,8 @@ - - + + A @@ -63,47 +63,47 @@ - - + + R - + - + get_int_map() : A<intmap> - + - + set_int_map(A<intmap> && int_map) : void - + - + a_int_map : A<intmap> - + - + a_string : A<thestring> - + - + a_vector_string : A<string_vector> diff --git a/docs/test_cases/t00049_class_mermaid.svg b/docs/test_cases/t00049_class_mermaid.svg index d6348c44..a61d192d 100644 --- a/docs/test_cases/t00049_class_mermaid.svg +++ b/docs/test_cases/t00049_class_mermaid.svg @@ -126,7 +126,7 @@ - + @@ -155,7 +155,7 @@ - + @@ -174,7 +174,7 @@ - + @@ -193,7 +193,7 @@ - + @@ -212,7 +212,7 @@ - + diff --git a/docs/test_cases/t00050_class.svg b/docs/test_cases/t00050_class.svg index 0c133617..8ba79774 100644 --- a/docs/test_cases/t00050_class.svg +++ b/docs/test_cases/t00050_class.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + A - - + + B - - + + C - - + + utils::D - - + + E @@ -52,8 +52,8 @@ E3 - - + + F @@ -62,43 +62,43 @@ - + - + t : T[N] - + - + v : V - - + + G - - + + NoComment - + Lorem ipsum dolor sit - + Lorem ipsum dolor sit - + Lorem ipsum dolor sit amet consectetur adipiscing elit, urna consequat felis vehicula class ultricies mollis dictumst, aenean non a in donec nulla. @@ -125,50 +125,50 @@ imperdiet praesent magnis ridiculus congue gravida curabitur dictum sagittis, enim et magna sit inceptos sodales parturient pharetra mollis, aenean vel nostra tellus commodo pretium sapien sociosqu. - + This is a short description of class G. - + This is an intermediate description of class G. - + This is a long description of class G. - + Lorem ipsum - + TODO 1. Write meaningful comment - + TODO 2. Write tests - + TODO 3. Implement - + Long comment example - + TODO Implement... - + Simple array wrapper. - + Template parameters diff --git a/docs/test_cases/t00050_class_mermaid.svg b/docs/test_cases/t00050_class_mermaid.svg index 4718e825..939a8a20 100644 --- a/docs/test_cases/t00050_class_mermaid.svg +++ b/docs/test_cases/t00050_class_mermaid.svg @@ -184,7 +184,7 @@ - + @@ -203,7 +203,7 @@ - + @@ -222,7 +222,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -260,7 +260,7 @@ - + @@ -294,7 +294,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -342,7 +342,7 @@ - + diff --git a/docs/test_cases/t00051_class.svg b/docs/test_cases/t00051_class.svg index 1d91a229..8904860d 100644 --- a/docs/test_cases/t00051_class.svg +++ b/docs/test_cases/t00051_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + B @@ -18,45 +18,45 @@ F,FF=F - + - + B(F && f, FF && ff) : void - + - + f() : void - + - + ff() : void - + - + f_ : F - + - + ff_ : FF - - + + B @@ -64,81 +64,81 @@ (lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27) - + - + B((lambda at t00051.cc:43:18) && f, (lambda at t00051.cc:43:27) && ff) : void - + - + f() : void - + - + ff() : void - + - + f_ : (lambda at t00051.cc:43:18) - + - + ff_ : (lambda at t00051.cc:43:27) - - + + A - + - + get_function() : (lambda at t00051.cc:48:16) - + - + start_thread1() : custom_thread1 - + - + start_thread2() : custom_thread2 - + - + start_thread3() : B<(lambda at t00051.cc:43:18),(lambda at t00051.cc:43:27)> - - + + A::custom_thread1 @@ -147,18 +147,18 @@ custom_thread1<Function,Args...>(Function && f, Args &&... args) : void - - + + A::custom_thread2 - + - + thread((lambda at t00051.cc:59:27) &&) : void diff --git a/docs/test_cases/t00051_class_mermaid.svg b/docs/test_cases/t00051_class_mermaid.svg index 05918c15..74806e14 100644 --- a/docs/test_cases/t00051_class_mermaid.svg +++ b/docs/test_cases/t00051_class_mermaid.svg @@ -102,7 +102,7 @@ - + @@ -146,7 +146,7 @@ - + @@ -190,7 +190,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -253,7 +253,7 @@ - + diff --git a/docs/test_cases/t00052_class.svg b/docs/test_cases/t00052_class.svg index 68d85db6..d9e5dda1 100644 --- a/docs/test_cases/t00052_class.svg +++ b/docs/test_cases/t00052_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -21,8 +21,8 @@ aa<F,Q>(F && f, Q q) : void - - + + B @@ -30,18 +30,18 @@ T - + - + b(T t) : T bb<F>(F && f, T t) : T - - + + C @@ -52,8 +52,8 @@ c<P>(P p) : T - - + + B @@ -62,8 +62,8 @@ - - + + C @@ -72,33 +72,33 @@ - - + + R - + - + a : A - + - + b : B<int> - + - + c : C<int> diff --git a/docs/test_cases/t00052_class_mermaid.svg b/docs/test_cases/t00052_class_mermaid.svg index 1d2c191a..47230ca6 100644 --- a/docs/test_cases/t00052_class_mermaid.svg +++ b/docs/test_cases/t00052_class_mermaid.svg @@ -114,7 +114,7 @@ - + @@ -143,7 +143,7 @@ - + @@ -172,7 +172,7 @@ - + @@ -196,7 +196,7 @@ - + @@ -215,7 +215,7 @@ - + @@ -234,7 +234,7 @@ - + diff --git a/docs/test_cases/t00053_class.svg b/docs/test_cases/t00053_class.svg index 890b0941..fbab5ee9 100644 --- a/docs/test_cases/t00053_class.svg +++ b/docs/test_cases/t00053_class.svg @@ -1,6 +1,6 @@ - + @@ -9,72 +9,72 @@ - - + + A - - + + C - - + + E - - + + F - - + + a - - + + c - - + + e - - + + f - - + + h @@ -82,8 +82,8 @@ hhh - - + + j @@ -91,56 +91,56 @@ jjj - - + + b - - + + d - - + + g - - + + B - - + + D - - + + G - - + + i diff --git a/docs/test_cases/t00053_class_mermaid.svg b/docs/test_cases/t00053_class_mermaid.svg index f0107c52..2c23e897 100644 --- a/docs/test_cases/t00053_class_mermaid.svg +++ b/docs/test_cases/t00053_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -190,7 +190,7 @@ - + @@ -209,7 +209,7 @@ - + @@ -228,7 +228,7 @@ - + @@ -247,7 +247,7 @@ - + @@ -266,7 +266,7 @@ - + @@ -285,7 +285,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -342,7 +342,7 @@ - + @@ -366,7 +366,7 @@ - + diff --git a/docs/test_cases/t00054_class.svg b/docs/test_cases/t00054_class.svg index c70948ee..551efd79 100644 --- a/docs/test_cases/t00054_class.svg +++ b/docs/test_cases/t00054_class.svg @@ -1,6 +1,6 @@ - + @@ -9,28 +9,28 @@ - + detail - + detail2 - + detail3 - + detail4 - - + + d - - + + a @@ -40,8 +40,8 @@ - - + + c @@ -51,8 +51,8 @@ - - + + e @@ -62,40 +62,40 @@ - - + + C - - + + F - - + + D - - + + E - - + + A @@ -104,8 +104,8 @@ - - + + B @@ -114,8 +114,8 @@ - - + + f @@ -124,8 +124,8 @@ - - + + G @@ -133,8 +133,8 @@ - - + + h @@ -143,8 +143,8 @@ hhh - - + + i @@ -153,8 +153,8 @@ iii - - + + j @@ -163,16 +163,16 @@ jjj - - + + b - - + + g diff --git a/docs/test_cases/t00054_class_mermaid.svg b/docs/test_cases/t00054_class_mermaid.svg index 6aec9550..05914386 100644 --- a/docs/test_cases/t00054_class_mermaid.svg +++ b/docs/test_cases/t00054_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -223,7 +223,7 @@ - + @@ -242,7 +242,7 @@ - + @@ -261,7 +261,7 @@ - + @@ -280,7 +280,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -328,7 +328,7 @@ - + @@ -352,7 +352,7 @@ - + @@ -371,7 +371,7 @@ - + diff --git a/docs/test_cases/t00055_class.svg b/docs/test_cases/t00055_class.svg index e2c3d7b3..cd306e4a 100644 --- a/docs/test_cases/t00055_class.svg +++ b/docs/test_cases/t00055_class.svg @@ -1,6 +1,6 @@ - + @@ -9,80 +9,80 @@ - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F - - + + G - - + + H - - + + I - - + + J diff --git a/docs/test_cases/t00055_class_mermaid.svg b/docs/test_cases/t00055_class_mermaid.svg index 0407ce56..16ea6f49 100644 --- a/docs/test_cases/t00055_class_mermaid.svg +++ b/docs/test_cases/t00055_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -128,7 +128,7 @@ - + @@ -147,7 +147,7 @@ - + @@ -166,7 +166,7 @@ - + @@ -185,7 +185,7 @@ - + @@ -204,7 +204,7 @@ - + @@ -223,7 +223,7 @@ - + diff --git a/docs/test_cases/t00056_class.svg b/docs/test_cases/t00056_class.svg index 16b8bc45..c972eac0 100644 --- a/docs/test_cases/t00056_class.svg +++ b/docs/test_cases/t00056_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + «concept» @@ -20,8 +20,8 @@ - - + + «concept» @@ -33,8 +33,8 @@ sizeof (l) > sizeof (r) - - + + «concept» @@ -44,8 +44,8 @@ - - + + «concept» @@ -58,8 +58,8 @@ container.begin() container.end() - - + + «concept» @@ -71,8 +71,8 @@ typename T::value_type - - + + «concept» @@ -86,8 +86,8 @@ {std::to_string(s)} noexcept {std::to_string(s)} -> std::same_as<std::string> - - + + «concept» @@ -97,8 +97,8 @@ - - + + «concept» @@ -108,8 +108,8 @@ - - + + A @@ -118,15 +118,15 @@ - + - + a : T - - + + B @@ -135,15 +135,15 @@ - + - + b : T - - + + C @@ -152,15 +152,15 @@ - + - + c : T - - + + D @@ -169,8 +169,8 @@ - - + + E @@ -179,29 +179,29 @@ - + - + e1 : T1 - + - + e2 : T2 - + - + e3 : T3 - - + + F @@ -210,25 +210,25 @@ - + - + f1 : T1 - + - + f2 : T2 - + - + f3 : T3 diff --git a/docs/test_cases/t00056_class_mermaid.svg b/docs/test_cases/t00056_class_mermaid.svg index 9c839011..01f61403 100644 --- a/docs/test_cases/t00056_class_mermaid.svg +++ b/docs/test_cases/t00056_class_mermaid.svg @@ -222,7 +222,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -270,7 +270,7 @@ - + @@ -289,7 +289,7 @@ - + @@ -323,7 +323,7 @@ - + @@ -352,7 +352,7 @@ - + @@ -391,7 +391,7 @@ - + @@ -410,7 +410,7 @@ - + @@ -429,7 +429,7 @@ - + @@ -453,7 +453,7 @@ - + @@ -477,7 +477,7 @@ - + @@ -501,7 +501,7 @@ - + @@ -520,7 +520,7 @@ - + @@ -554,7 +554,7 @@ - + diff --git a/docs/test_cases/t00057_class.svg b/docs/test_cases/t00057_class.svg index 1bc4d267..28feb8d5 100644 --- a/docs/test_cases/t00057_class.svg +++ b/docs/test_cases/t00057_class.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - - + + t00057_A - + - + a1 : int - - + + t00057_B - + - + b1 : int - - + + t00057_C - + - + c1 : int - - + + «union» @@ -63,73 +63,73 @@ - + - + d1 : int - + - + d2 : float - - + + t00057_E - + - + coordinates : t00057_E::(anonymous_739) - + - + e : int - + - + height : t00057_E::(anonymous_807) - - + + t00057_E::(coordinates) - + - + x : int - + - + y : int - - + + «union» @@ -137,105 +137,105 @@ - + - + t : double - + - + z : int - - + + t00057_G - + - + g1 : int - - + + t00057_R - + - + a : struct t00057_A - + - + b : t00057_B - + - + c : struct t00057_C * - + - + d : union t00057_D - + - + e : struct t00057_E * - + - + f : struct t00057_F * - + - + g : struct t00057_G * - - + + t00057_F - + - + f1 : int diff --git a/docs/test_cases/t00057_class_mermaid.svg b/docs/test_cases/t00057_class_mermaid.svg index f5431d12..77d8a797 100644 --- a/docs/test_cases/t00057_class_mermaid.svg +++ b/docs/test_cases/t00057_class_mermaid.svg @@ -162,7 +162,7 @@ - + @@ -186,7 +186,7 @@ - + @@ -210,7 +210,7 @@ - + @@ -234,7 +234,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -297,7 +297,7 @@ - + @@ -326,7 +326,7 @@ - + @@ -355,7 +355,7 @@ - + @@ -379,7 +379,7 @@ - + @@ -433,7 +433,7 @@ - + diff --git a/docs/test_cases/t00058_class.svg b/docs/test_cases/t00058_class.svg index 21ff06ec..fce401d0 100644 --- a/docs/test_cases/t00058_class.svg +++ b/docs/test_cases/t00058_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + first_type @@ -19,8 +19,8 @@ - - + + «concept» @@ -30,8 +30,8 @@ - - + + A @@ -40,15 +40,15 @@ - + - + a : std::vector<T> - - + + B @@ -57,22 +57,22 @@ - + - + b : std::vector<T> - + - + bb : P - - + + A @@ -81,8 +81,8 @@ - - + + A @@ -91,8 +91,8 @@ - - + + B @@ -101,26 +101,26 @@ - - + + R - + - + aa : A<int,int,double,std::string> - + - + bb : B<int,std::string,int,double,A<int,int>> diff --git a/docs/test_cases/t00058_class_mermaid.svg b/docs/test_cases/t00058_class_mermaid.svg index 17e902e6..9c2bca92 100644 --- a/docs/test_cases/t00058_class_mermaid.svg +++ b/docs/test_cases/t00058_class_mermaid.svg @@ -150,7 +150,7 @@ - + @@ -169,7 +169,7 @@ - + @@ -188,7 +188,7 @@ - + @@ -212,7 +212,7 @@ - + @@ -241,7 +241,7 @@ - + @@ -260,7 +260,7 @@ - + @@ -279,7 +279,7 @@ - + @@ -298,7 +298,7 @@ - + diff --git a/docs/test_cases/t00059_class.svg b/docs/test_cases/t00059_class.svg index 3fb109cb..c48a07ba 100644 --- a/docs/test_cases/t00059_class.svg +++ b/docs/test_cases/t00059_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + «concept» @@ -23,8 +23,8 @@ T{} t.get_name() - - + + «concept» @@ -36,8 +36,8 @@ t.get_sweetness() - - + + «concept» @@ -49,96 +49,96 @@ t.get_bitterness() - - + + gala_apple - + - + get_name() const : std::string - + - + get_sweetness() const : float - - + + empire_apple - + - + get_name() const : std::string - + - + get_sweetness() const : float - - + + lima_orange - + - + get_bitterness() const : float - + - + get_name() const : std::string - - + + valencia_orange - + - + get_bitterness() const : float - + - + get_name() const : std::string - - + + fruit_factory @@ -146,23 +146,23 @@ apple_c TA,orange_c TO - + - + create_apple() const : TA - + - + create_orange() const : TO - - + + fruit_factory @@ -171,8 +171,8 @@ - - + + fruit_factory @@ -181,26 +181,26 @@ - - + + R - + - + factory_1 : fruit_factory_1 - + - + factory_2 : fruit_factory_2 diff --git a/docs/test_cases/t00059_class_mermaid.svg b/docs/test_cases/t00059_class_mermaid.svg index fae6b89a..0c255039 100644 --- a/docs/test_cases/t00059_class_mermaid.svg +++ b/docs/test_cases/t00059_class_mermaid.svg @@ -198,7 +198,7 @@ - + @@ -232,7 +232,7 @@ - + @@ -261,7 +261,7 @@ - + @@ -290,7 +290,7 @@ - + @@ -319,7 +319,7 @@ - + @@ -348,7 +348,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -406,7 +406,7 @@ - + @@ -435,7 +435,7 @@ - + @@ -454,7 +454,7 @@ - + @@ -473,7 +473,7 @@ - + diff --git a/docs/test_cases/t00060_class.svg b/docs/test_cases/t00060_class.svg index b66edb1a..31c89eac 100644 --- a/docs/test_cases/t00060_class.svg +++ b/docs/test_cases/t00060_class.svg @@ -1,6 +1,6 @@ - + @@ -9,40 +9,40 @@ - - + + A - - + + B - - + + C - - + + D - - + + G @@ -51,15 +51,15 @@ - + - + g : T - - + + H @@ -68,18 +68,18 @@ - + - + h : G<T> - + - + hh : P diff --git a/docs/test_cases/t00060_class_mermaid.svg b/docs/test_cases/t00060_class_mermaid.svg index cee3f138..67c31939 100644 --- a/docs/test_cases/t00060_class_mermaid.svg +++ b/docs/test_cases/t00060_class_mermaid.svg @@ -116,7 +116,7 @@ - + @@ -135,7 +135,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -173,7 +173,7 @@ - + @@ -192,7 +192,7 @@ - + @@ -216,7 +216,7 @@ - + diff --git a/docs/test_cases/t00061_class.svg b/docs/test_cases/t00061_class.svg index 64641eeb..46b44e7c 100644 --- a/docs/test_cases/t00061_class.svg +++ b/docs/test_cases/t00061_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A diff --git a/docs/test_cases/t00061_class_mermaid.svg b/docs/test_cases/t00061_class_mermaid.svg index fc2deb6c..9d1124f6 100644 --- a/docs/test_cases/t00061_class_mermaid.svg +++ b/docs/test_cases/t00061_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00062_class.svg b/docs/test_cases/t00062_class.svg index 5cff962d..0fe9d762 100644 --- a/docs/test_cases/t00062_class.svg +++ b/docs/test_cases/t00062_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A @@ -19,15 +19,15 @@ - + - + u : U & - - + + A @@ -36,15 +36,15 @@ - + - + u : U & - - + + A @@ -53,8 +53,8 @@ - - + + A @@ -63,15 +63,15 @@ - + - + u : U ** - - + + A @@ -80,15 +80,15 @@ - + - + u : U *** - - + + A @@ -97,15 +97,15 @@ - + - + u : U *** - - + + A @@ -114,15 +114,15 @@ - + - + u : U && - - + + A @@ -131,15 +131,15 @@ - + - + u : const U & - - + + A @@ -148,22 +148,22 @@ - + - + c : C & - + - + m : M C::* - - + + A @@ -172,22 +172,22 @@ - + - + c : C && - + - + m : M C::* - - + + A @@ -196,22 +196,22 @@ - + - + c : C & - + - + m : M C::* - - + + A @@ -220,15 +220,15 @@ - + - + c : C & - - + + A @@ -237,22 +237,22 @@ - + - + c : C && - + - + m : M C::* - - + + A @@ -261,22 +261,22 @@ - + - + c : C && - + - + mf : float C::* - - + + A @@ -285,22 +285,22 @@ - + - + c : C & - + - + m : M C::* - - + + A @@ -309,15 +309,15 @@ - + - + n : char[N] - - + + A @@ -326,15 +326,15 @@ - + - + n : std::vector<char> - - + + A @@ -343,15 +343,15 @@ - + - + klm : char[K][L][M] - - + + A @@ -360,15 +360,15 @@ - + - + u : bool - - + + A @@ -377,15 +377,15 @@ - + - + c : C<T> - - + + A @@ -394,22 +394,22 @@ - + - + args : std::tuple<Args...> - + - + c : C<T> - - + + A diff --git a/docs/test_cases/t00062_class_mermaid.svg b/docs/test_cases/t00062_class_mermaid.svg index 1b17e031..b718e443 100644 --- a/docs/test_cases/t00062_class_mermaid.svg +++ b/docs/test_cases/t00062_class_mermaid.svg @@ -306,7 +306,7 @@ - + @@ -330,7 +330,7 @@ - + @@ -354,7 +354,7 @@ - + @@ -373,7 +373,7 @@ - + @@ -397,7 +397,7 @@ - + @@ -421,7 +421,7 @@ - + @@ -445,7 +445,7 @@ - + @@ -469,7 +469,7 @@ - + @@ -493,7 +493,7 @@ - + @@ -522,7 +522,7 @@ - + @@ -551,7 +551,7 @@ - + @@ -580,7 +580,7 @@ - + @@ -604,7 +604,7 @@ - + @@ -633,7 +633,7 @@ - + @@ -662,7 +662,7 @@ - + @@ -691,7 +691,7 @@ - + @@ -715,7 +715,7 @@ - + @@ -739,7 +739,7 @@ - + @@ -763,7 +763,7 @@ - + @@ -787,7 +787,7 @@ - + @@ -811,7 +811,7 @@ - + @@ -840,7 +840,7 @@ - + diff --git a/docs/test_cases/t00063_class.svg b/docs/test_cases/t00063_class.svg index 18fa22a5..6d584517 100644 --- a/docs/test_cases/t00063_class.svg +++ b/docs/test_cases/t00063_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + A diff --git a/docs/test_cases/t00063_class_mermaid.svg b/docs/test_cases/t00063_class_mermaid.svg index d7187c2a..5d8115af 100644 --- a/docs/test_cases/t00063_class_mermaid.svg +++ b/docs/test_cases/t00063_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00064_class.svg b/docs/test_cases/t00064_class.svg index 5e156dea..fffc773b 100644 --- a/docs/test_cases/t00064_class.svg +++ b/docs/test_cases/t00064_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + type_list @@ -19,8 +19,8 @@ - - + + type_list @@ -29,8 +29,8 @@ - - + + type_list @@ -39,8 +39,8 @@ - - + + type_list @@ -49,8 +49,8 @@ - - + + head @@ -59,8 +59,8 @@ - - + + type_list @@ -69,8 +69,8 @@ - - + + type_list @@ -79,8 +79,8 @@ - - + + type_list @@ -89,8 +89,8 @@ - - + + type_group_pair @@ -99,15 +99,15 @@ - + - + size : const size_t - - + + optional_ref @@ -116,8 +116,8 @@ - - + + optional_ref @@ -126,8 +126,8 @@ - - + + type_group_pair_it @@ -135,54 +135,54 @@ It,type_list<First...>,type_list<Second...> - + - + find(const value_type & v) constexpr : unsigned int - + - + get(unsigned int i) : ref_t - + - + getp(unsigned int i) : const value_type * - - + + A - - + + B - - + + C - - + + type_list @@ -191,8 +191,8 @@ - - + + type_list @@ -201,8 +201,8 @@ - - + + type_list @@ -211,8 +211,8 @@ - - + + type_group_pair @@ -221,30 +221,30 @@ - - + + R - + - + abc : type_group_pair<type_list<float,double>,type_list<A,B,C>> - + - + aboolint : type_list<A,bool,int> - - + + type_group_pair @@ -253,8 +253,8 @@ - - + + type_group_pair_it @@ -263,8 +263,8 @@ - - + + head diff --git a/docs/test_cases/t00064_class_mermaid.svg b/docs/test_cases/t00064_class_mermaid.svg index 86007aba..23dc5a8f 100644 --- a/docs/test_cases/t00064_class_mermaid.svg +++ b/docs/test_cases/t00064_class_mermaid.svg @@ -390,7 +390,7 @@ - + @@ -409,7 +409,7 @@ - + @@ -428,7 +428,7 @@ - + @@ -447,7 +447,7 @@ - + @@ -466,7 +466,7 @@ - + @@ -485,7 +485,7 @@ - + @@ -504,7 +504,7 @@ - + @@ -523,7 +523,7 @@ - + @@ -542,7 +542,7 @@ - + @@ -566,7 +566,7 @@ - + @@ -585,7 +585,7 @@ - + @@ -604,7 +604,7 @@ - + @@ -638,7 +638,7 @@ - + @@ -657,7 +657,7 @@ - + @@ -676,7 +676,7 @@ - + @@ -695,7 +695,7 @@ - + @@ -714,7 +714,7 @@ - + @@ -733,7 +733,7 @@ - + @@ -752,7 +752,7 @@ - + @@ -771,7 +771,7 @@ - + @@ -800,7 +800,7 @@ - + @@ -819,7 +819,7 @@ - + @@ -838,7 +838,7 @@ - + diff --git a/docs/test_cases/t00065_class.svg b/docs/test_cases/t00065_class.svg index 205313eb..dc369efc 100644 --- a/docs/test_cases/t00065_class.svg +++ b/docs/test_cases/t00065_class.svg @@ -1,6 +1,6 @@ - + @@ -9,20 +9,20 @@ - + module1 - + submodule1a - + module2 - + concepts - - + + ABC @@ -32,8 +32,8 @@ c - - + + XYZ @@ -43,68 +43,68 @@ z - - + + A - + - + abc : ABC - + - + pimpl : detail::AImpl * - + - + xyz : XYZ - - + + detail::AImpl - - + + B - + - + B() = default : void - + - + b() : void - - + + C @@ -113,15 +113,15 @@ - + - + t : T * - - + + C @@ -130,8 +130,8 @@ - - + + D @@ -140,22 +140,22 @@ - + - + c : C<int> - + - + t : T - - + + C @@ -164,8 +164,8 @@ - - + + D @@ -174,8 +174,8 @@ - - + + «concept» @@ -188,33 +188,33 @@ T{} t.b() - - + + R - + - + a : A * - + - + c : C<B> - + - + d : D<B> diff --git a/docs/test_cases/t00065_class_mermaid.svg b/docs/test_cases/t00065_class_mermaid.svg index 26d3872b..43a169cb 100644 --- a/docs/test_cases/t00065_class_mermaid.svg +++ b/docs/test_cases/t00065_class_mermaid.svg @@ -210,7 +210,7 @@ - + @@ -229,7 +229,7 @@ - + @@ -263,7 +263,7 @@ - + @@ -297,7 +297,7 @@ - + @@ -331,7 +331,7 @@ - + @@ -365,7 +365,7 @@ - + @@ -394,7 +394,7 @@ - + @@ -418,7 +418,7 @@ - + @@ -437,7 +437,7 @@ - + @@ -466,7 +466,7 @@ - + @@ -485,7 +485,7 @@ - + @@ -504,7 +504,7 @@ - + diff --git a/docs/test_cases/t00066_class.svg b/docs/test_cases/t00066_class.svg index dee8c5b0..3374976b 100644 --- a/docs/test_cases/t00066_class.svg +++ b/docs/test_cases/t00066_class.svg @@ -1,6 +1,6 @@ - + @@ -9,222 +9,222 @@ - - + + A - + - + public_member : int - + - + protected_member : int - + - + private_member : int - + - + a_ : int - + - + b_ : int - + - + c_ : int - + - + static_int : int - + - + static_const_int : const int - + - + auto_member : const unsigned long - + - + A() = default : void - + - + A(int i) : void - + - + A(A &&) = default : void - + - + A(const A &) = deleted : void - + - + ~A() = default : void - + - + basic_method() : void - + - + static_method() : int - + - + const_method() const : void - + - + auto_method() : int - + - + operator++() : A & - + - + operator=(A && other) noexcept : A & - + - + operator=(A & other) noexcept : A & - + - + size() const : std::size_t - + - + double_int(const int i) : int - + - + sum(const double a, const double b) : int - + - + default_int(int i = 12) : int - + - + default_string(int i, std::string s = "abc") : std::string - + - + create_from_int(int i) : A - + - + protected_method() : void - + - + private_method() : void - + - + compare : std::function<bool (const int)> diff --git a/docs/test_cases/t00066_class_mermaid.svg b/docs/test_cases/t00066_class_mermaid.svg index 05343238..1099c2b4 100644 --- a/docs/test_cases/t00066_class_mermaid.svg +++ b/docs/test_cases/t00066_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00067_class.svg b/docs/test_cases/t00067_class.svg index ff867edb..8620f1f8 100644 --- a/docs/test_cases/t00067_class.svg +++ b/docs/test_cases/t00067_class.svg @@ -1,6 +1,6 @@ - + @@ -9,152 +9,152 @@ - - + + A - + - + auto_method() : int - + - + basic_method() : void - + - + const_method() const : void - + - + default_int(int i = 12) : int - + - + default_string(int i, std::string s = "abc") : std::string - + - + double_int(const int i) : int - + - + private_method() : void - + - + protected_method() : void - + - + size() const : std::size_t - + - + sum(const double a, const double b) : int - + - + a_ : int - + - + auto_member : const unsigned long - + - + b_ : int - + - + c_ : int - + - + compare : std::function<bool (const int)> - + - + private_member : int - + - + protected_member : int - + - + public_member : int - + - + static_const_int : const int - + - + static_int : int diff --git a/docs/test_cases/t00067_class_mermaid.svg b/docs/test_cases/t00067_class_mermaid.svg index 8dc7a443..a87abbb3 100644 --- a/docs/test_cases/t00067_class_mermaid.svg +++ b/docs/test_cases/t00067_class_mermaid.svg @@ -52,7 +52,7 @@ - + diff --git a/docs/test_cases/t00068_r0_class.svg b/docs/test_cases/t00068_r0_class.svg index 7aeb173a..617b5c8e 100644 --- a/docs/test_cases/t00068_r0_class.svg +++ b/docs/test_cases/t00068_r0_class.svg @@ -1,6 +1,6 @@ - + @@ -10,26 +10,26 @@ AAA context of radius 0 - - + + AAA - + - + akind : AKind - + - + bb : BB * diff --git a/docs/test_cases/t00068_r0_class_mermaid.svg b/docs/test_cases/t00068_r0_class_mermaid.svg index 79280aa9..b9864ff5 100644 --- a/docs/test_cases/t00068_r0_class_mermaid.svg +++ b/docs/test_cases/t00068_r0_class_mermaid.svg @@ -53,7 +53,7 @@ - + diff --git a/docs/test_cases/t00068_r1_class.svg b/docs/test_cases/t00068_r1_class.svg index 9e8096d3..aa9d2e61 100644 --- a/docs/test_cases/t00068_r1_class.svg +++ b/docs/test_cases/t00068_r1_class.svg @@ -1,6 +1,6 @@ - + @@ -10,23 +10,23 @@ AAA context of radius 1 - - + + BB - + - + b : std::vector<B> - - + + AKind @@ -36,49 +36,49 @@ ThreeA - - + + AA - - + + AAA - + - + akind : AKind - + - + bb : BB * - - + + R - + - + aaa : AAA * diff --git a/docs/test_cases/t00068_r1_class_mermaid.svg b/docs/test_cases/t00068_r1_class_mermaid.svg index c7379c4c..7dd7cf10 100644 --- a/docs/test_cases/t00068_r1_class_mermaid.svg +++ b/docs/test_cases/t00068_r1_class_mermaid.svg @@ -101,7 +101,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -159,7 +159,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -207,7 +207,7 @@ - + diff --git a/docs/test_cases/t00068_r2_class.svg b/docs/test_cases/t00068_r2_class.svg index 2132d42f..6b5bdd51 100644 --- a/docs/test_cases/t00068_r2_class.svg +++ b/docs/test_cases/t00068_r2_class.svg @@ -1,6 +1,6 @@ - + @@ -10,31 +10,31 @@ AAA context of radius 2 - - + + B - - + + BB - + - + b : std::vector<B> - - + + AKind @@ -44,72 +44,72 @@ ThreeA - - + + A - - + + AA - - + + AAA - + - + akind : AKind - + - + bb : BB * - - + + R - + - + aaa : AAA * - - + + RR - + - + r : std::shared_ptr<R> diff --git a/docs/test_cases/t00068_r2_class_mermaid.svg b/docs/test_cases/t00068_r2_class_mermaid.svg index 68990c71..c1aaba39 100644 --- a/docs/test_cases/t00068_r2_class_mermaid.svg +++ b/docs/test_cases/t00068_r2_class_mermaid.svg @@ -135,7 +135,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -178,7 +178,7 @@ - + @@ -212,7 +212,7 @@ - + @@ -231,7 +231,7 @@ - + @@ -250,7 +250,7 @@ - + @@ -279,7 +279,7 @@ - + @@ -303,7 +303,7 @@ - + diff --git a/docs/test_cases/t00069_class.svg b/docs/test_cases/t00069_class.svg index b83d3c1e..af89ae0f 100644 --- a/docs/test_cases/t00069_class.svg +++ b/docs/test_cases/t00069_class.svg @@ -1,6 +1,6 @@ - + @@ -9,8 +9,8 @@ - - + + generator @@ -18,96 +18,96 @@ T - + - + generator(handle_type h) : void - + - + ~generator() : void - + - + full_ : bool - + - + h_ : handle_type - - + + generator::promise_type - + - + final_suspend() noexcept : std::suspend_always - + - + get_return_object() : generator<T> - + - + initial_suspend() : std::suspend_always - + - + return_void() : void - + - + unhandled_exception() : void yield_value<std::convertible_to From>(From && from) : std::suspend_always - + - + exception_ : std::exception_ptr - + - + value_ : T - - + + generator @@ -116,33 +116,33 @@ - - + + A - + - + iota() [coroutine] : generator<unsigned long> - + - + seed() [coroutine] : generator<unsigned long> - + - + counter_ : unsigned long diff --git a/docs/test_cases/t00069_class_mermaid.svg b/docs/test_cases/t00069_class_mermaid.svg index 8adddd19..7265dd52 100644 --- a/docs/test_cases/t00069_class_mermaid.svg +++ b/docs/test_cases/t00069_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -129,7 +129,7 @@ - + @@ -188,7 +188,7 @@ - + @@ -207,7 +207,7 @@ - + diff --git a/docs/test_cases/t00070_class.svg b/docs/test_cases/t00070_class.svg index 2afa381b..322543f7 100644 --- a/docs/test_cases/t00070_class.svg +++ b/docs/test_cases/t00070_class.svg @@ -1,6 +1,6 @@ - + @@ -9,16 +9,16 @@ - - + + B - - + + BB @@ -27,15 +27,15 @@ - + - + t : T - - + + BBB @@ -44,26 +44,26 @@ bbb2 - - + + A - + - + get() : int - + - + a : int diff --git a/docs/test_cases/t00070_class_mermaid.svg b/docs/test_cases/t00070_class_mermaid.svg index 50bbd3c1..a2f13009 100644 --- a/docs/test_cases/t00070_class_mermaid.svg +++ b/docs/test_cases/t00070_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -124,7 +124,7 @@ - + diff --git a/docs/test_cases/t00071_class.svg b/docs/test_cases/t00071_class.svg index 058efb0c..e5904abe 100644 --- a/docs/test_cases/t00071_class.svg +++ b/docs/test_cases/t00071_class.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - + app - + lib1 - + mod1 - + mod2 - + lib2 - - + + A - + - + get() : int - + - + a : int - - + + B - - + + BB @@ -64,15 +64,15 @@ - + - + t : T - - + + detail::BBB @@ -81,32 +81,32 @@ bbb2 - - + + D - - + + E - - + + C - - + + CC @@ -115,15 +115,15 @@ - + - + t : T - - + + detail::CCC @@ -132,33 +132,33 @@ ccc2 - - + + R - + - + a : A * - + - + b : B * - + - + c : C * diff --git a/docs/test_cases/t00071_class_mermaid.svg b/docs/test_cases/t00071_class_mermaid.svg index 162703bb..e842bb32 100644 --- a/docs/test_cases/t00071_class_mermaid.svg +++ b/docs/test_cases/t00071_class_mermaid.svg @@ -90,7 +90,7 @@ - + @@ -109,7 +109,7 @@ - + @@ -133,7 +133,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -181,7 +181,7 @@ - + @@ -200,7 +200,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -243,7 +243,7 @@ - + @@ -272,7 +272,7 @@ - + @@ -301,7 +301,7 @@ - + diff --git a/docs/test_cases/t00072_class.svg b/docs/test_cases/t00072_class.svg index 06d54547..0bbdc289 100644 --- a/docs/test_cases/t00072_class.svg +++ b/docs/test_cases/t00072_class.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - + app - + :lib1 - + mod1 - + mod2 - + :lib2 - - + + A - + - + get() : int - + - + a : int - - + + B - - + + BB @@ -64,15 +64,15 @@ - + - + t : T - - + + detail::BBB @@ -81,32 +81,32 @@ bbb2 - - + + D - - + + E - - + + C - - + + CC @@ -115,15 +115,15 @@ - + - + t : T - - + + detail::CCC diff --git a/docs/test_cases/t00072_class_mermaid.svg b/docs/test_cases/t00072_class_mermaid.svg index 4675d06d..ef68b4dc 100644 --- a/docs/test_cases/t00072_class_mermaid.svg +++ b/docs/test_cases/t00072_class_mermaid.svg @@ -52,7 +52,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -95,7 +95,7 @@ - + @@ -124,7 +124,7 @@ - + @@ -143,7 +143,7 @@ - + @@ -162,7 +162,7 @@ - + @@ -181,7 +181,7 @@ - + @@ -205,7 +205,7 @@ - + @@ -234,7 +234,7 @@ - + diff --git a/docs/test_cases/t00073.md b/docs/test_cases/t00073.md new file mode 100644 index 00000000..3a6ef4fc --- /dev/null +++ b/docs/test_cases/t00073.md @@ -0,0 +1,421 @@ +# t00073 - Class diagram for template overload pattern +## Config +```yaml +diagrams: + t00073_class: + type: class + glob: + - t00073.cc + include: + namespaces: + - clanguml::t00073 + using_namespace: clanguml::t00073 +``` +## Source code +File `tests/t00073/t00073.cc` +```cpp +namespace clanguml { +namespace t00073 { +struct A { }; +struct AHandler { + void handle(A &a) const { } + void operator()(A &a) const { handle(a); } +}; + +struct B { }; +struct BHandler { + void handle(B &b) const { } + void operator()(B &b) const { handle(b); } +}; + +template struct Overload : public Bases... { + using Bases::operator()...; +}; +template Overload(Bases...) -> Overload; + +struct R { + Overload dispatch; +}; +} +} +``` +## Generated PlantUML diagrams +![t00073_class](./t00073_class.svg "Class diagram for template overload pattern") +## Generated Mermaid diagrams +![t00073_class](./t00073_class_mermaid.svg "Class diagram for template overload pattern") +## Generated JSON models +```json +{ + "diagram_type": "class", + "elements": [ + { + "bases": [], + "display_name": "A", + "id": "1747277620916743482", + "is_abstract": false, + "is_nested": false, + "is_struct": true, + "is_template": false, + "is_union": false, + "members": [], + "methods": [], + "name": "A", + "namespace": "clanguml::t00073", + "source_location": { + "column": 8, + "file": "t00073.cc", + "line": 3, + "translation_unit": "t00073.cc" + }, + "template_parameters": [], + "type": "class" + }, + { + "bases": [], + "display_name": "AHandler", + "id": "1553077875896883107", + "is_abstract": false, + "is_nested": false, + "is_struct": true, + "is_template": false, + "is_union": false, + "members": [], + "methods": [ + { + "access": "public", + "is_const": true, + "is_consteval": false, + "is_constexpr": false, + "is_constructor": false, + "is_copy_assignment": false, + "is_coroutine": false, + "is_defaulted": false, + "is_deleted": false, + "is_move_assignment": false, + "is_noexcept": false, + "is_operator": false, + "is_pure_virtual": false, + "is_static": false, + "is_virtual": false, + "name": "handle", + "parameters": [ + { + "name": "a", + "type": "A &" + } + ], + "source_location": { + "column": 10, + "file": "t00073.cc", + "line": 5, + "translation_unit": "t00073.cc" + }, + "type": "void" + }, + { + "access": "public", + "is_const": true, + "is_consteval": false, + "is_constexpr": false, + "is_constructor": false, + "is_copy_assignment": false, + "is_coroutine": false, + "is_defaulted": false, + "is_deleted": false, + "is_move_assignment": false, + "is_noexcept": false, + "is_operator": true, + "is_pure_virtual": false, + "is_static": false, + "is_virtual": false, + "name": "operator()", + "parameters": [ + { + "name": "a", + "type": "A &" + } + ], + "source_location": { + "column": 10, + "file": "t00073.cc", + "line": 6, + "translation_unit": "t00073.cc" + }, + "type": "void" + } + ], + "name": "AHandler", + "namespace": "clanguml::t00073", + "source_location": { + "column": 8, + "file": "t00073.cc", + "line": 4, + "translation_unit": "t00073.cc" + }, + "template_parameters": [], + "type": "class" + }, + { + "bases": [], + "display_name": "B", + "id": "2289864660191173413", + "is_abstract": false, + "is_nested": false, + "is_struct": true, + "is_template": false, + "is_union": false, + "members": [], + "methods": [], + "name": "B", + "namespace": "clanguml::t00073", + "source_location": { + "column": 8, + "file": "t00073.cc", + "line": 9, + "translation_unit": "t00073.cc" + }, + "template_parameters": [], + "type": "class" + }, + { + "bases": [], + "display_name": "BHandler", + "id": "1150176578121877194", + "is_abstract": false, + "is_nested": false, + "is_struct": true, + "is_template": false, + "is_union": false, + "members": [], + "methods": [ + { + "access": "public", + "is_const": true, + "is_consteval": false, + "is_constexpr": false, + "is_constructor": false, + "is_copy_assignment": false, + "is_coroutine": false, + "is_defaulted": false, + "is_deleted": false, + "is_move_assignment": false, + "is_noexcept": false, + "is_operator": false, + "is_pure_virtual": false, + "is_static": false, + "is_virtual": false, + "name": "handle", + "parameters": [ + { + "name": "b", + "type": "B &" + } + ], + "source_location": { + "column": 10, + "file": "t00073.cc", + "line": 11, + "translation_unit": "t00073.cc" + }, + "type": "void" + }, + { + "access": "public", + "is_const": true, + "is_consteval": false, + "is_constexpr": false, + "is_constructor": false, + "is_copy_assignment": false, + "is_coroutine": false, + "is_defaulted": false, + "is_deleted": false, + "is_move_assignment": false, + "is_noexcept": false, + "is_operator": true, + "is_pure_virtual": false, + "is_static": false, + "is_virtual": false, + "name": "operator()", + "parameters": [ + { + "name": "b", + "type": "B &" + } + ], + "source_location": { + "column": 10, + "file": "t00073.cc", + "line": 12, + "translation_unit": "t00073.cc" + }, + "type": "void" + } + ], + "name": "BHandler", + "namespace": "clanguml::t00073", + "source_location": { + "column": 8, + "file": "t00073.cc", + "line": 10, + "translation_unit": "t00073.cc" + }, + "template_parameters": [], + "type": "class" + }, + { + "bases": [], + "display_name": "Overload", + "id": "128238421290776639", + "is_abstract": false, + "is_nested": false, + "is_struct": true, + "is_template": true, + "is_union": false, + "members": [], + "methods": [], + "name": "Overload", + "namespace": "clanguml::t00073", + "source_location": { + "column": 37, + "file": "t00073.cc", + "line": 15, + "translation_unit": "t00073.cc" + }, + "template_parameters": [ + { + "is_variadic": true, + "kind": "template_type", + "name": "Bases...", + "template_parameters": [] + } + ], + "type": "class" + }, + { + "bases": [ + { + "access": "public", + "id": "1553077875896883107", + "is_virtual": false, + "name": "clanguml::t00073::AHandler" + }, + { + "access": "public", + "id": "1150176578121877194", + "is_virtual": false, + "name": "clanguml::t00073::BHandler" + } + ], + "display_name": "Overload", + "id": "1942698483892029961", + "is_abstract": false, + "is_nested": false, + "is_struct": false, + "is_template": true, + "is_union": false, + "members": [], + "methods": [], + "name": "Overload", + "namespace": "clanguml::t00073", + "source_location": { + "column": 37, + "file": "t00073.cc", + "line": 15, + "translation_unit": "t00073.cc" + }, + "template_parameters": [ + { + "is_variadic": false, + "kind": "argument", + "template_parameters": [], + "type": "clanguml::t00073::AHandler" + }, + { + "is_variadic": false, + "kind": "argument", + "template_parameters": [], + "type": "clanguml::t00073::BHandler" + } + ], + "type": "class" + }, + { + "bases": [], + "display_name": "R", + "id": "441440190371151626", + "is_abstract": false, + "is_nested": false, + "is_struct": true, + "is_template": false, + "is_union": false, + "members": [ + { + "access": "public", + "is_static": false, + "name": "dispatch", + "source_location": { + "column": 34, + "file": "t00073.cc", + "line": 21, + "translation_unit": "t00073.cc" + }, + "type": "Overload" + } + ], + "methods": [], + "name": "R", + "namespace": "clanguml::t00073", + "source_location": { + "column": 8, + "file": "t00073.cc", + "line": 20, + "translation_unit": "t00073.cc" + }, + "template_parameters": [], + "type": "class" + } + ], + "name": "t00073_class", + "package_type": "namespace", + "relationships": [ + { + "access": "public", + "destination": "1747277620916743482", + "source": "1553077875896883107", + "type": "dependency" + }, + { + "access": "public", + "destination": "2289864660191173413", + "source": "1150176578121877194", + "type": "dependency" + }, + { + "access": "public", + "destination": "128238421290776639", + "source": "1942698483892029961", + "type": "instantiation" + }, + { + "access": "public", + "destination": "1553077875896883107", + "source": "1942698483892029961", + "type": "extension" + }, + { + "access": "public", + "destination": "1150176578121877194", + "source": "1942698483892029961", + "type": "extension" + }, + { + "access": "public", + "destination": "1942698483892029961", + "label": "dispatch", + "source": "441440190371151626", + "type": "aggregation" + } + ], + "using_namespace": "clanguml::t00073" +} +``` diff --git a/docs/test_cases/t00073_class.svg b/docs/test_cases/t00073_class.svg new file mode 100644 index 00000000..cc5ed417 --- /dev/null +++ b/docs/test_cases/t00073_class.svg @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + A + + + + + + + + AHandler + + + + + + + + operator()(A & a) const : void + + + + + + + + handle(A & a) const : void + + + + + + + B + + + + + + + + BHandler + + + + + + + + operator()(B & b) const : void + + + + + + + + handle(B & b) const : void + + + + + + + Overload + + Bases... + + + + + + + + Overload + + AHandler,BHandler + + + + + + + + R + + + + + + + + + dispatch : Overload<AHandler,BHandler> + + + + + + + + + + + + + + + dispatch + + diff --git a/docs/test_cases/t00073_class_mermaid.svg b/docs/test_cases/t00073_class_mermaid.svg new file mode 100644 index 00000000..c16c1382 --- /dev/null +++ b/docs/test_cases/t00073_class_mermaid.svg @@ -0,0 +1,286 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+
+
+
+ + + +
+ + + +
+
+
+
+ + + +
+ + + +
+
+
+
+ + + +
+ +
+
+
+
+ + + +
+ +
+
+
+
+ + + +
+ + +dispatch + +
+
+
+
+
+ + + + + + + + +
+ +
+
+ +
+ A +
+
+
+
+
+ + + + + + + +
+ +
+
+ +
+ AHandler +
+
+ +
+ +operator() : A & a) : [const] void +
+
+ +
+ +handle(A & a) : [const] void +
+
+
+
+
+ + + + + + + +
+ +
+
+ +
+ B +
+
+
+
+
+ + + + + + + +
+ +
+
+ +
+ BHandler +
+
+ +
+ +operator() : B & b) : [const] void +
+
+ +
+ +handle(B & b) : [const] void +
+
+
+
+
+ + + + + + + +
+ +
+
+ +
+ Overload<Bases...> +
+
+
+
+
+ + + + + + + +
+ +
+
+ +
+ Overload<AHandler,BHandler> +
+
+
+
+
+ + + + + + + +
+ +
+
+ +
+ R +
+
+ +
+ +dispatch : Overload<AHandler,BHandler> +
+
+
+
+
+
+
+
+
diff --git a/docs/test_cases/t20001_sequence.svg b/docs/test_cases/t20001_sequence.svg index 326c39a5..0a975d86 100644 --- a/docs/test_cases/t20001_sequence.svg +++ b/docs/test_cases/t20001_sequence.svg @@ -1,6 +1,6 @@ - + @@ -10,79 +10,79 @@ Basic sequence diagram example - - - - - - - - - + + + + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - + + B - + B - - - - - - - - - - + + + + + + + + + + A() - + B(A &) - + Just add 2 numbers - + add(int,int) - + And now add another 2 - + wrap_add3(int,int,int) - + add3(int,int,int) - + @@ -93,7 +93,7 @@ - + @@ -102,14 +102,14 @@ - + log_result(int) - + Main test function diff --git a/docs/test_cases/t20002_sequence.svg b/docs/test_cases/t20002_sequence.svg index 79b916b7..412c94af 100644 --- a/docs/test_cases/t20002_sequence.svg +++ b/docs/test_cases/t20002_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,51 +9,51 @@ - - - - + + + + - - + + m1() - + m1() - - + + m2() - + m2() - - + + m3() - + m3() - - + + m4() - + m4() - - - - - + + + + + - + - + diff --git a/docs/test_cases/t20003_sequence.svg b/docs/test_cases/t20003_sequence.svg index 47a57c50..e58641d5 100644 --- a/docs/test_cases/t20003_sequence.svg +++ b/docs/test_cases/t20003_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,51 +9,51 @@ - - - - + + + + - - + + m1<T>(T) - + m1<T>(T) - - + + m2<T>(T) - + m2<T>(T) - - + + m3<T>(T) - + m3<T>(T) - - + + m4<T>(T) - + m4<T>(T) - - - - - + + + + + - + - + diff --git a/docs/test_cases/t20004_sequence.svg b/docs/test_cases/t20004_sequence.svg index d1c01a18..c1502b1a 100644 --- a/docs/test_cases/t20004_sequence.svg +++ b/docs/test_cases/t20004_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,16 +9,16 @@ - - - - - - - - - - + + + + + + + + + + @@ -29,87 +29,87 @@ - - + + main() - + main() - - + + m1<float>(float) - + m1<float>(float) - - + + m1<unsigned long>(unsigned long) - + m1<unsigned long>(unsigned long) - - + + m4<unsigned long>(unsigned long) - + m4<unsigned long>(unsigned long) - - + + m1<std::string>(std::string) - + m1<std::string>(std::string) - - + + m2<std::string>(std::string) - + m2<std::string>(std::string) - - + + m1<int>(int) - + m1<int>(int) - - + + m2<int>(int) - + m2<int>(int) - - + + m3<int>(int) - + m3<int>(int) - - + + m4<int>(int) - + m4<int>(int) - - - - - - - - - - - + + + + + + + + + + + - + - + @@ -117,11 +117,11 @@ - + - + @@ -129,19 +129,19 @@ - + - + - + - + diff --git a/docs/test_cases/t20005_sequence.svg b/docs/test_cases/t20005_sequence.svg index f28536d5..28ad5101 100644 --- a/docs/test_cases/t20005_sequence.svg +++ b/docs/test_cases/t20005_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,42 +9,42 @@ - - - + + + - - + + C<T> - + C<T> - - + + B<T> - + B<T> - - + + A<T> - + A<T> - - - + + + c(T) - + b(T) - + a(T) diff --git a/docs/test_cases/t20006_sequence.svg b/docs/test_cases/t20006_sequence.svg index 48623498..66a550d0 100644 --- a/docs/test_cases/t20006_sequence.svg +++ b/docs/test_cases/t20006_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,24 +9,24 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + @@ -36,84 +36,84 @@ - - + + tmain() - + tmain() - - + + B<int> - + B<int> - - + + A<int> - + A<int> - - + + B<std::string> - + B<std::string> - - + + A<std::string> - + A<std::string> - - + + BB<int,std::string> - + BB<int,std::string> - - + + BB<int,float> - + BB<int,float> - - + + BB<int,int> - + BB<int,int> - - + + AA<int> - + AA<int> - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + b(int) - + a1(int) @@ -122,12 +122,12 @@ - + b(std::string) - + a2(std::string) @@ -136,69 +136,69 @@ - + BB(AA<int> *) - + BB(AA<int> &) - + bb1(int,int) - + aa1(int) - + bb2(int,int) - + aa2(int) - + bb1(int,std::string) - + aa2(int) - + bb2(int,std::string) - + aa1(int) - + bb1(int,float) - + bb2(int,float) - + aa2(int) diff --git a/docs/test_cases/t20007_sequence.svg b/docs/test_cases/t20007_sequence.svg index 11ad2bf4..7d14f952 100644 --- a/docs/test_cases/t20007_sequence.svg +++ b/docs/test_cases/t20007_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,57 +9,57 @@ - - - - + + + + - - + + tmain() - + tmain() - - + + Adder<int,int> - + Adder<int,int> - - + + Adder<int,float,double> - + Adder<int,float,double> - - + + Adder<std::string,std::string,std::string> - + Adder<std::string,std::string,std::string> - - - - - + + + + + add(int &&,int &&) - + add(int &&,float &&,double &&) - + add(std::string &&,std::string &&,std::string &&) diff --git a/docs/test_cases/t20008_sequence.svg b/docs/test_cases/t20008_sequence.svg index ab48d41b..59bf9adb 100644 --- a/docs/test_cases/t20008_sequence.svg +++ b/docs/test_cases/t20008_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,13 +9,13 @@ - - - - - - - + + + + + + + @@ -23,81 +23,81 @@ - - + + tmain() - + tmain() - - + + B<int> - + B<int> - - + + A<int> - + A<int> - - + + B<const char *> - + B<const char *> - - + + A<const char *> - + A<const char *> - - + + B<std::string> - + B<std::string> - - + + A<std::string> - + A<std::string> - - - - - - - - + + + + + + + + b(int) - + a1(int) - + b(const char *) - + a2(const char *) - + b(std::string) - + a3(std::string) diff --git a/docs/test_cases/t20009_sequence.svg b/docs/test_cases/t20009_sequence.svg index c3f776bd..b40e37f7 100644 --- a/docs/test_cases/t20009_sequence.svg +++ b/docs/test_cases/t20009_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,13 +9,13 @@ - - - - - - - + + + + + + + @@ -23,81 +23,81 @@ - - + + tmain() - + tmain() - - + + B<std::string> - + B<std::string> - - + + A<std::string> - + A<std::string> - - + + B<int> - + B<int> - - + + A<int> - + A<int> - - + + B<float> - + B<float> - - + + A<float> - + A<float> - - - - - - - - + + + + + + + + b(std::string) - + a(std::string) - + b(int) - + a(int) - + b(float) - + a(float) diff --git a/docs/test_cases/t20010_sequence.svg b/docs/test_cases/t20010_sequence.svg index 5fd0598a..cb54c7c4 100644 --- a/docs/test_cases/t20010_sequence.svg +++ b/docs/test_cases/t20010_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,81 +9,81 @@ - - - - - - - - - + + + + + + + + + - - + + tmain() - + tmain() - - + + B<int> - + B<int> - - + + A - + A - - - - - - - - - - + + + + + + + + + + b1() - + a1() - + b2() - + a2() - + b3() - + a3() - + b4() - + a4() diff --git a/docs/test_cases/t20011_sequence.svg b/docs/test_cases/t20011_sequence.svg index 172f88b6..55cd9b7a 100644 --- a/docs/test_cases/t20011_sequence.svg +++ b/docs/test_cases/t20011_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,42 +9,42 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - - - - - - - - - + + + + + + + + + + a(int) @@ -52,26 +52,26 @@ alt - + a(int) - + b(int) - + c(int) - + @@ -81,14 +81,14 @@ alt - + b(int) - + @@ -98,7 +98,7 @@ alt - + diff --git a/docs/test_cases/t20012_sequence.svg b/docs/test_cases/t20012_sequence.svg index 7cdff5d7..6ec07abd 100644 --- a/docs/test_cases/t20012_sequence.svg +++ b/docs/test_cases/t20012_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,31 +9,31 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + @@ -42,116 +42,116 @@ - - + + tmain() - + tmain() - - + + tmain()::(lambda t20012.cc:67:20) - + tmain()::(lambda t20012.cc:67:20) - - + + A - + A - - + + B - + B - - + + tmain()::(lambda t20012.cc:80:20) - + tmain()::(lambda t20012.cc:80:20) - - + + C - + C - - + + R<(lambda at t20012.cc:86:9)> - + R<(lambda at t20012.cc:86:9)> - - + + tmain()::(lambda t20012.cc:86:9) - + tmain()::(lambda t20012.cc:86:9) - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + operator()() - + a() - + aa() - + aaa() - + b() - + bb() - + @@ -160,67 +160,67 @@ - + operator()() - + c() - + cc() - + ccc() - + operator()() - + a() - + aa() - + aaa() - + b() - + bb() - + @@ -231,34 +231,34 @@ - + R((lambda at t20012.cc:86:9) &&) - + r() - + operator()() - + c() - + cc() - + diff --git a/docs/test_cases/t20013_sequence.svg b/docs/test_cases/t20013_sequence.svg index b10d950f..a7e85162 100644 --- a/docs/test_cases/t20013_sequence.svg +++ b/docs/test_cases/t20013_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,47 +9,47 @@ - - - - - - - + + + + + + + - - + + tmain(int,char **) - + tmain(int,char **) - - + + B - + B - - + + A - + A - - - - - - - - + + + + + + + + b(int) - + a1(int) @@ -58,12 +58,12 @@ - + b(double) - + a2(double) @@ -72,12 +72,12 @@ - + b(const char *) - + a3(const char *) diff --git a/docs/test_cases/t20014_sequence.svg b/docs/test_cases/t20014_sequence.svg index 342153a8..bc5baf7d 100644 --- a/docs/test_cases/t20014_sequence.svg +++ b/docs/test_cases/t20014_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,56 +9,56 @@ - - - - - - - - + + + + + + + + - - + + tmain() - + tmain() - - + + B - + B - - + + A - + A - - + + C<B,int> - + C<B,int> - - - - - - - - - + + + + + + + + + b1(int,int) - + a1(int,int) @@ -67,12 +67,12 @@ - + b2(int,int) - + a2(int,int) @@ -81,17 +81,17 @@ - + c1(int,int) - + b1(int,int) - + a1(int,int) diff --git a/docs/test_cases/t20015_sequence.svg b/docs/test_cases/t20015_sequence.svg index 9edbf337..cd1632ef 100644 --- a/docs/test_cases/t20015_sequence.svg +++ b/docs/test_cases/t20015_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,25 +9,25 @@ - - + + - - + + tmain() - + tmain() - - + + B - + B - - - + + + setup_a(std::shared_ptr<detail::A> &) diff --git a/docs/test_cases/t20016_sequence.svg b/docs/test_cases/t20016_sequence.svg index 685de7cf..cb7d76e6 100644 --- a/docs/test_cases/t20016_sequence.svg +++ b/docs/test_cases/t20016_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - - - - - + + + + + - - + + tmain() - + tmain() - - + + B<long> - + B<long> - - + + A - + A - - - - - - + + + + + + b1(long) - + a1(int) - + b2(long) - + a2(const long &) diff --git a/docs/test_cases/t20017_sequence.svg b/docs/test_cases/t20017_sequence.svg index 012b6ac2..73e985ad 100644 --- a/docs/test_cases/t20017_sequence.svg +++ b/docs/test_cases/t20017_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,65 +9,65 @@ - - - - - - + + + + + + - + t20017.cc - + t20017.cc - + include/t20017_a.h - + include/t20017_a.h - + include/t20017_b.h - + include/t20017_b.h - - - - - - + + + + + + tmain() - + a3(int,int) - + b1(int,int) - + a2(int,int) - + a1(int,int) - + b2<int>(int,int) diff --git a/docs/test_cases/t20018_sequence.svg b/docs/test_cases/t20018_sequence.svg index b23679dc..a0482d22 100644 --- a/docs/test_cases/t20018_sequence.svg +++ b/docs/test_cases/t20018_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,14 +9,14 @@ - - - - - - - - + + + + + + + + @@ -25,93 +25,93 @@ - - + + tmain() - + tmain() - - + + Answer<Factorial<5>,120> - + Answer<Factorial<5>,120> - - + + Factorial<5> - + Factorial<5> - - + + Factorial<4> - + Factorial<4> - - + + Factorial<3> - + Factorial<3> - - + + Factorial<2> - + Factorial<2> - - + + Factorial<1> - + Factorial<1> - - + + Factorial<0> - + Factorial<0> - - - - - - - - - + + + + + + + + + print() - + print(int) - + print(int) - + print(int) - + print(int) - + print(int) - + print(int) diff --git a/docs/test_cases/t20019_sequence.svg b/docs/test_cases/t20019_sequence.svg index b894321a..29b4a6db 100644 --- a/docs/test_cases/t20019_sequence.svg +++ b/docs/test_cases/t20019_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,95 +9,95 @@ - - - - - - - - - + + + + + + + + + - - + + tmain() - + tmain() - - + + Base<D1> - + Base<D1> - - + + D1 - + D1 - - + + Base<D2> - + Base<D2> - - + + D2 - + D2 - - - - - - - - - - + + + + + + + + + + name() - + impl() - + name() - + impl() - + name() - + impl() - + name() - + impl() diff --git a/docs/test_cases/t20020_sequence.svg b/docs/test_cases/t20020_sequence.svg index d7c4b5d2..91e99092 100644 --- a/docs/test_cases/t20020_sequence.svg +++ b/docs/test_cases/t20020_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,82 +9,82 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - - - + + + - - + + tmain() - + tmain() - - + + A - + A - - + + C - + C - - + + B - + B - - + + D<int> - + D<int> - - - - - - - - - - - - - - + + + + + + + + + + + + + + alt - + a1() @@ -92,7 +92,7 @@ - + a5() @@ -103,7 +103,7 @@ alt - + [ @@ -112,7 +112,7 @@ - + [ @@ -121,7 +121,7 @@ - + b1() @@ -129,7 +129,7 @@ - + [ @@ -138,7 +138,7 @@ - + b2() @@ -146,14 +146,14 @@ - + a4() - + log() @@ -161,7 +161,7 @@ alt - + c1() const @@ -169,7 +169,7 @@ alt - + @@ -182,7 +182,7 @@ - + @@ -192,7 +192,7 @@ alt - + d1(int,int) diff --git a/docs/test_cases/t20021_sequence.svg b/docs/test_cases/t20021_sequence.svg index 23851b01..7d9f7d78 100644 --- a/docs/test_cases/t20021_sequence.svg +++ b/docs/test_cases/t20021_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,74 +9,74 @@ - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - + + tmain() - + tmain() - - + + C - + C - - + + A - + A - - + + B - + B - - - - - - - - - - - - + + + + + + + + + + + + loop - + [ c4() ] - + @@ -89,7 +89,7 @@ - + a3() @@ -102,7 +102,7 @@ loop - + [ @@ -111,7 +111,7 @@ - + [ @@ -120,7 +120,7 @@ - + [ @@ -129,14 +129,14 @@ - + a1() - + [ @@ -148,7 +148,7 @@ loop - + b2() const @@ -158,7 +158,7 @@ loop - + [ @@ -167,7 +167,7 @@ - + b2() const diff --git a/docs/test_cases/t20022_sequence.svg b/docs/test_cases/t20022_sequence.svg index a64f267d..d5caad6c 100644 --- a/docs/test_cases/t20022_sequence.svg +++ b/docs/test_cases/t20022_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,47 +9,47 @@ - - - - + + + + - - + + tmain() - + tmain() - - + + A - + A - - + + B - + B - - - - - + + + + + A(std::unique_ptr ) - + a() - + b() diff --git a/docs/test_cases/t20023_sequence.svg b/docs/test_cases/t20023_sequence.svg index a2ab26c5..4b368862 100644 --- a/docs/test_cases/t20023_sequence.svg +++ b/docs/test_cases/t20023_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,37 +9,37 @@ - - - - - - - + + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - - - - - - + + + + + + + a() @@ -47,7 +47,7 @@ try - + @@ -60,7 +60,7 @@ [std::runtime_error &] - + @@ -73,7 +73,7 @@ [std::logic_error &] - + @@ -86,7 +86,7 @@ [...] - + diff --git a/docs/test_cases/t20024_sequence.svg b/docs/test_cases/t20024_sequence.svg index 83c1fe37..0e7374e7 100644 --- a/docs/test_cases/t20024_sequence.svg +++ b/docs/test_cases/t20024_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,23 +9,23 @@ - - - - - - - - - - - - + + + + + + + + + + + + - + @@ -33,36 +33,36 @@ - - + + tmain() - + tmain() - - + + A - + A - - + + B - + B - - - - - - - - - - - - + + + + + + + + + + + + select(enum_a) @@ -72,7 +72,7 @@ switch [zero] - + @@ -85,7 +85,7 @@ [one] - + @@ -98,7 +98,7 @@ [two] - + @@ -111,7 +111,7 @@ [default] - + @@ -124,7 +124,7 @@ - + select(colors) @@ -134,7 +134,7 @@ switch [enum colors::red] - + @@ -143,7 +143,7 @@ [enum colors::orange] - + @@ -152,7 +152,7 @@ [enum colors::green] - + @@ -161,7 +161,7 @@ [default] - + diff --git a/docs/test_cases/t20025_sequence.svg b/docs/test_cases/t20025_sequence.svg index 27b99137..40a87eb0 100644 --- a/docs/test_cases/t20025_sequence.svg +++ b/docs/test_cases/t20025_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,41 +9,41 @@ - - - + + + - - + + tmain() - + tmain() - - + + A - + A - - + + add(int,int) - + add(int,int) - - - - + + + + a() - + diff --git a/docs/test_cases/t20026_sequence.svg b/docs/test_cases/t20026_sequence.svg index 83daf47b..675768ce 100644 --- a/docs/test_cases/t20026_sequence.svg +++ b/docs/test_cases/t20026_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,25 +9,25 @@ - - + + - - + + tmain() - + tmain() - - + + A - + A - - - + + + a() diff --git a/docs/test_cases/t20027_sequence.svg b/docs/test_cases/t20027_sequence.svg index ecb7d47f..b40ccf82 100644 --- a/docs/test_cases/t20027_sequence.svg +++ b/docs/test_cases/t20027_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,25 +9,25 @@ - - + + - - + + tmain() - + tmain() - - + + A - + A - - - + + + a() diff --git a/docs/test_cases/t20028_sequence.svg b/docs/test_cases/t20028_sequence.svg index c5812426..22a073c7 100644 --- a/docs/test_cases/t20028_sequence.svg +++ b/docs/test_cases/t20028_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,36 +9,36 @@ - - - - - - + + + + + + - - + + tmain() - + tmain() - - + + A - + A - - - - - + + + + + alt - + [ @@ -47,14 +47,14 @@ - + b() - + c() @@ -62,7 +62,7 @@ - + d() diff --git a/docs/test_cases/t20029_sequence.svg b/docs/test_cases/t20029_sequence.svg index 42baa706..b186a250 100644 --- a/docs/test_cases/t20029_sequence.svg +++ b/docs/test_cases/t20029_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,69 +9,69 @@ - - - - - - - - - - - + + + + + + + + + + + - - + + tmain() - + tmain() - - + + Encoder<Retrier<ConnectionPool>> - + Encoder<Retrier<ConnectionPool>> - - + + Retrier<ConnectionPool> - + Retrier<ConnectionPool> - - + + ConnectionPool - + ConnectionPool - - + + encode_b64(std::string &&) - + encode_b64(std::string &&) - - - - - - - - + + + + + + + + Establish connection to the remote server synchronously - + connect() - + Repeat for each line in the input stream @@ -81,26 +81,26 @@ alt - + [ send(std::string &&) ] - + Encode the message using Base64 encoding and pass it to the next layer - + encode(std::string &&) - + @@ -110,12 +110,12 @@ - + send(std::string &&) - + Repeat until send() succeeds or retry count is exceeded @@ -125,7 +125,7 @@ alt - + [ diff --git a/docs/test_cases/t20030_sequence.svg b/docs/test_cases/t20030_sequence.svg index f501118f..1b5f77f6 100644 --- a/docs/test_cases/t20030_sequence.svg +++ b/docs/test_cases/t20030_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,81 +9,81 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - + + tmain(int) - + tmain(int) - - + + magic() - + magic() - - + + A - + A - - + + tmain(bool,int) - + tmain(bool,int) - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + A(int) - + operator+=(int) - + @@ -92,36 +92,36 @@ - + A() - + create() - + A() - + create() - + operator+=(int) - + @@ -130,12 +130,12 @@ - + operator=(const A &) - + @@ -144,7 +144,7 @@ - + value() const diff --git a/docs/test_cases/t20031_sequence.svg b/docs/test_cases/t20031_sequence.svg index 4d5d1097..26905e91 100644 --- a/docs/test_cases/t20031_sequence.svg +++ b/docs/test_cases/t20031_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,64 +9,64 @@ - - - - - + + + + + - - + + tmain(int) - + tmain(int) - - + + magic() - + magic() - - + + tmain(bool,int) - + tmain(bool,int) - - + + execute(std::function<int ()>) - + execute(std::function<int ()>) - - + + A - + A - - - - - - + + + + + + - + - + value() const diff --git a/docs/test_cases/t20032_sequence.svg b/docs/test_cases/t20032_sequence.svg index 4bef7283..0d6b3e72 100644 --- a/docs/test_cases/t20032_sequence.svg +++ b/docs/test_cases/t20032_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,47 +9,47 @@ - - - - - - - + + + + + + + - - + + tmain(int,char **) - + tmain(int,char **) - - + + B - + B - - + + A - + A - - - - - - - - + + + + + + + + b(int) - + a1(int) @@ -60,12 +60,12 @@ int - + b(double) - + a2(double) @@ -76,12 +76,12 @@ double - + b(const char *) - + a3(const char *) diff --git a/docs/test_cases/t20033_sequence.svg b/docs/test_cases/t20033_sequence.svg index 53c302b7..626b3d0d 100644 --- a/docs/test_cases/t20033_sequence.svg +++ b/docs/test_cases/t20033_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,73 +9,73 @@ - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - + + + + + - + - - + + tmain() - + tmain() - - + + A - + A - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + alt [false] [reinterpret_cast<uint64_t>(&a) % 100 == 0ULL] - + a1() @@ -84,7 +84,7 @@ [reinterpret_cast<uint64_t>(&a) % 64 == 0ULL] - + a2() @@ -93,7 +93,7 @@ [a.a2() == 2 && a.a3() == 3] - + [ @@ -102,7 +102,7 @@ - + [ @@ -111,7 +111,7 @@ - + a3() @@ -119,7 +119,7 @@ - + a4() @@ -130,7 +130,7 @@ alt [int i = a.a2(); i != 2] - + [ @@ -139,7 +139,7 @@ - + a3() @@ -150,7 +150,7 @@ loop [int i = 0; i < a.a2(); i++] - + [ @@ -159,14 +159,14 @@ - + a3() - + a3() @@ -177,7 +177,7 @@ loop [retry_count--] - + a2() @@ -188,14 +188,14 @@ loop [retry_count++ < a.a3()] - + a4() - + [ @@ -208,7 +208,7 @@ alt [a.a4() % 6] - + [ @@ -222,7 +222,7 @@ loop [ints] - + a4() diff --git a/docs/test_cases/t20034_sequence.svg b/docs/test_cases/t20034_sequence.svg index 7a2bea16..3436f411 100644 --- a/docs/test_cases/t20034_sequence.svg +++ b/docs/test_cases/t20034_sequence.svg @@ -1,6 +1,6 @@ - + @@ -14,154 +14,154 @@ - - + + D - + D - - + + C - + C - - + + B - + B - - + + A - + A - - + + D::d2()::(lambda t20034.cc:56:18) - + D::d2()::(lambda t20034.cc:56:18) d2() - + c2() - + b2() - + a2() - + d2() - + a2() - + d2() - + operator()() - + a2() - + d2() - + c4() - + b4() - + b2() - + a2() - + d2() - + c1() - + b1() - + a2() - + d2() - + c3() - + c2() - + b2() - + a2() diff --git a/docs/test_cases/t20035_sequence.svg b/docs/test_cases/t20035_sequence.svg index fc24281f..a9bca699 100644 --- a/docs/test_cases/t20035_sequence.svg +++ b/docs/test_cases/t20035_sequence.svg @@ -1,6 +1,6 @@ - + @@ -13,39 +13,39 @@ - - + + tmain(int,char **) - + tmain(int,char **) - - + + a(int) - + a(int) - - + + b1(int) - + b1(int) - - + + c(int) - + c(int) - + - + - + diff --git a/docs/test_cases/t20036_sequence.svg b/docs/test_cases/t20036_sequence.svg index b0d1e4e8..7fd46c9d 100644 --- a/docs/test_cases/t20036_sequence.svg +++ b/docs/test_cases/t20036_sequence.svg @@ -1,6 +1,6 @@ - + @@ -13,131 +13,131 @@ - - + + C - + C - - + + B - + B - - + + A - + A - - + + D - + D c1() - + b1() - + a2() - + d1() - + c2() - + b2() - + a2() - + d3() - + a2() - + c4() - + b2() - + a2() - + c3() - + c2() - + b2() - + a2() - + d2() - + c2() - + b2() - + a2() diff --git a/docs/test_cases/t20037_sequence.svg b/docs/test_cases/t20037_sequence.svg index 20664386..57816db3 100644 --- a/docs/test_cases/t20037_sequence.svg +++ b/docs/test_cases/t20037_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,95 +9,95 @@ - - - - - - - - - - - - + + + + + + + + + + + + - - + + tmain(int,char **) - + tmain(int,char **) - - + + a() - + a() - - + + A - + A - - + + initb() - + initb() - - + + B - + B - - + + c() - + c() - - - - - - - - - - - - - + + + + + + + + + + + + + - + A() - + - + get() - + @@ -105,18 +105,18 @@ - + - + get() - + @@ -124,18 +124,18 @@ - + - + get() - + diff --git a/docs/test_cases/t20038_sequence.svg b/docs/test_cases/t20038_sequence.svg index eae236cc..99830a35 100644 --- a/docs/test_cases/t20038_sequence.svg +++ b/docs/test_cases/t20038_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,29 +9,29 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - + @@ -39,62 +39,62 @@ - - + + tmain() - + tmain() - - + + B - + B - - + + A - + A - - + + add<int>(int,int) - + add<int>(int,int) - - + + add_impl<int>(int,int) - + add_impl<int>(int,int) - - + + add_impl<double>(double,double) - + add_impl<double>(double,double) - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + Nisl purus in mollis nunc sed id semper. Varius vel pharetra vel turpis. Arcu @@ -111,18 +111,18 @@ alt - + Repeat 5 times... loop - + b() - + a() @@ -132,15 +132,15 @@ - + ... or just once - + b() - + a() @@ -149,12 +149,12 @@ - + bbb() - + aaa() @@ -163,24 +163,24 @@ - + bbbb() - + aaaa() - + - + Invoke 'add' implementation - + @@ -192,47 +192,47 @@ - + This comment should be rendered only once - + wrap(int) - + What is 2 + 2? - + - + Calling B::bbbbb() - + bbbbb() - + aaaa() - + - + Invoke 'add' implementation - + @@ -244,20 +244,20 @@ - + This is a conditional operator alt - + [ bbb() ] - + aaa() diff --git a/docs/test_cases/t20039_sequence.svg b/docs/test_cases/t20039_sequence.svg index 84bd6fa4..cdf4601b 100644 --- a/docs/test_cases/t20039_sequence.svg +++ b/docs/test_cases/t20039_sequence.svg @@ -1,6 +1,6 @@ - + @@ -9,13 +9,13 @@ - - - - - - - + + + + + + + @@ -23,89 +23,89 @@ - - + + tmain() - + tmain() - - + + R - + R - - + + A<int> - + A<int> - - + + A<int_vec_t> - + A<int_vec_t> - - + + A<string_vec_t> - + A<string_vec_t> - - + + A<int_map_t> - + A<int_map_t> - - + + A<string_map_t> - + A<string_map_t> - - - - - - - - + + + + + + + + run() - + a(int) - + a(int_vec_t) - + a(string_vec_t) - + a(int_map_t) - + a(string_map_t) diff --git a/docs/test_cases/t20040.md b/docs/test_cases/t20040.md new file mode 100644 index 00000000..2dadfaaf --- /dev/null +++ b/docs/test_cases/t20040.md @@ -0,0 +1,335 @@ +# t20040 - Test case for recursive variadic template function call +## Config +```yaml +diagrams: + t20040_sequence: + type: sequence + glob: + - t20040.cc + include: + namespaces: + - clanguml::t20040 + using_namespace: clanguml::t20040 + from: + - function: "clanguml::t20040::tmain()" +``` +## Source code +File `tests/t20040/t20040.cc` +```cpp +#include +#include + +namespace clanguml { +namespace t20040 { +void print() { } + +template void print(T head, Ts... tail) +{ + std::cout << head << std::endl; + print(tail...); +} + +template void doublePrint(Ts... args) +{ + print(args + args...); +} + +void tmain() +{ + using namespace std::literals::string_literals; + + print(1, 3.14, "test"s); + + doublePrint("test"s, 2024 / 2); +} +} +} +``` +## Generated PlantUML diagrams +![t20040_sequence](./t20040_sequence.svg "Test case for recursive variadic template function call") +## Generated Mermaid diagrams +![t20040_sequence](./t20040_sequence_mermaid.svg "Test case for recursive variadic template function call") +## Generated JSON models +```json +{ + "diagram_type": "sequence", + "name": "t20040_sequence", + "participants": [ + { + "display_name": "tmain()", + "id": "998622560147459663", + "name": "tmain", + "namespace": "clanguml::t20040", + "source_location": { + "column": 6, + "file": "t20040.cc", + "line": 19, + "translation_unit": "t20040.cc" + }, + "type": "function" + }, + { + "display_name": "print(int,double,std::basic_string)", + "id": "466846361794024298", + "name": "print", + "namespace": "clanguml::t20040", + "source_location": { + "column": 44, + "file": "t20040.cc", + "line": 8, + "translation_unit": "t20040.cc" + }, + "type": "function_template" + }, + { + "display_name": "print(double,std::basic_string)", + "id": "1387681712381484036", + "name": "print", + "namespace": "clanguml::t20040", + "source_location": { + "column": 44, + "file": "t20040.cc", + "line": 8, + "translation_unit": "t20040.cc" + }, + "type": "function_template" + }, + { + "display_name": "print(std::basic_string)", + "id": "1353926867284821849", + "name": "print", + "namespace": "clanguml::t20040", + "source_location": { + "column": 44, + "file": "t20040.cc", + "line": 8, + "translation_unit": "t20040.cc" + }, + "type": "function_template" + }, + { + "display_name": "print()", + "id": "245418438894072749", + "name": "print", + "namespace": "clanguml::t20040", + "source_location": { + "column": 6, + "file": "t20040.cc", + "line": 6, + "translation_unit": "t20040.cc" + }, + "type": "function" + }, + { + "display_name": "doublePrint(std::basic_string,int)", + "id": "2024126405552345351", + "name": "doublePrint", + "namespace": "clanguml::t20040", + "source_location": { + "column": 32, + "file": "t20040.cc", + "line": 14, + "translation_unit": "t20040.cc" + }, + "type": "function_template" + }, + { + "display_name": "print(std::basic_string,int)", + "id": "1349996183789322606", + "name": "print", + "namespace": "clanguml::t20040", + "source_location": { + "column": 44, + "file": "t20040.cc", + "line": 8, + "translation_unit": "t20040.cc" + }, + "type": "function_template" + }, + { + "display_name": "print(int)", + "id": "1189427464789523930", + "name": "print", + "namespace": "clanguml::t20040", + "source_location": { + "column": 44, + "file": "t20040.cc", + "line": 8, + "translation_unit": "t20040.cc" + }, + "type": "function_template" + } + ], + "sequences": [ + { + "messages": [ + { + "from": { + "activity_id": "998622560147459663", + "participant_id": "998622560147459663" + }, + "name": "", + "return_type": "", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20040.cc", + "line": 23, + "translation_unit": "t20040.cc" + }, + "to": { + "activity_id": "466846361794024298", + "participant_id": "466846361794024298" + }, + "type": "message" + }, + { + "from": { + "activity_id": "466846361794024298", + "participant_id": "466846361794024298" + }, + "name": "", + "return_type": "", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20040.cc", + "line": 11, + "translation_unit": "t20040.cc" + }, + "to": { + "activity_id": "1387681712381484036", + "participant_id": "1387681712381484036" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1387681712381484036", + "participant_id": "1387681712381484036" + }, + "name": "", + "return_type": "", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20040.cc", + "line": 11, + "translation_unit": "t20040.cc" + }, + "to": { + "activity_id": "1353926867284821849", + "participant_id": "1353926867284821849" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1353926867284821849", + "participant_id": "1353926867284821849" + }, + "name": "", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20040.cc", + "line": 11, + "translation_unit": "t20040.cc" + }, + "to": { + "activity_id": "245418438894072749", + "participant_id": "245418438894072749" + }, + "type": "message" + }, + { + "from": { + "activity_id": "998622560147459663", + "participant_id": "998622560147459663" + }, + "name": "", + "return_type": "", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20040.cc", + "line": 25, + "translation_unit": "t20040.cc" + }, + "to": { + "activity_id": "2024126405552345351", + "participant_id": "2024126405552345351" + }, + "type": "message" + }, + { + "from": { + "activity_id": "2024126405552345351", + "participant_id": "2024126405552345351" + }, + "name": "", + "return_type": "", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20040.cc", + "line": 16, + "translation_unit": "t20040.cc" + }, + "to": { + "activity_id": "1349996183789322606", + "participant_id": "1349996183789322606" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1349996183789322606", + "participant_id": "1349996183789322606" + }, + "name": "", + "return_type": "", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20040.cc", + "line": 11, + "translation_unit": "t20040.cc" + }, + "to": { + "activity_id": "1189427464789523930", + "participant_id": "1189427464789523930" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1189427464789523930", + "participant_id": "1189427464789523930" + }, + "name": "", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20040.cc", + "line": 11, + "translation_unit": "t20040.cc" + }, + "to": { + "activity_id": "245418438894072749", + "participant_id": "245418438894072749" + }, + "type": "message" + } + ], + "start_from": { + "id": 998622560147459663, + "location": "clanguml::t20040::tmain()" + } + } + ], + "using_namespace": "clanguml::t20040" +} +``` diff --git a/docs/test_cases/t20040_sequence.svg b/docs/test_cases/t20040_sequence.svg new file mode 100644 index 00000000..c0024026 --- /dev/null +++ b/docs/test_cases/t20040_sequence.svg @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + tmain() + + tmain() + + + + print<int,double,std::string>(int,double,std::string) + + print<int,double,std::string>(int,double,std::string) + + + + print<double,std::string>(double,std::string) + + print<double,std::string>(double,std::string) + + + + print<std::string>(std::string) + + print<std::string>(std::string) + + + + print() + + print() + + + + doublePrint<std::string,int>(std::string,int) + + doublePrint<std::string,int>(std::string,int) + + + + print<std::string,int>(std::string,int) + + print<std::string,int>(std::string,int) + + + + print<int>(int) + + print<int>(int) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/test_cases/t20040_sequence_mermaid.svg b/docs/test_cases/t20040_sequence_mermaid.svg new file mode 100644 index 00000000..dc0e8965 --- /dev/null +++ b/docs/test_cases/t20040_sequence_mermaid.svg @@ -0,0 +1,203 @@ + + + + + print<int>(int) + + + + + + print<std::string,int>(std::string,int) + + + + + + doublePrint<std::string,int>(std::string,int) + + + + + + print() + + + + + + print<std::string>(std::string) + + + + + + print<double,std::string>(double,std::string) + + + + + + print<int,double,std::string>(int,double,std::string) + + + + + + tmain() + + + + + + + + print<int>(int) + + + + + + + + + print<std::string,int>(std::string,int) + + + + + + + + + doublePrint<std::string,int>(std::string,int) + + + + + + + + + print() + + + + + + + + + print<std::string>(std::string) + + + + + + + + + print<double,std::string>(double,std::string) + + + + + + + + + print<int,double,std::string>(int,double,std::string) + + + + + + + + + tmain() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ​ + + ​ + + ​ + + ​ + + ​ + + ​ + + ​ + + ​ + + diff --git a/docs/test_cases/t20041.md b/docs/test_cases/t20041.md new file mode 100644 index 00000000..2a504842 --- /dev/null +++ b/docs/test_cases/t20041.md @@ -0,0 +1,279 @@ +# t20041 - Test case for recursive variadic template class call +## Config +```yaml +diagrams: + t20041_sequence: + type: sequence + glob: + - t20041.cc + include: + namespaces: + - clanguml::t20041 + using_namespace: clanguml::t20041 + from: + - function: "clanguml::t20041::tmain()" +``` +## Source code +File `tests/t20041/t20041.cc` +```cpp +#include +#include + +namespace clanguml { +namespace t20041 { + +template struct A; + +template struct A { + void print(First first, Rest... rest) + { + std::cout << first << std::endl; + + A a; + a.print(rest...); + } +}; + +template <> struct A<> { + void print() { } +}; + +void tmain() +{ + using namespace std::literals::string_literals; + + A a; + a.print(1, 3.14, "test"s); +} +} +} +``` +## Generated PlantUML diagrams +![t20041_sequence](./t20041_sequence.svg "Test case for recursive variadic template class call") +## Generated Mermaid diagrams +![t20041_sequence](./t20041_sequence_mermaid.svg "Test case for recursive variadic template class call") +## Generated JSON models +```json +{ + "diagram_type": "sequence", + "name": "t20041_sequence", + "participants": [ + { + "display_name": "tmain()", + "id": "1389566400082670258", + "name": "tmain", + "namespace": "clanguml::t20041", + "source_location": { + "column": 6, + "file": "t20041.cc", + "line": 23, + "translation_unit": "t20041.cc" + }, + "type": "function" + }, + { + "activities": [ + { + "display_name": "print(int,double,std::string)", + "id": "532000038063429229", + "name": "print", + "namespace": "", + "source_location": { + "column": 10, + "file": "t20041.cc", + "line": 10, + "translation_unit": "t20041.cc" + }, + "type": "method" + } + ], + "display_name": "A", + "id": "832678750316145968", + "name": "A", + "namespace": "clanguml::t20041", + "source_location": { + "column": 52, + "file": "t20041.cc", + "line": 9, + "translation_unit": "t20041.cc" + }, + "type": "class" + }, + { + "activities": [ + { + "display_name": "print(double,std::string)", + "id": "1403962403457522629", + "name": "print", + "namespace": "", + "source_location": { + "column": 10, + "file": "t20041.cc", + "line": 10, + "translation_unit": "t20041.cc" + }, + "type": "method" + } + ], + "display_name": "A", + "id": "942399465509044163", + "name": "A", + "namespace": "clanguml::t20041", + "source_location": { + "column": 52, + "file": "t20041.cc", + "line": 9, + "translation_unit": "t20041.cc" + }, + "type": "class" + }, + { + "activities": [ + { + "display_name": "print(std::string)", + "id": "1658479415048358058", + "name": "print", + "namespace": "", + "source_location": { + "column": 10, + "file": "t20041.cc", + "line": 10, + "translation_unit": "t20041.cc" + }, + "type": "method" + } + ], + "display_name": "A", + "id": "1390965848075226081", + "name": "A", + "namespace": "clanguml::t20041", + "source_location": { + "column": 52, + "file": "t20041.cc", + "line": 9, + "translation_unit": "t20041.cc" + }, + "type": "class" + }, + { + "activities": [ + { + "display_name": "print()", + "id": "1295142493768214222", + "name": "print", + "namespace": "", + "source_location": { + "column": 10, + "file": "t20041.cc", + "line": 20, + "translation_unit": "t20041.cc" + }, + "type": "method" + } + ], + "display_name": "A", + "id": "1052108783247143031", + "name": "A", + "namespace": "clanguml::t20041", + "source_location": { + "column": 52, + "file": "t20041.cc", + "line": 9, + "translation_unit": "t20041.cc" + }, + "type": "class" + } + ], + "sequences": [ + { + "messages": [ + { + "from": { + "activity_id": "1389566400082670258", + "participant_id": "1389566400082670258" + }, + "name": "print(int,double,std::string)", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20041.cc", + "line": 28, + "translation_unit": "t20041.cc" + }, + "to": { + "activity_id": "532000038063429229", + "participant_id": "832678750316145968" + }, + "type": "message" + }, + { + "from": { + "activity_id": "532000038063429229", + "participant_id": "832678750316145968" + }, + "name": "print(double,std::string)", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 9, + "file": "t20041.cc", + "line": 15, + "translation_unit": "t20041.cc" + }, + "to": { + "activity_id": "1403962403457522629", + "participant_id": "942399465509044163" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1403962403457522629", + "participant_id": "942399465509044163" + }, + "name": "print(std::string)", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 9, + "file": "t20041.cc", + "line": 15, + "translation_unit": "t20041.cc" + }, + "to": { + "activity_id": "1658479415048358058", + "participant_id": "1390965848075226081" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1658479415048358058", + "participant_id": "1390965848075226081" + }, + "name": "print()", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 9, + "file": "t20041.cc", + "line": 15, + "translation_unit": "t20041.cc" + }, + "to": { + "activity_id": "1295142493768214222", + "participant_id": "1052108783247143031" + }, + "type": "message" + } + ], + "start_from": { + "id": 1389566400082670258, + "location": "clanguml::t20041::tmain()" + } + } + ], + "using_namespace": "clanguml::t20041" +} +``` diff --git a/docs/test_cases/t20041_sequence.svg b/docs/test_cases/t20041_sequence.svg new file mode 100644 index 00000000..5c931ffd --- /dev/null +++ b/docs/test_cases/t20041_sequence.svg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + tmain() + + tmain() + + + + A<int,double,std::string> + + A<int,double,std::string> + + + + A<double,std::string> + + A<double,std::string> + + + + A<std::string> + + A<std::string> + + + + A + + A + + + + + + + + + + print(int,double,std::string) + + + + + print(double,std::string) + + + + + print(std::string) + + + + + print() + + + diff --git a/docs/test_cases/t20041_sequence_mermaid.svg b/docs/test_cases/t20041_sequence_mermaid.svg new file mode 100644 index 00000000..48c81041 --- /dev/null +++ b/docs/test_cases/t20041_sequence_mermaid.svg @@ -0,0 +1,138 @@ + + + + + A + + + + + + A<std::string> + + + + + + A<double,std::string> + + + + + + A<int,double,std::string> + + + + + + tmain() + + + + + + + + A + + + + + + + + + A<std::string> + + + + + + + + + A<double,std::string> + + + + + + + + + A<int,double,std::string> + + + + + + + + + tmain() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + print(int,double,std::string) + + print(double,std::string) + + print(std::string) + + print() + + diff --git a/docs/test_cases/t20042.md b/docs/test_cases/t20042.md new file mode 100644 index 00000000..6c5136af --- /dev/null +++ b/docs/test_cases/t20042.md @@ -0,0 +1,248 @@ +# t20042 - Test case for template overload pattern +## Config +```yaml +diagrams: + t20042_sequence: + type: sequence + glob: + - t20042.cc + include: + namespaces: + - clanguml::t20042 + using_namespace: clanguml::t20042 + from: + - function: "clanguml::t20042::tmain()" +``` +## Source code +File `tests/t20042/t20042.cc` +```cpp +namespace clanguml { +namespace t20042 { +struct A { }; +struct AHandler { + void handle(A &a) const { } + void operator()(A &a) const { handle(a); } +}; + +struct B { }; +struct BHandler { + void handle(B &b) const { } + void operator()(B &b) const { handle(b); } +}; + +template struct Overload : public Bases... { + using Bases::operator()...; +}; +template Overload(Bases...) -> Overload; + +void tmain() +{ + Overload dispatch; + A a; + B b; + + dispatch(a); + dispatch(b); +} +} +} +``` +## Generated PlantUML diagrams +![t20042_sequence](./t20042_sequence.svg "Test case for template overload pattern") +## Generated Mermaid diagrams +![t20042_sequence](./t20042_sequence_mermaid.svg "Test case for template overload pattern") +## Generated JSON models +```json +{ + "diagram_type": "sequence", + "name": "t20042_sequence", + "participants": [ + { + "display_name": "tmain()", + "id": "609011973422503266", + "name": "tmain", + "namespace": "clanguml::t20042", + "source_location": { + "column": 6, + "file": "t20042.cc", + "line": 20, + "translation_unit": "t20042.cc" + }, + "type": "function" + }, + { + "activities": [ + { + "display_name": "operator()(A &) const", + "id": "1803150869170812951", + "name": "operator()", + "namespace": "", + "source_location": { + "column": 10, + "file": "t20042.cc", + "line": 6, + "translation_unit": "t20042.cc" + }, + "type": "method" + }, + { + "display_name": "handle(A &) const", + "id": "505918958102707204", + "name": "handle", + "namespace": "", + "source_location": { + "column": 10, + "file": "t20042.cc", + "line": 5, + "translation_unit": "t20042.cc" + }, + "type": "method" + } + ], + "display_name": "AHandler", + "id": "169029708750481998", + "name": "AHandler", + "namespace": "clanguml::t20042", + "source_location": { + "column": 8, + "file": "t20042.cc", + "line": 4, + "translation_unit": "t20042.cc" + }, + "type": "class" + }, + { + "activities": [ + { + "display_name": "operator()(B &) const", + "id": "1635511505447928279", + "name": "operator()", + "namespace": "", + "source_location": { + "column": 10, + "file": "t20042.cc", + "line": 12, + "translation_unit": "t20042.cc" + }, + "type": "method" + }, + { + "display_name": "handle(B &) const", + "id": "869419286648646110", + "name": "handle", + "namespace": "", + "source_location": { + "column": 10, + "file": "t20042.cc", + "line": 11, + "translation_unit": "t20042.cc" + }, + "type": "method" + } + ], + "display_name": "BHandler", + "id": "1969158228859108037", + "name": "BHandler", + "namespace": "clanguml::t20042", + "source_location": { + "column": 8, + "file": "t20042.cc", + "line": 10, + "translation_unit": "t20042.cc" + }, + "type": "class" + } + ], + "sequences": [ + { + "messages": [ + { + "from": { + "activity_id": "609011973422503266", + "participant_id": "609011973422503266" + }, + "name": "operator()(A &) const", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20042.cc", + "line": 26, + "translation_unit": "t20042.cc" + }, + "to": { + "activity_id": "1803150869170812951", + "participant_id": "169029708750481998" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1803150869170812951", + "participant_id": "169029708750481998" + }, + "name": "handle(A &) const", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 35, + "file": "t20042.cc", + "line": 6, + "translation_unit": "t20042.cc" + }, + "to": { + "activity_id": "505918958102707204", + "participant_id": "169029708750481998" + }, + "type": "message" + }, + { + "from": { + "activity_id": "609011973422503266", + "participant_id": "609011973422503266" + }, + "name": "operator()(B &) const", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 5, + "file": "t20042.cc", + "line": 27, + "translation_unit": "t20042.cc" + }, + "to": { + "activity_id": "1635511505447928279", + "participant_id": "1969158228859108037" + }, + "type": "message" + }, + { + "from": { + "activity_id": "1635511505447928279", + "participant_id": "1969158228859108037" + }, + "name": "handle(B &) const", + "return_type": "void", + "scope": "normal", + "source_location": { + "column": 35, + "file": "t20042.cc", + "line": 12, + "translation_unit": "t20042.cc" + }, + "to": { + "activity_id": "869419286648646110", + "participant_id": "1969158228859108037" + }, + "type": "message" + } + ], + "start_from": { + "id": 609011973422503266, + "location": "clanguml::t20042::tmain()" + } + } + ], + "using_namespace": "clanguml::t20042" +} +``` diff --git a/docs/test_cases/t20042_sequence.svg b/docs/test_cases/t20042_sequence.svg new file mode 100644 index 00000000..ee08c120 --- /dev/null +++ b/docs/test_cases/t20042_sequence.svg @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + tmain() + + tmain() + + + + AHandler + + AHandler + + + + BHandler + + BHandler + + + + + + + + + + operator()(A &) const + + + + + + + handle(A &) const + + + + + operator()(B &) const + + + + + + + handle(B &) const + + + diff --git a/docs/test_cases/t20042_sequence_mermaid.svg b/docs/test_cases/t20042_sequence_mermaid.svg new file mode 100644 index 00000000..616af878 --- /dev/null +++ b/docs/test_cases/t20042_sequence_mermaid.svg @@ -0,0 +1,108 @@ + + + + + BHandler + + + + + + AHandler + + + + + + tmain() + + + + + + + + BHandler + + + + + + + + + AHandler + + + + + + + + + tmain() + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + operator()(A &) const + + handle(A &) const + + operator()(B &) const + + handle(B &) const + + diff --git a/docs/test_cases/t30001_package.svg b/docs/test_cases/t30001_package.svg index 1b355bec..c151459a 100644 --- a/docs/test_cases/t30001_package.svg +++ b/docs/test_cases/t30001_package.svg @@ -1,6 +1,6 @@ - + @@ -10,67 +10,67 @@ Basic package diagram example - - + + A - - + + AA - - + + B - - + + AA - - + + AAA - - + + BBB - - + + BB - - + + AAA - - + + BBB - - + + BB - + A AAA note... - + This is namespace AA in namespace A - + This is namespace AA in namespace B - - - + + + diff --git a/docs/test_cases/t30002_package.svg b/docs/test_cases/t30002_package.svg index 60fb56e3..c7cab02b 100644 --- a/docs/test_cases/t30002_package.svg +++ b/docs/test_cases/t30002_package.svg @@ -1,6 +1,6 @@ - + @@ -9,118 +9,118 @@ - - + + A - - + + AA - - + + B - - + + BB - - + + A1 - - + + A2 - - + + A3 - - + + A4 - - + + A5 - - + + A6 - - + + A7 - - + + A8 - - + + A9 - - + + A10 - - + + A11 - - + + A12 - - + + A13 - - + + A14 - - + + A15 - - + + A16 - - + + A17 - - + + A18 - - + + BBB diff --git a/docs/test_cases/t30003_package.svg b/docs/test_cases/t30003_package.svg index 5ada5bb1..9a0a7e06 100644 --- a/docs/test_cases/t30003_package.svg +++ b/docs/test_cases/t30003_package.svg @@ -1,6 +1,6 @@ - + @@ -9,35 +9,35 @@ - - + + ns1 - - + + ns3 «deprecated» - - + + ns1 - - + + ns2_v1_0_0 - - + + ns2_v0_9_0 «deprecated» - - + + ns2 diff --git a/docs/test_cases/t30004_package.svg b/docs/test_cases/t30004_package.svg index 41434755..385b99e2 100644 --- a/docs/test_cases/t30004_package.svg +++ b/docs/test_cases/t30004_package.svg @@ -1,6 +1,6 @@ - + @@ -9,46 +9,46 @@ - - + + A - + Package AAA. - + Package BBB. - + CCCC package note. - + We skipped DDD. - - + + AAA - - + + BBB - - + + CCC - - + + EEE - - - - + + + + diff --git a/docs/test_cases/t30005_package.svg b/docs/test_cases/t30005_package.svg index 168e4b26..a0972b22 100644 --- a/docs/test_cases/t30005_package.svg +++ b/docs/test_cases/t30005_package.svg @@ -1,6 +1,6 @@ - + @@ -9,48 +9,48 @@ - - + + A - - + + AA - - + + B - - + + BB - - + + C - - + + CC - - + + AAA - - + + BBB - - + + CCC diff --git a/docs/test_cases/t30006_package.svg b/docs/test_cases/t30006_package.svg index a39d74a3..f58fb706 100644 --- a/docs/test_cases/t30006_package.svg +++ b/docs/test_cases/t30006_package.svg @@ -1,6 +1,6 @@ - + @@ -9,25 +9,25 @@ - - + + B - - + + A - - + + C - + Top A note. - + diff --git a/docs/test_cases/t30007_package.svg b/docs/test_cases/t30007_package.svg index 86fe9173..3e342cf0 100644 --- a/docs/test_cases/t30007_package.svg +++ b/docs/test_cases/t30007_package.svg @@ -1,6 +1,6 @@ - + @@ -9,30 +9,30 @@ - - + + A - - + + B - - + + AA - - + + C - + Compare layout with t30006. - + diff --git a/docs/test_cases/t30008_package.svg b/docs/test_cases/t30008_package.svg index 9fc2e16b..33160948 100644 --- a/docs/test_cases/t30008_package.svg +++ b/docs/test_cases/t30008_package.svg @@ -1,6 +1,6 @@ - + @@ -9,43 +9,43 @@ - - + + dependants - - + + dependencies - - + + A - - + + B - - + + C - - + + D - - + + E - - + + F diff --git a/docs/test_cases/t30009_package.svg b/docs/test_cases/t30009_package.svg index 9891180b..55cb3322 100644 --- a/docs/test_cases/t30009_package.svg +++ b/docs/test_cases/t30009_package.svg @@ -1,6 +1,6 @@ - + @@ -9,53 +9,53 @@ - - + + One - - + + Two - - + + B - - + + D - - + + A - - + + C - - + + A - - + + B - - + + C - - + + D diff --git a/docs/test_cases/t30010_package.svg b/docs/test_cases/t30010_package.svg index e394428c..12ae2459 100644 --- a/docs/test_cases/t30010_package.svg +++ b/docs/test_cases/t30010_package.svg @@ -1,6 +1,6 @@ - + @@ -9,31 +9,31 @@ - + libraries - - + + lib1 - - + + lib2 - - + + lib3 - - + + lib4 - - + + app diff --git a/docs/test_cases/t30011_package.svg b/docs/test_cases/t30011_package.svg index 4ba4a430..ebaec36e 100644 --- a/docs/test_cases/t30011_package.svg +++ b/docs/test_cases/t30011_package.svg @@ -1,6 +1,6 @@ - + @@ -9,31 +9,31 @@ - + libraries - - + + lib1 - - + + lib2 - - + + lib3 - - + + lib4 - - + + app diff --git a/docs/test_cases/t30012_package.svg b/docs/test_cases/t30012_package.svg index bc3fe46d..6d10019b 100644 --- a/docs/test_cases/t30012_package.svg +++ b/docs/test_cases/t30012_package.svg @@ -1,6 +1,6 @@ - + @@ -9,26 +9,26 @@ - + app - - + + lib1 - - + + mod1 - - + + mod2 - - + + lib2 diff --git a/docs/test_cases/t30013_package.svg b/docs/test_cases/t30013_package.svg index 040d9106..8a40042f 100644 --- a/docs/test_cases/t30013_package.svg +++ b/docs/test_cases/t30013_package.svg @@ -1,6 +1,6 @@ - + @@ -9,98 +9,98 @@ - - + + mod1 - - + + mod2 - - + + mod3 - - + + mod4 - - + + mod5 - - + + mod6 - - + + mod7 - - + + mod8 - - + + mod9 - - + + mod10 - - + + mod11 - - + + mod12 - - + + mod13 - - + + mod14 - - + + mod15 - - + + mod16 - - + + mod17 - - + + mod18 - - + + app diff --git a/docs/test_cases/t30014_package.svg b/docs/test_cases/t30014_package.svg index 86a07d5d..7066a2b7 100644 --- a/docs/test_cases/t30014_package.svg +++ b/docs/test_cases/t30014_package.svg @@ -1,6 +1,6 @@ - + @@ -9,21 +9,21 @@ - + app - - + + :lib1 - - + + mod1 - - + + :lib2 diff --git a/docs/test_cases/t30015_package.svg b/docs/test_cases/t30015_package.svg index 3453c7bb..ae8c4ef6 100644 --- a/docs/test_cases/t30015_package.svg +++ b/docs/test_cases/t30015_package.svg @@ -1,6 +1,6 @@ - + @@ -9,101 +9,101 @@ - + lib1 - - + + :mod1 - - + + :mod2 - - + + :mod3 - - + + :mod4 - - + + :mod5 - - + + :mod6 - - + + :mod7 - - + + :mod8 - - + + :mod9 - - + + :mod10 - - + + :mod11 - - + + :mod12 - - + + :mod13 - - + + :mod14 - - + + :mod15 - - + + :mod16 - - + + :mod17 - - + + :mod18 - - + + app diff --git a/docs/test_cases/t40001_include.svg b/docs/test_cases/t40001_include.svg index 7d5a28b7..0a02ff1c 100644 --- a/docs/test_cases/t40001_include.svg +++ b/docs/test_cases/t40001_include.svg @@ -1,6 +1,6 @@ - + @@ -10,41 +10,41 @@ Basic include diagram example - + src - + include - + lib1 - - + + t40001.cc - - + + t40001_include1.h - + lib1.h - + string - + vector - + yaml-cpp/yaml.h - + This is a lib1 include dir - + This is a t40001_include1.h include file @@ -59,7 +59,7 @@ - - + + diff --git a/docs/test_cases/t40001_include_mermaid.svg b/docs/test_cases/t40001_include_mermaid.svg index efe17f60..e0fda714 100644 --- a/docs/test_cases/t40001_include_mermaid.svg +++ b/docs/test_cases/t40001_include_mermaid.svg @@ -138,7 +138,7 @@ - + @@ -151,7 +151,7 @@ - + @@ -164,7 +164,7 @@ - + diff --git a/docs/test_cases/t40002_include.svg b/docs/test_cases/t40002_include.svg index 52c705a0..71bb8582 100644 --- a/docs/test_cases/t40002_include.svg +++ b/docs/test_cases/t40002_include.svg @@ -1,6 +1,6 @@ - + @@ -9,46 +9,46 @@ - + src - + lib1 - + lib2 - + include - + lib1 - + lib2 - - + + t40002.cc - - + + lib1.cc - - + + lib2.cc - - + + lib1.h - - + + lib2.h diff --git a/docs/test_cases/t40002_include_mermaid.svg b/docs/test_cases/t40002_include_mermaid.svg index a6475c8c..77f09547 100644 --- a/docs/test_cases/t40002_include_mermaid.svg +++ b/docs/test_cases/t40002_include_mermaid.svg @@ -137,7 +137,7 @@ - + @@ -150,7 +150,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -176,7 +176,7 @@ - + @@ -189,7 +189,7 @@ - + diff --git a/docs/test_cases/t40003_include.svg b/docs/test_cases/t40003_include.svg index 9667986e..7696038a 100644 --- a/docs/test_cases/t40003_include.svg +++ b/docs/test_cases/t40003_include.svg @@ -1,6 +1,6 @@ - + @@ -9,62 +9,62 @@ - + src - + dependants - + dependencies - + include - + dependants - + dependencies - - + + t1.cc - - + + t2.cc - - + + t3.h - - + + t2.h - + t1.h - - + + t3.h - - + + t2.h - + t1.h - - + + t5.h diff --git a/docs/test_cases/t40003_include_mermaid.svg b/docs/test_cases/t40003_include_mermaid.svg index 1422bce5..a21f8798 100644 --- a/docs/test_cases/t40003_include_mermaid.svg +++ b/docs/test_cases/t40003_include_mermaid.svg @@ -167,7 +167,7 @@ - + @@ -180,7 +180,7 @@ - + @@ -193,7 +193,7 @@ - + @@ -206,7 +206,7 @@ - + @@ -219,7 +219,7 @@ - + @@ -232,7 +232,7 @@ - + @@ -245,7 +245,7 @@ - + @@ -258,7 +258,7 @@ - + @@ -271,7 +271,7 @@ - +