47 ostr <<
"sequenceDiagram\n";
57 bool comment_generated_from_note_decorators{
false};
59 auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
60 if (note && note->applies_to_diagram(
config().name)) {
61 comment_generated_from_note_decorators =
true;
67 note->text,
config().message_comment_width());
70 ostr << formatted_message <<
'\n';
74 if (comment_generated_from_note_decorators)
77 if (
const auto &cmt = m.
comment();
config().generate_message_comments() &&
85 cmt.value().at(
"comment"),
config().message_comment_width());
89 ostr << formatted_message <<
'\n';
99 LOG_DBG(
"Skipping empty call from '{}' to '{}'", m.
from(), m.
to());
111 if (to.value().
type_name() ==
"method") {
112 const auto &f =
dynamic_cast<const model::method &
>(to.value());
115 else if (to.value().
type_name() ==
"objc_method") {
119 else if (
config().combine_free_functions_into_file_participants()) {
120 if (to.value().
type_name() ==
"function") {
125 if (f.is_cuda_kernel())
127 else if (f.is_cuda_device())
130 else if (to.value().
type_name() ==
"function_template") {
134 if (f.is_cuda_kernel())
136 else if (f.is_cuda_device())
150 ostr << indent(1) << from_alias <<
" "
178 if ((m.
from() != m.
to()) && !to.value().is_void()) {
183 ostr << indent(1) << to_alias <<
" "
185 <<
" " << from_alias <<
" : ";
187 if (
config().generate_return_types()) {
196 eid_t activity_id, std::ostream &ostr, std::vector<eid_t> &visited)
const
198 const auto &a =
model().get_activity(activity_id);
202 if (
config().fold_repeated_activities() && !inserted &&
203 !a.messages().empty()) {
215 for (
const auto &m : a.messages()) {
216 if (m.in_static_declaration_context()) {
223 if (m.type() == message_t::kCall) {
227 visited.push_back(m.from());
229 LOG_DBG(
"Generating message [{}] --> [{}]", m.from(), m.to());
235 ostr << indent(1) <<
"activate " << to_alias <<
'\n';
237 if (
model().sequences().find(m.to()) !=
model().sequences().end()) {
238 if (std::find(visited.begin(), visited.end(), m.to()) ==
241 LOG_DBG(
"Creating activity {} --> {} - missing sequence {}",
242 m.from(), m.to(), m.to());
247 LOG_DBG(
"Skipping activity {} --> {} - missing sequence {}",
248 m.from(), m.to(), m.to());
252 ostr << indent(1) <<
"deactivate " << to_alias <<
'\n';
256 else if (m.type() == message_t::kIf) {
259 ostr << indent(1) <<
"alt";
260 if (
const auto &text = m.condition_text(); text.has_value())
264 else if (m.type() == message_t::kElseIf) {
266 ostr << indent(1) <<
"else";
267 if (
const auto &text = m.condition_text(); text.has_value())
271 else if (m.type() == message_t::kElse) {
273 ostr << indent(1) <<
"else\n";
275 else if (m.type() == message_t::kIfEnd) {
276 ostr << indent(1) <<
"end\n";
278 else if (m.type() == message_t::kWhile) {
281 ostr << indent(1) <<
"loop";
282 if (
const auto &text = m.condition_text(); text.has_value())
286 else if (m.type() == message_t::kWhileEnd) {
287 ostr << indent(1) <<
"end\n";
289 else if (m.type() == message_t::kFor) {
292 ostr << indent(1) <<
"loop";
293 if (
const auto &text = m.condition_text(); text.has_value())
297 else if (m.type() == message_t::kForEnd) {
300 else if (m.type() == message_t::kDo) {
303 ostr << indent(1) <<
"loop";
304 if (
const auto &text = m.condition_text(); text.has_value())
308 else if (m.type() == message_t::kDoEnd) {
309 ostr << indent(1) <<
"end\n";
311 else if (m.type() == message_t::kTry) {
314 ostr << indent(1) <<
"critical\n";
316 else if (m.type() == message_t::kCatch) {
318 ostr << indent(1) <<
"option "
321 else if (m.type() == message_t::kTryEnd) {
323 ostr << indent(1) <<
"end\n";
325 else if (m.type() == message_t::kSwitch) {
328 ostr << indent(1) <<
"alt\n";
330 else if (m.type() == message_t::kCase) {
332 ostr << indent(1) <<
"else "
335 else if (m.type() == message_t::kSwitchEnd) {
336 ostr << indent(1) <<
"end\n";
338 else if (m.type() == message_t::kConditional) {
341 ostr << indent(1) <<
"alt";
342 if (
const auto &text = m.condition_text(); text.has_value())
346 else if (m.type() == message_t::kConditionalElse) {
348 ostr << indent(1) <<
"else\n";
350 else if (m.type() == message_t::kConditionalEnd) {
351 ostr << indent(1) <<
"end\n";
357 std::ostream &ostr,
const std::string &name)
const
359 auto p =
model().get(name);
361 if (!p.has_value()) {
362 LOG_WARN(
"Cannot find participant {} from `participants_order` option",
371 std::ostream &ostr,
eid_t id,
bool force)
const
373 eid_t participant_id{};
376 for (
const auto pid :
model().active_participants()) {
378 participant_id = pid;
386 if (participant_id == 0)
392 const auto &participant =
395 if (participant.type_name() ==
"method") {
396 const auto class_id =
405 const auto &class_participant =
410 auto participant_name =
411 config().using_namespace().relative(
config().simplify_template_type(
415 ostr << indent(1) <<
"participant " << class_participant.alias()
416 <<
" as " << participant_name;
422 else if (participant.type_name() ==
"objc_method") {
423 const auto class_id =
432 const auto &class_participant =
437 auto participant_name =
438 config().using_namespace().relative(
config().simplify_template_type(
442 ostr << indent(1) <<
"participant " << class_participant.alias()
443 <<
" as " <<
"<< ObjC Interface >><br>" << participant_name;
449 else if ((participant.type_name() ==
"function" ||
450 participant.type_name() ==
"function_template") &&
451 config().combine_free_functions_into_file_participants()) {
457 const auto &file_path = f.file();
459 assert(!file_path.empty());
467 std::filesystem::path{file_path},
config().root_directory())
470 ostr << indent(1) <<
"participant "
471 << fmt::format(
"C_{:022}", file_id.value()) <<
" as "
480 auto participant_name =
481 config().using_namespace().relative(
config().simplify_template_type(
485 ostr << indent(1) <<
"participant " << participant.alias() <<
" as ";
487 if (participant.type_name() ==
"function" ||
488 participant.type_name() ==
"function_template") {
494 if (f.is_cuda_kernel())
495 ostr <<
"<< CUDA Kernel >><br>";
496 else if (f.is_cuda_device())
497 ostr <<
"<< CUDA Device >><br>";
500 ostr << participant_name;
517 if ((participant.
type_name() ==
"function" ||
518 participant.
type_name() ==
"function_template") &&
519 config().combine_free_functions_into_file_participants()) {
522 return fmt::format(
"C_{:022}", file_id.value());
525 return participant.
alias();
532 if (
config().participants_order.has_value) {
533 for (
const auto &p :
config().participants_order()) {
534 LOG_DBG(
"Pregenerating participant {}", p);
539 bool star_participant_generated{
false};
553 std::vector<eid_t> visited_participants;
554 for (
const auto from_id : start_from) {
555 if (
model().participants().count(from_id) == 0)
560 if (!from.has_value()) {
561 LOG_WARN(
"Failed to find participant {} for 'from' "
577 if (from.value().type_name() ==
"method" ||
578 config().combine_free_functions_into_file_participants()) {
579 ostr << indent(1) <<
"* "
581 <<
" " << from_alias <<
" : "
582 << from.value().message_name(render_mode) <<
'\n';
585 ostr << indent(1) <<
"activate " << from_alias <<
'\n';
589 if (from.value().type_name() ==
"method" ||
590 config().combine_free_functions_into_file_participants()) {
592 if (!from.value().is_void()) {
593 ostr << indent(1) << from_alias <<
" "
598 if (
config().generate_return_types())
599 ostr << from.value().return_type();
605 ostr << indent(1) <<
"deactivate " << from_alias <<
'\n';
611 std::vector<model::message_chain_t> result;
613 for (
const auto &to_location :
config().to()) {
614 auto to_activity_ids =
model().get_to_activity_ids(to_location);
616 if (to_activity_ids.empty()) {
617 LOG_WARN(
"Failed to find participant matching '{}' for "
619 to_location.location.to_string());
622 for (
const auto &to_activity_id : to_activity_ids) {
623 std::vector<model::message_chain_t> message_chains_unique =
624 model().get_all_from_to_message_chains(
eid_t{}, to_activity_id);
626 result.insert(result.end(), message_chains_unique.begin(),
627 message_chains_unique.end());
636 std::vector<model::message_chain_t> message_chains =
639 for (
const auto &mc : message_chains) {
640 const auto from_activity_id = mc.front().from();
642 if (
model().participants().count(from_activity_id) == 0)
648 if (from.value().type_name() ==
"method" ||
649 config().combine_free_functions_into_file_participants()) {
651 ostr << indent(1) <<
"* "
654 << from.value().message_name(
659 for (
const auto &m : mc) {
666 std::ostream &ostr,
bool star_participant_generated)
const
668 for (
const auto &ft :
config().from_to()) {
671 assert(ft.size() == 2);
673 const auto &from_location = ft.front();
674 const auto &to_location = ft.back();
676 auto from_activity_ids =
model().get_from_activity_ids(from_location);
677 auto to_activity_ids =
model().get_to_activity_ids(to_location);
679 if (from_activity_ids.empty()) {
682 fmt::format(
"Failed to find participant matching '{}' for "
683 "'from' condition: ",
684 from_location.location.to_string()));
687 if (from_activity_ids.empty() || to_activity_ids.empty()) {
690 fmt::format(
"Failed to find participant matching '{}' for "
692 to_location.location.to_string()));
695 for (
const auto from_activity_id : from_activity_ids) {
696 if (
model().participants().count(from_activity_id) == 0)
699 for (
const auto to_activity_id : to_activity_ids) {
700 if (
model().participants().count(to_activity_id) == 0)
703 auto message_chains_unique =
704 model().get_all_from_to_message_chains(
705 from_activity_id, to_activity_id);
707 for (
const auto &mc : message_chains_unique) {
711 if (from.value().type_name() ==
"method" ||
713 .combine_free_functions_into_file_participants()) {
714 if (!star_participant_generated) {
715 ostr << indent(1) <<
"participant *\n";
716 star_participant_generated =
true;
719 ostr << indent(1) <<
"* "
723 << from.value().message_name(
728 for (
const auto &m : mc) {
739 std::vector<eid_t> start_from;
740 for (
const auto &sf :
config().from()) {
741 if (sf.location_type == location_t::function) {
743 for (
const auto &[k, v] :
model().sequences()) {
744 if (
model().participants().count(v.from()) == 0)
747 const auto &caller = *
model().participants().at(v.from());
748 std::string vfrom = caller.full_name(
false);
749 if (sf.location == vfrom) {
750 LOG_DBG(
"Found sequence diagram start point: {}", k);
751 start_from.push_back(k);
759 fmt::format(
"Failed to find participant matching '{}' for "
760 "'from' condition: ",
761 sf.location.to_string()));
771 if (
config().generate_method_arguments() ==