Fixed dependants and dependencies include diagram handling

This commit is contained in:
Bartek Kryza
2022-04-23 16:31:01 +02:00
parent d7781794ec
commit cc22494c79
14 changed files with 295 additions and 97 deletions

View File

@@ -20,6 +20,7 @@
#include "class_diagram/model/class.h"
#include "common/model/package.h"
#include "include_diagram/model/diagram.h"
#include "package_diagram/model/diagram.h"
namespace clanguml::common::model {
@@ -47,6 +48,13 @@ const std::vector<type_safe::object_ref<const common::model::package>> &view(
return d.packages();
}
template <>
const std::vector<type_safe::object_ref<const common::model::source_file>> &
view(const include_diagram::model::diagram &d)
{
return d.files();
}
template <>
const type_safe::optional_ref<const class_diagram::model::class_> get(
const class_diagram::model::diagram &d, const std::string &full_name)
@@ -61,8 +69,15 @@ const type_safe::optional_ref<const common::model::package> get(
return d.get_package(full_name);
}
template <>
const type_safe::optional_ref<const common::model::source_file> get(
const include_diagram::model::diagram &d, const std::string &full_name)
{
return d.get_file(full_name);
}
} // namespace detail
filter_visitor::filter_visitor(filter_t type)
: type_{type}
{
@@ -124,6 +139,13 @@ tvl::value_t anyof_filter::match(
[&d, &e](const auto &f) { return f->match(d, e); });
}
tvl::value_t anyof_filter::match(
const diagram &d, const common::model::source_file &e) const
{
return tvl::any_of(filters_.begin(), filters_.end(),
[&d, &e](const auto &f) { return f->match(d, e); });
}
namespace_filter::namespace_filter(
filter_t type, std::vector<namespace_> namespaces)
: filter_visitor{type}
@@ -389,33 +411,72 @@ void diagram_filter::init_filters(const config::diagram &c)
element_filters.emplace_back(std::make_unique<element_filter>(
filter_t::kInclusive, c.include().elements));
element_filters.emplace_back(std::make_unique<subclass_filter>(
filter_t::kInclusive, c.include().subclasses));
if (c.type() == diagram_t::kClass) {
element_filters.emplace_back(std::make_unique<subclass_filter>(
filter_t::kInclusive, c.include().subclasses));
element_filters.emplace_back(
std::make_unique<tree_element_filter<class_diagram::model::diagram,
class_diagram::model::class_>>(filter_t::kInclusive,
element_filters.emplace_back(std::make_unique<
tree_element_filter<class_diagram::model::diagram,
class_diagram::model::class_>>(filter_t::kInclusive,
relationship_t::kInstantiation, c.include().specializations));
element_filters.emplace_back(
std::make_unique<tree_element_filter<class_diagram::model::diagram,
class_diagram::model::class_>>(filter_t::kInclusive,
element_filters.emplace_back(std::make_unique<
tree_element_filter<class_diagram::model::diagram,
class_diagram::model::class_>>(filter_t::kInclusive,
relationship_t::kDependency, c.include().dependants));
element_filters.emplace_back(std::make_unique<tree_element_filter<
package_diagram::model::diagram, common::model::package>>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependants));
element_filters.emplace_back(
std::make_unique<tree_element_filter<class_diagram::model::diagram,
class_diagram::model::class_>>(filter_t::kInclusive,
element_filters.emplace_back(std::make_unique<
tree_element_filter<class_diagram::model::diagram,
class_diagram::model::class_>>(filter_t::kInclusive,
relationship_t::kDependency, c.include().dependencies, true));
}
else if (c.type() == diagram_t::kPackage) {
element_filters.emplace_back(std::make_unique<tree_element_filter<
package_diagram::model::diagram, common::model::package>>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependants));
element_filters.emplace_back(std::make_unique<tree_element_filter<
package_diagram::model::diagram, common::model::package>>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependencies, true));
element_filters.emplace_back(std::make_unique<tree_element_filter<
package_diagram::model::diagram, common::model::package>>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependencies, true));
}
else if (c.type() == diagram_t::kInclude) {
std::vector<std::string> dependants;
std::vector<std::string> dependencies;
for (auto &&path : c.include().dependants) {
std::filesystem::path dep_path{path};
if (dep_path.is_relative()) {
dep_path = c.base_directory() / path;
dep_path = relative(dep_path, c.relative_to());
}
dependants.emplace_back(dep_path.lexically_normal().string());
}
for (auto &&path : c.include().dependencies) {
std::filesystem::path dep_path{path};
if (dep_path.is_relative()) {
dep_path = c.base_directory() / path;
dep_path = relative(dep_path, c.relative_to());
}
dependencies.emplace_back(dep_path.lexically_normal().string());
}
element_filters.emplace_back(std::make_unique<
tree_element_filter<include_diagram::model::diagram,
common::model::source_file, common::model::source_file>>(
filter_t::kInclusive, relationship_t::kAssociation,
dependants));
element_filters.emplace_back(std::make_unique<
tree_element_filter<include_diagram::model::diagram,
common::model::source_file, common::model::source_file>>(
filter_t::kInclusive, relationship_t::kAssociation,
dependencies, true));
}
element_filters.emplace_back(std::make_unique<context_filter>(
filter_t::kInclusive, c.include().context));
@@ -469,6 +530,41 @@ void diagram_filter::init_filters(const config::diagram &c)
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependencies, true));
if (c.type() == diagram_t::kInclude) {
std::vector<std::string> dependants;
std::vector<std::string> dependencies;
for (auto &&path : c.exclude().dependants) {
std::filesystem::path dep_path{path};
if (dep_path.is_relative()) {
dep_path = c.base_directory() / path;
dep_path = relative(dep_path, c.relative_to());
}
dependants.emplace_back(dep_path.lexically_normal().string());
}
for (auto &&path : c.exclude().dependencies) {
std::filesystem::path dep_path{path};
if (dep_path.is_relative()) {
dep_path = c.base_directory() / path;
dep_path = relative(dep_path, c.relative_to());
}
dependencies.emplace_back(dep_path.lexically_normal().string());
}
add_exclusive_filter(std::make_unique<
tree_element_filter<include_diagram::model::diagram,
common::model::source_file>>(filter_t::kExclusive,
relationship_t::kAssociation, dependencies, true));
add_exclusive_filter(std::make_unique<
tree_element_filter<include_diagram::model::diagram,
common::model::source_file>>(filter_t::kExclusive,
relationship_t::kAssociation, dependants));
}
add_exclusive_filter(std::make_unique<context_filter>(
filter_t::kExclusive, c.exclude().context));
}

