34 const std::string &full_name)
const
62 ctx[
"type"] =
"sequence";
64 inja::json::array_t elements{};
68 elements.emplace_back(p->context());
71 ctx[
"elements"] = elements;
78 const auto participant_id = p->id();
80 assert(participant_id.is_global());
83 LOG_DBG(
"Adding '{}' participant: {}, {} [{}]", p->type_name(),
84 p->full_name(
false), p->id(),
85 p->type_name() ==
"method"
132 std::move(
message), start_type, current_messages);
139 const auto caller_id = m.from();
144 if (current_messages.back().type() == message_t::kCase) {
148 current_messages.emplace_back(std::move(m));
165const std::map<eid_t, std::unique_ptr<participant>> &
188 std::vector<std::string> result;
193 const auto &full_name = from_activity.full_name(
false);
194 if (!full_name.empty())
195 result.push_back(full_name);
198 std::sort(result.begin(), result.end());
199 result.erase(std::unique(result.begin(), result.end()), result.end());
206 std::vector<std::string> result;
209 for (
const auto &m : act.messages()) {
212 const auto &full_name = to_activity.full_name(
false);
213 if (!full_name.empty())
214 result.push_back(full_name);
219 std::sort(result.begin(), result.end());
220 result.erase(std::unique(result.begin(), result.end()), result.end());
228 std::optional<eid_t> to_activity{};
231 for (
const auto &m : v.messages()) {
235 std::string vto = callee.full_name(
false);
238 "Found sequence diagram end point '{}': {}", vto, m.to());
239 to_activity = m.to();
245 if (!to_activity.has_value()) {
246 LOG_WARN(
"Failed to find 'to' participant {} for to "
257 std::optional<eid_t> from_activity{};
261 std::string vfrom = caller.full_name(
false);
262 if (vfrom == from_location.
location) {
263 LOG_DBG(
"Found sequence diagram start point '{}': {}", vfrom, k);
269 if (!from_activity.has_value()) {
270 LOG_WARN(
"Failed to find 'from' participant {} for from "
275 return from_activity;
279 const eid_t from_activity,
const eid_t to_activity)
const
281 std::vector<message_chain_t> message_chains_unique{};
284 std::vector<message_chain_t> message_chains;
289 for (
const auto &m : v.messages()) {
293 if (m.to() == to_activity) {
294 message_chains.emplace_back();
295 message_chains.back().push_back(m);
300 std::map<unsigned int, std::vector<model::message>> calls_to_current_chain;
301 std::map<unsigned int, message_chain_t> current_chain;
305 bool added_message_to_some_chain{
false};
309 if (!calls_to_current_chain.empty()) {
310 for (
auto &[message_chain_index, messages] :
311 calls_to_current_chain) {
312 for (
auto &m : messages) {
313 message_chains.push_back(
314 current_chain[message_chain_index]);
316 message_chains.back().push_back(std::move(m));
319 calls_to_current_chain.clear();
322 LOG_TRACE(
"Message chains after iteration {}", iter++);
323 int message_chain_index{};
324 for (
const auto &mc : message_chains) {
325 LOG_TRACE(
"\t{}: {}", message_chain_index++,
326 fmt::join(util::map<std::string>(mc,
333 for (
auto i = 0U; i < message_chains.size(); i++) {
334 auto &mc = message_chains[i];
335 current_chain[i] = mc;
337 for (
const auto &m : v.messages()) {
342 if (m.to() == m.from() ||
344 cbegin(mc), cend(mc), [&m](
const auto &msg) {
345 return msg.to() == m.from();
350 if (m.to() == mc.back().from()) {
351 calls_to_current_chain[i].push_back(m);
352 added_message_to_some_chain =
true;
359 if (calls_to_current_chain.count(i) > 0 &&
360 !calls_to_current_chain[i].empty()) {
361 mc.push_back(calls_to_current_chain[i][0]);
362 calls_to_current_chain[i].erase(
363 calls_to_current_chain[i].begin());
368 if (!added_message_to_some_chain)
374 for (
auto &mc : message_chains) {
375 std::reverse(mc.begin(), mc.end());
380 if (std::find(message_chains_unique.begin(),
381 message_chains_unique.end(), mc) != message_chains_unique.end())
384 if (from_activity.
value() == 0 ||
385 (mc.front().from() == from_activity)) {
386 message_chains_unique.push_back(mc);
390 LOG_TRACE(
"Message chains unique", iter++);
391 int message_chain_index{};
392 for (
const auto &mc : message_chains_unique) {
393 LOG_TRACE(
"\t{}: {}", message_chain_index++,
394 fmt::join(util::map<std::string>(mc,
401 return message_chains_unique;
411 std::map<eid_t, activity> activities;
412 std::map<eid_t, std::unique_ptr<participant>>
participants;
419 auto maybe_lambda_activity = get_participant<model::method>(
id);
421 if (maybe_lambda_activity) {
422 const auto parent_class_id =
423 maybe_lambda_activity.value().class_id();
424 auto maybe_parent_class =
425 get_participant<model::class_>(parent_class_id);
427 if (maybe_parent_class && maybe_parent_class.value().is_lambda()) {
435 for (
auto &m : act.messages()) {
437 auto message_call_to_lambda{
false};
439 message_call_to_lambda =
442 if (!message_call_to_lambda)
443 new_activity.add_message(m);
447 activities.insert({id, std::move(new_activity)});
452 if (
const auto *maybe_class =
454 maybe_class !=
nullptr && maybe_class->
is_lambda()) {
459 if (
const auto *maybe_method =
461 maybe_method !=
nullptr) {
463 get_participant<model::class_>(maybe_method->class_id());
464 if (maybe_class && maybe_class.value().is_lambda())
469 auto participant_id = p->id();
475 if (participants.count(
id) > 0) {
488 bool message_call_to_lambda{
false};
489 auto maybe_lambda_operator = get_participant<model::method>(m.
to());
491 if (maybe_lambda_operator) {
492 const auto parent_class_id = maybe_lambda_operator.value().class_id();
493 auto maybe_parent_class =
494 get_participant<model::class_>(parent_class_id);
496 if (maybe_parent_class && maybe_parent_class.value().is_lambda()) {
502 for (
auto &mm : lambda_operator_activity.messages()) {
504 auto new_message{mm};
506 new_message.set_from(
id);
512 message_call_to_lambda =
true;
516 return message_call_to_lambda;
535 LOG_TRACE(
" Activity id={}, from={}:", act.from(),
536 from_activity.full_name(
false));
538 for (
const auto &
message : act.messages()) {
545 LOG_TRACE(
" Message from={}, from_id={}, "
546 "to={}, to_id={}, name={}, type={}",
547 from_participant.full_name(
false), from_participant.id(),
554 std::string message_comment{
"None"};
556 message_comment = cmt.value().at(
"comment");
559 LOG_TRACE(
" Message from={}, from_id={}, "
560 "to={}, to_id={}, name={}, type={}, comment={}",
561 from_participant.full_name(
false), from_participant.id(),
562 to_participant.full_name(
false), to_participant.id(),
572 std::vector<message> ¤t_messages)
const
574 bool is_empty_statement{
true};
576 auto rit = current_messages.rbegin();
577 for (; rit != current_messages.rend(); rit++) {
578 if (rit->type() == statement_begin) {
582 is_empty_statement =
false;
587 if (is_empty_statement) {
588 current_messages.erase((rit + 1).base(), current_messages.end());
591 current_messages.emplace_back(std::move(m));
604 if (m.type() != message_t::kCall)
607 const auto &to = get_participant<model::participant>(m.to());
608 if (!to || to.value().skip())
611 if (!should_include(to.value())) {
612 LOG_DBG(
"Excluding call from [{}] to {} [{}]", m.from(),
613 to.value().full_name(false), m.to());
622 for (
auto &[
id, act] : activities_) {
623 int64_t block_nest_level{0};
624 std::vector<std::vector<message>> block_message_stack;
627 block_message_stack.emplace_back();
631 for (
auto &m : act.messages()) {
632 if (is_begin_block_message(m.type())) {
634 block_message_stack.push_back({m});
636 else if (is_end_block_message(m.type())) {
639 block_message_stack.back().push_back(m);
643 if (std::count_if(block_message_stack.back().begin(),
644 block_message_stack.back().end(), [](
auto &m) {
645 return m.type() == message_t::kCall;
647 std::copy(block_message_stack.back().begin(),
648 block_message_stack.back().end(),
650 block_message_stack.at(block_nest_level)));
653 block_message_stack.pop_back();
655 assert(block_nest_level >= 0);
658 if (m.type() == message_t::kCall) {
661 auto to_participant =
662 get_participant<sequence_diagram::model::function>(
664 if (to_participant.has_value()) {
665 m.set_return_type(to_participant.value().return_type());
668 block_message_stack.back().push_back(m);
672 act.messages().clear();
674 for (
auto &m : block_message_stack[0]) {
683bool check_diagram_type<clanguml::sequence_diagram::model::diagram>(
diagram_t t)
685 return t == diagram_t::kSequence;