Skip to content

Commit

Permalink
Refactored diagram_filter initialization to a factory (#289)
Browse files Browse the repository at this point in the history
  • Loading branch information
bkryza committed Jun 24, 2024
1 parent c0f5d5f commit 19bb8ae
Show file tree
Hide file tree
Showing 12 changed files with 397 additions and 289 deletions.
2 changes: 1 addition & 1 deletion src/class_diagram/model/diagram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#include "diagram.h"

#include "common/model/diagram_filter.h"
#include "common/model/filters/diagram_filter.h"
#include "util/error.h"
#include "util/util.h"

Expand Down
4 changes: 2 additions & 2 deletions src/common/generators/generators.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "class_diagram/generators/plantuml/class_diagram_generator.h"
#include "cli/cli_handler.h"
#include "common/compilation_database.h"
#include "common/model/diagram_filter.h"
#include "common/model/filters/diagram_filter_factory.h"
#include "config/config.h"
#include "include_diagram/generators/json/include_diagram_generator.h"
#include "include_diagram/generators/mermaid/include_diagram_generator.h"
Expand Down Expand Up @@ -369,7 +369,7 @@ std::unique_ptr<DiagramModel> generate(const common::compilation_database &db,
auto diagram = std::make_unique<DiagramModel>();
diagram->set_name(name);
diagram->set_filter(
std::make_unique<model::diagram_filter>(*diagram, config));
model::diagram_filter_factory::create(*diagram, config));

LOG_DBG("Found translation units for diagram {}: {}", name,
fmt::join(translation_units, ", "));
Expand Down
2 changes: 1 addition & 1 deletion src/common/generators/json/generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#pragma once

#include "common/generators/generator.h"
#include "common/model/diagram_filter.h"
#include "common/model/filters/diagram_filter.h"
#include "config/config.h"
#include "util/error.h"
#include "util/util.h"
Expand Down
2 changes: 1 addition & 1 deletion src/common/generators/mermaid/generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#pragma once

#include "common/generators/generator.h"
#include "common/model/diagram_filter.h"
#include "common/model/filters/diagram_filter.h"
#include "config/config.h"
#include "util/error.h"
#include "util/util.h"
Expand Down
2 changes: 1 addition & 1 deletion src/common/generators/plantuml/generator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
#pragma once

#include "common/generators/generator.h"
#include "common/model/diagram_filter.h"
#include "common/model/filters/diagram_filter.h"
#include "common/model/relationship.h"
#include "config/config.h"
#include "util/error.h"
Expand Down
2 changes: 1 addition & 1 deletion src/common/model/diagram.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

#include "diagram.h"

#include "diagram_filter.h"
#include "filters/diagram_filter.h"
#include "namespace.h"

namespace clanguml::common::model {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -972,11 +972,10 @@ tvl::value_t class_member_filter::match(
return access_filter_->match(d, m.access());
}

diagram_filter::diagram_filter(
const common::model::diagram &d, const config::diagram &c)
diagram_filter::diagram_filter(const common::model::diagram &d,
const config::diagram &c, private_constructor_tag_t /*unused*/)
: diagram_{d}
{
init_filters(c);
}

void diagram_filter::add_inclusive_filter(std::unique_ptr<filter_visitor> fv)
Expand All @@ -1003,254 +1002,6 @@ bool diagram_filter::should_include(
return false;
}

void diagram_filter::init_filters(const config::diagram &c)
{
using specializations_filter_t =
edge_traversal_filter<class_diagram::model::diagram,
class_diagram::model::class_, common::string_or_regex>;

using class_dependants_filter_t =
edge_traversal_filter<class_diagram::model::diagram,
class_diagram::model::class_, common::string_or_regex>;
using class_dependencies_filter_t =
edge_traversal_filter<class_diagram::model::diagram,
class_diagram::model::class_, common::string_or_regex>;

using package_dependants_filter_t =
edge_traversal_filter<package_diagram::model::diagram,
common::model::package, common::string_or_regex>;
using package_dependencies_filter_t =
edge_traversal_filter<package_diagram::model::diagram,
common::model::package, common::string_or_regex>;

using source_file_dependency_filter_t =
edge_traversal_filter<include_diagram::model::diagram,
common::model::source_file, std::string,
common::model::source_file>;

// Process inclusive filters
if (c.include) {
add_inclusive_filter(std::make_unique<namespace_filter>(
filter_t::kInclusive, c.include().namespaces));

add_inclusive_filter(std::make_unique<modules_filter>(
filter_t::kInclusive, c.include().modules));

add_inclusive_filter(std::make_unique<module_access_filter>(
filter_t::kInclusive, c.include().module_access));

add_inclusive_filter(std::make_unique<relationship_filter>(
filter_t::kInclusive, c.include().relationships));

add_inclusive_filter(std::make_unique<access_filter>(
filter_t::kInclusive, c.include().access));

add_inclusive_filter(std::make_unique<paths_filter>(
filter_t::kInclusive, c.root_directory(), c.include().paths));

add_inclusive_filter(
std::make_unique<class_method_filter>(filter_t::kInclusive,
std::make_unique<access_filter>(
filter_t::kInclusive, c.include().access),
std::make_unique<method_type_filter>(
filter_t::kInclusive, c.include().method_types)));

add_inclusive_filter(
std::make_unique<class_member_filter>(filter_t::kInclusive,
std::make_unique<access_filter>(
filter_t::kInclusive, c.include().access)));

// Include any of these matches even if one them does not match
std::vector<std::unique_ptr<filter_visitor>> element_filters;

element_filters.emplace_back(std::make_unique<element_filter>(
filter_t::kInclusive, c.include().elements));

element_filters.emplace_back(std::make_unique<element_type_filter>(
filter_t::kInclusive, c.include().element_types));

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<parents_filter>(
filter_t::kInclusive, c.include().parents));

element_filters.emplace_back(
std::make_unique<specializations_filter_t>(filter_t::kInclusive,
relationship_t::kInstantiation,
c.include().specializations));

element_filters.emplace_back(
std::make_unique<class_dependants_filter_t>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependants));

element_filters.emplace_back(
std::make_unique<class_dependencies_filter_t>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependencies, true));
}
else if (c.type() == diagram_t::kSequence) {
element_filters.emplace_back(std::make_unique<callee_filter>(
filter_t::kInclusive, c.include().callee_types));
}
else if (c.type() == diagram_t::kPackage) {
element_filters.emplace_back(
std::make_unique<package_dependants_filter_t>(
filter_t::kInclusive, relationship_t::kDependency,
c.include().dependants));

element_filters.emplace_back(
std::make_unique<package_dependencies_filter_t>(
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) {
if (auto p = path.get<std::string>(); p.has_value()) {
const std::filesystem::path dep_path{*p};
dependants.emplace_back(
dep_path.lexically_normal().string());
}
}

for (auto &&path : c.include().dependencies) {
if (auto p = path.get<std::string>(); p.has_value()) {
const std::filesystem::path dep_path{*p};
dependencies.emplace_back(
dep_path.lexically_normal().string());
}
}

element_filters.emplace_back(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kInclusive, relationship_t::kAssociation,
dependants, false));

element_filters.emplace_back(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kInclusive, relationship_t::kAssociation,
dependencies, true));
}

