Added highlight of calls within condition statements of if/else blocks

This commit is contained in:
Bartek Kryza
2022-12-12 21:07:28 +01:00
parent b2396d7b44
commit d7c13edbf9
10 changed files with 93 additions and 9 deletions

View File

@@ -164,6 +164,22 @@ std::string get_source_text(
return get_source_text_raw(printable_range, sm);
}
bool is_subexpr_of(const clang::Stmt *parent_stmt, const clang::Stmt *sub_stmt)
{
if (parent_stmt == nullptr || sub_stmt == nullptr)
return false;
if (parent_stmt == sub_stmt)
return true;
for (const auto *e : parent_stmt->children()) {
if (is_subexpr_of(e, sub_stmt))
return true;
}
return false;
}
template <> id_t to_id(const std::string &full_name)
{
return std::hash<std::string>{}(full_name) >> 3;

View File

@@ -68,6 +68,8 @@ std::string get_source_text_raw(
std::string get_source_text(
clang::SourceRange range, const clang::SourceManager &sm);
bool is_subexpr_of(const clang::Stmt *parent_stmt, const clang::Stmt *sub_stmt);
template <typename T> id_t to_id(const T &declaration);
template <> id_t to_id(const std::string &full_name);

View File

@@ -39,6 +39,7 @@ enum class relationship_t {
kDependency
};
/// Types of sequence diagram activity elements
enum class message_t {
kCall,
kReturn,
@@ -55,6 +56,13 @@ enum class message_t {
kNone
};
/// The scope of the call expression represented in the sequence diagram
enum class message_scope_t {
kNormal, // This is a regular call expression
kCondition // This is a call expression from within a control condition
// e.g if(a->is_valid()) { ... }
};
std::string to_string(relationship_t r);
std::string to_string(access_t r);

View File

@@ -79,14 +79,25 @@ void generator::generate_call(const message &m, std::ostream &ostr) const
const std::string to_alias = generate_alias(to.value());
ostr << from_alias << " "
<< common::generators::plantuml::to_plantuml(message_t::kCall) << " "
<< to_alias;
<< common::generators::plantuml::to_plantuml(message_t::kCall) << " ";
ostr << to_alias;
if (m_config.generate_links) {
common_generator<diagram_config, diagram_model>::generate_link(ostr, m);
}
ostr << " : " << message << std::endl;
ostr << " : ";
if (m.message_scope() == common::model::message_scope_t::kCondition)
ostr << "**[**";
ostr << message;
if (m.message_scope() == common::model::message_scope_t::kCondition)
ostr << "**]**";
ostr << '\n';
LOG_DBG("Generated call '{}' from {} [{}] to {} [{}]", message, from,
m.from(), to, m.to());

View File

@@ -50,4 +50,11 @@ void message::set_return_type(std::string t) { return_type_ = std::move(t); }
const std::string &message::return_type() const { return return_type_; }
void message::set_message_scope(common::model::message_scope_t scope)
{
scope_ = scope;
}
common::model::message_scope_t message::message_scope() const { return scope_; }
}

View File

@@ -47,6 +47,9 @@ public:
void set_return_type(std::string t);
const std::string &return_type() const;
void set_message_scope(common::model::message_scope_t scope);
common::model::message_scope_t message_scope() const;
private:
common::model::message_t type_{common::model::message_t::kNone};
@@ -54,6 +57,9 @@ private:
common::model::diagram_element::id_t to_{};
common::model::message_scope_t scope_{
common::model::message_scope_t::kNormal};
// This is only for better verbose messages, we cannot rely on this
// always
std::string message_name_{};

View File

@@ -732,6 +732,7 @@ bool translation_unit_visitor::TraverseCXXForRangeStmt(
bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
{
using clanguml::common::model::message_scope_t;
using clanguml::common::model::message_t;
using clanguml::common::model::namespace_;
using clanguml::sequence_diagram::model::activity;
@@ -774,6 +775,20 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
}
}
if (context().current_ifstmt()) {
if (common::is_subexpr_of(
context().current_ifstmt()->getCond(), expr)) {
m.set_message_scope(common::model::message_scope_t::kCondition);
}
}
if (context().current_elseifstmt()) {
if (common::is_subexpr_of(
context().current_elseifstmt()->getCond(), expr)) {
m.set_message_scope(common::model::message_scope_t::kCondition);
}
}
if (const auto *operator_call_expr =
clang::dyn_cast_or_null<clang::CXXOperatorCallExpr>(expr);
operator_call_expr != nullptr) {