diff --git a/src/class_diagram/model/class_element.h b/src/class_diagram/model/class_element.h index ec7c50eb..d2aea1b0 100644 --- a/src/class_diagram/model/class_element.h +++ b/src/class_diagram/model/class_element.h @@ -49,7 +49,7 @@ public: * * @return Elements name. */ - std::string name() const; + std::string name() const override; /** * @brief Set elements name. diff --git a/src/class_diagram/model/diagram.cc b/src/class_diagram/model/diagram.cc index 64c53dc6..ad7c607c 100644 --- a/src/class_diagram/model/diagram.cc +++ b/src/class_diagram/model/diagram.cc @@ -159,7 +159,7 @@ bool diagram::has_element( std::string diagram::to_alias( clanguml::common::model::diagram_element::id_t id) const { - LOG_DBG("Looking for alias for {}", id); + LOG_TRACE("Looking for alias for {}", id); for (const auto &c : classes()) { if (c.get().id() == id) { diff --git a/src/class_diagram/model/method_parameter.h b/src/class_diagram/model/method_parameter.h index f6db2529..547f1b6d 100644 --- a/src/class_diagram/model/method_parameter.h +++ b/src/class_diagram/model/method_parameter.h @@ -70,7 +70,7 @@ public: * * @return Parameters name. */ - std::string name() const; + std::string name() const override; /** * @brief Set parameters default value. diff --git a/src/common/model/decorated_element.cc b/src/common/model/decorated_element.cc index 39951b90..dcdcafc4 100644 --- a/src/common/model/decorated_element.cc +++ b/src/common/model/decorated_element.cc @@ -20,6 +20,11 @@ namespace clanguml::common::model { +std::string to_string(const decorated_element &e) +{ + return e.full_name(false); +} + bool decorated_element::skip() const { return std::any_of( diff --git a/src/common/model/decorated_element.h b/src/common/model/decorated_element.h index 57409872..16d85ecc 100644 --- a/src/common/model/decorated_element.h +++ b/src/common/model/decorated_element.h @@ -49,6 +49,18 @@ class decorated_element { public: virtual ~decorated_element() = default; + virtual std::string name() const { return ""; } + + /** + * @brief Return the elements fully qualified name. + * + * This method should be implemented in each subclass, and ensure that + * for instance it includes fully qualified namespace, template params, etc. + * + * @return Full elements name. + */ + virtual std::string full_name(bool /*relative*/) const { return name(); } + /** * Whether this element should be skipped from the diagram. * @@ -139,4 +151,6 @@ private: std::optional comment_; }; +std::string to_string(const decorated_element &e); + } // namespace clanguml::common::model diff --git a/src/common/model/diagram.cc b/src/common/model/diagram.cc index 22f8e290..0aed9c23 100644 --- a/src/common/model/diagram.cc +++ b/src/common/model/diagram.cc @@ -67,7 +67,7 @@ bool diagram::should_include(const element &e) const return true; return filter_->should_include(e) && - filter_->should_include(dynamic_cast(e)); + filter_->should_include(dynamic_cast(e)); } bool diagram::should_include(const namespace_ &ns) const diff --git a/src/common/model/diagram_element.h b/src/common/model/diagram_element.h index 179b6f0d..312dbe93 100644 --- a/src/common/model/diagram_element.h +++ b/src/common/model/diagram_element.h @@ -99,7 +99,7 @@ public: * * @return Diagram's name. */ - std::string name() const { return name_; } + std::string name() const override { return name_; } /** * Return the type name of the diagram. @@ -108,16 +108,6 @@ public: */ virtual std::string type_name() const { return "__undefined__"; }; - /** - * @brief Return the elements fully qualified name. - * - * This method should be implemented in each subclass, and ensure that - * for instance it includes fully qualified namespace, template params, etc. - * - * @return Full elements name. - */ - virtual std::string full_name(bool /*relative*/) const { return name(); } - /** * Return all relationships outgoing from this element. * diff --git a/src/common/model/diagram_filter.cc b/src/common/model/diagram_filter.cc index 49b3ac0f..6ce43a92 100644 --- a/src/common/model/diagram_filter.cc +++ b/src/common/model/diagram_filter.cc @@ -29,6 +29,15 @@ namespace clanguml::common::model { +std::string to_string(const filter_t t) { + switch(t) { + case filter_t::kInclusive: + return "inclusive"; + case filter_t::kExclusive: + return "exclusive"; + } +} + namespace detail { template <> @@ -124,7 +133,7 @@ tvl::value_t filter_visitor::match( } tvl::value_t filter_visitor::match( - const diagram & /*d*/, const common::model::source_location & /*f*/) const + const diagram & /*d*/, const common::model::diagram_element & /*f*/) const { return {}; } @@ -170,7 +179,8 @@ tvl::value_t anyof_filter::match( const diagram &d, const common::model::element &e) const { return tvl::any_of(filters_.begin(), filters_.end(), - [&d, &e](const auto &f) { return f->match(d, e); }); + [&d, &e](const auto &f) { + return f->match(d, e); }); } tvl::value_t anyof_filter::match( @@ -248,6 +258,7 @@ tvl::value_t namespace_filter::match(const diagram &d, const element &e) const e.full_name(false); }); + return result; } @@ -321,6 +332,8 @@ tvl::value_t modules_filter::match( return std::get(modit.value()) %= e.module().value(); }); + log_match(e, result); + return result; } @@ -337,11 +350,14 @@ tvl::value_t element_filter::match(const diagram &d, const element &e) const if (d.type() == diagram_t::kClass && e.type_name() == "package") return std::nullopt; - return tvl::any_of( + auto result = tvl::any_of( elements_.begin(), elements_.end(), [&e](const auto &el) { return ((el == e.full_name(false)) || (el == fmt::format("::{}", e.full_name(false)))); }); + + log_match(e, result); + return result; } element_type_filter::element_type_filter( @@ -370,7 +386,8 @@ method_type_filter::method_type_filter( tvl::value_t method_type_filter::match( const diagram & /*d*/, const class_diagram::model::class_method &m) const { - return tvl::any_of( + + const auto result = tvl::any_of( method_types_.begin(), method_types_.end(), [&m](auto mt) { switch (mt) { case config::method_type::constructor: @@ -391,6 +408,9 @@ tvl::value_t method_type_filter::match( return false; }); + + log_match(m, result); + return result; } callee_filter::callee_filter( @@ -451,6 +471,7 @@ tvl::value_t callee_filter::match( return false; }); + log_match(p, res); return res; } @@ -496,8 +517,10 @@ tvl::value_t subclass_filter::match(const diagram &d, const element &e) const for (const auto &root : roots_) { for (const auto &parent : parents) { auto full_name = parent.get().full_name(false); - if (root == full_name) + if (root == full_name) { + log_match(e, true); return true; + } } } @@ -589,13 +612,16 @@ tvl::value_t module_access_filter::match( if (access_.empty()) return {}; - return tvl::any_of( + auto result = tvl::any_of( access_.begin(), access_.end(), [&e](const auto &access) { if (access == module_access_t::kPublic) return !e.module_private(); - else - return e.module_private(); + + return e.module_private(); }); + + log_match(e, result); + return result; } context_filter::context_filter( @@ -756,8 +782,10 @@ tvl::value_t context_filter::match(const diagram &d, const element &e) const return {}; for (const auto &ec : effective_contexts_) { - if (ec.count(e.id()) > 0) + if (ec.count(e.id()) > 0) { + log_match(e, true); return true; + } } return false; @@ -827,6 +855,8 @@ tvl::value_t paths_filter::match( if (pp.root_name().string() == path.root_name().string() && util::starts_with(pp.relative_path(), path.relative_path())) { + log_match(p, true); + return true; } } @@ -835,7 +865,7 @@ tvl::value_t paths_filter::match( } tvl::value_t paths_filter::match( - const diagram & /*d*/, const common::model::source_location &p) const + const diagram & /*d*/, const common::model::diagram_element &p) const { if (paths_.empty()) { return {}; @@ -853,6 +883,7 @@ tvl::value_t paths_filter::match( if (sl_path.root_name().string() == path.root_name().string() && util::starts_with(sl_path.relative_path(), path.relative_path())) { + log_match(p, true); return true; } } @@ -874,6 +905,7 @@ tvl::value_t class_method_filter::match( tvl::value_t res = tvl::or_( access_filter_->match(d, m.access()), method_type_filter_->match(d, m)); + log_match(m, res); return res; } @@ -887,7 +919,9 @@ class_member_filter::class_member_filter( tvl::value_t class_member_filter::match( const diagram &d, const class_diagram::model::class_member &m) const { - return access_filter_->match(d, m.access()); + auto res = access_filter_->match(d, m.access()); + log_match(m, res); + return res; } diagram_filter::diagram_filter( @@ -996,18 +1030,18 @@ void diagram_filter::init_filters(const config::diagram &c) element_filters.emplace_back( std::make_unique(filter_t::kInclusive, - relationship_t::kInstantiation, - c.include().specializations)); + relationship_t::kInstantiation, c.include().specializations, + "specializations")); element_filters.emplace_back( std::make_unique( filter_t::kInclusive, relationship_t::kDependency, - c.include().dependants)); + c.include().dependants, "dependants")); element_filters.emplace_back( std::make_unique( filter_t::kInclusive, relationship_t::kDependency, - c.include().dependencies, true)); + c.include().dependencies, "dependencies", true)); } else if (c.type() == diagram_t::kSequence) { element_filters.emplace_back(std::make_unique( @@ -1017,12 +1051,12 @@ void diagram_filter::init_filters(const config::diagram &c) element_filters.emplace_back( std::make_unique( filter_t::kInclusive, relationship_t::kDependency, - c.include().dependants)); + c.include().dependants, "dependants")); element_filters.emplace_back( std::make_unique( filter_t::kInclusive, relationship_t::kDependency, - c.include().dependencies, true)); + c.include().dependencies, "dependencies", true)); } else if (c.type() == diagram_t::kInclude) { std::vector dependants; @@ -1047,12 +1081,12 @@ void diagram_filter::init_filters(const config::diagram &c) element_filters.emplace_back( std::make_unique( filter_t::kInclusive, relationship_t::kAssociation, - dependants)); + dependants, "dependants")); element_filters.emplace_back( std::make_unique( filter_t::kInclusive, relationship_t::kAssociation, - dependencies, true)); + dependencies, "dependencies", true)); } element_filters.emplace_back(std::make_unique( @@ -1106,25 +1140,21 @@ void diagram_filter::init_filters(const config::diagram &c) add_exclusive_filter(std::make_unique( filter_t::kExclusive, c.exclude().parents)); - 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::kInstantiation, + c.exclude().specializations, "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, "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, "dependencies", true)); add_exclusive_filter(std::make_unique( filter_t::kExclusive, relationship_t::kDependency, - c.exclude().dependencies, true)); + c.exclude().dependencies, "dependencies", true)); if (c.type() == diagram_t::kSequence) { add_exclusive_filter(std::make_unique( @@ -1161,12 +1191,13 @@ void diagram_filter::init_filters(const config::diagram &c) add_exclusive_filter(std::make_unique< edge_traversal_filter>(filter_t::kExclusive, - relationship_t::kAssociation, dependencies, true)); + relationship_t::kAssociation, dependencies, "dependencies", + true)); add_exclusive_filter(std::make_unique< edge_traversal_filter>(filter_t::kExclusive, - relationship_t::kAssociation, dependants)); + relationship_t::kAssociation, dependants, "dependants")); } add_exclusive_filter(std::make_unique( diff --git a/src/common/model/diagram_filter.h b/src/common/model/diagram_filter.h index 416411c6..ceeb7e24 100644 --- a/src/common/model/diagram_filter.h +++ b/src/common/model/diagram_filter.h @@ -47,6 +47,8 @@ enum class filter_t { kExclusive /*!< Filter is exclusve */ }; +std::string to_string(filter_t t); + namespace detail { template const clanguml::common::reference_vector &view(const DiagramT &d); @@ -81,6 +83,8 @@ public: virtual ~filter_visitor() = default; + virtual std::string_view name() const = 0; + virtual tvl::value_t match( const diagram &d, const common::model::element &e) const; @@ -97,7 +101,7 @@ public: const diagram &d, const common::model::source_file &f) const; virtual tvl::value_t match( - const diagram &d, const common::model::source_location &f) const; + const diagram &d, const common::model::diagram_element &f) const; virtual tvl::value_t match( const diagram &d, const class_diagram::model::class_method &m) const; @@ -113,6 +117,15 @@ public: filter_t type() const; +protected: + template void log_match(const T& e, tvl::value_t result) const + { + if (tvl::is_true(result)) { + LOG_DBG("Filter '{}:{}' matched '{}'", this->name(), to_string(this->type()), + to_string(e)); + } + } + private: filter_t type_; }; @@ -123,6 +136,11 @@ struct anyof_filter : public filter_visitor { ~anyof_filter() override = default; + std::string_view name() const override + { + return "anyof()"; + } + tvl::value_t match( const diagram &d, const common::model::element &e) const override; @@ -146,6 +164,8 @@ struct namespace_filter : public filter_visitor { ~namespace_filter() override = default; + std::string_view name() const override { return "namespace"; } + tvl::value_t match(const diagram &d, const namespace_ &ns) const override; tvl::value_t match(const diagram &d, const element &e) const override; @@ -163,6 +183,8 @@ struct modules_filter : public filter_visitor { ~modules_filter() override = default; + std::string_view name() const override { return "modules"; } + tvl::value_t match(const diagram &d, const element &e) const override; private: @@ -178,6 +200,8 @@ struct element_filter : public filter_visitor { ~element_filter() override = default; + std::string_view name() const override { return "element"; } + tvl::value_t match(const diagram &d, const element &e) const override; private: @@ -192,6 +216,8 @@ struct element_type_filter : public filter_visitor { ~element_type_filter() override = default; + std::string_view name() const override { return "element_type"; } + tvl::value_t match(const diagram &d, const element &e) const override; private: @@ -207,6 +233,8 @@ struct method_type_filter : public filter_visitor { ~method_type_filter() override = default; + std::string_view name() const override { return "method_type"; } + tvl::value_t match(const diagram &d, const class_diagram::model::class_method &e) const override; @@ -222,6 +250,8 @@ struct callee_filter : public filter_visitor { ~callee_filter() override = default; + std::string_view name() const override { return "callee"; } + tvl::value_t match(const diagram &d, const sequence_diagram::model::participant &p) const override; @@ -238,6 +268,8 @@ struct subclass_filter : public filter_visitor { ~subclass_filter() override = default; + std::string_view name() const override { return "subclass"; } + tvl::value_t match(const diagram &d, const element &e) const override; private: @@ -253,6 +285,8 @@ struct parents_filter : public filter_visitor { ~parents_filter() override = default; + std::string_view name() const override { return "parents"; } + tvl::value_t match(const diagram &d, const element &e) const override; private: @@ -278,16 +312,20 @@ template struct edge_traversal_filter : public filter_visitor { edge_traversal_filter(filter_t type, relationship_t relationship, - std::vector roots, bool forward = false) + std::vector roots, const std::string &name, + bool forward = false) : filter_visitor{type} , roots_{std::move(roots)} , relationship_{relationship} , forward_{forward} + , name_{name} { } ~edge_traversal_filter() override = default; + std::string_view name() const override { return name_; } + tvl::value_t match(const diagram &d, const MatchOverrideT &e) const override { // This filter should only be run only on diagram models after the @@ -425,6 +463,7 @@ private: mutable bool initialized_{false}; mutable clanguml::common::reference_set matching_elements_; bool forward_; + std::string name_; }; /** @@ -436,6 +475,8 @@ struct relationship_filter : public filter_visitor { ~relationship_filter() override = default; + std::string_view name() const override { return "relationship"; } + tvl::value_t match( const diagram &d, const relationship_t &r) const override; @@ -451,6 +492,8 @@ struct access_filter : public filter_visitor { ~access_filter() override = default; + std::string_view name() const override { return "access"; } + tvl::value_t match(const diagram &d, const access_t &a) const override; private: @@ -465,6 +508,8 @@ struct module_access_filter : public filter_visitor { ~module_access_filter() override = default; + std::string_view name() const override { return "module_access"; } + tvl::value_t match(const diagram &d, const element &a) const override; private: @@ -480,6 +525,8 @@ struct context_filter : public filter_visitor { ~context_filter() override = default; + std::string_view name() const override { return "context"; } + tvl::value_t match(const diagram &d, const element &r) const override; private: @@ -553,11 +600,13 @@ struct paths_filter : public filter_visitor { ~paths_filter() override = default; + std::string_view name() const override { return "paths"; } + tvl::value_t match( const diagram &d, const common::model::source_file &r) const override; tvl::value_t match(const diagram &d, - const common::model::source_location &sl) const override; + const common::model::diagram_element &sl) const override; private: std::vector paths_; @@ -573,6 +622,8 @@ struct class_method_filter : public filter_visitor { ~class_method_filter() override = default; + std::string_view name() const override { return "class_method"; } + tvl::value_t match(const diagram &d, const class_diagram::model::class_method &m) const override; @@ -589,6 +640,8 @@ struct class_member_filter : public filter_visitor { ~class_member_filter() override = default; + std::string_view name() const override { return "class_member"; } + tvl::value_t match(const diagram &d, const class_diagram::model::class_member &m) const override; @@ -641,14 +694,31 @@ public: */ template bool should_include(const T &e) const { - auto exc = tvl::any_of(exclusive_.begin(), exclusive_.end(), - [this, &e](const auto &ex) { return ex->match(diagram_, e); }); + auto exc = tvl::any_of( + exclusive_.begin(), exclusive_.end(), [this, &e](const auto &ex) { + const auto res = ex->match(diagram_, e); + + if (tvl::is_true(res)) { + LOG_DBG("'{}' rejected by exclusive filter '{}'", + to_string(e), ex->name()); + } + + return res; + }); if (tvl::is_true(exc)) return false; - auto inc = tvl::all_of(inclusive_.begin(), inclusive_.end(), - [this, &e](const auto &in) { return in->match(diagram_, e); }); + auto inc = tvl::all_of( + inclusive_.begin(), inclusive_.end(), [this, &e](const auto &in) { + const auto res = in->match(diagram_, e); + + if (tvl::is_false(res)) + LOG_DBG("'{}' rejected by inclusive filter '{}'", + to_string(e), in->name()); + + return res; + }); return static_cast(tvl::is_undefined(inc) || tvl::is_true(inc)); } diff --git a/src/common/model/element.h b/src/common/model/element.h index 2d94d393..38849d13 100644 --- a/src/common/model/element.h +++ b/src/common/model/element.h @@ -39,8 +39,6 @@ class element : public diagram_element { public: element(namespace_ using_namespace, path_type pt = path_type::kNamespace); - element(path_type pt); - ~element() override = default; /** diff --git a/src/common/model/path.cc b/src/common/model/path.cc new file mode 100644 index 00000000..9a16e033 --- /dev/null +++ b/src/common/model/path.cc @@ -0,0 +1,25 @@ +/** + * @file src/common/model/path.cc + * + * Copyright (c) 2021-2023 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. + */ + +#include "path.h" + +namespace clanguml::common::model { + +std::string to_string(const path &p) { return p.to_string(); } + +} // namespace clanguml::common::model \ No newline at end of file diff --git a/src/common/model/path.h b/src/common/model/path.h index 3cb030eb..491f2f81 100644 --- a/src/common/model/path.h +++ b/src/common/model/path.h @@ -166,6 +166,8 @@ public: return fmt::format("{}", fmt::join(path_, std::string{separator()})); } + std::string full_name(bool /*relative*/) const { return to_string(); } + /** * Whether the path is empty. * @@ -393,4 +395,6 @@ private: container_type path_; }; +std::string to_string(const path&p); + } // namespace clanguml::common::model \ No newline at end of file diff --git a/src/common/model/source_location.cc b/src/common/model/source_location.cc index 89358a08..47009f80 100644 --- a/src/common/model/source_location.cc +++ b/src/common/model/source_location.cc @@ -17,3 +17,9 @@ */ #include "source_location.h" + +namespace clanguml::common::model { +//std::string to_string(const source_location& sl) { +// sl.to +//} +} \ No newline at end of file diff --git a/src/common/model/source_location.h b/src/common/model/source_location.h index 2dc98af4..faee5107 100644 --- a/src/common/model/source_location.h +++ b/src/common/model/source_location.h @@ -17,6 +17,8 @@ */ #pragma once +#include + #include #include @@ -137,4 +139,7 @@ private: unsigned int column_{0}; unsigned int hash_{0}; }; + +//std::string to_string(const source_location& sl); + } // namespace clanguml::common::model \ No newline at end of file diff --git a/src/include_diagram/model/diagram.cc b/src/include_diagram/model/diagram.cc index d21a9f56..0cbacf6a 100644 --- a/src/include_diagram/model/diagram.cc +++ b/src/include_diagram/model/diagram.cc @@ -91,7 +91,7 @@ void diagram::add_file(std::unique_ptr &&f) std::string diagram::to_alias(const std::string &full_name) const { - LOG_DBG("Looking for alias for {}", full_name); + LOG_TRACE("Looking for alias for {}", full_name); auto path = common::model::filesystem_path{full_name}; diff --git a/src/package_diagram/model/diagram.cc b/src/package_diagram/model/diagram.cc index f6e2d45c..22bc7344 100644 --- a/src/package_diagram/model/diagram.cc +++ b/src/package_diagram/model/diagram.cc @@ -49,7 +49,7 @@ common::optional_ref diagram::get( std::string diagram::to_alias( const clanguml::common::model::diagram_element::id_t id) const { - LOG_DBG("Looking for alias for {}", id); + LOG_TRACE("Looking for alias for {}", id); auto p = find(id); if (p.has_value() && p.value().id() == id) diff --git a/src/sequence_diagram/model/diagram.cc b/src/sequence_diagram/model/diagram.cc index 26215680..88b84e06 100644 --- a/src/sequence_diagram/model/diagram.cc +++ b/src/sequence_diagram/model/diagram.cc @@ -190,7 +190,7 @@ bool diagram::should_include( { return filter().should_include(p) && filter().should_include( - dynamic_cast(p)); + dynamic_cast(p)); } std::vector diagram::list_from_values() const