Make sure sequence diagram messages generated during static variable initialization are rendered only once
This commit is contained in:
@@ -256,6 +256,13 @@ void generator::process_call_message(const model::message &m,
|
||||
{
|
||||
visited.push_back(m.from());
|
||||
|
||||
if (m.in_static_declaration_context()) {
|
||||
if (util::contains(already_generated_in_static_context_, m))
|
||||
return;
|
||||
|
||||
already_generated_in_static_context_.push_back(m);
|
||||
}
|
||||
|
||||
LOG_DBG("Generating message {} --> {}", m.from(), m.to());
|
||||
|
||||
generate_call(m, current_block_statement());
|
||||
|
||||
@@ -243,6 +243,8 @@ private:
|
||||
|
||||
mutable std::vector<std::reference_wrapper<nlohmann::json>>
|
||||
block_statements_stack_;
|
||||
|
||||
mutable std::vector<model::message> already_generated_in_static_context_;
|
||||
};
|
||||
|
||||
} // namespace clanguml::sequence_diagram::generators::json
|
||||
|
||||
@@ -139,6 +139,13 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
||||
std::vector<common::model::diagram_element::id_t> &visited) const
|
||||
{
|
||||
for (const auto &m : a.messages()) {
|
||||
if (m.in_static_declaration_context()) {
|
||||
if (util::contains(already_generated_in_static_context_, m))
|
||||
continue;
|
||||
|
||||
already_generated_in_static_context_.push_back(m);
|
||||
}
|
||||
|
||||
if (m.type() == message_t::kCall) {
|
||||
const auto &to =
|
||||
model().get_participant<model::participant>(m.to());
|
||||
|
||||
@@ -137,9 +137,17 @@ private:
|
||||
*/
|
||||
std::string generate_alias(const model::participant &participant) const;
|
||||
|
||||
mutable std::set<common::id_t> generated_participants_;
|
||||
/**
|
||||
* @brief Convert config to model message render mode.
|
||||
*
|
||||
* @return Method render mode.
|
||||
*/
|
||||
model::function::message_render_mode
|
||||
select_method_arguments_render_mode() const;
|
||||
|
||||
mutable std::set<common::id_t> generated_participants_;
|
||||
|
||||
mutable std::vector<model::message> already_generated_in_static_context_;
|
||||
};
|
||||
|
||||
} // namespace mermaid
|
||||
|
||||
@@ -135,6 +135,13 @@ void generator::generate_activity(const activity &a, std::ostream &ostr,
|
||||
std::vector<common::model::diagram_element::id_t> &visited) const
|
||||
{
|
||||
for (const auto &m : a.messages()) {
|
||||
if (m.in_static_declaration_context()) {
|
||||
if (util::contains(already_generated_in_static_context_, m))
|
||||
continue;
|
||||
|
||||
already_generated_in_static_context_.push_back(m);
|
||||
}
|
||||
|
||||
if (m.type() == message_t::kCall) {
|
||||
const auto &to =
|
||||
model().get_participant<model::participant>(m.to());
|
||||
|
||||
@@ -139,9 +139,17 @@ private:
|
||||
*/
|
||||
std::string render_name(std::string name) const;
|
||||
|
||||
mutable std::set<common::id_t> generated_participants_;
|
||||
/**
|
||||
* @brief Convert config to model message render mode.
|
||||
*
|
||||
* @return Method render mode.
|
||||
*/
|
||||
model::function::message_render_mode
|
||||
select_method_arguments_render_mode() const;
|
||||
|
||||
mutable std::set<common::id_t> generated_participants_;
|
||||
|
||||
mutable std::vector<model::message> already_generated_in_static_context_;
|
||||
};
|
||||
|
||||
} // namespace plantuml
|
||||
|
||||
@@ -78,4 +78,14 @@ std::optional<std::string> message::condition_text() const
|
||||
return condition_text_;
|
||||
}
|
||||
|
||||
bool message::in_static_declaration_context() const
|
||||
{
|
||||
return in_static_declaration_context_;
|
||||
}
|
||||
|
||||
void message::in_static_declaration_context(bool v)
|
||||
{
|
||||
in_static_declaration_context_ = v;
|
||||
}
|
||||
|
||||
} // namespace clanguml::sequence_diagram::model
|
||||
|
||||
@@ -150,6 +150,10 @@ public:
|
||||
*/
|
||||
std::optional<std::string> condition_text() const;
|
||||
|
||||
bool in_static_declaration_context() const;
|
||||
|
||||
void in_static_declaration_context(bool v);
|
||||
|
||||
private:
|
||||
common::model::message_t type_{common::model::message_t::kNone};
|
||||
|
||||
@@ -167,6 +171,8 @@ private:
|
||||
std::string return_type_{};
|
||||
|
||||
std::optional<std::string> condition_text_;
|
||||
|
||||
bool in_static_declaration_context_{false};
|
||||
};
|
||||
|
||||
} // namespace clanguml::sequence_diagram::model
|
||||
|
||||
@@ -936,6 +936,8 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
||||
|
||||
message m{message_t::kCall, context().caller_id()};
|
||||
|
||||
m.in_static_declaration_context(within_static_variable_declaration_ > 0);
|
||||
|
||||
set_source_location(*expr, m);
|
||||
|
||||
// If we're currently inside a lambda expression, set it's id as
|
||||
@@ -1031,6 +1033,27 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::TraverseVarDecl(clang::VarDecl *decl)
|
||||
{
|
||||
LOG_TRACE("Traversing cxx variable declaration at {} [caller_id = {}]",
|
||||
decl->getBeginLoc().printToString(source_manager()),
|
||||
context().caller_id());
|
||||
|
||||
decl->dump();
|
||||
|
||||
decl->getInit()->dump();
|
||||
|
||||
if (decl->isStaticLocal())
|
||||
within_static_variable_declaration_++;
|
||||
|
||||
RecursiveASTVisitor::TraverseVarDecl(decl);
|
||||
|
||||
if (decl->isStaticLocal())
|
||||
within_static_variable_declaration_--;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::VisitCXXConstructExpr(
|
||||
clang::CXXConstructExpr *expr)
|
||||
{
|
||||
@@ -1051,8 +1074,12 @@ bool translation_unit_visitor::VisitCXXConstructExpr(
|
||||
expr->getBeginLoc().printToString(source_manager()),
|
||||
context().caller_id());
|
||||
|
||||
expr->dump();
|
||||
|
||||
message m{message_t::kCall, context().caller_id()};
|
||||
|
||||
m.in_static_declaration_context(within_static_variable_declaration_ > 0);
|
||||
|
||||
set_source_location(*expr, m);
|
||||
|
||||
if (context().lambda_caller_id() != 0) {
|
||||
@@ -2427,6 +2454,7 @@ bool translation_unit_visitor::should_include(const clang::CallExpr *expr) const
|
||||
return false;
|
||||
|
||||
const auto expr_file = expr->getBeginLoc().printToString(source_manager());
|
||||
|
||||
return diagram().should_include(common::model::source_file{expr_file});
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,8 @@ public:
|
||||
|
||||
bool TraverseCallExpr(clang::CallExpr *expr);
|
||||
|
||||
bool TraverseVarDecl(clang::VarDecl *VD);
|
||||
|
||||
bool TraverseCXXMemberCallExpr(clang::CXXMemberCallExpr *expr);
|
||||
|
||||
bool TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr *expr);
|
||||
@@ -540,5 +542,9 @@ private:
|
||||
std::tuple<std::string /* field name */, common::model::relationship_t,
|
||||
common::model::access_t>>
|
||||
anonymous_struct_relationships_;
|
||||
|
||||
mutable unsigned within_static_variable_declaration_{0};
|
||||
mutable std::set<const clang::Expr *>
|
||||
already_visited_in_static_declaration_{};
|
||||
};
|
||||
} // namespace clanguml::sequence_diagram::visitor
|
||||
|
||||
Reference in New Issue
Block a user