Skip to content

Commit

Permalink
Added option include_system_headers to enable processing of system he…
Browse files Browse the repository at this point in the history
…aders
  • Loading branch information
bkryza committed Jun 27, 2024
1 parent fbe3631 commit f47d119
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 35 deletions.
7 changes: 2 additions & 5 deletions src/class_diagram/visitor/translation_unit_visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ bool translation_unit_visitor::VisitNamespaceDecl(clang::NamespaceDecl *ns)
p->set_id(common::to_id(*ns));
id_mapper().add(ns->getID(), p->id());

if (diagram().should_include(*p) && !diagram().get(p->id())) {
if (config().filter_mode() == config::filter_mode_t::advanced ||
(diagram().should_include(*p) && !diagram().get(p->id()))) {
process_comment(*ns, *p);
set_source_location(*ns, *p);

Expand Down Expand Up @@ -667,10 +668,6 @@ void translation_unit_visitor::process_concept_specialization_relationships(

bool translation_unit_visitor::VisitCXXRecordDecl(clang::CXXRecordDecl *cls)
{
// Skip system headers
if (source_manager().isInSystemHeader(cls->getSourceRange().getBegin()))
return true;

if (!should_include(cls))
return true;

Expand Down
19 changes: 19 additions & 0 deletions src/common/model/filters/diagram_filter_factory.cc
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,25 @@ void basic_diagram_filter_initializer::initialize()
}
}

template <>
void advanced_diagram_filter_initializer::add_filter<
source_file_dependency_filter_t>(const filter_t &filter_type,
const std::vector<common::string_or_regex> &filter_config,
std::vector<std::unique_ptr<filter_visitor>> &result, relationship_t &&rt,
bool &&direction)
{
std::vector<std::string> deps;
for (auto &&path : filter_config) {
if (auto p = path.get<std::string>(); p.has_value()) {
const std::filesystem::path dep_path{*p};
deps.emplace_back(dep_path.lexically_normal().string());
}
}

result.emplace_back(std::make_unique<source_file_dependency_filter_t>(
filter_type, deps, rt, direction));
}

std::vector<std::unique_ptr<filter_visitor>>
advanced_diagram_filter_initializer::build(
filter_t filter_type, const config::filter &filter_config)
Expand Down
26 changes: 7 additions & 19 deletions src/common/model/filters/diagram_filter_factory.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,27 +84,15 @@ class advanced_diagram_filter_initializer : public diagram_filter_initializer {
result.emplace_back(std::make_unique<FT>(
filter_type, filter_config, std::forward<Args>(args)...));
}

template <>
void add_filter<source_file_dependency_filter_t>(
const filter_t &filter_type,
const std::vector<common::string_or_regex> &filter_config,
std::vector<std::unique_ptr<filter_visitor>> &result,
relationship_t &&rt, bool &&direction)
{
std::vector<std::string> deps;
for (auto &&path : filter_config) {
if (auto p = path.get<std::string>(); p.has_value()) {
const std::filesystem::path dep_path{*p};
deps.emplace_back(dep_path.lexically_normal().string());
}
}

result.emplace_back(std::make_unique<source_file_dependency_filter_t>(
filter_type, deps, rt, direction));
}
};

template <>
void advanced_diagram_filter_initializer::add_filter<
source_file_dependency_filter_t>(const filter_t &filter_type,
const std::vector<common::string_or_regex> &filter_config,
std::vector<std::unique_ptr<filter_visitor>> &result, relationship_t &&rt,
bool &&direction);

class diagram_filter_factory {
public:
static std::unique_ptr<diagram_filter> create(
Expand Down
13 changes: 11 additions & 2 deletions src/common/visitor/translation_unit_visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,13 @@ template <typename ConfigT, typename DiagramT> class translation_unit_visitor {
return stripped_comment;
}

bool skip_system_header_decl(const clang::NamedDecl *decl)
{
return !config().include_system_headers() &&
source_manager().isInSystemHeader(
decl->getSourceRange().getBegin());
}

/**
* @brief Check if the diagram should include a declaration.
*
Expand All @@ -301,10 +308,12 @@ template <typename ConfigT, typename DiagramT> class translation_unit_visitor {
if (decl == nullptr)
return false;

if (source_manager().isInSystemHeader(
decl->getSourceRange().getBegin()))
if (skip_system_header_decl(decl))
return false;

if (config().filter_mode() == config::filter_mode_t::advanced)
return true;

auto should_include_namespace = diagram().should_include(
common::model::namespace_{decl->getQualifiedNameAsString()});

Expand Down
1 change: 1 addition & 0 deletions src/config/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ void inheritable_diagram_options::inherit(
include_relations_also_as_members.override(
parent.include_relations_also_as_members);
filter_mode.override(parent.filter_mode);
include_system_headers.override(parent.include_system_headers);
include.override(parent.include);
exclude.override(parent.exclude);
puml.override(parent.puml);
Expand Down
1 change: 1 addition & 0 deletions src/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,7 @@ struct inheritable_diagram_options {
option<bool> include_relations_also_as_members{
"include_relations_also_as_members", true};
option<filter_mode_t> filter_mode{"filter_mode", filter_mode_t::basic};
option<bool> include_system_headers{"include_system_headers", false};
option<filter> include{"include"};
option<filter> exclude{"exclude"};
option<plantuml> puml{"plantuml", option_inherit_mode::kAppend};
Expand Down
9 changes: 9 additions & 0 deletions src/config/schema.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ const std::string schema_str = R"(
comment_parser: !optional comment_parser_t
debug_mode: !optional bool
filter_mode: !optional filter_mode_t
include_system_headers: !optional bool
exclude: !optional filter_t
generate_links: !optional generate_links_t
git: !optional git_t
Expand Down Expand Up @@ -221,6 +222,8 @@ const std::string schema_str = R"(
debug_mode: !optional bool
exclude: !optional filter_t
generate_links: !optional generate_links_t
filter_mode: !optional filter_mode_t
include_system_headers: !optional bool
git: !optional git_t
glob: !optional [string]
include: !optional filter_t
Expand Down Expand Up @@ -264,6 +267,8 @@ const std::string schema_str = R"(
generate_links: !optional generate_links_t
git: !optional git_t
glob: !optional [string]
filter_mode: !optional filter_mode_t
include_system_headers: !optional bool
include: !optional filter_t
plantuml: !optional
before: !optional [string]
Expand Down Expand Up @@ -292,6 +297,8 @@ const std::string schema_str = R"(
__parent_path: !optional string
comment_parser: !optional comment_parser_t
debug_mode: !optional bool
filter_mode: !optional filter_mode_t
include_system_headers: !optional bool
exclude: !optional filter_t
generate_links: !optional generate_links_t
git: !optional git_t
Expand Down Expand Up @@ -377,6 +384,8 @@ const std::string schema_str = R"(
generate_template_argument_dependencies: !optional bool
skip_redundant_dependencies: !optional bool
type_aliases: !optional map_t<string;string>
filter_mode: !optional filter_mode_t
include_system_headers: !optional bool
)";

} // namespace clanguml::config
3 changes: 2 additions & 1 deletion src/config/yaml_decoders.cc
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ template <> struct convert<filter> {
}

if (node["allof"]) {
rhs.anyof = std::make_unique<filter>(node["anyof"].as<filter>());
rhs.allof = std::make_unique<filter>(node["allof"].as<filter>());
}

if (node["namespaces"]) {
Expand Down Expand Up @@ -655,6 +655,7 @@ template <typename T> bool decode_diagram(const Node &node, T &rhs)
get_option(node, rhs.using_namespace);
get_option(node, rhs.using_module);
get_option(node, rhs.filter_mode);
get_option(node, rhs.include_system_headers);
get_option(node, rhs.include);
get_option(node, rhs.exclude);
get_option(node, rhs.puml);
Expand Down
14 changes: 14 additions & 0 deletions tests/t00080/.clang-uml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
diagrams:
t00080_class:
type: class
filter_mode: advanced
include_system_headers: true
glob:
- t00080.cc
include:
anyof:
namespaces:
- clanguml::t00080
elements:
- std::thread
using_namespace: clanguml::t00080
24 changes: 24 additions & 0 deletions tests/t00080/t00080.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#include <thread>

namespace clanguml {
namespace t00080 {

class Worker : public std::thread {
public:
using std::thread::thread;

~Worker()
{
if (this->joinable()) {
this->join();
}
}

void start(int delay) { }
};

struct R {
Worker *w;
};
}
}
35 changes: 35 additions & 0 deletions tests/t00080/test_case.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* tests/t00080/test_case.h
*
* Copyright (c) 2021-2024 Bartek Kryza <[email protected]>
*
* 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.
*/

TEST_CASE("t00080")
{
using namespace clanguml::test;
using namespace std::string_literals;

auto [config, db, diagram, model] =
CHECK_CLASS_MODEL("t00080", "t00080_class");

CHECK_CLASS_DIAGRAM(*config, diagram, *model, [](const auto &src) {
REQUIRE(IsClass(src, "Worker"));
REQUIRE(IsClass(src, "R"));
REQUIRE(IsClass(src, "std::thread"));
REQUIRE(!IsClass(src, "std::jthread"));

REQUIRE(IsAssociation<Public>(src, "R", "Worker", "w"));
});
}
1 change: 1 addition & 0 deletions tests/test_cases.cc
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ void CHECK_INCLUDE_DIAGRAM(const clanguml::config::config &config,
#include "t00077/test_case.h"
#include "t00078/test_case.h"
#include "t00079/test_case.h"
#include "t00080/test_case.h"

///
/// Sequence diagram tests
Expand Down
3 changes: 3 additions & 0 deletions tests/test_cases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ test_cases:
- name: t00079
title: Test case for context diagram exclude filter with relationships option
description:
- name: t00080
title: Test case for including elements from system headers
description:
Sequence diagrams:
- name: t20001
title: Basic sequence diagram test case
Expand Down
12 changes: 10 additions & 2 deletions tests/test_config_data/filters_advanced.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
compilation_database_dir: debug
output_directory: output
filter_mode: advanced
diagrams:
anyof_test:
type: class
relative_to: ../../../src
glob:
- src/**/*.cc
- src/**/*.h
filter_mode: advanced
include:
anyof:
namespaces:
Expand All @@ -17,4 +17,12 @@ diagrams:
exclude:
anyof:
namespaces:
- ns1::ns2::detail
- ns1::ns2::detail
modules_test:
type: class
include:
anyof:
modules:
- mod1::mod2
namespaces:
- ns1::ns2
44 changes: 38 additions & 6 deletions tests/test_filters_advanced.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,14 @@
#include "sequence_diagram/model/diagram.h"

#include <filesystem>
using clanguml::common::model::diagram_filter;
using clanguml::common::model::diagram_filter_factory;
using clanguml::common::model::namespace_;
using clanguml::common::model::source_file;
using clanguml::config::filter_mode_t;

TEST_CASE("Test advanced diagram filter anyof")
{
using clanguml::common::model::diagram_filter;
using clanguml::common::model::diagram_filter_factory;
using clanguml::common::model::namespace_;
using clanguml::common::model::source_file;
using clanguml::config::filter_mode_t;

auto cfg =
clanguml::config::load("./test_config_data/filters_advanced.yml");

Expand All @@ -61,6 +60,39 @@ TEST_CASE("Test advanced diagram filter anyof")
CHECK_FALSE(filter.should_include(namespace_{"ns1::ns2::detail"}));
}

TEST_CASE("Test advanced diagram filter modules")
{
auto cfg =
clanguml::config::load("./test_config_data/filters_advanced.yml");

auto &config = *cfg.diagrams["modules_test"];
clanguml::include_diagram::model::diagram diagram;

auto filter_ptr = diagram_filter_factory::create(diagram, config);
diagram_filter &filter = *filter_ptr;

CHECK(config.filter_mode() == filter_mode_t::advanced);
CHECK(filter.should_include(namespace_{"ns1::ns2"}));
CHECK_FALSE(filter.should_include(namespace_{"std::string"}));

clanguml::common::model::element std_string{{}};
std_string.set_namespace(namespace_{"std"});
std_string.set_name("string");

CHECK_FALSE(filter.should_include(std_string));

CHECK(filter.should_include(namespace_{"ns1"}));

clanguml::common::model::element e1{{}};
e1.set_module("mod1::mod2");
e1.set_namespace(namespace_{"ns5::ns6"});
e1.set_name("ClassA");
CHECK(filter.should_include(e1));

e1.set_module("mod1::mod3");
CHECK_FALSE(filter.should_include(e1));
}

///
/// Main test function
///
Expand Down

0 comments on commit f47d119

Please sign in to comment.