Enabled advanced diagram filters in sequence diagrams (#289)
This commit is contained in:
@@ -389,6 +389,12 @@ tvl::value_t namespace_filter::match(const diagram &d, const element &e) const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tvl::value_t namespace_filter::match(
|
||||||
|
const diagram &d, const sequence_diagram::model::participant &p) const
|
||||||
|
{
|
||||||
|
return match(d, dynamic_cast<const element &>(p));
|
||||||
|
}
|
||||||
|
|
||||||
modules_filter::modules_filter(
|
modules_filter::modules_filter(
|
||||||
filter_t type, std::vector<common::string_or_regex> modules)
|
filter_t type, std::vector<common::string_or_regex> modules)
|
||||||
: filter_visitor{type}
|
: filter_visitor{type}
|
||||||
|
|||||||
@@ -232,6 +232,9 @@ struct namespace_filter : public filter_visitor {
|
|||||||
|
|
||||||
tvl::value_t match(const diagram &d, const element &e) const override;
|
tvl::value_t match(const diagram &d, const element &e) const override;
|
||||||
|
|
||||||
|
tvl::value_t match(const diagram &d,
|
||||||
|
const sequence_diagram::model::participant &p) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<common::namespace_or_regex> namespaces_;
|
std::vector<common::namespace_or_regex> namespaces_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ public:
|
|||||||
return stripped_comment;
|
return stripped_comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool skip_system_header_decl(const clang::NamedDecl *decl)
|
bool skip_system_header_decl(const clang::NamedDecl *decl) const
|
||||||
{
|
{
|
||||||
return !config().include_system_headers() &&
|
return !config().include_system_headers() &&
|
||||||
source_manager().isInSystemHeader(
|
source_manager().isInSystemHeader(
|
||||||
@@ -302,7 +302,7 @@ public:
|
|||||||
* @param decl Clang declaration.
|
* @param decl Clang declaration.
|
||||||
* @return True, if the entity should be included in the diagram.
|
* @return True, if the entity should be included in the diagram.
|
||||||
*/
|
*/
|
||||||
bool should_include(const clang::NamedDecl *decl)
|
bool should_include(const clang::NamedDecl *decl) const
|
||||||
{
|
{
|
||||||
if (decl == nullptr)
|
if (decl == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -380,7 +380,7 @@ private:
|
|||||||
struct method : public function {
|
struct method : public function {
|
||||||
method(const common::model::namespace_ &using_namespace);
|
method(const common::model::namespace_ &using_namespace);
|
||||||
|
|
||||||
method(const function &) = delete;
|
method(const method &) = delete;
|
||||||
method(method &&) noexcept = delete;
|
method(method &&) noexcept = delete;
|
||||||
method &operator=(const method &) = delete;
|
method &operator=(const method &) = delete;
|
||||||
method &operator=(method &&) = delete;
|
method &operator=(method &&) = delete;
|
||||||
|
|||||||
@@ -1085,6 +1085,9 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
|||||||
auto generated_message_from_comment = generate_message_from_comment(m);
|
auto generated_message_from_comment = generate_message_from_comment(m);
|
||||||
|
|
||||||
if (!generated_message_from_comment && !should_include(expr)) {
|
if (!generated_message_from_comment && !should_include(expr)) {
|
||||||
|
LOG_DBG("Skipping call expression due to filter at: {}",
|
||||||
|
expr->getBeginLoc().printToString(source_manager()));
|
||||||
|
|
||||||
processed_comments().erase(raw_expr_comment);
|
processed_comments().erase(raw_expr_comment);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1178,7 +1181,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
|||||||
auto success = process_function_call_expression(m, expr);
|
auto success = process_function_call_expression(m, expr);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
LOG_DBG("Skipping call to call expression at: {}",
|
LOG_DBG("Skipping call expression at: {}",
|
||||||
expr->getBeginLoc().printToString(source_manager()));
|
expr->getBeginLoc().printToString(source_manager()));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -2098,6 +2101,7 @@ translation_unit_visitor::create_lambda_method_model(
|
|||||||
ns.pop_back();
|
ns.pop_back();
|
||||||
method_model_ptr->set_name(ns.name());
|
method_model_ptr->set_name(ns.name());
|
||||||
ns.pop_back();
|
ns.pop_back();
|
||||||
|
method_model_ptr->set_namespace(ns);
|
||||||
|
|
||||||
method_model_ptr->is_defaulted(declaration->isDefaulted());
|
method_model_ptr->is_defaulted(declaration->isDefaulted());
|
||||||
method_model_ptr->is_assignment(declaration->isCopyAssignmentOperator() ||
|
method_model_ptr->is_assignment(declaration->isCopyAssignmentOperator() ||
|
||||||
@@ -2137,6 +2141,7 @@ translation_unit_visitor::create_method_model(clang::CXXMethodDecl *declaration)
|
|||||||
ns.pop_back();
|
ns.pop_back();
|
||||||
method_model_ptr->set_name(ns.name());
|
method_model_ptr->set_name(ns.name());
|
||||||
ns.pop_back();
|
ns.pop_back();
|
||||||
|
method_model_ptr->set_namespace(ns);
|
||||||
|
|
||||||
method_model_ptr->is_defaulted(declaration->isDefaulted());
|
method_model_ptr->is_defaulted(declaration->isDefaulted());
|
||||||
method_model_ptr->is_assignment(declaration->isCopyAssignmentOperator() ||
|
method_model_ptr->is_assignment(declaration->isCopyAssignmentOperator() ||
|
||||||
@@ -2191,14 +2196,8 @@ translation_unit_visitor::create_method_model(clang::CXXMethodDecl *declaration)
|
|||||||
|
|
||||||
bool translation_unit_visitor::should_include(const clang::TagDecl *decl) const
|
bool translation_unit_visitor::should_include(const clang::TagDecl *decl) const
|
||||||
{
|
{
|
||||||
if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
|
return visitor_specialization_t::should_include(
|
||||||
return false;
|
dynamic_cast<const clang::NamedDecl *>(decl));
|
||||||
|
|
||||||
const auto decl_file = decl->getLocation().printToString(source_manager());
|
|
||||||
|
|
||||||
return diagram().should_include(
|
|
||||||
namespace_{decl->getQualifiedNameAsString()}) &&
|
|
||||||
diagram().should_include(common::model::source_file{decl_file});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool translation_unit_visitor::should_include(
|
bool translation_unit_visitor::should_include(
|
||||||
@@ -2236,8 +2235,11 @@ bool translation_unit_visitor::should_include(const clang::CallExpr *expr) const
|
|||||||
if (callee_decl != nullptr) {
|
if (callee_decl != nullptr) {
|
||||||
const auto *callee_function = callee_decl->getAsFunction();
|
const auto *callee_function = callee_decl->getAsFunction();
|
||||||
|
|
||||||
if ((callee_function == nullptr) || !should_include(callee_function))
|
if ((callee_function == nullptr) || !should_include(callee_function)) {
|
||||||
|
LOG_DBG("Skipping call expression at {}",
|
||||||
|
expr->getBeginLoc().printToString(source_manager()));
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return should_include(callee_function);
|
return should_include(callee_function);
|
||||||
}
|
}
|
||||||
@@ -2263,30 +2265,19 @@ bool translation_unit_visitor::should_include(
|
|||||||
bool translation_unit_visitor::should_include(
|
bool translation_unit_visitor::should_include(
|
||||||
const clang::FunctionDecl *decl) const
|
const clang::FunctionDecl *decl) const
|
||||||
{
|
{
|
||||||
const auto decl_file = decl->getLocation().printToString(source_manager());
|
return visitor_specialization_t::should_include(decl);
|
||||||
|
|
||||||
return diagram().should_include(
|
|
||||||
namespace_{decl->getQualifiedNameAsString()}) &&
|
|
||||||
diagram().should_include(common::model::source_file{decl_file});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool translation_unit_visitor::should_include(
|
bool translation_unit_visitor::should_include(
|
||||||
const clang::FunctionTemplateDecl *decl) const
|
const clang::FunctionTemplateDecl *decl) const
|
||||||
{
|
{
|
||||||
return should_include(decl->getAsFunction());
|
return visitor_specialization_t::should_include(decl->getAsFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool translation_unit_visitor::should_include(
|
bool translation_unit_visitor::should_include(
|
||||||
const clang::ClassTemplateDecl *decl) const
|
const clang::ClassTemplateDecl *decl) const
|
||||||
{
|
{
|
||||||
if (source_manager().isInSystemHeader(decl->getSourceRange().getBegin()))
|
return visitor_specialization_t::should_include(decl);
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto decl_file = decl->getLocation().printToString(source_manager());
|
|
||||||
|
|
||||||
return diagram().should_include(
|
|
||||||
namespace_{decl->getQualifiedNameAsString()}) &&
|
|
||||||
diagram().should_include(common::model::source_file{decl_file});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> translation_unit_visitor::get_expression_comment(
|
std::optional<std::string> translation_unit_visitor::get_expression_comment(
|
||||||
|
|||||||
15
tests/t20055/.clang-uml
Normal file
15
tests/t20055/.clang-uml
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
diagrams:
|
||||||
|
t20055_sequence:
|
||||||
|
type: sequence
|
||||||
|
filter_mode: advanced
|
||||||
|
glob:
|
||||||
|
- t20055.cc
|
||||||
|
include:
|
||||||
|
anyof:
|
||||||
|
namespaces:
|
||||||
|
- clanguml::t20055::ns2
|
||||||
|
elements:
|
||||||
|
- clanguml::t20055::ns1::B
|
||||||
|
using_namespace: clanguml::t20055
|
||||||
|
from:
|
||||||
|
- function: "clanguml::t20055::ns2::tmain()"
|
||||||
34
tests/t20055/t20055.cc
Normal file
34
tests/t20055/t20055.cc
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
namespace clanguml {
|
||||||
|
namespace t20055 {
|
||||||
|
namespace ns1 {
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
void a() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B {
|
||||||
|
A a;
|
||||||
|
void b() { a.a(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ns1
|
||||||
|
namespace ns2 {
|
||||||
|
void f() { }
|
||||||
|
struct C {
|
||||||
|
ns1::B b;
|
||||||
|
void c()
|
||||||
|
{
|
||||||
|
b.b();
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void tmain()
|
||||||
|
{
|
||||||
|
C c;
|
||||||
|
c.c();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ns2
|
||||||
|
}
|
||||||
|
}
|
||||||
39
tests/t20055/test_case.h
Normal file
39
tests/t20055/test_case.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* tests/t20055/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("t20055")
|
||||||
|
{
|
||||||
|
using namespace clanguml::test;
|
||||||
|
using namespace std::string_literals;
|
||||||
|
|
||||||
|
auto [config, db, diagram, model] =
|
||||||
|
CHECK_SEQUENCE_MODEL("t20055", "t20055_sequence");
|
||||||
|
|
||||||
|
CHECK_SEQUENCE_DIAGRAM(*config, diagram, *model, [](const auto &src) {
|
||||||
|
REQUIRE(MessageOrder(src,
|
||||||
|
{
|
||||||
|
//
|
||||||
|
{{"ns2", "tmain()"}, {"ns2", "C"}, "c()"},
|
||||||
|
{{"ns2", "C"}, {"ns1", "B"}, "b()"},
|
||||||
|
{{"ns2", "C"}, {"ns2", "f()"}, ""}
|
||||||
|
//
|
||||||
|
}));
|
||||||
|
|
||||||
|
REQUIRE(!HasMessage(src, {{"ns1", "B"}, {"ns1", "A"}, "a()"}));
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -9,25 +9,6 @@ module;
|
|||||||
export module t30015.app;
|
export module t30015.app;
|
||||||
import t30015.lib1;
|
import t30015.lib1;
|
||||||
|
|
||||||
// import t30015.app;
|
|
||||||
// import t30015.mod2;
|
|
||||||
// import t30015.mod3;
|
|
||||||
// import t30015.mod4;
|
|
||||||
// import t30015.mod5;
|
|
||||||
// import t30015.mod6;
|
|
||||||
// import t30015.mod7;
|
|
||||||
// import t30015.mod8;
|
|
||||||
// import t30015.mod9;
|
|
||||||
// import t30015.mod10;
|
|
||||||
// import t30015.mod11;
|
|
||||||
// import t30015.mod12;
|
|
||||||
// import t30015.mod13;
|
|
||||||
// import t30015.mod14;
|
|
||||||
// import t30015.mod15;
|
|
||||||
// import t30015.mod16;
|
|
||||||
// import t30015.mod17;
|
|
||||||
// import t30015.mod18;
|
|
||||||
|
|
||||||
export namespace clanguml::t30015 {
|
export namespace clanguml::t30015 {
|
||||||
|
|
||||||
class CBA : public CF {
|
class CBA : public CF {
|
||||||
|
|||||||
@@ -623,6 +623,7 @@ void CHECK_INCLUDE_DIAGRAM(const clanguml::config::config &config,
|
|||||||
#include "t20052/test_case.h"
|
#include "t20052/test_case.h"
|
||||||
#include "t20053/test_case.h"
|
#include "t20053/test_case.h"
|
||||||
#include "t20054/test_case.h"
|
#include "t20054/test_case.h"
|
||||||
|
#include "t20055/test_case.h"
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Package diagram tests
|
/// Package diagram tests
|
||||||
|
|||||||
@@ -339,8 +339,16 @@ std::optional<nlohmann::json> get_participant(
|
|||||||
if (!j.contains("participants"))
|
if (!j.contains("participants"))
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
|
std::string using_namespace{};
|
||||||
|
if (j.contains("using_namespace")) {
|
||||||
|
using_namespace =
|
||||||
|
fmt::format("{}::", j["using_namespace"].get<std::string>());
|
||||||
|
}
|
||||||
|
|
||||||
for (const nlohmann::json &e : j.at("participants")) {
|
for (const nlohmann::json &e : j.at("participants")) {
|
||||||
if (e["display_name"] == name)
|
if (e["display_name"] == name ||
|
||||||
|
e["full_name"].get<std::string>().substr(using_namespace.size()) ==
|
||||||
|
name)
|
||||||
return {e};
|
return {e};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2482,7 +2490,7 @@ int64_t FindMessage(
|
|||||||
if (!fail)
|
if (!fail)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
std::cout << "FindMessage failed with error " << e.what() << "\n";
|
std::cout << "FindMessage failed with error: " << e.what() << "\n";
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -409,6 +409,9 @@ test_cases:
|
|||||||
- name: t20054
|
- name: t20054
|
||||||
title: Test case for sequence diagram with nested classes
|
title: Test case for sequence diagram with nested classes
|
||||||
description:
|
description:
|
||||||
|
- name: t20055
|
||||||
|
title: Test case for advanced filter in sequence diagram
|
||||||
|
description:
|
||||||
Package diagrams:
|
Package diagrams:
|
||||||
- name: t30001
|
- name: t30001
|
||||||
title: Basic package diagram test case
|
title: Basic package diagram test case
|
||||||
|
|||||||
Reference in New Issue
Block a user