Added option include_system_headers to enable processing of system headers
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -84,27 +84,15 @@ private:
|
||||
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(
|
||||
|
||||
@@ -290,6 +290,13 @@ public:
|
||||
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.
|
||||
*
|
||||
@@ -301,10 +308,12 @@ public:
|
||||
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()});
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -177,6 +177,7 @@ types:
|
||||
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
|
||||
@@ -221,6 +222,8 @@ types:
|
||||
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
|
||||
@@ -264,6 +267,8 @@ types:
|
||||
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]
|
||||
@@ -292,6 +297,8 @@ types:
|
||||
__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
|
||||
@@ -377,6 +384,8 @@ root:
|
||||
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
|
||||
@@ -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"]) {
|
||||
@@ -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);
|
||||
|
||||
14
tests/t00080/.clang-uml
Normal file
14
tests/t00080/.clang-uml
Normal file
@@ -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
tests/t00080/t00080.cc
Normal file
24
tests/t00080/t00080.cc
Normal file
@@ -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
tests/t00080/test_case.h
Normal file
35
tests/t00080/test_case.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* tests/t00080/test_case.h
|
||||
*
|
||||
* Copyright (c) 2021-2024 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.
|
||||
*/
|
||||
|
||||
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"));
|
||||
});
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
compilation_database_dir: debug
|
||||
output_directory: output
|
||||
filter_mode: advanced
|
||||
diagrams:
|
||||
anyof_test:
|
||||
type: class
|
||||
@@ -7,7 +8,6 @@ diagrams:
|
||||
glob:
|
||||
- src/**/*.cc
|
||||
- src/**/*.h
|
||||
filter_mode: advanced
|
||||
include:
|
||||
anyof:
|
||||
namespaces:
|
||||
@@ -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
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
///
|
||||
|
||||
Reference in New Issue
Block a user