Compare commits

...

1 Commits

Author SHA1 Message Date
Bartek Kryza
db857d2913 WIP 2023-12-23 16:55:29 +01:00
17 changed files with 210 additions and 62 deletions

View File

@@ -49,7 +49,7 @@ public:
*
* @return Elements name.
*/
std::string name() const;
std::string name() const override;
/**
* @brief Set elements name.

View File

@@ -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) {

View File

@@ -70,7 +70,7 @@ public:
*
* @return Parameters name.
*/
std::string name() const;
std::string name() const override;
/**
* @brief Set parameters default value.

View File

@@ -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(

View File

@@ -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_t> comment_;
};
std::string to_string(const decorated_element &e);
} // namespace clanguml::common::model

View File

@@ -67,7 +67,7 @@ bool diagram::should_include(const element &e) const
return true;
return filter_->should_include(e) &&
filter_->should_include(dynamic_cast<const source_location &>(e));
filter_->should_include(dynamic_cast<const diagram_element &>(e));
}
bool diagram::should_include(const namespace_ &ns) const

View File

@@ -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.
*

View File

@@ -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<common::regex>(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<specializations_filter_t>(filter_t::kInclusive,
relationship_t::kInstantiation,
c.include().specializations));
relationship_t::kInstantiation, c.include().specializations,
"specializations"));
element_filters.emplace_back(
std::make_unique<class_dependants_filter_t>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependants));
c.include().dependants, "dependants"));
element_filters.emplace_back(
std::make_unique<class_dependencies_filter_t>(
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<callee_filter>(
@@ -1017,12 +1051,12 @@ void diagram_filter::init_filters(const config::diagram &c)
element_filters.emplace_back(
std::make_unique<package_dependants_filter_t>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependants));
c.include().dependants, "dependants"));
element_filters.emplace_back(
std::make_unique<package_dependencies_filter_t>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependencies, true));
c.include().dependencies, "dependencies", true));
}
else if (c.type() == diagram_t::kInclude) {
std::vector<std::string> dependants;
@@ -1047,12 +1081,12 @@ void diagram_filter::init_filters(const config::diagram &c)
element_filters.emplace_back(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kInclusive, relationship_t::kAssociation,
dependants));
dependants, "dependants"));
element_filters.emplace_back(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kInclusive, relationship_t::kAssociation,
dependencies, true));
dependencies, "dependencies", true));
}
element_filters.emplace_back(std::make_unique<context_filter>(
@@ -1106,25 +1140,21 @@ void diagram_filter::init_filters(const config::diagram &c)
add_exclusive_filter(std::make_unique<parents_filter>(
filter_t::kExclusive, c.exclude().parents));
add_exclusive_filter(
std::make_unique<specializations_filter_t>(filter_t::kExclusive,
relationship_t::kInstantiation, c.exclude().specializations));
add_exclusive_filter(std::make_unique<specializations_filter_t>(
filter_t::kExclusive, relationship_t::kInstantiation,
c.exclude().specializations, "specializations"));
add_exclusive_filter(
std::make_unique<class_dependants_filter_t>(filter_t::kExclusive,
relationship_t::kDependency, c.exclude().dependants));
add_exclusive_filter(std::make_unique<class_dependants_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependants, "dependants"));
add_exclusive_filter(
std::make_unique<package_dependants_filter_t>(filter_t::kExclusive,
relationship_t::kDependency, c.exclude().dependants));
add_exclusive_filter(
std::make_unique<class_dependencies_filter_t>(filter_t::kExclusive,
relationship_t::kDependency, c.exclude().dependencies, true));
add_exclusive_filter(std::make_unique<class_dependencies_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependencies, "dependencies", true));
add_exclusive_filter(std::make_unique<package_dependencies_filter_t>(
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<callee_filter>(
@@ -1161,12 +1191,13 @@ void diagram_filter::init_filters(const config::diagram &c)
add_exclusive_filter(std::make_unique<
edge_traversal_filter<include_diagram::model::diagram,
common::model::source_file>>(filter_t::kExclusive,
relationship_t::kAssociation, dependencies, true));
relationship_t::kAssociation, dependencies, "dependencies",
true));
add_exclusive_filter(std::make_unique<
edge_traversal_filter<include_diagram::model::diagram,
common::model::source_file>>(filter_t::kExclusive,
relationship_t::kAssociation, dependants));
relationship_t::kAssociation, dependants, "dependants"));
}
add_exclusive_filter(std::make_unique<context_filter>(

View File

@@ -47,6 +47,8 @@ enum class filter_t {
kExclusive /*!< Filter is exclusve */
};
std::string to_string(filter_t t);
namespace detail {
template <typename ElementT, typename DiagramT>
const clanguml::common::reference_vector<ElementT> &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<typename T> 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 <typename DiagramT, typename ElementT,
typename MatchOverrideT = common::model::element>
struct edge_traversal_filter : public filter_visitor {
edge_traversal_filter(filter_t type, relationship_t relationship,
std::vector<ConfigEntryT> roots, bool forward = false)
std::vector<ConfigEntryT> 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<ElementT> 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<std::filesystem::path> 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 <typename T> 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<bool>(tvl::is_undefined(inc) || tvl::is_true(inc));
}

View File

@@ -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;
/**

25
src/common/model/path.cc Normal file
View File

@@ -0,0 +1,25 @@
/**
* @file src/common/model/path.cc
*
* Copyright (c) 2021-2023 Bartek Kryza <bkryza@gmail.com>
*
* 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

View File

@@ -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

View File

@@ -17,3 +17,9 @@
*/
#include "source_location.h"
namespace clanguml::common::model {
//std::string to_string(const source_location& sl) {
// sl.to
//}
}

View File

@@ -17,6 +17,8 @@
*/
#pragma once
#include <spdlog/fmt/fmt.h>
#include <string>
#include <utility>
@@ -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

View File

@@ -91,7 +91,7 @@ void diagram::add_file(std::unique_ptr<common::model::source_file> &&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};

View File

@@ -49,7 +49,7 @@ common::optional_ref<clanguml::common::model::diagram_element> 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<package>(id);
if (p.has_value() && p.value().id() == id)

View File

@@ -190,7 +190,7 @@ bool diagram::should_include(
{
return filter().should_include(p) &&
filter().should_include(
dynamic_cast<const common::model::source_location &>(p));
dynamic_cast<const common::model::diagram_element &>(p));
}
std::vector<std::string> diagram::list_from_values() const