From 5b8e40c1eb6d56297203c1642a344ab724202e06 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Mon, 18 Apr 2022 19:29:08 +0200 Subject: [PATCH] Added package dependencies and dependants filter --- src/class_diagram/model/class.h | 16 ++++++ src/class_diagram/model/diagram.cc | 8 +++ src/class_diagram/model/diagram.h | 16 +----- src/common/model/diagram.h | 1 + src/common/model/diagram_filter.cc | 50 +++++++++++++++++ src/common/model/diagram_filter.h | 42 ++++++++++---- src/common/model/enums.cc | 19 ++++++- src/common/model/enums.h | 6 +- src/common/model/package.cc | 8 +-- src/common/model/package.h | 16 +++++- src/common/model/relationship.cc | 2 +- src/common/model/stylable_element.cc | 2 +- src/common/model/stylable_element.h | 2 +- src/config/config.cc | 33 ++++------- src/config/config.h | 18 ++---- src/include_diagram/model/diagram.cc | 8 +++ src/include_diagram/model/diagram.h | 5 ++ src/main.cc | 10 ++-- .../plantuml/package_diagram_generator.cc | 11 ++-- src/package_diagram/model/diagram.cc | 17 +++++- src/package_diagram/model/diagram.h | 8 +++ src/sequence_diagram/model/diagram.cc | 8 +++ src/sequence_diagram/model/diagram.h | 6 ++ tests/t30008/.clang-uml | 17 ++++++ tests/t30008/t30008.cc | 45 +++++++++++++++ tests/t30008/test_case.h | 55 +++++++++++++++++++ tests/test_cases.cc | 1 + tests/test_cases.yaml | 5 +- tests/test_config.cc | 16 +++--- 29 files changed, 359 insertions(+), 92 deletions(-) create mode 100644 tests/t30008/.clang-uml create mode 100644 tests/t30008/t30008.cc create mode 100644 tests/t30008/test_case.h diff --git a/src/class_diagram/model/class.h b/src/class_diagram/model/class.h index 8b66d0f4..ff1f194e 100644 --- a/src/class_diagram/model/class.h +++ b/src/class_diagram/model/class.h @@ -26,6 +26,8 @@ #include "common/model/stylable_element.h" #include "type_alias.h" +#include + #include #include @@ -90,3 +92,17 @@ private: }; } + +namespace std { +template <> +struct hash< + type_safe::object_ref> { + std::size_t operator()(const type_safe::object_ref< + const clanguml::class_diagram::model::class_> &key) const + { + using clanguml::class_diagram::model::class_; + + return std::hash{}(key.get().full_name(false)); + } +}; +} diff --git a/src/class_diagram/model/diagram.cc b/src/class_diagram/model/diagram.cc index 23f2147a..527f6bac 100644 --- a/src/class_diagram/model/diagram.cc +++ b/src/class_diagram/model/diagram.cc @@ -192,3 +192,11 @@ std::string diagram::to_alias(const std::string &full_name) const } } + +namespace clanguml::common::model { +template <> +bool check_diagram_type(diagram_t t) +{ + return t == diagram_t::kClass; +} +} diff --git a/src/class_diagram/model/diagram.h b/src/class_diagram/model/diagram.h index eb19cdd1..ccfc546d 100644 --- a/src/class_diagram/model/diagram.h +++ b/src/class_diagram/model/diagram.h @@ -83,17 +83,7 @@ private: }; } -namespace std { - +namespace clanguml::common::model { template <> -struct hash< - type_safe::object_ref> { - std::size_t operator()(const type_safe::object_ref< - const clanguml::class_diagram::model::class_> &key) const - { - using clanguml::class_diagram::model::class_; - - return std::hash{}(key.get().full_name(false)); - } -}; -} +bool check_diagram_type(diagram_t t); +} \ No newline at end of file diff --git a/src/common/model/diagram.h b/src/common/model/diagram.h index 579c2c1a..b49bd953 100644 --- a/src/common/model/diagram.h +++ b/src/common/model/diagram.h @@ -72,4 +72,5 @@ private: bool complete_{false}; }; +template bool check_diagram_type(diagram_t t); } diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc index 92c11606..2c60930b 100644 --- a/src/common/model/diagram_filter.cc +++ b/src/common/model/diagram_filter.cc @@ -19,6 +19,8 @@ #include "diagram_filter.h" #include "class_diagram/model/class.h" +#include "common/model/package.h" +#include "package_diagram/model/diagram.h" namespace clanguml::common::model { @@ -38,6 +40,13 @@ view(const class_diagram::model::diagram &d) return d.enums(); } +template <> +const std::vector> &view( + const package_diagram::model::diagram &d) +{ + return d.packages(); +} + template <> const type_safe::optional_ref get( const class_diagram::model::diagram &d, const std::string &full_name) @@ -45,6 +54,13 @@ const type_safe::optional_ref get( return d.get_class(full_name); } +template <> +const type_safe::optional_ref get( + const package_diagram::model::diagram &d, const std::string &full_name) +{ + return d.get_package(full_name); +} + } filter_visitor::filter_visitor(filter_t type) @@ -357,17 +373,22 @@ void diagram_filter::init_filters(const config::diagram &c) if (c.include) { add_inclusive_filter(std::make_unique( filter_t::kInclusive, c.include().namespaces)); + add_inclusive_filter(std::make_unique( filter_t::kInclusive, c.include().relationships)); + add_inclusive_filter(std::make_unique( filter_t::kInclusive, c.include().access)); + add_inclusive_filter(std::make_unique( filter_t::kInclusive, c.base_directory(), c.include().paths)); // Include any of these matches even if one them does not match std::vector> element_filters; + element_filters.emplace_back(std::make_unique( filter_t::kInclusive, c.include().elements)); + element_filters.emplace_back(std::make_unique( filter_t::kInclusive, c.include().subclasses)); @@ -381,11 +402,21 @@ void diagram_filter::init_filters(const config::diagram &c) class_diagram::model::class_>>(filter_t::kInclusive, relationship_t::kDependency, c.include().dependants)); + element_filters.emplace_back(std::make_unique>( + filter_t::kInclusive, relationship_t::kDependency, + c.include().dependants)); + element_filters.emplace_back( std::make_unique>(filter_t::kInclusive, relationship_t::kDependency, c.include().dependencies, true)); + element_filters.emplace_back(std::make_unique>( + filter_t::kInclusive, relationship_t::kDependency, + c.include().dependencies, true)); + element_filters.emplace_back(std::make_unique( filter_t::kInclusive, c.include().context)); @@ -397,28 +428,47 @@ void diagram_filter::init_filters(const config::diagram &c) if (c.exclude) { add_exclusive_filter(std::make_unique( filter_t::kExclusive, c.exclude().namespaces)); + add_exclusive_filter(std::make_unique( filter_t::kExclusive, c.base_directory(), c.exclude().paths)); + add_exclusive_filter(std::make_unique( filter_t::kExclusive, c.exclude().elements)); + add_exclusive_filter(std::make_unique( filter_t::kExclusive, c.exclude().relationships)); + add_exclusive_filter(std::make_unique( filter_t::kExclusive, c.exclude().access)); + add_exclusive_filter(std::make_unique( filter_t::kExclusive, c.exclude().subclasses)); + add_exclusive_filter( std::make_unique>(filter_t::kExclusive, relationship_t::kInstantiation, c.exclude().specializations)); + add_exclusive_filter( std::make_unique>(filter_t::kExclusive, relationship_t::kDependency, c.exclude().dependants)); + + add_exclusive_filter(std::make_unique>( + filter_t::kExclusive, relationship_t::kDependency, + c.exclude().dependants)); + add_exclusive_filter( std::make_unique>(filter_t::kExclusive, relationship_t::kDependency, c.exclude().dependencies, true)); + + add_exclusive_filter(std::make_unique>( + filter_t::kExclusive, relationship_t::kDependency, + c.exclude().dependencies, true)); + add_exclusive_filter(std::make_unique( filter_t::kExclusive, c.exclude().context)); } diff --git a/src/common/model/diagram_filter.h b/src/common/model/diagram_filter.h index 3ed8ffbc..e837ea1e 100644 --- a/src/common/model/diagram_filter.h +++ b/src/common/model/diagram_filter.h @@ -125,14 +125,17 @@ struct tree_element_filter : public filter_visitor { tvl::value_t match(const diagram &d, const element &e) const override { - if (roots_.empty()) - return {}; - // This filter should only be run on the completely generated diagram // model by visitor if (!d.complete()) return {}; + if (!check_diagram_type(d.type())) + return {}; + + if (roots_.empty()) + return {}; + const auto &cd = dynamic_cast(d); // Calculate the set of matching elements @@ -146,14 +149,10 @@ struct tree_element_filter : public filter_visitor { return false; // Now check if the e element is contained in the calculated set - const auto &e_full_name = e.full_name(false); - bool res = - std::find_if(matching_elements_.begin(), matching_elements_.end(), - [&e_full_name](const auto &te) { - return te->full_name(false) == e_full_name; - }) != matching_elements_.end(); - - return res; + return std::any_of(matching_elements_.begin(), matching_elements_.end(), + [&e](const auto &te) { + return te->full_name(false) == e.full_name(false); + }); } private: @@ -207,6 +206,27 @@ private: } } + if constexpr (std::is_same_v) { + if (type() == filter_t::kInclusive) { + // For package diagrams, add also all parents of matching + // packages + decltype(matching_elements_) parents; + util::for_each(matching_elements_, + [this, &cd, &parents](const auto &package) { + auto parent_path = package.get().path(); + auto parent = cd.get_package(parent_path.to_string()); + while (parent.has_value()) { + parents.emplace(type_safe::ref(parent.value())); + parent = cd.get_package( + parent.value().path().to_string()); + } + }); + + matching_elements_.insert( + std::begin(parents), std::end(parents)); + } + } + initialized_ = true; } diff --git a/src/common/model/enums.cc b/src/common/model/enums.cc index f1336fa6..218844b9 100644 --- a/src/common/model/enums.cc +++ b/src/common/model/enums.cc @@ -1,5 +1,5 @@ /** - * src/class_diagram/model/enums.cc + * src/common/model/enums.cc * * Copyright (c) 2021-2022 Bartek Kryza * @@ -74,4 +74,21 @@ std::string to_string(message_t r) assert(false); } } + +std::string to_string(const diagram_t t) +{ + switch (t) { + case diagram_t::kClass: + return "class"; + case diagram_t::kSequence: + return "sequence"; + case diagram_t::kPackage: + return "package"; + case diagram_t::kInclude: + return "include"; + default: + assert(false); + } +} + } diff --git a/src/common/model/enums.h b/src/common/model/enums.h index fbbeb21f..650ff2bf 100644 --- a/src/common/model/enums.h +++ b/src/common/model/enums.h @@ -1,5 +1,5 @@ /** - * src/class_diagram/model/enums.h + * src/common/model/enums.h * * Copyright (c) 2021-2022 Bartek Kryza * @@ -21,7 +21,7 @@ namespace clanguml::common::model { -enum class diagram_t { kClass, kSequence, kPackage }; +enum class diagram_t { kClass, kSequence, kPackage, kInclude }; enum class access_t { kPublic, kProtected, kPrivate }; @@ -47,4 +47,6 @@ std::string to_string(access_t r); std::string to_string(message_t r); +std::string to_string(diagram_t r); + } diff --git a/src/common/model/package.cc b/src/common/model/package.cc index b4a6aa7d..7116efea 100644 --- a/src/common/model/package.cc +++ b/src/common/model/package.cc @@ -1,5 +1,5 @@ /** - * src/common/model/class.h + * src/common/model/package.cc * * Copyright (c) 2021-2022 Bartek Kryza * @@ -18,8 +18,6 @@ #include "package.h" -#include "util/util.h" - #include namespace clanguml::common::model { @@ -35,11 +33,11 @@ std::string package::full_name(bool relative) const return res.to_string(); } - return (get_namespace().relative_to(using_namespace()) | name()) - .to_string(); + return (get_namespace() | name()).to_string(); } bool package::is_deprecated() const { return is_deprecated_; } void package::set_deprecated(bool deprecated) { is_deprecated_ = deprecated; } + } \ No newline at end of file diff --git a/src/common/model/package.h b/src/common/model/package.h index 1fdac159..1de5e675 100644 --- a/src/common/model/package.h +++ b/src/common/model/package.h @@ -1,5 +1,5 @@ /** - * src/package_diagram/model/class.h + * src/common/model/package.h * * Copyright (c) 2021-2022 Bartek Kryza * @@ -54,3 +54,17 @@ private: bool is_deprecated_{false}; }; } + +namespace std { +template <> +struct hash> { + std::size_t operator()( + const type_safe::object_ref + &key) const + { + using clanguml::common::model::package; + + return std::hash{}(key.get().full_name(false)); + } +}; +} diff --git a/src/common/model/relationship.cc b/src/common/model/relationship.cc index 28b0d961..2dfef55b 100644 --- a/src/common/model/relationship.cc +++ b/src/common/model/relationship.cc @@ -1,5 +1,5 @@ /** - * src/common/model/class_relationship.cc + * src/common/model/relationship.cc * * Copyright (c) 2021-2022 Bartek Kryza * diff --git a/src/common/model/stylable_element.cc b/src/common/model/stylable_element.cc index e1919fb7..05ca4625 100644 --- a/src/common/model/stylable_element.cc +++ b/src/common/model/stylable_element.cc @@ -1,5 +1,5 @@ /** - * src/class_diagram/model/stylable_element.cc + * src/common/model/stylable_element.cc * * Copyright (c) 2021-2022 Bartek Kryza * diff --git a/src/common/model/stylable_element.h b/src/common/model/stylable_element.h index ab0059ae..ee025096 100644 --- a/src/common/model/stylable_element.h +++ b/src/common/model/stylable_element.h @@ -1,5 +1,5 @@ /** - * src/class_diagram/model/stylable_element.h + * src/common/model/stylable_element.h * * Copyright (c) 2021-2022 Bartek Kryza * diff --git a/src/config/config.cc b/src/config/config.cc index 022e59e8..ed727822 100644 --- a/src/config/config.cc +++ b/src/config/config.cc @@ -60,22 +60,6 @@ config load(const std::string &config_file) } } -std::string to_string(const diagram_type t) -{ - switch (t) { - case diagram_type::class_diagram: - return "class"; - case diagram_type::sequence_diagram: - return "sequence"; - case diagram_type::package_diagram: - return "package"; - case diagram_type::include_diagram: - return "include"; - default: - assert(false); - } -} - std::string to_string(const hint_t t) { switch (t) { @@ -115,7 +99,10 @@ void inheritable_diagram_options::inherit( relative_to.override(parent.relative_to); } -diagram_type class_diagram::type() const { return diagram_type::class_diagram; } +common::model::diagram_t class_diagram::type() const +{ + return common::model::diagram_t::kClass; +} bool class_diagram::has_class(std::string clazz) { @@ -133,19 +120,19 @@ bool class_diagram::has_class(std::string clazz) return false; } -diagram_type sequence_diagram::type() const +common::model::diagram_t sequence_diagram::type() const { - return diagram_type::sequence_diagram; + return common::model::diagram_t::kSequence; } -diagram_type package_diagram::type() const +common::model::diagram_t package_diagram::type() const { - return diagram_type::package_diagram; + return common::model::diagram_t::kPackage; } -diagram_type include_diagram::type() const +common::model::diagram_t include_diagram::type() const { - return diagram_type::include_diagram; + return common::model::diagram_t::kInclude; } template <> diff --git a/src/config/config.h b/src/config/config.h index 056c870f..6e454eae 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -35,13 +35,6 @@ namespace clanguml { namespace config { -enum class diagram_type { - class_diagram, - sequence_diagram, - package_diagram, - include_diagram -}; - enum class method_arguments { full, abbreviated, none }; struct plantuml { @@ -102,7 +95,6 @@ struct git_config { std::string toplevel; }; -std::string to_string(const diagram_type t); std::string to_string(const hint_t t); struct inheritable_diagram_options { @@ -127,7 +119,7 @@ struct inheritable_diagram_options { struct diagram : public inheritable_diagram_options { virtual ~diagram() = default; - virtual diagram_type type() const = 0; + virtual common::model::diagram_t type() const = 0; std::string name; }; @@ -141,7 +133,7 @@ struct source_location { struct class_diagram : public diagram { virtual ~class_diagram() = default; - diagram_type type() const override; + common::model::diagram_t type() const override; option> classes{"classes"}; option layout{"layout"}; @@ -152,7 +144,7 @@ struct class_diagram : public diagram { struct sequence_diagram : public diagram { virtual ~sequence_diagram() = default; - diagram_type type() const override; + common::model::diagram_t type() const override; option> start_from{"start_from"}; }; @@ -160,7 +152,7 @@ struct sequence_diagram : public diagram { struct package_diagram : public diagram { virtual ~package_diagram() = default; - diagram_type type() const override; + common::model::diagram_t type() const override; option layout{"layout"}; }; @@ -168,7 +160,7 @@ struct package_diagram : public diagram { struct include_diagram : public diagram { virtual ~include_diagram() = default; - diagram_type type() const override; + common::model::diagram_t type() const override; option layout{"layout"}; }; diff --git a/src/include_diagram/model/diagram.cc b/src/include_diagram/model/diagram.cc index a46c50e2..d6a7a17a 100644 --- a/src/include_diagram/model/diagram.cc +++ b/src/include_diagram/model/diagram.cc @@ -95,3 +95,11 @@ std::string diagram::to_alias(const std::string &full_name) const } } + +namespace clanguml::common::model { +template <> +bool check_diagram_type(diagram_t t) +{ + return t == diagram_t::kInclude; +} +} diff --git a/src/include_diagram/model/diagram.h b/src/include_diagram/model/diagram.h index 58ed1581..21d82c1e 100644 --- a/src/include_diagram/model/diagram.h +++ b/src/include_diagram/model/diagram.h @@ -57,3 +57,8 @@ private: files_; }; } + +namespace clanguml::common::model { +template <> +bool check_diagram_type(diagram_t t); +} \ No newline at end of file diff --git a/src/main.cc b/src/main.cc index 547f317c..8ffe930b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -130,8 +130,8 @@ void generate_diagram(const std::string &od, const std::string &name, std::shared_ptr diagram, const cppast::libclang_compilation_database &db, bool verbose) { + using clanguml::common::model::diagram_t; using clanguml::config::class_diagram; - using clanguml::config::diagram_type; using clanguml::config::include_diagram; using clanguml::config::package_diagram; using clanguml::config::sequence_diagram; @@ -140,7 +140,7 @@ void generate_diagram(const std::string &od, const std::string &name, std::ofstream ofs; ofs.open(path, std::ofstream::out | std::ofstream::trunc); - if (diagram->type() == diagram_type::class_diagram) { + if (diagram->type() == diagram_t::kClass) { using diagram_config = class_diagram; using diagram_model = clanguml::class_diagram::model::diagram; using diagram_visitor = @@ -154,7 +154,7 @@ void generate_diagram(const std::string &od, const std::string &name, ofs << clanguml::class_diagram::generators::plantuml::generator( dynamic_cast(*diagram), *model); } - else if (diagram->type() == diagram_type::sequence_diagram) { + else if (diagram->type() == diagram_t::kSequence) { using diagram_config = sequence_diagram; using diagram_model = clanguml::sequence_diagram::model::diagram; using diagram_visitor = @@ -169,7 +169,7 @@ void generate_diagram(const std::string &od, const std::string &name, dynamic_cast(*diagram), *model); } - else if (diagram->type() == diagram_type::package_diagram) { + else if (diagram->type() == diagram_t::kPackage) { using diagram_config = package_diagram; using diagram_model = clanguml::package_diagram::model::diagram; using diagram_visitor = @@ -183,7 +183,7 @@ void generate_diagram(const std::string &od, const std::string &name, ofs << clanguml::package_diagram::generators::plantuml::generator( dynamic_cast(*diagram), *model); } - else if (diagram->type() == diagram_type::include_diagram) { + else if (diagram->type() == diagram_t::kInclude) { using diagram_config = include_diagram; using diagram_model = clanguml::include_diagram::model::diagram; using diagram_visitor = diff --git a/src/package_diagram/generators/plantuml/package_diagram_generator.cc b/src/package_diagram/generators/plantuml/package_diagram_generator.cc index 0074e0f0..b99640c1 100644 --- a/src/package_diagram/generators/plantuml/package_diagram_generator.cc +++ b/src/package_diagram/generators/plantuml/package_diagram_generator.cc @@ -85,7 +85,8 @@ void generator::generate(const package &p, std::ostream &ostr) const } for (const auto &subpackage : p) { - generate(dynamic_cast(*subpackage), ostr); + if (m_model.should_include(dynamic_cast(*subpackage))) + generate(dynamic_cast(*subpackage), ostr); } if (!uns.starts_with(p.full_name(false))) { @@ -102,14 +103,14 @@ void generator::generate(std::ostream &ostr) const generate_plantuml_directives(ostr, m_config.puml().before); for (const auto &p : m_model) { - generate(dynamic_cast(*p), ostr); - ostr << '\n'; + if (m_model.should_include(dynamic_cast(*p))) + generate(dynamic_cast(*p), ostr); } // Process package relationships for (const auto &p : m_model) { - generate_relationships(dynamic_cast(*p), ostr); - ostr << '\n'; + if (m_model.should_include(dynamic_cast(*p))) + generate_relationships(dynamic_cast(*p), ostr); } generate_config_layout_hints(ostr); diff --git a/src/package_diagram/model/diagram.cc b/src/package_diagram/model/diagram.cc index 21d469c9..88d31318 100644 --- a/src/package_diagram/model/diagram.cc +++ b/src/package_diagram/model/diagram.cc @@ -28,6 +28,12 @@ common::model::diagram_t diagram::type() const return common::model::diagram_t::kPackage; } +const std::vector> & +diagram::packages() const +{ + return packages_; +} + void diagram::add_package(std::unique_ptr &&p) { LOG_DBG("Adding package: {}, {}", p->name(), p->full_name(true)); @@ -43,7 +49,8 @@ type_safe::optional_ref diagram::get_package( const std::string &name) const { for (const auto &p : packages_) { - if (p.get().full_name(false) == name) { + auto p_full_name = p.get().full_name(false); + if (p_full_name == name) { return {p}; } } @@ -76,3 +83,11 @@ std::string diagram::to_alias(const std::string &full_name) const return package.value().alias(); } } + +namespace clanguml::common::model { +template <> +bool check_diagram_type(diagram_t t) +{ + return t == diagram_t::kPackage; +} +} \ No newline at end of file diff --git a/src/package_diagram/model/diagram.h b/src/package_diagram/model/diagram.h index 2a32826f..0511141d 100644 --- a/src/package_diagram/model/diagram.h +++ b/src/package_diagram/model/diagram.h @@ -41,6 +41,9 @@ public: common::model::diagram_t type() const override; + const std::vector> & + packages() const; + type_safe::optional_ref get( const std::string &full_name) const; @@ -56,3 +59,8 @@ private: packages_; }; } + +namespace clanguml::common::model { +template <> +bool check_diagram_type(diagram_t t); +} diff --git a/src/sequence_diagram/model/diagram.cc b/src/sequence_diagram/model/diagram.cc index 0a7f1a88..460ce2ea 100644 --- a/src/sequence_diagram/model/diagram.cc +++ b/src/sequence_diagram/model/diagram.cc @@ -40,3 +40,11 @@ std::string diagram::to_alias(const std::string &full_name) const } } + +namespace clanguml::common::model { +template <> +bool check_diagram_type(diagram_t t) +{ + return t == diagram_t::kSequence; +} +} diff --git a/src/sequence_diagram/model/diagram.h b/src/sequence_diagram/model/diagram.h index 97c7f4f1..cf15c3de 100644 --- a/src/sequence_diagram/model/diagram.h +++ b/src/sequence_diagram/model/diagram.h @@ -47,3 +47,9 @@ public: }; } + +namespace clanguml::common::model { +template <> +bool check_diagram_type( + diagram_t t); +} \ No newline at end of file diff --git a/tests/t30008/.clang-uml b/tests/t30008/.clang-uml new file mode 100644 index 00000000..60e4959d --- /dev/null +++ b/tests/t30008/.clang-uml @@ -0,0 +1,17 @@ +compilation_database_dir: .. +output_directory: puml +diagrams: + t30008_package: + type: package + glob: + - ../../tests/t30008/t30008.cc + include: + dependants: + - clanguml::t30008::dependants::A + dependencies: + - clanguml::t30008::dependencies::F + using_namespace: + - clanguml::t30008 + plantuml: + before: + - "' t30008 test package diagram" \ No newline at end of file diff --git a/tests/t30008/t30008.cc b/tests/t30008/t30008.cc new file mode 100644 index 00000000..c7eca1df --- /dev/null +++ b/tests/t30008/t30008.cc @@ -0,0 +1,45 @@ +namespace clanguml { +namespace t30008 { + +namespace dependants { +namespace X { +} +namespace A { +struct AA { +}; +} +namespace B { +struct BB { + A::AA *aa; +}; +} +namespace C { +struct CC { + B::BB *bb; +}; +} + +} // namespace dependants + +namespace dependencies { +namespace Y { +} + +namespace D { +struct DD { +}; +} +namespace E { +struct EE { + D::DD *dd; +}; +} +namespace F { +struct FF { + E::EE *ee; +}; +} +} // namespace dependencies + +} // namespace t30008 +} // namespace clanguml \ No newline at end of file diff --git a/tests/t30008/test_case.h b/tests/t30008/test_case.h new file mode 100644 index 00000000..caace744 --- /dev/null +++ b/tests/t30008/test_case.h @@ -0,0 +1,55 @@ +/** + * tests/t30008/test_case.cc + * + * Copyright (c) 2021-2022 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("t30008", "[test-case][package]") +{ + auto [config, db] = load_config("t30008"); + + auto diagram = config.diagrams["t30008_package"]; + + REQUIRE(diagram->name == "t30008_package"); + + auto model = generate_package_diagram(db, diagram); + + REQUIRE(model->name() == "t30008_package"); + + auto puml = generate_package_puml(diagram, *model); + AliasMatcher _A(puml); + + REQUIRE_THAT(puml, StartsWith("@startuml")); + REQUIRE_THAT(puml, EndsWith("@enduml\n")); + + REQUIRE_THAT(puml, IsPackage("A")); + REQUIRE_THAT(puml, IsPackage("B")); + REQUIRE_THAT(puml, IsPackage("C")); + REQUIRE_THAT(puml, !IsPackage("X")); + + REQUIRE_THAT(puml, IsDependency(_A("B"), _A("A"))); + REQUIRE_THAT(puml, IsDependency(_A("C"), _A("B"))); + + REQUIRE_THAT(puml, IsPackage("D")); + REQUIRE_THAT(puml, IsPackage("E")); + REQUIRE_THAT(puml, IsPackage("F")); + REQUIRE_THAT(puml, !IsPackage("Y")); + + REQUIRE_THAT(puml, IsDependency(_A("E"), _A("D"))); + REQUIRE_THAT(puml, IsDependency(_A("F"), _A("E"))); + + save_puml( + "./" + config.output_directory() + "/" + diagram->name + ".puml", puml); +} diff --git a/tests/test_cases.cc b/tests/test_cases.cc index ad07b853..46ce797b 100644 --- a/tests/test_cases.cc +++ b/tests/test_cases.cc @@ -242,6 +242,7 @@ using namespace clanguml::test::matchers; #include "t30005/test_case.h" #include "t30006/test_case.h" #include "t30007/test_case.h" +#include "t30008/test_case.h" // // Include diagram tests diff --git a/tests/test_cases.yaml b/tests/test_cases.yaml index 81201d17..c4c2b7ae 100644 --- a/tests/test_cases.yaml +++ b/tests/test_cases.yaml @@ -124,7 +124,7 @@ test_cases: title: Specialization class template diagram filter test description: - name: t00043 - title: Dependants and dependencies diagram filter test + title: Dependants and dependencies class diagram filter test description: Sequence diagrams: - name: t20001 @@ -155,6 +155,9 @@ test_cases: - name: t30007 title: Package diagram layout hints test case description: + - name: t30008 + title: Dependants and dependencies package diagram filter test + description: Include diagrams: - name: t40001 title: Basic include graph diagram test case diff --git a/tests/test_config.cc b/tests/test_config.cc index 6fca0f3b..58266156 100644 --- a/tests/test_config.cc +++ b/tests/test_config.cc @@ -28,7 +28,7 @@ TEST_CASE("Test config simple", "[unit-test]") CHECK(cfg.diagrams.size() == 1); auto &diagram = *cfg.diagrams["class_main"]; - CHECK(diagram.type() == clanguml::config::diagram_type::class_diagram); + CHECK(diagram.type() == clanguml::common::model::diagram_t::kClass); CHECK(diagram.glob().size() == 2); CHECK(clanguml::util::contains(diagram.using_namespace(), "clanguml")); CHECK(diagram.generate_method_arguments() == @@ -47,7 +47,7 @@ TEST_CASE("Test config inherited", "[unit-test]") CHECK(cfg.diagrams.size() == 2); auto &def = *cfg.diagrams["class_default"]; - CHECK(def.type() == clanguml::config::diagram_type::class_diagram); + CHECK(def.type() == clanguml::common::model::diagram_t::kClass); CHECK(def.glob().size() == 2); CHECK(def.glob()[0] == "src/**/*.cc"); CHECK(def.glob()[1] == "src/**/*.h"); @@ -56,7 +56,7 @@ TEST_CASE("Test config inherited", "[unit-test]") CHECK(def.generate_links == false); auto &cus = *cfg.diagrams["class_custom"]; - CHECK(cus.type() == clanguml::config::diagram_type::class_diagram); + CHECK(cus.type() == clanguml::common::model::diagram_t::kClass); CHECK(cus.glob().size() == 1); CHECK(cus.glob()[0] == "src/main.cc"); CHECK(cus.using_namespace().starts_with({"clanguml::ns1"})); @@ -71,7 +71,7 @@ TEST_CASE("Test config includes", "[unit-test]") CHECK(cfg.diagrams.size() == 2); auto &def = *cfg.diagrams["class_1"]; - CHECK(def.type() == clanguml::config::diagram_type::class_diagram); + CHECK(def.type() == clanguml::common::model::diagram_t::kClass); CHECK(def.glob().size() == 2); CHECK(def.glob()[0] == "src/**/*.cc"); CHECK(def.glob()[1] == "src/**/*.h"); @@ -80,7 +80,7 @@ TEST_CASE("Test config includes", "[unit-test]") clanguml::config::method_arguments::none); auto &cus = *cfg.diagrams["class_2"]; - CHECK(cus.type() == clanguml::config::diagram_type::class_diagram); + CHECK(cus.type() == clanguml::common::model::diagram_t::kClass); CHECK(cus.glob().size() == 1); CHECK(cus.glob()[0] == "src/main.cc"); CHECK(cus.using_namespace().starts_with({"clanguml::ns1"})); @@ -99,7 +99,7 @@ TEST_CASE("Test config layout", "[unit-test]") *cfg.diagrams["class_main"]); auto check_layout = [](const auto &diagram, - const clanguml::config::diagram_type type) { + const clanguml::common::model::diagram_t type) { CHECK(diagram.type() == type); CHECK(diagram.layout().at("ABCD").size() == 2); @@ -123,9 +123,9 @@ TEST_CASE("Test config layout", "[unit-test]") check_layout(static_cast( *cfg.diagrams["class_main"]), - clanguml::config::diagram_type::class_diagram); + clanguml::common::model::diagram_t::kClass); check_layout(static_cast( *cfg.diagrams["package_main"]), - clanguml::config::diagram_type::package_diagram); + clanguml::common::model::diagram_t::kPackage); } \ No newline at end of file