From 92422624cb53fd5aa9d26f7386dfb4e5d12db77c Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Tue, 10 Oct 2023 22:28:58 +0200 Subject: [PATCH] Skip dependencies between parent and child packages in package diagrams (Fixes #186) --- src/common/model/diagram_element.cc | 10 +++++ src/common/model/diagram_element.h | 15 ++++++++ src/common/model/diagram_filter.cc | 11 ------ src/common/model/nested_trait.h | 4 +- .../plantuml/package_diagram_generator.cc | 5 ++- .../visitor/translation_unit_visitor.cc | 38 ++++++++++++++++++- .../visitor/translation_unit_visitor.h | 3 ++ 7 files changed, 70 insertions(+), 16 deletions(-) diff --git a/src/common/model/diagram_element.cc b/src/common/model/diagram_element.cc index e810c37d..429dc2f2 100644 --- a/src/common/model/diagram_element.cc +++ b/src/common/model/diagram_element.cc @@ -30,6 +30,16 @@ diagram_element::id_t diagram_element::id() const { return id_; } void diagram_element::set_id(diagram_element::id_t id) { id_ = id; } +std::optional diagram_element::parent_element_id() const +{ + return parent_element_id_; +} + +void diagram_element::set_parent_element_id(diagram_element::id_t id) +{ + parent_element_id_ = id; +} + std::string diagram_element::alias() const { assert(id_ >= 0); diff --git a/src/common/model/diagram_element.h b/src/common/model/diagram_element.h index c8c7b89e..179b6f0d 100644 --- a/src/common/model/diagram_element.h +++ b/src/common/model/diagram_element.h @@ -64,6 +64,20 @@ public: */ void set_id(id_t id); + /** + * Get elements parent package id. + * + * @return Parent package id if element is nested. + */ + std::optional parent_element_id() const; + + /** + * Set elements parent package id. + * + * @param id Id of parent package. + */ + void set_parent_element_id(diagram_element::id_t id); + /** * @brief Return elements' diagram alias. * @@ -174,6 +188,7 @@ public: private: id_t id_{0}; + std::optional parent_element_id_{0}; std::string name_; std::vector relationships_; bool nested_{false}; diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc index 560a427a..ac6ddf4b 100644 --- a/src/common/model/diagram_filter.cc +++ b/src/common/model/diagram_filter.cc @@ -248,10 +248,6 @@ tvl::value_t namespace_filter::match(const diagram &d, const element &e) const e.full_name(false); }); - if (tvl::is_false(result)) - LOG_DBG("Element {} rejected by namespace_filter 1", - e.full_name(false)); - return result; } @@ -273,10 +269,6 @@ tvl::value_t namespace_filter::match(const diagram &d, const element &e) const e.full_name(false); }); - if (tvl::is_false(result)) - LOG_DBG("Element {} rejected by namespace_filter (package diagram)", - e.full_name(false)); - return result; } @@ -290,9 +282,6 @@ tvl::value_t namespace_filter::match(const diagram &d, const element &e) const return std::get(nsit.value()) %= e.full_name(false); }); - if (tvl::is_false(result)) - LOG_DBG("Element {} rejected by namespace_filter", e.full_name(false)); - return result; } diff --git a/src/common/model/nested_trait.h b/src/common/model/nested_trait.h index 55f143b9..a7050da3 100644 --- a/src/common/model/nested_trait.h +++ b/src/common/model/nested_trait.h @@ -94,9 +94,11 @@ public: auto parent = get_element(path); - if (parent && dynamic_cast *>(&parent.value())) + if (parent && dynamic_cast *>(&parent.value())) { + p->set_parent_element_id(parent.value().id()); return dynamic_cast &>(parent.value()) .template add_element(std::move(p)); + } LOG_INFO("No parent element found at: {}", path.to_string()); diff --git a/src/package_diagram/generators/plantuml/package_diagram_generator.cc b/src/package_diagram/generators/plantuml/package_diagram_generator.cc index fd6ec167..b8d3c3d1 100644 --- a/src/package_diagram/generators/plantuml/package_diagram_generator.cc +++ b/src/package_diagram/generators/plantuml/package_diagram_generator.cc @@ -62,8 +62,9 @@ void generator::generate_relationships( // Process it's subpackages relationships for (const auto &subpackage : p) { - generate_relationships( - dynamic_cast(*subpackage), ostr); + if (model().should_include(dynamic_cast(*subpackage))) + generate_relationships( + dynamic_cast(*subpackage), ostr); } } diff --git a/src/package_diagram/visitor/translation_unit_visitor.cc b/src/package_diagram/visitor/translation_unit_visitor.cc index 964c826f..edabb3d8 100644 --- a/src/package_diagram/visitor/translation_unit_visitor.cc +++ b/src/package_diagram/visitor/translation_unit_visitor.cc @@ -76,12 +76,12 @@ bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns) p->set_name(name); p->set_namespace(package_parent); p->set_id(common::to_id(*ns)); + set_source_location(*ns, *p); assert(p->id() > 0); if (diagram().should_include(*p) && !diagram().get(p->id())) { process_comment(*ns, *p); - set_source_location(*ns, *p); p->set_style(p->style_spec()); @@ -232,8 +232,10 @@ void translation_unit_visitor::add_relationships( pkg->set_name(pkg_name); pkg->set_id(get_package_id(cls)); + set_source_location(*cls, *pkg); - diagram().add(parent_path, std::move(pkg)); + if (diagram().should_include(*pkg)) + diagram().add(parent_path, std::move(pkg)); } auto current_package_id = get_package_id(cls); @@ -246,8 +248,21 @@ void translation_unit_visitor::add_relationships( auto current_package = diagram().get(current_package_id); if (current_package) { + std::vector parent_ids = + get_parent_package_ids(current_package_id); + for (const auto &dependency : relationships) { const auto destination_id = std::get<0>(dependency); + + // Skip dependency relationships to parent packages + if (util::contains(parent_ids, destination_id)) + continue; + + // Skip dependency relationship to child packages + if (util::contains( + get_parent_package_ids(destination_id), current_package_id)) + continue; + relationship r{relationship_t::kDependency, destination_id, common::model::access_t::kNone}; if (destination_id != current_package_id) @@ -605,4 +620,23 @@ translation_unit_visitor::config() const void translation_unit_visitor::finalize() { } +std::vector +translation_unit_visitor::get_parent_package_ids( + common::model::diagram_element::id_t id) +{ + std::vector parent_ids; + std::optional parent_id = id; + + while (parent_id.has_value()) { + parent_ids.push_back(parent_id.value()); + auto parent = this->diagram().get(parent_id.value()); + if (parent) + parent_id = parent.value().parent_element_id(); + else + break; + } + + return parent_ids; +} + } // namespace clanguml::package_diagram::visitor diff --git a/src/package_diagram/visitor/translation_unit_visitor.h b/src/package_diagram/visitor/translation_unit_visitor.h index e44eced5..239ae924 100644 --- a/src/package_diagram/visitor/translation_unit_visitor.h +++ b/src/package_diagram/visitor/translation_unit_visitor.h @@ -214,6 +214,9 @@ private: void add_relationships( clang::Decl *cls, found_relationships_t &relationships); + std::vector get_parent_package_ids( + common::model::diagram_element::id_t id); + // Reference to the output diagram model clanguml::package_diagram::model::diagram &diagram_;