View File

@@ -25,6 +25,7 @@
#include "config/config.h"
#include "cx/util.h"
#include "diagram.h"
#include "include_diagram/model/diagram.h"
#include "source_file.h"
#include "tvl.h"
@@ -79,6 +80,9 @@ struct anyof_filter : public filter_visitor {
tvl::value_t match(
const diagram &d, const common::model::element &e) const override;
tvl::value_t match(
const diagram &d, const common::model::source_file &e) const override;
private:
std::vector<std::unique_ptr<filter_visitor>> filters_;
};
@@ -112,7 +116,8 @@ private:
std::vector<std::string> roots_;
};
template <typename DiagramT, typename ElementT>
template <typename DiagramT, typename ElementT,
typename MatchOverrideT = common::model::element>
struct tree_element_filter : public filter_visitor {
tree_element_filter(filter_t type, relationship_t relationship,
std::vector<std::string> roots, bool forward = false)
@@ -123,7 +128,7 @@ struct tree_element_filter : public filter_visitor {
{
}
tvl::value_t match(const diagram &d, const element &e) const override
tvl::value_t match(const diagram &d, const MatchOverrideT &e) const override
{
// This filter should only be run on the completely generated diagram
// model by visitor
@@ -168,41 +173,92 @@ private:
matching_elements_.emplace(template_ref.value());
}
auto match_tree_rel = [&, this](const auto &from, const auto &to) {
bool added_new_element{false};
assert(!matching_elements_.empty());
for (const auto &from_el : from) {
// Check if any of its relationships of type relationship_
// points to an element already in the matching_elements_
// set
for (const auto &rel : from_el->relationships()) {
if (rel.type() == relationship_) {
for (const auto &to_el : to) {
if (rel.destination() == to_el->full_name(false)) {
const auto &to_add = forward_ ? to_el : from_el;
if (matching_elements_.insert(to_add).second)
added_new_element = true;
if constexpr (std::is_same_v<ElementT, common::model::source_file>) {
auto match_tree_rel = [&, this](const auto &from, const auto &to) {
bool added_new_element{false};
for (const auto &from_el : from) {
// Check if any of its relationships of type relationship_
// points to an element already in the matching_elements_
// set
for (const auto &rel : from_el->relationships()) {
if (rel.type() == relationship_) {
for (const auto &to_el : to) {
auto dest = rel.destination();
auto alias = to_el->alias();
if (dest == alias) {
const auto &to_add =
forward_ ? to_el : from_el;
if (matching_elements_.insert(to_add)
.second)
added_new_element = true;
}
}
}
}
}
}
return added_new_element;
};
return added_new_element;
};
bool keep_looking{true};
while (keep_looking) {
keep_looking = false;
if (forward_) {
if (match_tree_rel(
matching_elements_, detail::view<ElementT>(cd)))
keep_looking = true;
bool keep_looking{true};
while (keep_looking) {
keep_looking = false;
if (forward_) {
if (match_tree_rel(
matching_elements_, detail::view<ElementT>(cd)))
keep_looking = true;
}
else {
if (match_tree_rel(
detail::view<ElementT>(cd), matching_elements_))
keep_looking = true;
}
}
else {
if (match_tree_rel(
detail::view<ElementT>(cd), matching_elements_))
keep_looking = true;
}
else {
auto match_tree_rel = [&, this](const auto &from, const auto &to) {
bool added_new_element{false};
for (const auto &from_el : from) {
// Check if any of its relationships of type relationship_
// points to an element already in the matching_elements_
// set
for (const auto &rel : from_el->relationships()) {
if (rel.type() == relationship_) {
for (const auto &to_el : to) {
auto dest = rel.destination();
auto to_el_fn = to_el->full_name(false);
if (dest == to_el_fn) {
const auto &to_add =
forward_ ? to_el : from_el;
if (matching_elements_.insert(to_add)
.second)
added_new_element = true;
}
}
}
}
}
return added_new_element;
};
bool keep_looking{true};
while (keep_looking) {
keep_looking = false;
if (forward_) {
if (match_tree_rel(
matching_elements_, detail::view<ElementT>(cd)))
keep_looking = true;
}
else {
if (match_tree_rel(
detail::view<ElementT>(cd), matching_elements_))
keep_looking = true;
}
}
}

View File

@@ -129,4 +129,15 @@ template <> struct hash<clanguml::common::model::filesystem_path> {
}
};
template <>
struct hash<type_safe::object_ref<const clanguml::common::model::source_file>> {
std::size_t operator()(
const type_safe::object_ref<const clanguml::common::model::source_file>
&key) const
{
using clanguml::common::model::source_file;
return std::hash<std::string>{}(key.get().full_name(false));
}
};
}