31 std::vector<std::vector<eid_t>> all_message_chains;
32 std::vector<eid_t> current_chain;
38 current_chain.push_back(node.activity_id);
40 if (node.callers.empty()) {
41 auto reversed = current_chain;
42 std::reverse(reversed.begin(), reversed.end());
43 all_message_chains.emplace_back(std::move(reversed));
46 for (
const auto &child : node.callers) {
52 current_chain.pop_back();
58 return all_message_chains;
67 const std::string &full_name)
const
93 const auto participant_id = p->id();
97 assert(participant_id.is_global());
100 LOG_DBG(
"Adding '{}' participant: {}, {} [{}]", p->type_name(),
101 p->full_name(
false), p->id(),
102 p->type_name() ==
"method"
157 std::move(
message), start_type, current_messages);
164 const auto caller_id = m.from();
169 if (current_messages.back().type() == message_t::kCase) {
173 current_messages.emplace_back(std::move(m));
190const std::map<eid_t, std::unique_ptr<participant>> &
213 std::vector<std::string> result;
218 const auto &full_name = from_activity.full_name(
false);
219 if (!full_name.empty())
220 result.push_back(full_name);
223 std::sort(result.begin(), result.end());
224 result.erase(std::unique(result.begin(), result.end()), result.end());
231 std::vector<std::string> result;
234 for (
const auto &m : act.messages()) {
237 const auto &full_name = to_activity.full_name(
false);
238 if (!full_name.empty())
239 result.push_back(full_name);
244 std::sort(result.begin(), result.end());
245 result.erase(std::unique(result.begin(), result.end()), result.end());
253 std::vector<eid_t> to_activities{};
256 for (
const auto &m : v.messages()) {
261 std::string vto = callee.full_name(
false);
264 "Found sequence diagram end point '{}': {}", vto, m.to());
265 to_activities.push_back(m.to());
270 if (to_activities.empty()) {
271 LOG_WARN(
"Failed to find 'to' participant {} for to "
278 return to_activities;
284 std::vector<eid_t> from_activities{};
291 std::string vfrom = caller.full_name(
false);
292 if (from_location.
location == vfrom) {
293 LOG_DBG(
"Found sequence diagram start point '{}': {}", vfrom, k);
294 from_activities.push_back(k);
298 if (from_activities.empty()) {
299 LOG_WARN(
"Failed to find 'from' participant {} for from "
306 return from_activities;
310 std::set<eid_t> visited_callers)
const
321 for (
const auto &caller : callers) {
322 if (visited_callers.count(caller) > 0) {
332 node.
callers.emplace_back(std::move(caller_node));
337 const eid_t from_activity,
const eid_t to_activity)
const
340 std::vector<message_chain_t> message_chains;
348 for (
const auto &m : v.messages()) {
352 if (m.to() == to_activity) {
355 target_roots.
callers.emplace_back(std::move(node));
362 for (
auto &caller : target_roots.
callers)
370 sort(begin(activity_id_chains), end(activity_id_chains));
371 activity_id_chains.erase(
372 unique(begin(activity_id_chains), end(activity_id_chains)),
373 end(activity_id_chains));
376 for (
const auto &chain : activity_id_chains) {
378 for (
auto it = begin(chain); it != end(chain); it++) {
379 const auto next_it = it + 1;
380 if (next_it == end(chain))
387 auto to_id = *(next_it);
391 for (
const auto &m : act.messages()) {
392 if (m.to() == to_id) {
393 message_chain.push_back(m);
398 message_chains.emplace_back(std::move(message_chain));
402 std::vector<message_chain_t> message_chains_filtered{};
404 for (
auto &mc : message_chains) {
410 if (from_activity.
value() == 0 ||
411 (mc.front().from() == from_activity)) {
412 message_chains_filtered.push_back(mc);
416 int message_chain_index{};
417 for (
const auto &mc : message_chains_filtered) {
418 LOG_INFO(
"\t{}: {}", message_chain_index++,
419 fmt::join(util::map<std::string>(mc,
426 return message_chains_filtered;
436 using namespace std::string_literals;
438 std::map<eid_t, activity> activities;
439 std::map<eid_t, std::unique_ptr<participant>>
participants;
448 auto maybe_lambda_activity = get_participant<model::method>(
id);
450 if (maybe_lambda_activity) {
451 const auto parent_class_id =
452 maybe_lambda_activity.value().class_id();
453 auto maybe_parent_class =
454 get_participant<model::class_>(parent_class_id);
456 if (maybe_parent_class && maybe_parent_class.value().is_lambda()) {
464 for (
auto &m : act.messages()) {
466 auto message_call_to_lambda{
false};
468 message_call_to_lambda =
471 if (!message_call_to_lambda)
472 new_activity.add_message(m);
476 activities.insert({id, std::move(new_activity)});
481 if (
const auto *maybe_class =
483 maybe_class !=
nullptr && maybe_class->
is_lambda()) {
488 if (
const auto *maybe_method =
490 maybe_method !=
nullptr) {
492 get_participant<model::class_>(maybe_method->class_id());
493 if (maybe_class && maybe_class.value().is_lambda()) {
499 auto participant_id = p->id();
505 if (participants.count(
id) > 0) {
518 using namespace std::string_literals;
520 bool message_call_to_lambda{
false};
521 auto maybe_lambda_operator = get_participant<model::method>(m.
to());
523 if (maybe_lambda_operator) {
524 const auto parent_class_id = maybe_lambda_operator.value().class_id();
525 auto maybe_parent_class =
526 get_participant<model::class_>(parent_class_id);
528 if (maybe_parent_class && maybe_parent_class.value().is_lambda()) {
534 for (
auto &mm : lambda_operator_activity.messages()) {
542 auto new_message{mm};
544 new_message.set_from(
id);
551 message_call_to_lambda =
true;
555 return message_call_to_lambda;
574 LOG_TRACE(
" Activity id={}, from={}:", act.from(),
575 from_activity.full_name(
false));
577 for (
const auto &
message : act.messages()) {
586 " Return from={}, from_id={}, name={}, type={}",
587 from_participant.full_name(
false),
591 const auto &to_participant =
594 LOG_TRACE(
" Return from={}, from_id={}, "
595 "to={}, to_id={}, name={}, type={}",
596 from_participant.full_name(
false),
597 from_participant.id(), to_participant.full_name(
false),
603 LOG_TRACE(
" Message from={}, from_id={}, "
604 "to={}, to_id={}, name={}, type={}",
605 from_participant.full_name(
false), from_participant.id(),
612 std::string message_comment{
"None"};
614 message_comment = cmt.value().at(
"comment");
617 LOG_TRACE(
" Message from={}, from_id={}, "
618 "to={}, to_id={}, name={}, type={}, comment={}",
619 from_participant.full_name(
false), from_participant.id(),
620 to_participant.full_name(
false), to_participant.id(),
630 std::vector<message> ¤t_messages)
const
632 bool is_empty_statement{
true};
634 auto rit = current_messages.rbegin();
635 for (; rit != current_messages.rend(); rit++) {
636 if (rit->type() == statement_begin) {
640 is_empty_statement =
false;
644 is_empty_statement =
false;
648 is_empty_statement =
false;
653 if (is_empty_statement) {
654 current_messages.erase((rit + 1).base(), current_messages.end());
657 current_messages.emplace_back(std::move(m));
670 if (m.type() != message_t::kCall)
673 const auto &to = get_participant<model::participant>(m.to());
674 if (!to || to.value().skip())
677 if (!should_include(to.value())) {
678 LOG_DBG(
"Excluding call from [{}] to {} [{}]", m.from(),
679 to.value().full_name(false), m.to());
688 for (
auto &[
id, act] : activities_) {
689 int64_t block_nest_level{0};
690 std::vector<std::vector<message>> block_message_stack;
693 block_message_stack.emplace_back();
697 for (
auto &m : act.messages()) {
698 if (is_begin_block_message(m.type())) {
700 block_message_stack.push_back({m});
702 else if (is_end_block_message(m.type())) {
705 block_message_stack.back().push_back(m);
709 if (std::count_if(block_message_stack.back().begin(),
710 block_message_stack.back().end(), [](
auto &m) {
711 return (m.type() == message_t::kCall) ||
712 (m.type() == message_t::kReturn) ||
713 (m.type() == message_t::kCoReturn);
715 std::copy(block_message_stack.back().begin(),
716 block_message_stack.back().end(),
718 block_message_stack.at(block_nest_level)));
721 block_message_stack.pop_back();
723 assert(block_nest_level >= 0);
726 if (m.type() == message_t::kCall) {
729 auto to_participant =
730 get_participant<sequence_diagram::model::function>(
732 if (to_participant.has_value()) {
733 m.set_return_type(to_participant.value().return_type());
736 block_message_stack.back().push_back(m);
740 act.messages().clear();
742 for (
auto &m : block_message_stack[0]) {
751bool check_diagram_type<clanguml::sequence_diagram::model::diagram>(
diagram_t t)
753 return t == diagram_t::kSequence;