23#include <inja/inja.hpp> 
   32          *
this, config.generate_packages()}
 
   43    if (maybe_link_pattern) {
 
   44        const auto &[link_prefix, link_pattern] = *maybe_link_pattern;
 
   57    if (maybe_tooltip_pattern) {
 
   58        const auto &[tooltip_prefix, tooltip_pattern] = *maybe_tooltip_pattern;
 
   73    std::string class_type{
"class"};
 
   75        class_type = 
"abstract";
 
   77    std::string full_name;
 
   78    if (!
config().generate_fully_qualified_name())
 
   83    assert(!full_name.empty());
 
   87    auto fn = 
config().simplify_template_type(full_name);
 
   92        fn = fn.substr(0, fn.size() - 2) + 
"< >";
 
   95    ostr << class_type << 
" \"" << fn;
 
   97    ostr << 
"\" as " << c.
alias() << 
'\n';
 
  107    if (!
config().generate_fully_qualified_name())
 
  112    ostr << 
"\" as " << e.
alias() << 
'\n';
 
  122    if (!
config().generate_fully_qualified_name())
 
  127    ostr << 
"\" as " << c.
alias() << 
'\n';
 
  145    ostr << 
"\" as " << e.
alias() << 
'\n';
 
  153    std::string class_type{
"class"};
 
  155        class_type = 
"abstract";
 
  157    ostr << class_type << 
" " << c.
alias();
 
  160        ostr << 
" " << 
"<<union>>";
 
  162    if (
config().generate_links) {
 
  168    ostr << 
" {" << 
'\n';
 
  184    std::set<std::string> rendered_relations;
 
  186    std::stringstream all_relations_str;
 
  192            LOG_DBG(
"Skipping {} relation from {} to {} due " 
  194                to_string(r.type()), c.
full_name(
true), r.destination(),
 
  202    std::vector<clanguml::class_diagram::model::class_member> members{
 
  210    for (
const auto &m : members) {
 
  211        if (!
config().include_relations_also_as_members() &&
 
  212            rendered_relations.find(m.name()) != rendered_relations.end())
 
  224    for (
const auto &member : c.
members())
 
  227    for (
const auto &method : c.
methods())
 
  234    const std::vector<class_method> &methods, std::ostream &ostr)
 const 
  236    auto sorted_methods = methods;
 
  239    for (
const auto &m : sorted_methods) {
 
  246    const std::vector<objc_method> &methods, std::ostream &ostr)
 const 
  248    auto sorted_methods = methods;
 
  251    for (
const auto &m : sorted_methods) {
 
  261    const auto &uns = 
config().using_namespace();
 
  263    constexpr auto kAbbreviatedMethodArgumentsLength{15};
 
  268        ostr << 
"{abstract} ";
 
  273    std::string type{uns.relative(
config().simplify_template_type(m.
type()))};
 
  275    ostr << plantuml_common::to_plantuml(m.
access()) << m.
name();
 
  282    if (
config().generate_method_arguments() !=
 
  284        std::vector<std::string> params;
 
  286            std::back_inserter(params), [
this](
const auto &mp) {
 
  287                return config().simplify_template_type(
 
  288                    mp.to_string(config().using_namespace()));
 
  290        auto args_string = fmt::format(
"{}", fmt::join(params, 
", "));
 
  291        if (
config().generate_method_arguments() ==
 
  294                args_string, kAbbreviatedMethodArgumentsLength);
 
  301        ostr << 
" constexpr";
 
  303        ostr << 
" consteval";
 
  317        ostr << 
" = default";
 
  319        ostr << 
" = deleted";
 
  322        ostr << 
" [coroutine]";
 
  324    ostr << 
" : " << type;
 
  326    if (
config().generate_links) {
 
  335    const auto &uns = 
config().using_namespace();
 
  342    ostr << plantuml_common::to_plantuml(m.
access())
 
  344         << uns.relative(
config().simplify_template_type(
 
  347    if (
config().generate_links) {
 
  354    std::string class_type{
"class"};
 
  356    ostr << class_type << 
" " << c.
alias() << 
" <<concept>>";
 
  358    if (
config().generate_links) {
 
  364    ostr << 
" {" << 
'\n';
 
  366    if (
config().generate_concept_requirements() &&
 
  368        std::vector<std::string> parameters;
 
  371            parameters.emplace_back(p.to_string(
config().using_namespace()));
 
  374        ostr << fmt::format(
"({})\n", fmt::join(parameters, 
","));
 
  386    std::string class_type{
"class"};
 
  388        class_type = 
"protocol";
 
  390    ostr << class_type << 
" " << c.
alias();
 
  394        ostr << 
"<<ObjC Protocol>>";
 
  396        ostr << 
"<<ObjC Category>>";
 
  398        ostr << 
"<<ObjC Interface>>";
 
  400    if (
config().generate_links) {
 
  406    ostr << 
" {" << 
'\n';
 
  417    std::set<std::string> rendered_relations;
 
  419    std::stringstream all_relations_str;
 
  425            LOG_DBG(
"Skipping {} relation from {} to {} due " 
  427                to_string(r.type()), c.
full_name(
true), r.destination(),
 
  435    std::vector<clanguml::class_diagram::model::objc_member> members{
 
  443    for (
const auto &m : members) {
 
  444        if (!
config().include_relations_also_as_members() &&
 
  445            rendered_relations.find(m.name()) != rendered_relations.end())
 
  457    for (
const auto &member : c.
members())
 
  460    for (
const auto &method : c.
methods())
 
  468    const auto &uns = 
config().using_namespace();
 
  470    constexpr auto kAbbreviatedMethodArgumentsLength{15};
 
  477    std::string type{uns.relative(
config().simplify_template_type(m.
type()))};
 
  479    ostr << plantuml_common::to_plantuml(m.
access()) << m.
name();
 
  482    if (
config().generate_method_arguments() !=
 
  484        std::vector<std::string> params;
 
  486            std::back_inserter(params), [
this](
const auto &mp) {
 
  487                return config().simplify_template_type(
 
  488                    mp.to_string(config().using_namespace()));
 
  490        auto args_string = fmt::format(
"{}", fmt::join(params, 
", "));
 
  491        if (
config().generate_method_arguments() ==
 
  494                args_string, kAbbreviatedMethodArgumentsLength);
 
  500    ostr << 
" : " << type;
 
  502    if (
config().generate_links) {
 
  511    const auto &uns = 
config().using_namespace();
 
  518    ostr << plantuml_common::to_plantuml(m.
access())
 
  520         << uns.relative(
config().simplify_template_type(
 
  523    if (
config().generate_links) {
 
  531    for (
const auto &decorator : member.
decorators()) {
 
  532        auto note = std::dynamic_pointer_cast<decorators::note>(decorator);
 
  533        if (note && note->applies_to_diagram(
config().name)) {
 
  534            ostr << 
"note " << note->position << 
" of " << alias
 
  535                 << 
"::" << member.
name() << 
'\n' 
  536                 << note->text << 
'\n' 
  543    const relationship &r, std::set<std::string> &rendered_relations)
 const 
  547    LOG_DBG(
"Processing relationship {}", to_string(r.
type()));
 
  549    std::string destination;
 
  552    if (!target_element.has_value())
 
  554            "Missing element in the model for ID: {}", r.
destination())};
 
  556    destination = target_element.value().full_name(
false);
 
  559        destination = destination.substr(2, destination.size());
 
  561    std::string puml_relation;
 
  565    puml_relation += plantuml_common::to_plantuml(r, 
config());
 
  570    if (!r.
label().empty()) {
 
  571        rendered_relations.emplace(r.
label());
 
  576    const class_ &c, std::ostream &ostr)
 const 
  583    std::set<std::string> rendered_relations;
 
  585    std::stringstream all_relations_str;
 
  586    std::set<std::string> unique_relations;
 
  589        LOG_TRACE(
"== Processing relationship {}",
 
  590            plantuml_common::to_plantuml(r, 
config()));
 
  592        std::stringstream relstr;
 
  595            destination = r.destination();
 
  597            std::string puml_relation;
 
  598            if (!r.multiplicity_source().empty())
 
  599                puml_relation += 
"\"" + r.multiplicity_source() + 
"\" ";
 
  601            puml_relation += plantuml_common::to_plantuml(r, 
config());
 
  603            if (!r.multiplicity_destination().empty())
 
  604                puml_relation += 
" \"" + r.multiplicity_destination() + 
"\"";
 
  606            std::string target_alias;
 
  608                target_alias = 
model().to_alias(destination);
 
  611                LOG_DBG(
"Failed to find alias to {}", destination);
 
  619            if (r.type() != relationship_t::kExtension)
 
  620                relstr << c.
alias() << 
" " << puml_relation << 
" " 
  623                relstr << target_alias << 
" <|-- " << c.
alias();
 
  625            if (
config().generate_links) {
 
  630            if (!r.label().empty()) {
 
  631                relstr << 
" : " << plantuml_common::to_plantuml(r.access())
 
  633                rendered_relations.emplace(r.label());
 
  636            if (unique_relations.count(relstr.str()) == 0) {
 
  637                unique_relations.emplace(relstr.str());
 
  639                LOG_TRACE(
"=== Adding relation {}", relstr.str());
 
  641                all_relations_str << relstr.str() << 
'\n';
 
  645            LOG_DBG(
"=== Skipping {} relation from {} to {} due " 
  647                to_string(r.type()), c.
full_name(
true), destination, e.what());
 
  651    ostr << all_relations_str.str();
 
  655    const concept_ &c, std::ostream &ostr)
 const 
  662    std::set<std::string> rendered_relations;
 
  664    std::stringstream all_relations_str;
 
  665    std::set<std::string> unique_relations;
 
  668        if (!
model().should_include(r.type()))
 
  671        LOG_TRACE(
"== Processing relationship {}", to_string(r.type()));
 
  673        std::stringstream relstr;
 
  676            destination = r.destination();
 
  678            std::string puml_relation;
 
  679            if (!r.multiplicity_source().empty())
 
  680                puml_relation += 
"\"" + r.multiplicity_source() + 
"\" ";
 
  682            puml_relation += plantuml_common::to_plantuml(r, 
config());
 
  684            if (!r.multiplicity_destination().empty())
 
  685                puml_relation += 
" \"" + r.multiplicity_destination() + 
"\"";
 
  687            std::string target_alias;
 
  689                target_alias = 
model().to_alias(destination);
 
  692                LOG_DBG(
"Failed to find alias to {}", destination);
 
  700            relstr << c.
alias() << 
" " << puml_relation << 
" " << target_alias;
 
  702            if (
config().generate_links) {
 
  707            if (!r.label().empty()) {
 
  708                relstr << 
" : " << plantuml_common::to_plantuml(r.access())
 
  710                rendered_relations.emplace(r.label());
 
  713            if (unique_relations.count(relstr.str()) == 0) {
 
  714                unique_relations.emplace(relstr.str());
 
  716                LOG_TRACE(
"=== Adding relation {}", relstr.str());
 
  718                all_relations_str << relstr.str() << 
'\n';
 
  722            LOG_DBG(
"=== Skipping {} relation from {} to {} due " 
  724                to_string(r.type()), c.
full_name(
true), destination, e.what());
 
  728    ostr << all_relations_str.str();
 
  733    ostr << 
"enum " << e.
alias();
 
  735    if (
config().generate_links) {
 
  741    ostr << 
" {" << 
'\n';
 
  743    for (
const auto &enum_constant : e.
constants()) {
 
  744        ostr << enum_constant << 
'\n';
 
  756        std::stringstream relstr;
 
  758            destination = r.destination();
 
  760            auto target_alias = 
model().to_alias(destination);
 
  766            relstr << e.
alias() << 
" " 
  769                   << 
" " << target_alias;
 
  771            if (
config().generate_links) {
 
  776            if (!r.label().empty())
 
  777                relstr << 
" : " << r.label();
 
  781            ostr << relstr.str();
 
  784            LOG_DBG(
"Skipping {} relation from {} to {} due " 
  788                e.
full_name(
true), destination, ex.what());
 
  801    std::set<std::string> rendered_relations;
 
  803    std::stringstream all_relations_str;
 
  804    std::set<std::string> unique_relations;
 
  807        LOG_TRACE(
"== Processing relationship {}",
 
  808            plantuml_common::to_plantuml(r, 
config()));
 
  810        std::stringstream relstr;
 
  813            destination = r.destination();
 
  815            std::string puml_relation;
 
  816            if (!r.multiplicity_source().empty())
 
  817                puml_relation += 
"\"" + r.multiplicity_source() + 
"\" ";
 
  819            puml_relation += plantuml_common::to_plantuml(r, 
config());
 
  821            if (!r.multiplicity_destination().empty())
 
  822                puml_relation += 
" \"" + r.multiplicity_destination() + 
"\"";
 
  824            std::string target_alias;
 
  826                target_alias = 
model().to_alias(destination);
 
  829                LOG_DBG(
"Failed to find alias to {}", destination);
 
  837            if (r.type() != relationship_t::kExtension)
 
  838                relstr << c.
alias() << 
" " << puml_relation << 
" " 
  841                relstr << target_alias << 
" <|-- " << c.
alias();
 
  843            if (
config().generate_links) {
 
  848            if (!r.label().empty()) {
 
  849                relstr << 
" : " << plantuml_common::to_plantuml(r.access())
 
  851                rendered_relations.emplace(r.label());
 
  854            if (unique_relations.count(relstr.str()) == 0) {
 
  855                unique_relations.emplace(relstr.str());
 
  857                LOG_TRACE(
"=== Adding relation {}", relstr.str());
 
  859                all_relations_str << relstr.str() << 
'\n';
 
  863            LOG_DBG(
"=== Skipping {} relation from {} to {} due " 
  865                to_string(r.type()), c.
full_name(
true), destination, e.what());
 
  869    ostr << all_relations_str.str();
 
  874    if (
config().generate_packages()) {
 
  875        LOG_DBG(
"Generating package {}",
 
  881        ostr << 
"as " << p.
alias();
 
  884            ostr << 
" <<deprecated>>";
 
  888        ostr << 
" {" << 
'\n';
 
  894    if (
config().generate_packages()) {
 
  901    const std::string & , std::ostream &ostr)
 const 
  903    ostr << 
"together {\n";
 
  907    const std::string & , std::ostream &ostr)
 const