25#include "glob/glob.hpp"
173 filter_t type, std::vector<std::unique_ptr<filter_visitor>> filters)
175 , filters_{
std::move(filters)}
234 filter_t type, std::vector<std::unique_ptr<filter_visitor>> filters)
236 , filters_{
std::move(filters)}
295 filter_t type, std::vector<common::namespace_or_regex> namespaces)
297 , namespaces_{
std::move(namespaces)}
309 if (std::holds_alternative<namespace_>(nsit.value())) {
310 const auto &ns_pattern = std::get<namespace_>(nsit.value());
312 return ns.starts_with(ns_pattern) ||
313 ns_pattern.starts_with(ns);
315 return ns.starts_with(ns_pattern);
318 const auto &
regex = std::get<common::regex>(nsit.value());
326 dynamic_cast<const package *
>(&e) !=
nullptr) {
329 if (std::holds_alternative<namespace_>(nsit.value())) {
330 const auto &ns_pattern = std::get<namespace_>(nsit.value());
332 auto element_full_name_starts_with_namespace =
333 namespace_{e.name_and_ns()}.starts_with(ns_pattern);
335 auto element_full_name_equals_pattern =
338 auto pattern_starts_with_element_full_name =
341 auto result = element_full_name_starts_with_namespace ||
342 element_full_name_equals_pattern;
346 result || pattern_starts_with_element_full_name;
351 return std::get<common::regex>(nsit.value()) %=
359 auto result =
tvl::any_of(namespaces_.begin(), namespaces_.end(),
360 [&e, is_inclusive = is_inclusive()](
const auto &nsit) {
361 if (std::holds_alternative<namespace_>(nsit.value())) {
362 auto e_ns = namespace_{e.full_name(false)};
363 auto nsit_ns = std::get<namespace_>(nsit.value());
366 return e_ns.starts_with(nsit_ns) ||
367 nsit_ns.starts_with(e_ns) || e_ns == nsit_ns;
369 return e_ns.starts_with(nsit_ns) || e_ns == nsit_ns;
372 return std::get<common::regex>(nsit.value()) %=
379 auto result = tvl::any_of(
380 namespaces_.begin(), namespaces_.end(), [&e](
const auto &nsit) {
381 if (std::holds_alternative<namespace_>(nsit.value())) {
382 return e.get_namespace().starts_with(
383 std::get<namespace_>(nsit.value()));
386 return std::get<common::regex>(nsit.value()) %= e.full_name(
false);
395 return match(d,
dynamic_cast<const element &
>(p));
398modules_filter::modules_filter(
399 filter_t type, std::vector<common::string_or_regex> modules)
401 , modules_{
std::move(modules)}
411 if (!e.
module().has_value())
417 if (
dynamic_cast<const package *
>(&e) !=
nullptr &&
419 module_toks.push_back(e.
name());
423 [&e, &module_toks](
const auto &modit) {
424 if (std::holds_alternative<std::string>(modit.value())) {
425 const auto &modit_str = std::get<std::string>(modit.value());
426 const auto modit_toks =
427 path::split(modit_str, path_type::kModule);
429 return e.module() == modit_str ||
430 util::starts_with(module_toks, modit_toks);
433 return std::get<common::regex>(modit.value()) %= e.
module().value();
440 filter_t type, std::vector<common::string_or_regex> elements)
442 , elements_{
std::move(elements)}
454 return ((el == e.full_name(false)) ||
455 (el == fmt::format(
"::{}", e.full_name(false))));
468 const auto &sequence_model =
471 [&sequence_model, &p](
const auto &el) {
472 if (p.type_name() ==
"method") {
474 const auto &m = dynamic_cast<const method &>(p);
475 const auto class_id = m.class_id();
476 const auto &class_participant =
477 sequence_model.get_participant<participant>(class_id)
480 return el == p.full_name(false) ||
481 el == class_participant.full_name(false);
489 filter_t type, std::vector<std::string> element_types)
491 , element_types_{
std::move(element_types)}
499 [&e](
const auto &element_type) {
500 return e.type_name() == element_type;
505 filter_t type, std::vector<config::method_type> method_types)
507 , method_types_{
std::move(method_types)}
517 case config::method_type::constructor:
518 return m.is_constructor();
519 case config::method_type::destructor:
520 return m.is_destructor();
521 case config::method_type::assignment:
522 return m.is_copy_assignment() || m.is_move_assignment();
523 case config::method_type::operator_:
524 return m.is_operator();
525 case config::method_type::defaulted:
526 return m.is_defaulted();
527 case config::method_type::deleted:
528 return m.is_deleted();
529 case config::method_type::static_:
530 return m.is_static();
538 filter_t type, std::vector<config::callee_type> callee_types)
540 , callee_types_{
std::move(callee_types)}
552 auto is_lambda = [&d](
const method &m) {
553 auto class_participant =
555 .get_participant<class_>(m.class_id());
556 if (!class_participant)
559 return class_participant.value().is_lambda();
564 auto is_function = [](const participant *p) {
565 return dynamic_cast<const function *>(p) != nullptr;
568 auto is_cuda_kernel = [](
const participant *p) {
569 const auto *f =
dynamic_cast<const function *
>(p);
570 return (f !=
nullptr) && (f->is_cuda_kernel());
573 auto is_cuda_device = [](
const participant *p) {
574 const auto *f =
dynamic_cast<const function *
>(p);
575 return (f !=
nullptr) && (f->is_cuda_device());
583 ((method &)p).is_constructor();
586 ((method &)p).is_assignment();
588 return is_function(&p) && ((function &)p).is_operator();
591 ((method &)p).is_defaulted();
593 return is_function(&p) && ((function &)p).is_static();
597 return p.
type_name() ==
"function_template";
599 return p.
type_name() ==
"method" && is_lambda((method &)p);
601 return is_cuda_kernel(&p);
603 return is_cuda_device(&p);
613 filter_t type, std::vector<common::string_or_regex> roots)
615 , roots_{
std::move(roots)}
638 if (!class_ref.has_value())
641 parents.emplace(class_ref.value());
643 cd.get_parents(parents);
645 std::vector<std::string> parents_names;
646 for (
const auto p : parents)
647 parents_names.push_back(p.get().full_name(
false));
651 for (
const auto &root :
roots_) {
652 for (
const auto &parent : parents) {
653 auto full_name = parent.get().
full_name(
false);
654 if (root == full_name) {
664 filter_t type, std::vector<common::string_or_regex> children)
666 , children_{
std::move(children)}
686 for (
const auto &child_pattern :
children_) {
689 for (
auto &child : child_refs) {
690 if (child.has_value())
691 parents.emplace(child.value());
695 cd.get_parents(parents);
697 for (
const auto &parent : parents) {
698 if (e == parent.get())
706 filter_t type, std::vector<relationship_t> relationships)
708 , relationships_{
std::move(relationships)}
716 [&r](
const auto &rel) { return r == rel; });
721 , access_{
std::move(access)}
729 [&a](
const auto &access) { return a == access; });
733 filter_t type, std::vector<module_access_t> access)
735 , access_{
std::move(access)}
742 if (!e.
module().has_value())
750 if (access == module_access_t::kPublic)
751 return !e.module_private();
753 return e.module_private();
765 const diagram &d,
unsigned idx)
const
767 bool effective_context_extended{
true};
772 const auto &context_cfg =
context_.at(idx);
773 const auto &context_matches =
775 .find<class_diagram::model::class_>(context_cfg.pattern);
777 for (
const auto &maybe_match : context_matches) {
779 effective_context.emplace(maybe_match.value().id());
782 const auto &context_enum_matches =
784 .find<class_diagram::model::enum_>(context_cfg.pattern);
786 for (
const auto &maybe_match : context_enum_matches) {
788 effective_context.emplace(maybe_match.value().id());
791 const auto &context_concept_matches =
793 .find<class_diagram::model::concept_>(context_cfg.pattern);
795 for (
const auto &maybe_match : context_concept_matches) {
797 effective_context.emplace(maybe_match.value().id());
802 auto radius_counter = context_cfg.radius;
803 std::set<eid_t> current_iteration_context;
805 while (radius_counter > 0 && effective_context_extended) {
809 effective_context_extended =
false;
810 current_iteration_context.clear();
813 find_elements_in_direct_relationship<class_diagram::model::class_>(
814 d, context_cfg, effective_context, current_iteration_context);
817 d, context_cfg, effective_context, current_iteration_context);
820 find_elements_in_direct_relationship<class_diagram::model::concept_>(
821 d, context_cfg, effective_context, current_iteration_context);
824 find_elements_in_direct_relationship<class_diagram::model::enum_>(
825 d, context_cfg, effective_context, current_iteration_context);
827 for (
auto id : current_iteration_context) {
828 if (effective_context.count(
id) == 0) {
830 effective_context.emplace(
id);
831 effective_context_extended =
true;
846 std::set<eid_t> &effective_context,
847 std::set<eid_t> ¤t_iteration_context)
const
855 for (
const auto &c : cd.classes()) {
860 d, effective_context, current_iteration_context, cd, c);
865 effective_context, current_iteration_context, cd, c);
870 std::set<eid_t> &effective_context,
871 std::set<eid_t> ¤t_iteration_context,
873 const std::reference_wrapper<class_diagram::model::class_> &c)
const
875 for (
const auto &ec : effective_context) {
883 for (
const auto &p : maybe_child.value().parents()) {
884 if (p.name() == c.get().full_name(
false)) {
885 current_iteration_context.emplace(c.get().id());
891 std::set<eid_t> &effective_context,
892 std::set<eid_t> ¤t_iteration_context,
894 const std::reference_wrapper<class_diagram::model::class_> &c)
const
897 for (
const auto &ec : effective_context) {
898 const auto &maybe_parent =
904 maybe_parent.value().full_name(
false) == p.name())
905 current_iteration_context.emplace(c.get().id());
918 for (
auto i = 0U; i <
context_.size(); i++) {
937 [](
const auto &ec) { return ec.empty(); }))
941 if (ec.count(e.
id()) > 0)
959 const std::filesystem::path &root)
963 for (
const auto &
path : p) {
964 std::filesystem::path absolute_path;
967 absolute_path = root;
968 else if (std::filesystem::path{
path}.is_relative())
969 absolute_path = root /
path;
971 absolute_path =
path;
973 bool match_successful{
false};
974 for (
auto &resolved_glob_path :
975 glob::glob(absolute_path.string(),
true)) {
977 auto resolved_absolute_path = absolute(resolved_glob_path);
978 resolved_absolute_path =
979 canonical(resolved_absolute_path.lexically_normal());
981 resolved_absolute_path.make_preferred();
983 LOG_DBG(
"Added path {} to paths_filter",
984 resolved_absolute_path.string());
986 paths_.emplace_back(std::move(resolved_absolute_path));
988 match_successful =
true;
990 catch (std::filesystem::filesystem_error &e) {
991 LOG_WARN(
"Cannot add non-existent path {} to "
993 absolute_path.string());
998 if (!match_successful)
999 LOG_WARN(
"Paths filter pattern '{}' did not match "
1000 "any files relative to '{}'",
1019 if (pp.root_name().string() ==
path.root_name().string() &&
1036 auto sl_path = std::filesystem::path{p.
file()};
1040 if (p.
file().empty() || sl_path.is_relative()) {
1045 if (sl_path.root_name().string() ==
path.root_name().string() &&
1056 std::unique_ptr<access_filter> af, std::unique_ptr<method_type_filter> mtf)
1058 , access_filter_{
std::move(af)}
1059 , method_type_filter_{
std::move(mtf)}
1073 filter_t type, std::unique_ptr<access_filter> af)
1075 , access_filter_{
std::move(af)}
1092 filter_t filter_type, std::unique_ptr<filter_visitor> fv)
1111 const namespace_ &ns,
const std::string &name)
const
1116 e.set_namespace(ns);
1125bool diagram_filter::should_include<std::string>(
const std::string &name)
const
1132 return should_include(ns, n);