From ad5ec1c973bca214e334f5c9d90b4fd7dd60d649 Mon Sep 17 00:00:00 2001 From: Bartek Kryza Date: Mon, 24 Oct 2022 01:09:40 +0200 Subject: [PATCH] Added participant generation in sequence diagrams --- src/common/model/diagram_element.h | 2 +- .../plantuml/sequence_diagram_generator.cc | 52 ++++++++++++------- .../plantuml/sequence_diagram_generator.h | 2 + src/sequence_diagram/model/diagram.h | 7 +++ src/sequence_diagram/model/participant.cc | 7 +++ src/sequence_diagram/model/participant.h | 8 +-- .../visitor/translation_unit_visitor.cc | 9 +++- 7 files changed, 63 insertions(+), 24 deletions(-) diff --git a/src/common/model/diagram_element.h b/src/common/model/diagram_element.h index 084b09e2..e303edbc 100644 --- a/src/common/model/diagram_element.h +++ b/src/common/model/diagram_element.h @@ -43,7 +43,7 @@ public: void set_id(id_t id); - std::string alias() const; + virtual std::string alias() const; void set_name(const std::string &name) { name_ = name; } diff --git a/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc b/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc index 6a7912b7..6c7a736e 100644 --- a/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc +++ b/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.cc @@ -38,11 +38,11 @@ generator::generator( void generator::generate_call(const message &m, std::ostream &ostr) const { - const auto from = m_config.using_namespace().relative(m.from_name); - const auto to = m_config.using_namespace().relative(m.to_name); + const auto &from = m_model.get_participant(m.from); + const auto &to = m_model.get_participant(m.to); - if (from.empty() || to.empty()) { - LOG_DBG("Skipping empty call from '{}' to '{}'", from, to); + if (!from || !to) { + LOG_DBG("Skipping empty call from '{}' to '{}'", m.from, m.to); return; } @@ -52,9 +52,9 @@ void generator::generate_call(const message &m, std::ostream &ostr) const message += "()"; } - ostr << '"' << from << "\" " - << common::generators::plantuml::to_plantuml(message_t::kCall) << " \"" - << to << "\" : " << message << std::endl; + ostr << from.value().alias() << " " + << common::generators::plantuml::to_plantuml(message_t::kCall) << " " + << to.value().alias() << " : " << message << std::endl; LOG_DBG("Generated call '{}' from {} [{}] to {} [{}]", message, from, m.from_name, to, m.to_name); @@ -65,28 +65,26 @@ void generator::generate_return(const message &m, std::ostream &ostr) const // Add return activity only for messages between different actors and // only if the return type is different than void if ((m.from != m.to) && (m.return_type != "void")) { - const auto from = m_config.using_namespace().relative(m.from_name); - const auto to = m_config.using_namespace().relative(m.to_name); + const auto &from = m_model.get_participant(m.from); + const auto &to = m_model.get_participant(m.to); - ostr << '"' << to << "\" " + ostr << to.value().alias() << " " << common::generators::plantuml::to_plantuml(message_t::kReturn) - << " \"" << from << "\"" << std::endl; + << " " << from.value().alias() << '\n'; } } void generator::generate_activity(const activity &a, std::ostream &ostr) const { for (const auto &m : a.messages) { - const auto to = m_config.using_namespace().relative(m.to_name); - - if (to.empty()) + const auto &to = m_model.get_participant(m.to); + if (!to) continue; - LOG_DBG("Generating message {} --> {}", - m.from_name, m.to_name); + LOG_DBG("Generating message {} --> {}", m.from_name, m.to_name); generate_call(m, ostr); - ostr << "activate " << '"' << to << '"' << std::endl; + ostr << "activate " << to.value().alias() << std::endl; if (m_model.sequences.find(m.to) != m_model.sequences.end()) { LOG_DBG("Creating activity {} --> {} - missing sequence {}", @@ -99,7 +97,23 @@ void generator::generate_activity(const activity &a, std::ostream &ostr) const generate_return(m, ostr); - ostr << "deactivate " << '"' << to << '"' << std::endl; + ostr << "deactivate " << to.value().alias() << std::endl; + } +} + +void generator::generate_participants(std::ostream &ostr) const +{ + for (const auto participant_id : m_model.active_participants_) { + const auto &participant = + m_model.get_participant(participant_id).value(); + + if (participant.type_name() == "method") + continue; + + ostr << "participant \"" + << m_config.using_namespace().relative( + participant.full_name(false)) + << "\" as " << participant.alias()<< '\n'; } } @@ -111,6 +125,8 @@ void generator::generate(std::ostream &ostr) const generate_plantuml_directives(ostr, m_config.puml().before); + generate_participants(ostr); + for (const auto &sf : m_config.start_from()) { if (sf.location_type == source_location::location_t::function) { std::int64_t start_from; diff --git a/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h b/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h index 30e9ef63..a5d13a34 100644 --- a/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h +++ b/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h @@ -52,6 +52,8 @@ public: void generate_return(const clanguml::sequence_diagram::model::message &m, std::ostream &ostr) const; + void generate_participants(std::ostream &ostr) const; + void generate_activity(const clanguml::sequence_diagram::model::activity &a, std::ostream &ostr) const; diff --git a/src/sequence_diagram/model/diagram.h b/src/sequence_diagram/model/diagram.h index 4579917a..4b66d149 100644 --- a/src/sequence_diagram/model/diagram.h +++ b/src/sequence_diagram/model/diagram.h @@ -79,10 +79,17 @@ public: } } + void add_active_participant(common::model::diagram_element::id_t id) + { + active_participants_.emplace(id); + } + std::map sequences; std::map> participants; + + std::set active_participants_; }; } diff --git a/src/sequence_diagram/model/participant.cc b/src/sequence_diagram/model/participant.cc index e4a28399..8b37dc6d 100644 --- a/src/sequence_diagram/model/participant.cc +++ b/src/sequence_diagram/model/participant.cc @@ -128,4 +128,11 @@ method::method(const common::model::namespace_ &using_namespace) : participant{using_namespace} { } + +std::string method::alias() const +{ + assert(class_id_ >= 0); + + return fmt::format("C_{:022}", class_id_); +} } \ No newline at end of file diff --git a/src/sequence_diagram/model/participant.h b/src/sequence_diagram/model/participant.h index 31c3f525..cb22fa3e 100644 --- a/src/sequence_diagram/model/participant.h +++ b/src/sequence_diagram/model/participant.h @@ -157,11 +157,11 @@ struct method : public participant { std::string type_name() const override { return "method"; } - const std::string method_name() const { - return method_name_; - } + const std::string method_name() const { return method_name_; } - void set_method_name(const std::string& name) { method_name_ = name; } + std::string alias() const override; + + void set_method_name(const std::string &name) { method_name_ = name; } void set_class_id(diagram_element::id_t id) { class_id_ = id; } diff --git a/src/sequence_diagram/visitor/translation_unit_visitor.cc b/src/sequence_diagram/visitor/translation_unit_visitor.cc index e7082a8c..b62a2198 100644 --- a/src/sequence_diagram/visitor/translation_unit_visitor.cc +++ b/src/sequence_diagram/visitor/translation_unit_visitor.cc @@ -339,6 +339,10 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr) m.message_name = method_decl->getNameAsString(); m.return_type = method_call_expr->getCallReturnType(current_ast_context) .getAsString(); + + if (get_ast_local_id(callee_decl->getID())) + diagram().add_active_participant( + get_ast_local_id(callee_decl->getID()).value()); } else if (const auto *function_call_expr = clang::dyn_cast_or_null(expr); @@ -400,7 +404,7 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr) return true; } - if(m.from > 0 && m.to > 0) { + if (m.from > 0 && m.to > 0) { if (diagram().sequences.find(m.from) == diagram().sequences.end()) { activity a; a.usr = m.from; @@ -408,6 +412,9 @@ bool translation_unit_visitor::VisitCallExpr(clang::CallExpr *expr) diagram().sequences.insert({m.from, std::move(a)}); } + diagram().add_active_participant(m.from); + diagram().add_active_participant(m.to); + LOG_DBG("Found call {} from {} [{}] to {} [{}] ", m.message_name, m.from_name, m.from, m.to_name, m.to);