element_filters.emplace_back(std::make_unique<context_filter>(
filter_t::kInclusive, c.include().context));

add_inclusive_filter(std::make_unique<anyof_filter>(
filter_t::kInclusive, std::move(element_filters)));
}

// Process exclusive filters
if (c.exclude) {
add_exclusive_filter(std::make_unique<namespace_filter>(
filter_t::kExclusive, c.exclude().namespaces));

add_exclusive_filter(std::make_unique<modules_filter>(
filter_t::kExclusive, c.exclude().modules));

add_exclusive_filter(std::make_unique<module_access_filter>(
filter_t::kExclusive, c.exclude().module_access));

add_exclusive_filter(std::make_unique<paths_filter>(
filter_t::kExclusive, c.root_directory(), c.exclude().paths));

add_exclusive_filter(std::make_unique<element_filter>(
filter_t::kExclusive, c.exclude().elements));

add_exclusive_filter(std::make_unique<element_type_filter>(
filter_t::kExclusive, c.exclude().element_types));

add_exclusive_filter(std::make_unique<relationship_filter>(
filter_t::kExclusive, c.exclude().relationships));

add_exclusive_filter(std::make_unique<access_filter>(
filter_t::kExclusive, c.exclude().access));

add_exclusive_filter(
std::make_unique<class_method_filter>(filter_t::kExclusive,
std::make_unique<access_filter>(
filter_t::kExclusive, c.exclude().access),
std::make_unique<method_type_filter>(
filter_t::kExclusive, c.exclude().method_types)));

add_exclusive_filter(
std::make_unique<class_member_filter>(filter_t::kExclusive,
std::make_unique<access_filter>(
filter_t::kExclusive, c.exclude().access)));

add_exclusive_filter(std::make_unique<subclass_filter>(
filter_t::kExclusive, c.exclude().subclasses));

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));

if (c.type() == diagram_t::kClass) {
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_dependencies_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependencies, true));
}
else if (c.type() == diagram_t::kSequence) {
add_exclusive_filter(std::make_unique<callee_filter>(
filter_t::kExclusive, c.exclude().callee_types));
}
else if (c.type() == diagram_t::kPackage) {
add_exclusive_filter(
std::make_unique<package_dependencies_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependencies, true));

add_exclusive_filter(std::make_unique<package_dependants_filter_t>(
filter_t::kExclusive, relationship_t::kDependency,
c.exclude().dependants));
}
else if (c.type() == diagram_t::kInclude) {
std::vector<std::string> dependants;
std::vector<std::string> dependencies;

for (auto &&path : c.exclude().dependants) {
if (auto p = path.get<std::string>(); p.has_value()) {
std::filesystem::path dep_path{*p};
dependants.emplace_back(
dep_path.lexically_normal().string());
}
}

for (auto &&path : c.exclude().dependencies) {
if (auto p = path.get<std::string>(); p.has_value()) {
std::filesystem::path dep_path{*p};
dependencies.emplace_back(
dep_path.lexically_normal().string());
}
}

add_exclusive_filter(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kExclusive, relationship_t::kAssociation,
dependants, false));

add_exclusive_filter(
std::make_unique<source_file_dependency_filter_t>(
filter_t::kExclusive, relationship_t::kAssociation,
dependencies, true));
}

add_exclusive_filter(std::make_unique<context_filter>(
filter_t::kExclusive, c.exclude().context));
}
}

template <>
bool diagram_filter::should_include<std::string>(const std::string &name) const
{
Expand Down
Loading

0 comments on commit 19bb8ae

Please sign in to comment.