Added callee_filter for including/excluding messages based on receiver type (#152)

This commit is contained in:
Bartek Kryza
2023-07-01 21:19:51 +02:00
parent 213483dd3b
commit e50a7b1846
24 changed files with 590 additions and 43 deletions

View File

@@ -253,9 +253,15 @@ void generator::process_call_message(const model::message &m,
std::vector<common::model::diagram_element::id_t> &visited) const
{
const auto &to = m_model.get_participant<model::participant>(m.to());
if (!to || to.value().skip())
return;
if (!m_model.should_include(to.value())) {
LOG_DBG("Excluding call from '{}' to '{}'", m.from(), m.to());
return;
}
visited.push_back(m.from());
LOG_DBG("Generating message {} --> {}", m.from(), m.to());

View File

@@ -142,9 +142,15 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
if (!to || to.value().skip())
continue;
if (!m_model.should_include(to.value())) {
LOG_DBG("Excluding call from [{}] to {} [{}]", m.from(),
to.value().full_name(false), m.to());
continue;
}
visited.push_back(m.from());
LOG_DBG("Generating message {} --> {}", m.from(), m.to());
LOG_DBG("Generating message [{}] --> [{}]", m.from(), m.to());
generate_call(m, ostr);

View File

@@ -18,6 +18,8 @@
#include "diagram.h"
#include "common/model/diagram_filter.h"
#include <functional>
#include <memory>
@@ -171,6 +173,14 @@ std::set<common::model::diagram_element::id_t> &diagram::active_participants()
return active_participants_;
}
bool diagram::should_include(
const sequence_diagram::model::participant &p) const
{
return filter().should_include(p) &&
filter().should_include(
dynamic_cast<const common::model::source_location &>(p));
}
void diagram::print() const
{
LOG_TRACE(" --- Participants ---");

View File

@@ -74,7 +74,7 @@ public:
*/
template <typename T>
common::optional_ref<T> get_participant(
common::model::diagram_element::id_t id)
common::model::diagram_element::id_t id) const
{
if (participants_.find(id) == participants_.end()) {
return {};
@@ -202,6 +202,16 @@ public:
*/
void print() const;
// Implicitly import should_include overloads from base class
using common::model::diagram::should_include;
/**
* @brief Convenience `should_include` overload for participant
* @param p Participant model
* @return True, if the participant should be included in the diagram
*/
bool should_include(const sequence_diagram::model::participant &p) const;
private:
/**
* This method checks the last messages in sequence (current_messages),

View File

@@ -164,6 +164,22 @@ std::string method::alias() const
return fmt::format("C_{:022}", class_id_);
}
bool method::is_constructor() const { return is_constructor_; }
void method::is_constructor(bool c) { is_constructor_ = c; }
bool method::is_defaulted() const { return is_defaulted_; }
void method::is_defaulted(bool d) { is_defaulted_ = d; }
bool method::is_assignment() const { return is_assignment_; }
void method::is_assignment(bool a) { is_assignment_ = a; }
bool method::is_operator() const { return is_operator_; }
void method::is_operator(bool o) { is_operator_ = o; }
void method::set_method_name(const std::string &name) { method_name_ = name; }
void method::set_class_id(diagram_element::id_t id) { class_id_ = id; }

View File

@@ -401,10 +401,70 @@ struct method : public function {
*/
std::string to_string() const override;
/**
* @brief Check, if the method is a constructor
*
* @return True, if the method is a constructor
*/
bool is_constructor() const;
/**
* @brief Set whether the method is a constructor
*
* @param v True, if the method is a constructor
*/
void is_constructor(bool c);
/**
* @brief Check, if the method is defaulted
*
* @return True, if the method is defaulted
*/
bool is_defaulted() const;
/**
* @brief Set whether the method is defaulted
*
* @param v True, if the method is defaulted
*/
void is_defaulted(bool c);
/**
* @brief Check, if the method is an assignment operator
*
* @return True, if the method is an assignment operator
*/
bool is_assignment() const;
/**
* @brief Set whether the method is an assignment operator
*
* @param v True, if the method is an assignment operator
*/
void is_assignment(bool a);
/**
* @brief Check, if the method is an operator
*
* @return True, if the method is an operator
*/
bool is_operator() const;
/**
* @brief Set whether the method is an operator
*
* @param v True, if the method is an operator
*/
void is_operator(bool o);
private:
diagram_element::id_t class_id_{};
std::string method_name_;
std::string class_full_name_;
bool is_constructor_{false};
bool is_defaulted_{false};
bool is_assignment_{false};
bool is_operator_{false};
};
/**

View File

@@ -897,14 +897,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
// message source rather then enclosing context
// Unless the lambda is declared in a function or method call
if (context().lambda_caller_id() != 0) {
if (!std::holds_alternative<clang::CallExpr *>(
context().current_callexpr())) {
m.set_from(context().lambda_caller_id());
}
else {
LOG_DBG("Current lambda declaration is passed to a method or "
"function - keep the original caller id");
}
m.set_from(context().lambda_caller_id());
}
if (context().is_expr_in_current_control_statement_condition(expr)) {
@@ -1009,7 +1002,11 @@ bool translation_unit_visitor::VisitCXXConstructExpr(
using clanguml::sequence_diagram::model::activity;
using clanguml::sequence_diagram::model::message;
if (!should_include(expr->getConstructor()))
if (expr == nullptr)
return true;
if (const auto *ctor = expr->getConstructor();
ctor != nullptr && !should_include(ctor))
return true;
LOG_TRACE("Visiting cxx construct expression at {} [caller_id = {}]",
@@ -1021,14 +1018,7 @@ bool translation_unit_visitor::VisitCXXConstructExpr(
set_source_location(*expr, m);
if (context().lambda_caller_id() != 0) {
if (!std::holds_alternative<clang::CallExpr *>(
context().current_callexpr())) {
m.set_from(context().lambda_caller_id());
}
else {
LOG_DBG("Current lambda declaration is passed to a method or "
"function - keep the original caller id");
}
m.set_from(context().lambda_caller_id());
}
if (context().is_expr_in_current_control_statement_condition(expr)) {
@@ -1427,7 +1417,7 @@ translation_unit_visitor::create_class_model(clang::CXXRecordDecl *cls)
c.set_id(common::to_id(c.full_name(false)));
// TODO: Check if lambda is declared as an argument passed to a
// function/method call
// function/method call
}
else {
LOG_WARN("Cannot find parent declaration for lambda {}",
@@ -2303,6 +2293,16 @@ translation_unit_visitor::create_method_model(clang::CXXMethodDecl *declaration)
method_model_ptr->set_name(ns.name());
ns.pop_back();
method_model_ptr->is_defaulted(declaration->isDefaulted());
method_model_ptr->is_assignment(declaration->isCopyAssignmentOperator() ||
declaration->isMoveAssignmentOperator());
method_model_ptr->is_const(declaration->isConst());
method_model_ptr->is_static(declaration->isStatic());
method_model_ptr->is_static(declaration->isStatic());
method_model_ptr->is_operator(declaration->isOverloadedOperator());
method_model_ptr->is_constructor(
clang::dyn_cast<clang::CXXConstructorDecl>(declaration) != nullptr);
clang::Decl *parent_decl = declaration->getParent();
if (context().current_class_template_decl_ != nullptr)