Refactored include and exclude filters
This commit is contained in:
@@ -110,7 +110,7 @@ void generator::generate(
|
||||
// Process methods
|
||||
//
|
||||
for (const auto &m : c.methods()) {
|
||||
if (!m_config.should_include(m.scope()))
|
||||
if (!m_model.should_include(m.scope()))
|
||||
continue;
|
||||
|
||||
if (m.is_pure_virtual())
|
||||
@@ -168,8 +168,7 @@ void generator::generate(
|
||||
std::stringstream all_relations_str;
|
||||
std::set<std::string> unique_relations;
|
||||
for (const auto &r : c.relationships()) {
|
||||
if (!m_config.should_include_relationship(
|
||||
common::model::to_string(r.type())))
|
||||
if (!m_model.should_include(r.type()))
|
||||
continue;
|
||||
|
||||
LOG_DBG("== Processing relationship {}",
|
||||
@@ -223,7 +222,7 @@ void generator::generate(
|
||||
// Process members
|
||||
//
|
||||
for (const auto &m : c.members()) {
|
||||
if (!m_config.should_include(m.scope()))
|
||||
if (!m_model.should_include(m.scope()))
|
||||
continue;
|
||||
|
||||
if (!m_config.include_relations_also_as_members() &&
|
||||
@@ -245,7 +244,7 @@ void generator::generate(
|
||||
|
||||
ostr << "}" << '\n';
|
||||
|
||||
if (m_config.should_include_relationship("inheritance")) {
|
||||
if (m_model.should_include(relationship_t::kExtension)) {
|
||||
for (const auto &b : c.parents()) {
|
||||
std::stringstream relstr;
|
||||
try {
|
||||
@@ -288,8 +287,7 @@ void generator::generate(
|
||||
ostr << "}" << '\n';
|
||||
|
||||
for (const auto &r : e.relationships()) {
|
||||
if (!m_config.should_include_relationship(
|
||||
common::model::to_string(r.type())))
|
||||
if (!m_model.should_include(r.type()))
|
||||
continue;
|
||||
|
||||
std::string destination;
|
||||
|
||||
@@ -184,6 +184,11 @@ clanguml::class_diagram::model::diagram &translation_unit_context::diagram()
|
||||
return diagram_;
|
||||
}
|
||||
|
||||
clanguml::class_diagram::model::diagram &translation_unit_context::diagram() const
|
||||
{
|
||||
return diagram_;
|
||||
}
|
||||
|
||||
void translation_unit_context::set_current_package(
|
||||
type_safe::optional_ref<common::model::package> p)
|
||||
{
|
||||
|
||||
@@ -74,6 +74,8 @@ public:
|
||||
|
||||
clanguml::class_diagram::model::diagram &diagram();
|
||||
|
||||
clanguml::class_diagram::model::diagram &diagram() const;
|
||||
|
||||
void set_current_package(type_safe::optional_ref<common::model::package> p);
|
||||
|
||||
type_safe::optional_ref<common::model::package> get_current_package() const;
|
||||
|
||||
@@ -146,7 +146,7 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.config().should_include(
|
||||
if (ctx.diagram().should_include(
|
||||
ctx.get_namespace(), cls.name()))
|
||||
process_class_declaration(cls);
|
||||
}
|
||||
@@ -157,7 +157,7 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
|
||||
|
||||
auto &enm = static_cast<const cppast::cpp_enum &>(e);
|
||||
|
||||
if (ctx.config().should_include(
|
||||
if (ctx.diagram().should_include(
|
||||
ctx.get_namespace(), enm.name()))
|
||||
process_enum_declaration(enm);
|
||||
}
|
||||
@@ -214,7 +214,7 @@ void translation_unit_visitor::process_type_alias_template(
|
||||
cx::util::full_name(ctx.get_namespace(), at),
|
||||
type_safe::ref(at.type_alias().underlying_type()));
|
||||
|
||||
if (ctx.config().should_include(tinst->get_namespace() | tinst->name()))
|
||||
if (ctx.diagram().should_include(tinst->get_namespace(), tinst->name()))
|
||||
ctx.diagram().add_class(std::move(tinst));
|
||||
}
|
||||
}
|
||||
@@ -241,7 +241,7 @@ void translation_unit_visitor::process_namespace(
|
||||
|
||||
auto usn = ctx.config().using_namespace();
|
||||
|
||||
if (ctx.config().should_include_package(package_path)) {
|
||||
if (ctx.diagram().should_include(package_path)) {
|
||||
auto p = std::make_unique<common::model::package>(usn);
|
||||
package_path = package_path.relative_to(usn);
|
||||
|
||||
@@ -397,7 +397,8 @@ void translation_unit_visitor::process_class_declaration(
|
||||
fmt::ptr(reinterpret_cast<const void *>(&cls)));
|
||||
|
||||
assert(c_ptr);
|
||||
if (ctx.config().should_include(c.full_name(false)))
|
||||
|
||||
if (ctx.diagram().should_include(c))
|
||||
ctx.diagram().add_class(std::move(c_ptr));
|
||||
}
|
||||
|
||||
@@ -729,7 +730,7 @@ bool translation_unit_visitor::process_field_with_template_instantiation(
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx.config().should_include(tinst.get_namespace(), tinst.name())) {
|
||||
if (ctx.diagram().should_include(tinst.get_namespace(), tinst.name())) {
|
||||
LOG_DBG("Adding field instantiation relationship {} {} {} : {}",
|
||||
rr.destination(), clanguml::common::model::to_string(rr.type()),
|
||||
c.full_name(), rr.label());
|
||||
@@ -1100,7 +1101,8 @@ void translation_unit_visitor::process_function_parameter(
|
||||
relationship_t::kDependency);
|
||||
|
||||
for (const auto &[type, relationship_type] : relationships) {
|
||||
if (ctx.config().should_include(cx::util::split_ns(type)) &&
|
||||
auto [type_ns, type_name] = cx::util::split_ns(type);
|
||||
if (ctx.diagram().should_include(type_ns, type_name) &&
|
||||
(relationship_type != relationship_t::kNone) &&
|
||||
(type != c.name_and_ns())) {
|
||||
relationship r{relationship_t::kDependency, type};
|
||||
@@ -1165,7 +1167,7 @@ void translation_unit_visitor::
|
||||
// arguments string
|
||||
}
|
||||
|
||||
if (!ctx.config().should_include(ctx.get_namespace(),
|
||||
if (!ctx.diagram().should_include(ctx.get_namespace(),
|
||||
template_instantiation_type.primary_template()
|
||||
.get(ctx.entity_index())[0]
|
||||
.get()
|
||||
@@ -1202,7 +1204,7 @@ void translation_unit_visitor::
|
||||
|
||||
c.add_relationship(std::move(rr));
|
||||
|
||||
if (ctx.config().should_include(c.full_name(false)))
|
||||
if (ctx.diagram().should_include(c))
|
||||
ctx.diagram().add_class(std::move(tinst_ptr));
|
||||
}
|
||||
}
|
||||
@@ -1249,7 +1251,7 @@ void translation_unit_visitor::process_friend(
|
||||
if (f.type()) {
|
||||
const auto [name_with_ns, name] =
|
||||
cx::util::split_ns(cppast::to_string(f.type().value()));
|
||||
if (!ctx.config().should_include(name_with_ns, name))
|
||||
if (!ctx.diagram().should_include(name_with_ns, name))
|
||||
return;
|
||||
|
||||
LOG_DBG("Type friend declaration {}", name);
|
||||
@@ -1288,7 +1290,7 @@ void translation_unit_visitor::process_friend(
|
||||
name = cx::util::full_name(ctx.get_namespace(), f.entity().value());
|
||||
}
|
||||
|
||||
if (!ctx.config().should_include(ctx.get_namespace(), name))
|
||||
if (!ctx.diagram().should_include(ctx.get_namespace(), name))
|
||||
return;
|
||||
|
||||
r.set_destination(name);
|
||||
@@ -1398,7 +1400,7 @@ bool translation_unit_visitor::find_relationships_in_template_instantiation(
|
||||
LOG_DBG("Failed to process template argument of std::vector at: {}",
|
||||
fn);
|
||||
}
|
||||
else if (ctx.config().should_include(ns, name)) {
|
||||
else if (ctx.diagram().should_include(ns, name)) {
|
||||
LOG_DBG("User defined template instantiation: {} | {}",
|
||||
cppast::to_string(t_), cppast::to_string(t_.canonical()));
|
||||
|
||||
@@ -1509,7 +1511,7 @@ bool translation_unit_visitor::find_relationships_in_unexposed_template_params(
|
||||
type_with_namespace = common::model::namespace_{ct.type()};
|
||||
}
|
||||
|
||||
if (ctx.config().should_include(type_with_namespace.value())) {
|
||||
if (ctx.diagram().should_include(type_with_namespace.value().to_string())) {
|
||||
relationships.emplace_back(type_with_namespace.value().to_string(),
|
||||
relationship_t::kDependency);
|
||||
found = true;
|
||||
@@ -1704,7 +1706,7 @@ void translation_unit_visitor::
|
||||
|
||||
auto nested_tinst =
|
||||
build_template_instantiation(nested_template_parameter,
|
||||
ctx.config().should_include(tinst_ns, tinst_name)
|
||||
ctx.diagram().should_include(tinst_ns, tinst_name)
|
||||
? std::make_optional(&tinst)
|
||||
: parent);
|
||||
|
||||
@@ -1713,11 +1715,11 @@ void translation_unit_visitor::
|
||||
|
||||
auto nested_tinst_full_name = nested_tinst->full_name();
|
||||
|
||||
if (ctx.config().should_include(fn_ns, fn_name)) {
|
||||
if (ctx.diagram().should_include(fn_ns, fn_name)) {
|
||||
ctx.diagram().add_class(std::move(nested_tinst));
|
||||
}
|
||||
|
||||
if (ctx.config().should_include(tinst_ns, tinst_name)
|
||||
if (ctx.diagram().should_include(tinst_ns, tinst_name)
|
||||
// TODO: check why this breaks t00033:
|
||||
// && ctx.config().should_include(
|
||||
// cx::util::split_ns(tinst_dependency.destination()))
|
||||
@@ -1753,7 +1755,7 @@ void translation_unit_visitor::
|
||||
"type {} -> {}",
|
||||
tinst.full_name(), tinst_dependency.destination());
|
||||
|
||||
if (ctx.config().should_include(fn_ns, fn_name)) {
|
||||
if (ctx.diagram().should_include(fn_ns, fn_name)) {
|
||||
tinst.add_relationship(std::move(tinst_dependency));
|
||||
}
|
||||
else if (parent) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "common/model/diagram_filter.h"
|
||||
#include "config/config.h"
|
||||
#include "util/error.h"
|
||||
#include "util/util.h"
|
||||
@@ -225,16 +226,18 @@ void generator<C, D>::generate_link(
|
||||
template <typename DiagramModel, typename DiagramConfig,
|
||||
typename DiagramVisitor>
|
||||
DiagramModel generate(const cppast::libclang_compilation_database &db,
|
||||
const std::string &name, DiagramConfig &diagram, bool verbose = false)
|
||||
const std::string &name, DiagramConfig &config, bool verbose = false)
|
||||
{
|
||||
LOG_INFO("Generating diagram {}.puml", name);
|
||||
DiagramModel d;
|
||||
d.set_name(name);
|
||||
DiagramModel diagram{};
|
||||
diagram.set_name(name);
|
||||
diagram.set_filter(
|
||||
std::make_unique<model::diagram_filter>(diagram, config));
|
||||
|
||||
// Get all translation units matching the glob from diagram
|
||||
// configuration
|
||||
std::vector<std::string> translation_units{};
|
||||
for (const auto &g : diagram.glob()) {
|
||||
for (const auto &g : config.glob()) {
|
||||
LOG_DBG("Processing glob: {}", g);
|
||||
const auto matches = glob::rglob(g);
|
||||
std::copy(matches.begin(), matches.end(),
|
||||
@@ -248,12 +251,12 @@ DiagramModel generate(const cppast::libclang_compilation_database &db,
|
||||
type_safe::ref(idx), std::move(logger)};
|
||||
|
||||
// Process all matching translation units
|
||||
DiagramVisitor ctx(idx, d, diagram);
|
||||
DiagramVisitor ctx(idx, diagram, config);
|
||||
cppast::parse_files(parser, translation_units, db);
|
||||
for (auto &file : parser.files())
|
||||
ctx(file);
|
||||
|
||||
return std::move(d);
|
||||
return std::move(diagram);
|
||||
}
|
||||
|
||||
template <typename C, typename D> void generator<C, D>::init_context()
|
||||
|
||||
@@ -18,10 +18,63 @@
|
||||
|
||||
#include "diagram.h"
|
||||
|
||||
#include "diagram_filter.h"
|
||||
#include "namespace.h"
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
diagram::diagram() = default;
|
||||
|
||||
diagram::~diagram() = default;
|
||||
|
||||
diagram::diagram(diagram &&) = default;
|
||||
|
||||
diagram &diagram::operator=(diagram &&) = default;
|
||||
|
||||
std::string diagram::name() const { return name_; }
|
||||
|
||||
void diagram::set_name(const std::string &name) { name_ = name; }
|
||||
|
||||
void diagram::set_filter(std::unique_ptr<diagram_filter> filter)
|
||||
{
|
||||
filter_ = std::move(filter);
|
||||
}
|
||||
|
||||
bool diagram::should_include(const element &e) const {
|
||||
if (filter_.get() == nullptr)
|
||||
return true;
|
||||
|
||||
return filter_->should_include(e);
|
||||
}
|
||||
|
||||
bool diagram::should_include(const std::string &name) const {
|
||||
if (filter_.get() == nullptr)
|
||||
return true;
|
||||
|
||||
return filter_->should_include(name);
|
||||
}
|
||||
|
||||
bool diagram::should_include(const relationship_t r) const {
|
||||
if (filter_.get() == nullptr)
|
||||
return true;
|
||||
|
||||
return filter_->should_include(r);
|
||||
}
|
||||
|
||||
bool diagram::should_include(const scope_t s) const {
|
||||
if (filter_.get() == nullptr)
|
||||
return true;
|
||||
|
||||
return filter_->should_include(s);
|
||||
}
|
||||
|
||||
bool diagram::should_include(
|
||||
const namespace_ &ns, const std::string &name) const
|
||||
{
|
||||
if (filter_.get() == nullptr)
|
||||
return true;
|
||||
|
||||
return filter_->should_include(ns, name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -17,18 +17,44 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "enums.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
class diagram_filter;
|
||||
class namespace_;
|
||||
class element;
|
||||
class relationship;
|
||||
|
||||
class diagram {
|
||||
public:
|
||||
std::string name() const;
|
||||
diagram();
|
||||
virtual ~diagram();
|
||||
|
||||
diagram(const diagram &) = delete;
|
||||
diagram(diagram &&);
|
||||
diagram &operator=(const diagram &) = delete;
|
||||
diagram &operator=(diagram &&);
|
||||
|
||||
void set_name(const std::string &name);
|
||||
std::string name() const;
|
||||
|
||||
void set_filter(std::unique_ptr<diagram_filter> filter);
|
||||
|
||||
// TODO: refactor to a template method
|
||||
bool should_include(const element &e) const;
|
||||
bool should_include(const std::string &e) const;
|
||||
bool should_include(const relationship r) const;
|
||||
bool should_include(const relationship_t r) const;
|
||||
bool should_include(const scope_t s) const;
|
||||
bool should_include(const namespace_ &ns, const std::string &name) const;
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
std::unique_ptr<diagram_filter> filter_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
53
src/common/model/diagram_filter.cc
Normal file
53
src/common/model/diagram_filter.cc
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* src/common/model/diagram_filter.h
|
||||
*
|
||||
* Copyright (c) 2021-2022 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 "diagram_filter.h"
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
bool filter_visitor::match(const diagram &d, const common::model::element &e)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool filter_visitor::match(
|
||||
const diagram &d, const common::model::relationship_t &r)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool filter_visitor::match(const diagram &d, const common::model::scope_t &r)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool filter_visitor::match(
|
||||
const diagram &d, const common::model::namespace_ &ns)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool diagram_filter::should_include<std::string>(const std::string &name)
|
||||
{
|
||||
auto [ns, n] = cx::util::split_ns(name);
|
||||
|
||||
return should_include(ns, n);
|
||||
}
|
||||
|
||||
}
|
||||
266
src/common/model/diagram_filter.h
Normal file
266
src/common/model/diagram_filter.h
Normal file
@@ -0,0 +1,266 @@
|
||||
/**
|
||||
* src/common/model/entity_filter.h
|
||||
*
|
||||
* Copyright (c) 2021-2022 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.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "common/model/diagram.h"
|
||||
#include "common/model/element.h"
|
||||
#include "common/model/enums.h"
|
||||
#include "common/model/namespace.h"
|
||||
#include "config/config.h"
|
||||
#include "cx/util.h"
|
||||
#include "diagram.h"
|
||||
|
||||
namespace clanguml::common::model {
|
||||
|
||||
enum filter_t { kInclusive, kExclusive };
|
||||
|
||||
class filter_visitor {
|
||||
public:
|
||||
filter_visitor(filter_t type)
|
||||
: type_{type}
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool match(const diagram &d, const common::model::element &e);
|
||||
virtual bool match(
|
||||
const diagram &d, const common::model::relationship_t &r);
|
||||
virtual bool match(const diagram &d, const common::model::scope_t &r);
|
||||
virtual bool match(const diagram &d, const common::model::namespace_ &ns);
|
||||
|
||||
bool is_inclusive() const { return type_ == filter_t::kInclusive; }
|
||||
bool is_exclusive() const { return type_ == filter_t::kExclusive; }
|
||||
|
||||
filter_t type_;
|
||||
};
|
||||
|
||||
struct namespace_filter : public filter_visitor {
|
||||
namespace_filter(filter_t type, std::vector<namespace_> namespaces)
|
||||
: filter_visitor{type}
|
||||
, namespaces_{namespaces}
|
||||
{
|
||||
}
|
||||
|
||||
bool match(const diagram &d, const namespace_ &ns) override
|
||||
{
|
||||
if (namespaces_.empty())
|
||||
return is_inclusive();
|
||||
|
||||
return std::any_of(namespaces_.begin(), namespaces_.end(),
|
||||
[&ns](const auto &nsit) { return ns.starts_with(nsit); });
|
||||
}
|
||||
|
||||
bool match(const diagram &d, const element &e) override
|
||||
{
|
||||
return std::any_of(
|
||||
namespaces_.begin(), namespaces_.end(), [&e](const auto &nsit) {
|
||||
return e.get_namespace().starts_with(nsit);
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<namespace_> namespaces_;
|
||||
};
|
||||
|
||||
struct element_filter : public filter_visitor {
|
||||
element_filter(filter_t type, std::vector<std::string> elements)
|
||||
: filter_visitor{type}
|
||||
, elements_{elements}
|
||||
{
|
||||
}
|
||||
|
||||
bool match(const diagram &d, const element &e) override
|
||||
{
|
||||
return std::any_of(
|
||||
elements_.begin(), elements_.end(), [&e](const auto &el) {
|
||||
auto fn = e.full_name(false);
|
||||
bool result = fn == el;
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::string> elements_;
|
||||
};
|
||||
|
||||
struct subclass_filter : public filter_visitor {
|
||||
subclass_filter(filter_t type, std::vector<std::string> roots)
|
||||
: filter_visitor{type}
|
||||
, roots_{roots}
|
||||
{
|
||||
}
|
||||
|
||||
bool match(const diagram &d, const element &e) override
|
||||
{
|
||||
if (roots_.empty())
|
||||
return is_inclusive();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> roots_;
|
||||
};
|
||||
|
||||
struct relationship_filter : public filter_visitor {
|
||||
relationship_filter(filter_t type, std::vector<std::string> relationships)
|
||||
: filter_visitor{type}
|
||||
, relationships_{relationships}
|
||||
{
|
||||
}
|
||||
|
||||
bool match(const diagram &d, const relationship_t &r) override
|
||||
{
|
||||
if (relationships_.empty())
|
||||
return is_inclusive();
|
||||
|
||||
return std::any_of(relationships_.begin(), relationships_.end(),
|
||||
[&r](const auto &rel) {
|
||||
bool res = to_string(r) == rel;
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::string> relationships_;
|
||||
};
|
||||
|
||||
struct scope_filter : public filter_visitor {
|
||||
scope_filter(filter_t type, std::vector<std::string> scopes)
|
||||
: filter_visitor{type}
|
||||
, scopes_{scopes}
|
||||
{
|
||||
}
|
||||
|
||||
bool match(const diagram &d, const scope_t &s) override
|
||||
{
|
||||
if (scopes_.empty())
|
||||
return is_inclusive();
|
||||
|
||||
return std::any_of(scopes_.begin(), scopes_.end(),
|
||||
[&s](const auto &rel) {
|
||||
bool res = to_string(s) == rel;
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<std::string> scopes_;
|
||||
};
|
||||
|
||||
struct context_filter : public filter_visitor {
|
||||
context_filter(filter_t type, std::vector<std::string> context)
|
||||
: filter_visitor{type}
|
||||
, context_{context}
|
||||
{
|
||||
}
|
||||
|
||||
bool match(const diagram &d, const element &r) override
|
||||
{
|
||||
if (context_.empty())
|
||||
return is_inclusive();
|
||||
|
||||
return std::any_of(context_.begin(), context_.end(),
|
||||
[&r](const auto &rel) { return true; });
|
||||
}
|
||||
|
||||
std::vector<std::string> context_;
|
||||
};
|
||||
|
||||
class diagram_filter {
|
||||
public:
|
||||
diagram_filter(const common::model::diagram &d, const config::diagram &c)
|
||||
: diagram_{d}
|
||||
{
|
||||
init_filters(c);
|
||||
}
|
||||
|
||||
void add_inclusive_filter(std::unique_ptr<filter_visitor> fv)
|
||||
{
|
||||
inclusive_.emplace_back(std::move(fv));
|
||||
}
|
||||
|
||||
void add_exclusive_filter(std::unique_ptr<filter_visitor> fv)
|
||||
{
|
||||
exclusive_.emplace_back(std::move(fv));
|
||||
}
|
||||
|
||||
bool should_include(namespace_ ns, const std::string &name)
|
||||
{
|
||||
if (should_include(ns)) {
|
||||
element e{namespace_{}};
|
||||
e.set_name(name);
|
||||
e.set_namespace(ns);
|
||||
|
||||
return should_include(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T> bool should_include(const T &e)
|
||||
{
|
||||
if (std::any_of(exclusive_.begin(), exclusive_.end(),
|
||||
[this, &e](const auto &ex) { return ex->match(diagram_, e); }))
|
||||
return false;
|
||||
|
||||
if (std::any_of(inclusive_.begin(), inclusive_.end(),
|
||||
[this, &e](const auto &in) { return in->match(diagram_, e); }))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void init_filters(const config::diagram &c)
|
||||
{
|
||||
// Process inclusive filters
|
||||
if (c.include) {
|
||||
inclusive_.emplace_back(std::make_unique<namespace_filter>(
|
||||
filter_t::kInclusive, c.include().namespaces));
|
||||
inclusive_.emplace_back(std::make_unique<element_filter>(
|
||||
filter_t::kInclusive, c.include().elements));
|
||||
inclusive_.emplace_back(std::make_unique<relationship_filter>(
|
||||
filter_t::kInclusive, c.include().relationships));
|
||||
inclusive_.emplace_back(std::make_unique<scope_filter>(
|
||||
filter_t::kInclusive, c.include().scopes));
|
||||
inclusive_.emplace_back(std::make_unique<subclass_filter>(
|
||||
filter_t::kInclusive, c.include().subclasses));
|
||||
inclusive_.emplace_back(std::make_unique<context_filter>(
|
||||
filter_t::kInclusive, c.include().context));
|
||||
}
|
||||
|
||||
// Process exclusive filters
|
||||
if (c.exclude) {
|
||||
exclusive_.emplace_back(std::make_unique<namespace_filter>(
|
||||
filter_t::kExclusive, c.exclude().namespaces));
|
||||
exclusive_.emplace_back(std::make_unique<element_filter>(
|
||||
filter_t::kExclusive, c.exclude().elements));
|
||||
exclusive_.emplace_back(std::make_unique<relationship_filter>(
|
||||
filter_t::kExclusive, c.include().relationships));
|
||||
exclusive_.emplace_back(std::make_unique<scope_filter>(
|
||||
filter_t::kExclusive, c.include().scopes));
|
||||
exclusive_.emplace_back(std::make_unique<subclass_filter>(
|
||||
filter_t::kExclusive, c.exclude().subclasses));
|
||||
exclusive_.emplace_back(std::make_unique<context_filter>(
|
||||
filter_t::kExclusive, c.exclude().context));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<filter_visitor>> inclusive_;
|
||||
std::vector<std::unique_ptr<filter_visitor>> exclusive_;
|
||||
const common::model::diagram &diagram_;
|
||||
};
|
||||
|
||||
template <>
|
||||
bool diagram_filter::should_include<std::string>(const std::string &name);
|
||||
}
|
||||
@@ -108,134 +108,6 @@ void inheritable_diagram_options::inherit(
|
||||
git.override(parent.git);
|
||||
}
|
||||
|
||||
bool diagram::should_include_entities(const std::string &ent)
|
||||
{
|
||||
for (const auto &ex : exclude().entity_types) {
|
||||
if (ent == ex)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (include().entity_types.empty())
|
||||
return true;
|
||||
|
||||
for (const auto &in : include().entity_types) {
|
||||
if (ent == in)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool diagram::should_include_relationship(const std::string &rel)
|
||||
{
|
||||
for (const auto &ex : exclude().relationships) {
|
||||
if (rel == ex)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (include().relationships.empty())
|
||||
return true;
|
||||
|
||||
for (const auto &in : include().relationships) {
|
||||
if (rel == in)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool diagram::should_include(
|
||||
const std::pair<common::model::namespace_, std::string> &name) const
|
||||
{
|
||||
return should_include(std::get<0>(name), std::get<1>(name));
|
||||
}
|
||||
|
||||
bool diagram::should_include(
|
||||
const common::model::namespace_ &ns, const std::string &name) const
|
||||
{
|
||||
return should_include(ns | name);
|
||||
}
|
||||
|
||||
bool diagram::should_include(const std::string &name_) const
|
||||
{
|
||||
auto name = clanguml::util::unqualify(name_);
|
||||
|
||||
for (const auto &ex : exclude().namespaces) {
|
||||
if (name.find(ex.to_string()) == 0) {
|
||||
LOG_DBG("Skipping from diagram: {}", name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If no inclusive namespaces are provided,
|
||||
// allow all
|
||||
if (include().namespaces.empty())
|
||||
return true;
|
||||
|
||||
for (const auto &in : include().namespaces) {
|
||||
if (name.find(in.to_string()) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_DBG("Skipping from diagram: {}", name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool diagram::should_include(const common::model::namespace_ &path) const
|
||||
{
|
||||
return should_include(path.to_string());
|
||||
}
|
||||
|
||||
bool diagram::should_include_package(
|
||||
const common::model::namespace_ &path) const
|
||||
{
|
||||
return should_include_package(path.to_string());
|
||||
}
|
||||
|
||||
bool diagram::should_include_package(const std::string &name) const
|
||||
{
|
||||
|
||||
for (const auto &ex : exclude().namespaces) {
|
||||
if (name.find(ex.to_string()) == 0) {
|
||||
LOG_DBG("Skipping from diagram: {}", name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// If no inclusive namespaces are provided,
|
||||
// allow all
|
||||
if (include().namespaces.empty())
|
||||
return true;
|
||||
|
||||
for (const auto &in : include().namespaces) {
|
||||
if (in.to_string().find(name) == 0 || name.find(in.to_string()) == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG_DBG("Skipping from diagram: {}", name);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool diagram::should_include(const clanguml::common::model::scope_t scope) const
|
||||
{
|
||||
for (const auto &s : exclude().scopes) {
|
||||
if (s == scope)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (include().scopes.empty())
|
||||
return true;
|
||||
|
||||
for (const auto &s : include().scopes) {
|
||||
if (s == scope)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
diagram_type class_diagram::type() const { return diagram_type::class_diagram; }
|
||||
|
||||
bool class_diagram::has_class(std::string clazz)
|
||||
@@ -445,13 +317,19 @@ template <> struct convert<filter> {
|
||||
rhs.relationships =
|
||||
node["relationships"].as<decltype(rhs.relationships)>();
|
||||
|
||||
if (node["entity_types"])
|
||||
rhs.entity_types =
|
||||
node["entity_types"].as<decltype(rhs.entity_types)>();
|
||||
if (node["elements"])
|
||||
rhs.elements =
|
||||
node["elements"].as<decltype(rhs.elements)>();
|
||||
|
||||
if (node["scopes"])
|
||||
rhs.scopes = node["scopes"].as<decltype(rhs.scopes)>();
|
||||
|
||||
if (node["subclasses"])
|
||||
rhs.subclasses = node["subclasses"].as<decltype(rhs.subclasses)>();
|
||||
|
||||
if (node["context"])
|
||||
rhs.context = node["context"].as<decltype(rhs.context)>();
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
namespace clanguml {
|
||||
namespace config {
|
||||
|
||||
|
||||
enum class diagram_type { class_diagram, sequence_diagram, package_diagram };
|
||||
enum class method_arguments { full, abbreviated, none };
|
||||
|
||||
@@ -48,21 +49,23 @@ struct plantuml {
|
||||
struct filter {
|
||||
std::vector<common::model::namespace_> namespaces;
|
||||
|
||||
// Valid values are:
|
||||
std::vector<std::string> elements;
|
||||
|
||||
// E.g.:
|
||||
// - inheritance
|
||||
// - dependency
|
||||
// - instantiation
|
||||
std::vector<std::string> relationships;
|
||||
|
||||
// E.g.:
|
||||
// - classes
|
||||
// - enums
|
||||
std::vector<std::string> entity_types;
|
||||
|
||||
// E.g.:
|
||||
// - public
|
||||
// - protected
|
||||
// - private
|
||||
std::vector<common::model::scope_t> scopes;
|
||||
std::vector<std::string> scopes;
|
||||
|
||||
std::vector<std::string> subclasses;
|
||||
|
||||
std::vector<std::string> context;
|
||||
};
|
||||
|
||||
enum class hint_t { up, down, left, right };
|
||||
@@ -111,26 +114,6 @@ struct diagram : public inheritable_diagram_options {
|
||||
|
||||
virtual diagram_type type() const = 0;
|
||||
|
||||
bool should_include_entities(const std::string &ent);
|
||||
|
||||
bool should_include_relationship(const std::string &rel);
|
||||
|
||||
bool should_include_package(const std::string &name) const;
|
||||
|
||||
bool should_include_package(const common::model::namespace_ &path) const;
|
||||
|
||||
bool should_include(
|
||||
const std::pair<common::model::namespace_, std::string> &name) const;
|
||||
|
||||
bool should_include(
|
||||
const common::model::namespace_ &ns, const std::string &name) const;
|
||||
|
||||
bool should_include(const common::model::scope_t scope) const;
|
||||
|
||||
bool should_include(const std::string &name_) const;
|
||||
|
||||
bool should_include(const common::model::namespace_ &path) const;
|
||||
|
||||
std::string name;
|
||||
};
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ void generator::generate_relationships(
|
||||
const auto &uns = m_config.using_namespace();
|
||||
|
||||
// Generate this packages relationship
|
||||
if (m_config.should_include_relationship("dependency")) {
|
||||
if (m_model.should_include(relationship_t::kDependency)) {
|
||||
for (const auto &r : p.relationships()) {
|
||||
std::stringstream relstr;
|
||||
try {
|
||||
|
||||
@@ -95,7 +95,7 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
|
||||
auto package_path = package_parent | e.name();
|
||||
auto usn = ctx.config().using_namespace();
|
||||
|
||||
if (ctx.config().should_include_package(package_path)) {
|
||||
if (ctx.diagram().should_include(package_path)) {
|
||||
auto p = std::make_unique<package>(usn);
|
||||
package_path = package_path.relative_to(usn);
|
||||
|
||||
@@ -465,7 +465,7 @@ bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
||||
found = find_relationships(args[0u].type().value(), relationships,
|
||||
relationship_t::kDependency);
|
||||
}
|
||||
else if (ctx.config().should_include(t_ns, t_name)) {
|
||||
else if (ctx.diagram().should_include(t_ns, t_name)) {
|
||||
LOG_DBG("User defined template instantiation: {} | {}",
|
||||
cppast::to_string(t_), cppast::to_string(t_.canonical()));
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ void translation_unit_visitor::process_activities(const cppast::cpp_function &e)
|
||||
.value();
|
||||
m.from = cx::util::ns(caller) + "::" + caller.name();
|
||||
|
||||
if (!ctx.config().should_include(
|
||||
if (!ctx.diagram().should_include(
|
||||
common::model::namespace_{cx::util::ns(caller)}, caller.name()))
|
||||
continue;
|
||||
|
||||
@@ -98,7 +98,7 @@ void translation_unit_visitor::process_activities(const cppast::cpp_function &e)
|
||||
if (callee.kind() == cpp_entity_kind::function_t)
|
||||
m.to += "()";
|
||||
|
||||
if (!ctx.config().should_include(
|
||||
if (!ctx.diagram().should_include(
|
||||
common::model::namespace_{cx::util::ns(callee)}, callee.name()))
|
||||
continue;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user