49 LOG_DBG(
"Skipping empty call from '{}' to '{}'", m.
from(), m.
to());
62 const auto &f =
dynamic_cast<const model::method &
>(to.value());
63 const std::string_view style = f.
is_static() ?
"__" :
"";
65 fmt::format(
"{}{}{}", style, f.message_name(render_mode), style);
67 else if (to.value().
type_name() ==
"objc_method") {
69 const std::string_view style = f.
is_static() ?
"__" :
"";
71 fmt::format(
"{}{}{}", style, f.message_name(render_mode), style);
73 else if (
config().combine_free_functions_into_file_participants()) {
74 if (to.value().
type_name() ==
"function") {
78 if (f.is_cuda_kernel())
80 else if (f.is_cuda_device())
83 else if (to.value().
type_name() ==
"function_template") {
87 if (f.is_cuda_kernel())
89 else if (f.is_cuda_device())
103 ostr << from_alias <<
" "
108 if (
config().generate_links) {
139 if (to.has_value() && !to.value().is_void()) {
144 ostr << to_alias <<
" "
146 <<
" " << from_alias;
148 if (
config().generate_return_types()) {
157 eid_t activity_id, std::ostream &ostr, std::vector<eid_t> &visited)
const
159 const auto &a =
model().get_activity(activity_id);
163 if (
config().fold_repeated_activities() && !inserted &&
164 !a.messages().empty()) {
178 for (
const auto &m : a.messages()) {
179 if (m.in_static_declaration_context()) {
186 if (m.type() == message_t::kCall) {
190 visited.push_back(m.from());
192 LOG_DBG(
"Generating message [{}] --> [{}]", m.from(), m.to());
198 ostr <<
"activate " << to_alias <<
'\n';
200 if (
model().sequences().find(m.to()) !=
model().sequences().end()) {
201 if (std::find(visited.begin(), visited.end(), m.to()) ==
204 LOG_DBG(
"Creating activity {} --> {} - missing sequence {}",
205 m.from(), m.to(), m.to());
210 LOG_DBG(
"Skipping activity {} --> {} - missing sequence {}",
211 m.from(), m.to(), m.to());
215 ostr <<
"deactivate " << to_alias <<
'\n';
219 else if (m.type() == message_t::kIf) {
223 if (
const auto &text = m.condition_text(); text.has_value())
224 ostr <<
" " << text.value();
227 else if (m.type() == message_t::kElseIf) {
230 if (
const auto &text = m.condition_text(); text.has_value())
231 ostr <<
" " << text.value();
234 else if (m.type() == message_t::kElse) {
238 else if (m.type() == message_t::kIfEnd) {
241 else if (m.type() == message_t::kWhile) {
245 if (
const auto &text = m.condition_text(); text.has_value())
246 ostr <<
" " << text.value();
249 else if (m.type() == message_t::kWhileEnd) {
252 else if (m.type() == message_t::kFor) {
256 if (
const auto &text = m.condition_text(); text.has_value())
257 ostr <<
" " << text.value();
260 else if (m.type() == message_t::kForEnd) {
263 else if (m.type() == message_t::kDo) {
267 if (
const auto &text = m.condition_text(); text.has_value())
268 ostr <<
" " << text.value();
271 else if (m.type() == message_t::kDoEnd) {
274 else if (m.type() == message_t::kTry) {
277 ostr <<
"group try\n";
279 else if (m.type() == message_t::kCatch) {
281 ostr <<
"else " << m.message_name() <<
'\n';
283 else if (m.type() == message_t::kTryEnd) {
287 else if (m.type() == message_t::kSwitch) {
290 ostr <<
"group switch\n";
292 else if (m.type() == message_t::kCase) {
294 ostr <<
"else " << m.message_name() <<
'\n';
296 else if (m.type() == message_t::kSwitchEnd) {
299 else if (m.type() == message_t::kConditional) {
303 if (
const auto &text = m.condition_text(); text.has_value())
304 ostr <<
" " << text.value();
307 else if (m.type() == message_t::kConditionalElse) {
311 else if (m.type() == message_t::kConditionalEnd) {
325 bool comment_generated_from_note_decorators{
false};
326 for (
const auto &decorator : m.
decorators()) {
327 auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
328 if (note && note->applies_to_diagram(
config().name)) {
329 comment_generated_from_note_decorators =
true;
334 note->text,
config().message_comment_width())
337 ostr <<
"end note" <<
'\n';
341 if (comment_generated_from_note_decorators)
344 if (!
config().generate_message_comments())
348 if (
const auto &comment = m.
comment(); comment &&
354 config().message_comment_width())
357 ostr <<
"end note" <<
'\n';
362 std::ostream &ostr,
const std::string &name)
const
364 auto p =
model().get(name);
366 if (!p.has_value()) {
367 LOG_WARN(
"Cannot find participant {} from `participants_order` "
377 std::ostream &ostr,
eid_t id,
bool force)
const
379 eid_t participant_id{};
382 for (
const auto pid :
model().active_participants()) {
384 participant_id = pid;
392 if (participant_id == 0)
398 const auto &participant =
401 if (participant.type_name() ==
"method") {
402 const auto class_id =
411 const auto &class_participant =
416 auto participant_name =
config().simplify_template_type(
419 config().using_namespace().relative(participant_name);
423 ostr <<
"participant \"" << participant_name <<
"\" as "
424 << class_participant.alias();
426 if (
config().generate_links) {
428 ostr, class_participant);
435 else if (participant.type_name() ==
"objc_method") {
436 const auto class_id =
445 const auto &class_participant =
450 auto participant_name =
config().simplify_template_type(
453 config().using_namespace().relative(participant_name);
457 ostr <<
"participant \"" << participant_name <<
"\" as "
458 << class_participant.alias() <<
" <<ObjC Interface>>";
460 if (
config().generate_links) {
462 ostr, class_participant);
469 else if ((participant.type_name() ==
"function" ||
470 participant.type_name() ==
"function_template") &&
471 config().combine_free_functions_into_file_participants()) {
474 const auto &file_path =
480 assert(!file_path.empty());
488 std::filesystem::path{file_path},
config().root_directory())
491 ostr <<
"participant \"" << participant_name <<
"\" as "
492 << fmt::format(
"C_{:022}", file_id.value());
501 auto participant_name =
502 config().using_namespace().relative(
config().simplify_template_type(
506 ostr <<
"participant \"" << participant_name <<
"\" as "
507 << participant.alias();
509 if (
const auto *function_ptr =
512 if (function_ptr->is_cuda_kernel())
513 ostr <<
" << CUDA Kernel >>";
514 else if (function_ptr->is_cuda_device())
515 ostr <<
" << CUDA Device >>";
518 if (
config().generate_links) {
539 if ((participant.
type_name() ==
"function" ||
540 participant.
type_name() ==
"function_template") &&
541 config().combine_free_functions_into_file_participants()) {
544 return fmt::format(
"C_{:022}", file_id.value());
547 return participant.
alias();
554 if (
config().participants_order.has_value) {
555 for (
const auto &p :
config().participants_order()) {
556 LOG_DBG(
"Pregenerating participant {}", p);
573 std::vector<eid_t> visited_participants;
575 for (
const auto from_id : start_from) {
576 if (
model().participants().count(from_id) == 0)
581 if (!from.has_value()) {
582 LOG_WARN(
"Failed to find participant {} for 'from' "
598 if (from.value().type_name() ==
"method" ||
599 from.value().type_name() ==
"objc_method" ||
600 config().combine_free_functions_into_file_participants()) {
601 ostr <<
"[->" <<
" " << from_alias <<
" : "
602 << from.value().message_name(render_mode) <<
'\n';
605 ostr <<
"activate " << from_alias <<
'\n';
609 if (from.value().type_name() ==
"method" ||
610 from.value().type_name() ==
"objc_method" ||
611 config().combine_free_functions_into_file_participants()) {
613 if (!from.value().is_void()) {
614 ostr <<
"[<--" <<
" " << from_alias;
616 if (
config().generate_return_types())
617 ostr <<
" : //" << from.value().return_type() <<
"//";
623 ostr <<
"deactivate " << from_alias <<
'\n';
629 std::vector<eid_t> start_from;
630 for (
const auto &sf :
config().from()) {
631 if (sf.location_type == location_t::function) {
633 for (
const auto &[k, v] :
model().sequences()) {
634 if (
model().participants().count(v.from()) == 0)
637 const auto &caller = *
model().participants().at(v.from());
638 std::string vfrom = caller.full_name(
false);
639 if (sf.location == vfrom) {
640 LOG_DBG(
"Found sequence diagram start point: {}", k);
641 start_from.push_back(k);
649 fmt::format(
"Failed to find participant matching '{}' for "
650 "'from' condition: ",
651 sf.location.to_string()));
660 std::vector<model::message_chain_t> result;
662 for (
const auto &to_location :
config().to()) {
663 auto to_activity_ids =
model().get_to_activity_ids(to_location);
665 if (to_activity_ids.empty()) {
666 LOG_WARN(
"Failed to find participant matching '{}' for "
668 to_location.location.to_string());
671 for (
const auto &to_activity_id : to_activity_ids) {
672 std::vector<model::message_chain_t> message_chains_unique =
673 model().get_all_from_to_message_chains(
eid_t{}, to_activity_id);
675 result.insert(result.end(), message_chains_unique.begin(),
676 message_chains_unique.end());
685 std::vector<model::message_chain_t> message_chains =
688 bool first_separator_skipped{
false};
689 for (
const auto &mc : message_chains) {
690 if (!first_separator_skipped)
691 first_separator_skipped =
true;
695 const auto from_activity_id = mc.front().from();
697 if (
model().participants().count(from_activity_id) == 0)
703 if (from.value().type_name() ==
"method" ||
704 from.value().type_name() ==
"objc_method" ||
705 config().combine_free_functions_into_file_participants()) {
708 << from.value().message_name(
713 for (
const auto &m : mc) {
721 for (
const auto &ft :
config().from_to()) {
724 assert(ft.size() == 2);
726 const auto &from_location = ft.front();
727 const auto &to_location = ft.back();
729 const auto from_activity_ids =
730 model().get_from_activity_ids(from_location);
732 const auto to_activity_ids =
model().get_to_activity_ids(to_location);
734 if (from_activity_ids.empty()) {
737 fmt::format(
"Failed to find participant matching '{}' for "
738 "'from' condition: ",
739 from_location.location.to_string()));
742 if (from_activity_ids.empty() || to_activity_ids.empty()) {
745 fmt::format(
"Failed to find participant matching '{}' for "
747 to_location.location.to_string()));
750 bool first_separator_skipped{
false};
752 for (
const auto from_activity_id : from_activity_ids) {
753 if (
model().participants().count(from_activity_id) == 0)
756 for (
const auto to_activity_id : to_activity_ids) {
757 if (
model().participants().count(to_activity_id) == 0)
760 auto message_chains_unique =
761 model().get_all_from_to_message_chains(
762 from_activity_id, to_activity_id);
764 for (
const auto &mc : message_chains_unique) {
765 if (!first_separator_skipped)
766 first_separator_skipped =
true;
773 if (from.value().type_name() ==
"method" ||
774 from.value().type_name() ==
"objc_method" ||
776 .combine_free_functions_into_file_participants()) {
780 << from.value().message_name(
785 for (
const auto &m : mc) {
797 if (
config().generate_method_arguments() ==