diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc index 4be9dc29..92c11606 100644 --- a/src/common/model/diagram_filter.cc +++ b/src/common/model/diagram_filter.cc @@ -381,6 +381,11 @@ 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().dependencies, true)); + element_filters.emplace_back(std::make_unique( filter_t::kInclusive, c.include().context)); @@ -410,6 +415,10 @@ void diagram_filter::init_filters(const config::diagram &c) 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, c.exclude().context)); } diff --git a/src/common/model/diagram_filter.h b/src/common/model/diagram_filter.h index 9751dd2a..94c13042 100644 --- a/src/common/model/diagram_filter.h +++ b/src/common/model/diagram_filter.h @@ -115,10 +115,11 @@ private: template struct tree_element_filter : public filter_visitor { tree_element_filter(filter_t type, relationship_t relationship, - std::vector roots) + std::vector roots, bool forward = false) : filter_visitor{type} , relationship_{relationship} , roots_{roots} + , forward_{forward} { } @@ -187,17 +188,40 @@ private: } }; - while (found_new_template) { - found_new_template = false; - // For each element of type ElementT in the diagram - for (const auto &el : detail::view(cd)) { - // Check if any of its relationships of type relationship_ - // points to an element already in the matching_elements_ set - for (const auto &rel : el->relationships()) { - reverse_relationship_match(rel, el); + if (!forward_) + while (found_new_template) { + found_new_template = false; + // For each element of type ElementT in the diagram + for (const auto &el : detail::view(cd)) { + // Check if any of its relationships of type relationship_ + // points to an element already in the matching_elements_ + // set + for (const auto &rel : el->relationships()) { + reverse_relationship_match(rel, el); + } } } - } + else + while (found_new_template) { + found_new_template = false; + // For each of the already matched elements + for (const auto &already_matching : matching_elements_) + // Check if any of its relationships of type relationship_ + // points to an element already in the matching_elements_ + // set + for (const auto &rel : already_matching->relationships()) { + if (rel.type() == relationship_) { + for (const auto &el : detail::view(cd)) { + if (rel.destination() == el->full_name(false)) { + auto inserted = + matching_elements_.insert(el); + if (inserted.second) + found_new_template = true; + } + } + } + } + } initialized_ = true; } @@ -207,6 +231,7 @@ private: mutable bool initialized_{false}; mutable std::unordered_set> matching_elements_; + bool forward_; }; struct relationship_filter : public filter_visitor { diff --git a/src/config/config.cc b/src/config/config.cc index a4ee2ed8..022e59e8 100644 --- a/src/config/config.cc +++ b/src/config/config.cc @@ -415,6 +415,10 @@ template <> struct convert { if (node["dependants"]) rhs.dependants = node["dependants"].as(); + if (node["dependencies"]) + rhs.dependencies = + node["dependencies"].as(); + if (node["context"]) rhs.context = node["context"].as(); diff --git a/src/config/config.h b/src/config/config.h index 09e4b155..056c870f 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -74,6 +74,8 @@ struct filter { std::vector dependants; + std::vector dependencies; + std::vector context; std::vector paths; diff --git a/tests/t00043/.clang-uml b/tests/t00043/.clang-uml index f45e5fbc..404fc413 100644 --- a/tests/t00043/.clang-uml +++ b/tests/t00043/.clang-uml @@ -11,5 +11,7 @@ diagrams: include: dependants: - clanguml::t00043::dependants::A + dependencies: + - clanguml::t00043::dependencies::J relationships: - dependency \ No newline at end of file diff --git a/tests/t00043/t00043.cc b/tests/t00043/t00043.cc index 15be26a6..a0a2a04d 100644 --- a/tests/t00043/t00043.cc +++ b/tests/t00043/t00043.cc @@ -29,4 +29,30 @@ struct F { }; } // namespace dependants +namespace dependencies { + +struct G { +}; + +struct GG { +}; + +struct H { + void h(G *g) { } + void hh(GG *gg) { } +}; + +struct HH { + void hh(G *g) { } +}; + +struct I { + void i(H *h) { } +}; + +struct J { + void i(I *i) { } +}; + +} // namespace dependencies } // namespace clanguml::t00043 diff --git a/tests/t00043/test_case.h b/tests/t00043/test_case.h index 484039b2..8ccca644 100644 --- a/tests/t00043/test_case.h +++ b/tests/t00043/test_case.h @@ -35,6 +35,7 @@ TEST_CASE("t00043", "[test-case][class]") REQUIRE_THAT(puml, StartsWith("@startuml")); REQUIRE_THAT(puml, EndsWith("@enduml\n")); + // Check dependants filter REQUIRE_THAT(puml, IsClass(_A("A"))); REQUIRE_THAT(puml, IsClass(_A("B"))); REQUIRE_THAT(puml, IsClass(_A("BB"))); @@ -48,6 +49,19 @@ TEST_CASE("t00043", "[test-case][class]") REQUIRE_THAT(puml, IsDependency(_A("D"), _A("C"))); REQUIRE_THAT(puml, IsDependency(_A("E"), _A("D"))); + // Check dependencies filter + REQUIRE_THAT(puml, IsClass(_A("G"))); + REQUIRE_THAT(puml, IsClass(_A("GG"))); + REQUIRE_THAT(puml, IsClass(_A("H"))); + REQUIRE_THAT(puml, !IsClass(_A("HH"))); + REQUIRE_THAT(puml, IsClass(_A("I"))); + REQUIRE_THAT(puml, IsClass(_A("J"))); + + REQUIRE_THAT(puml, IsDependency(_A("H"), _A("G"))); + REQUIRE_THAT(puml, IsDependency(_A("H"), _A("GG"))); + REQUIRE_THAT(puml, IsDependency(_A("I"), _A("H"))); + REQUIRE_THAT(puml, IsDependency(_A("J"), _A("I"))); + save_puml( "./" + config.output_directory() + "/" + diagram->name + ".puml", puml); }