diff --git a/src/sequence_diagram/generators/json/sequence_diagram_generator.cc b/src/sequence_diagram/generators/json/sequence_diagram_generator.cc index 45e13927..4dcdacd9 100644 --- a/src/sequence_diagram/generators/json/sequence_diagram_generator.cc +++ b/src/sequence_diagram/generators/json/sequence_diagram_generator.cc @@ -110,6 +110,8 @@ void generator::generate_call(const message &m, nlohmann::json &parent) const msg["from"]["activity_id"] = std::to_string(from.value().id()); msg["to"]["activity_id"] = std::to_string(to.value().id()); msg["to"]["activity_name"] = to.value().full_name(false); + if (m.comment()) + msg["comment"] = m.comment().value(); if (from.value().type_name() == "method") { const auto &class_participant = diff --git a/src/sequence_diagram/generators/mermaid/sequence_diagram_generator.cc b/src/sequence_diagram/generators/mermaid/sequence_diagram_generator.cc index 6f364767..bd034f92 100644 --- a/src/sequence_diagram/generators/mermaid/sequence_diagram_generator.cc +++ b/src/sequence_diagram/generators/mermaid/sequence_diagram_generator.cc @@ -53,6 +53,27 @@ void generator::generate_diagram_type(std::ostream &ostr) const ostr << "sequenceDiagram\n"; } +void generator::generate_message_comment( + std::ostream &ostr, const model::message &m) const +{ + if (!config().generate_message_comments() || !m.comment()) + return; + + const auto &from = model().get_participant(m.from()); + + if (!from) + return; + + ostr << indent(1) << "note over " << generate_alias(from.value()) << ": "; + + auto formatted_message = util::format_message_comment( + m.comment().value(), config().message_comment_width()); + + util::replace_all(formatted_message, "\n", "
"); + + ostr << formatted_message << '\n'; +} + void generator::generate_call(const message &m, std::ostream &ostr) const { const auto &from = model().get_participant(m.from()); @@ -91,6 +112,8 @@ void generator::generate_call(const message &m, std::ostream &ostr) const print_debug(m, ostr); + generate_message_comment(ostr, m); + ostr << indent(1) << from_alias << " " << common::generators::mermaid::to_mermaid(message_t::kCall) << " "; @@ -182,6 +205,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr, } else if (m.type() == message_t::kIf) { print_debug(m, ostr); + generate_message_comment(ostr, m); ostr << indent(1) << "alt"; if (const auto &text = m.condition_text(); text.has_value()) ostr << " " << render_message_text(text.value()); @@ -203,6 +227,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr, } else if (m.type() == message_t::kWhile) { print_debug(m, ostr); + generate_message_comment(ostr, m); ostr << indent(1) << "loop"; if (const auto &text = m.condition_text(); text.has_value()) ostr << " " << render_message_text(text.value()); @@ -213,6 +238,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr, } else if (m.type() == message_t::kFor) { print_debug(m, ostr); + generate_message_comment(ostr, m); ostr << indent(1) << "loop"; if (const auto &text = m.condition_text(); text.has_value()) ostr << " " << render_message_text(text.value()); @@ -223,6 +249,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr, } else if (m.type() == message_t::kDo) { print_debug(m, ostr); + generate_message_comment(ostr, m); ostr << indent(1) << "loop"; if (const auto &text = m.condition_text(); text.has_value()) ostr << " " << render_message_text(text.value()); @@ -233,6 +260,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr, } else if (m.type() == message_t::kTry) { print_debug(m, ostr); + generate_message_comment(ostr, m); ostr << indent(1) << "critical\n"; } else if (m.type() == message_t::kCatch) { @@ -246,6 +274,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr, } else if (m.type() == message_t::kSwitch) { print_debug(m, ostr); + generate_message_comment(ostr, m); ostr << indent(1) << "alt\n"; } else if (m.type() == message_t::kCase) { @@ -258,6 +287,7 @@ void generator::generate_activity(const activity &a, std::ostream &ostr, } else if (m.type() == message_t::kConditional) { print_debug(m, ostr); + generate_message_comment(ostr, m); ostr << indent(1) << "alt"; if (const auto &text = m.condition_text(); text.has_value()) ostr << " " << render_message_text(text.value()); diff --git a/src/sequence_diagram/generators/mermaid/sequence_diagram_generator.h b/src/sequence_diagram/generators/mermaid/sequence_diagram_generator.h index acb11be4..ef7f60f3 100644 --- a/src/sequence_diagram/generators/mermaid/sequence_diagram_generator.h +++ b/src/sequence_diagram/generators/mermaid/sequence_diagram_generator.h @@ -137,6 +137,15 @@ private: */ std::string generate_alias(const model::participant &participant) const; + /** + * @brief Generate message call note + * + * @param ostr Output stream + * @param m Message + */ + void generate_message_comment( + std::ostream &ostr, const model::message &m) const; + /** * @brief Convert config to model message render mode. * diff --git a/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h b/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h index 17dc676f..35dc31ba 100644 --- a/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h +++ b/src/sequence_diagram/generators/plantuml/sequence_diagram_generator.h @@ -139,6 +139,15 @@ private: */ std::string render_name(std::string name) const; + /** + * @brief Generate message call note + * + * @param ostr Output stream + * @param m Message + */ + void generate_message_comment( + std::ostream &ostr, const model::message &m) const; + /** * @brief Convert config to model message render mode. * @@ -147,9 +156,6 @@ private: model::function::message_render_mode select_method_arguments_render_mode() const; - void generate_message_comment( - std::ostream &ostr, const model::message &m) const; - mutable std::set generated_participants_; mutable std::vector already_generated_in_static_context_; }; diff --git a/tests/t20029/test_case.h b/tests/t20029/test_case.h index 80ac68e8..8ae6262a 100644 --- a/tests/t20029/test_case.h +++ b/tests/t20029/test_case.h @@ -59,6 +59,27 @@ TEST_CASE("t20029", "[test-case][sequence]") !HasCall( _A("ConnectionPool"), _A("ConnectionPool"), "connect_impl()")); + REQUIRE_THAT(src, + HasMessageComment(_A("tmain()"), + "Establish connection to the\\n" + "remote server synchronously")); + + REQUIRE_THAT(src, + HasMessageComment(_A("tmain()"), + "Repeat for each line in the\\n" + "input stream")); + + REQUIRE_THAT(src, + HasMessageComment(_A("Encoder>"), + "Encode the message using\\n" + "Base64 encoding and pass\\n" + "it to the next layer")); + + REQUIRE_THAT(src, + HasMessageComment(_A("Retrier"), + "Repeat until send\\(\\) succeeds\\n" + "or retry count is exceeded")); + save_puml(config.output_directory(), diagram->name + ".puml", src); } @@ -90,6 +111,7 @@ TEST_CASE("t20029", "[test-case][sequence]") mermaid::SequenceDiagramAliasMatcher _A(src); using mermaid::HasCall; using mermaid::HasCallInControlCondition; + using mermaid::HasMessageComment; REQUIRE_THAT( src, HasCall(_A("tmain()"), _A("ConnectionPool"), "connect()")); @@ -115,6 +137,27 @@ TEST_CASE("t20029", "[test-case][sequence]") !HasCall( _A("ConnectionPool"), _A("ConnectionPool"), "connect_impl()")); + REQUIRE_THAT(src, + HasMessageComment(_A("tmain()"), + "Establish connection to the
" + "remote server synchronously")); + + REQUIRE_THAT(src, + HasMessageComment(_A("tmain()"), + "Repeat for each line in the
" + "input stream")); + + REQUIRE_THAT(src, + HasMessageComment(_A("Encoder>"), + "Encode the message using
" + "Base64 encoding and pass
" + "it to the next layer")); + + REQUIRE_THAT(src, + HasMessageComment(_A("Retrier"), + "Repeat until send\\(\\) succeeds
" + "or retry count is exceeded")); + save_mermaid(config.output_directory(), diagram->name + ".mmd", src); } } \ No newline at end of file diff --git a/tests/test_cases.h b/tests/test_cases.h index 4620800d..0e3a9c99 100644 --- a/tests/test_cases.h +++ b/tests/test_cases.h @@ -852,7 +852,22 @@ ContainsMatcher HasNote(std::string const &cls, std::string const &position, fmt::format("note {} of {}", position, cls), caseSensitivity)); } +auto HasMessageComment(std::string const &alias, std::string const ¬e, + CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +{ + return Catch::Matchers::Matches( + std::string("note over ") + alias + "\\n" + note + "\\n" + "end note", + caseSensitivity); +} + namespace mermaid { +auto HasMessageComment(std::string const &alias, std::string const ¬e, + CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes) +{ + return Catch::Matchers::Matches( + std::string("note over ") + alias + ": " + note, caseSensitivity); +} + ContainsMatcher HasNote(std::string const &cls, std::string const &position = "", std::string const ¬e = "", CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes)