Removed usr from class diagram generator and visitor

This commit is contained in:
Bartek Kryza
2021-09-26 22:58:31 +02:00
parent 29c8c93478
commit 52c6ebfa19
6 changed files with 204 additions and 209 deletions

View File

@@ -106,7 +106,7 @@ void generator::generate_alias(const class_ &c, std::ostream &ostr) const
if (c.is_abstract()) if (c.is_abstract())
class_type = "abstract"; class_type = "abstract";
ostr << class_type << " \"" << c.full_name(m_config.using_namespace); ostr << class_type << " \"" << c.full_name();
ostr << "\" as " << c.alias() << '\n'; ostr << "\" as " << c.alias() << '\n';
} }
@@ -114,7 +114,7 @@ void generator::generate_alias(const class_ &c, std::ostream &ostr) const
void generator::generate_alias(const enum_ &e, std::ostream &ostr) const void generator::generate_alias(const enum_ &e, std::ostream &ostr) const
{ {
ostr << "enum" ostr << "enum"
<< " \"" << e.full_name(m_config.using_namespace); << " \"" << e.full_name();
ostr << "\" as " << e.alias() << '\n'; ostr << "\" as " << e.alias() << '\n';
} }
@@ -186,7 +186,7 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
std::stringstream all_relations_str; std::stringstream all_relations_str;
std::set<std::string> unique_relations; std::set<std::string> unique_relations;
for (const auto &r : c.relationships) { for (const auto &r : c.relationships()) {
if (!m_config.should_include_relationship(name(r.type))) if (!m_config.should_include_relationship(name(r.type)))
continue; continue;
@@ -195,21 +195,7 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
std::stringstream relstr; std::stringstream relstr;
std::string destination; std::string destination;
try { try {
if (r.destination.find("#") != std::string::npos ||
r.destination.find("@") != std::string::npos) {
destination = m_model.usr_to_name(uns, r.destination);
// If something went wrong and we have an empty destination
// generate the relationship but comment it out for
// debugging
if (destination.empty()) {
relstr << "' ";
destination = r.destination; destination = r.destination;
}
}
else {
destination = r.destination;
}
LOG_DBG("=== Destination is: {}", destination); LOG_DBG("=== Destination is: {}", destination);
@@ -222,9 +208,9 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
if (!r.multiplicity_destination.empty()) if (!r.multiplicity_destination.empty())
puml_relation += " \"" + r.multiplicity_destination + "\""; puml_relation += " \"" + r.multiplicity_destination + "\"";
relstr << m_model.to_alias(uns, ns_relative(uns, c.full_name(uns))) relstr << m_model.to_alias(ns_relative(uns, c.full_name())) << " "
<< " " << puml_relation << " " << puml_relation << " "
<< m_model.to_alias(uns, ns_relative(uns, destination)); << m_model.to_alias(ns_relative(uns, destination));
if (!r.label.empty()) { if (!r.label.empty()) {
relstr << " : " << to_string(r.scope) << r.label; relstr << " : " << to_string(r.scope) << r.label;
@@ -244,7 +230,7 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
catch (error::uml_alias_missing &e) { catch (error::uml_alias_missing &e) {
LOG_ERROR("=== Skipping {} relation from {} to {} due " LOG_ERROR("=== Skipping {} relation from {} to {} due "
"to: {}", "to: {}",
to_string(r.type), c.full_name(uns), destination, e.what()); to_string(r.type), c.full_name(), destination, e.what());
} }
} }
@@ -272,17 +258,15 @@ void generator::generate(const class_ &c, std::ostream &ostr) const
for (const auto &b : c.bases) { for (const auto &b : c.bases) {
std::stringstream relstr; std::stringstream relstr;
try { try {
relstr << m_model.to_alias(uns, ns_relative(uns, b.name)) relstr << m_model.to_alias(ns_relative(uns, b.name)) << " <|-- "
<< " <|-- " << m_model.to_alias(ns_relative(uns, c.full_name()))
<< m_model.to_alias(
uns, ns_relative(uns, c.full_name(uns)))
<< '\n'; << '\n';
ostr << relstr.str(); ostr << relstr.str();
} }
catch (error::uml_alias_missing &e) { catch (error::uml_alias_missing &e) {
LOG_ERROR("=== Skipping inheritance relation from {} to {} due " LOG_ERROR("=== Skipping inheritance relation from {} to {} due "
"to: {}", "to: {}",
b.name, c.name, e.what()); b.name, c.name(), e.what());
} }
} }
@@ -311,36 +295,26 @@ void generator::generate(const enum_ &e, std::ostream &ostr) const
ostr << " {" << '\n'; ostr << " {" << '\n';
for (const auto &enum_constant : e.constants) { for (const auto &enum_constant : e.constants()) {
ostr << enum_constant << '\n'; ostr << enum_constant << '\n';
} }
ostr << "}" << '\n'; ostr << "}" << '\n';
for (const auto &r : e.relationships) { for (const auto &r : e.relationships()) {
if (!m_config.should_include_relationship(name(r.type))) if (!m_config.should_include_relationship(name(r.type)))
continue; continue;
std::string destination; std::string destination;
std::stringstream relstr; std::stringstream relstr;
try { try {
if (r.destination.find("#") != std::string::npos ||
r.destination.find("@") != std::string::npos) {
destination = m_model.usr_to_name(
m_config.using_namespace, r.destination);
if (destination.empty()) {
relstr << "' ";
destination = r.destination;
}
}
else {
destination = r.destination;
}
relstr << m_model.to_alias(m_config.using_namespace, destination = r.destination;
ns_relative(m_config.using_namespace, e.name))
relstr << m_model.to_alias(
ns_relative(m_config.using_namespace, e.name()))
<< " " << to_string(r.type) << " " << " " << to_string(r.type) << " "
<< m_model.to_alias(m_config.using_namespace, << m_model.to_alias(
ns_relative(m_config.using_namespace, destination)); ns_relative(m_config.using_namespace, destination));
if (!r.label.empty()) if (!r.label.empty())
@@ -353,7 +327,7 @@ void generator::generate(const enum_ &e, std::ostream &ostr) const
catch (error::uml_alias_missing &ex) { catch (error::uml_alias_missing &ex) {
LOG_ERROR("Skipping {} relation from {} to {} due " LOG_ERROR("Skipping {} relation from {} to {} due "
"to: {}", "to: {}",
to_string(r.type), e.name, destination, ex.what()); to_string(r.type), e.full_name(), destination, ex.what());
} }
} }
@@ -378,8 +352,7 @@ void generator::generate(std::ostream &ostr) const
std::string note{b}; std::string note{b};
std::tuple<std::string, size_t, size_t> alias_match; std::tuple<std::string, size_t, size_t> alias_match;
while (util::find_element_alias(note, alias_match)) { while (util::find_element_alias(note, alias_match)) {
auto alias = m_model.to_alias(m_config.using_namespace, auto alias = m_model.to_alias(ns_relative(
ns_relative(
m_config.using_namespace, std::get<0>(alias_match))); m_config.using_namespace, std::get<0>(alias_match)));
note.replace( note.replace(
std::get<1>(alias_match), std::get<2>(alias_match), alias); std::get<1>(alias_match), std::get<2>(alias_match), alias);
@@ -390,14 +363,14 @@ void generator::generate(std::ostream &ostr) const
if (m_config.should_include_entities("classes")) { if (m_config.should_include_entities("classes")) {
for (const auto &c : m_model.classes) { for (const auto &c : m_model.classes) {
if (!c.is_template_instantiation && if (!c.is_template_instantiation &&
!m_config.should_include(c.name)) !m_config.should_include(c.name()))
continue; continue;
generate_alias(c, ostr); generate_alias(c, ostr);
ostr << '\n'; ostr << '\n';
} }
for (const auto &e : m_model.enums) { for (const auto &e : m_model.enums) {
if (!m_config.should_include(e.name)) if (!m_config.should_include(e.name()))
continue; continue;
generate_alias(e, ostr); generate_alias(e, ostr);
ostr << '\n'; ostr << '\n';
@@ -405,7 +378,7 @@ void generator::generate(std::ostream &ostr) const
for (const auto &c : m_model.classes) { for (const auto &c : m_model.classes) {
if (!c.is_template_instantiation && if (!c.is_template_instantiation &&
!m_config.should_include(c.name)) !m_config.should_include(c.name()))
continue; continue;
generate(c, ostr); generate(c, ostr);
ostr << '\n'; ostr << '\n';
@@ -423,8 +396,7 @@ void generator::generate(std::ostream &ostr) const
std::string note{b}; std::string note{b};
std::tuple<std::string, size_t, size_t> alias_match; std::tuple<std::string, size_t, size_t> alias_match;
while (util::find_element_alias(note, alias_match)) { while (util::find_element_alias(note, alias_match)) {
auto alias = m_model.to_alias(m_config.using_namespace, auto alias = m_model.to_alias(ns_relative(
ns_relative(
m_config.using_namespace, std::get<0>(alias_match))); m_config.using_namespace, std::get<0>(alias_match)));
note.replace( note.replace(
std::get<1>(alias_match), std::get<2>(alias_match), alias); std::get<1>(alias_match), std::get<2>(alias_match), alias);

View File

@@ -29,7 +29,6 @@ using clanguml::model::sequence_diagram::message_t;
using clanguml::visitor::sequence_diagram::tu_context; using clanguml::visitor::sequence_diagram::tu_context;
using namespace clanguml::util; using namespace clanguml::util;
// //
// generator // generator
// //

View File

@@ -105,13 +105,48 @@ std::string decorated_element::style_spec()
// element // element
// //
element::element() element::element(const std::vector<std::string> &using_namespaces)
: m_id{m_nextId++} : using_namespaces_{using_namespaces}
, m_id{m_nextId++}
{ {
} }
std::string element::alias() const { return fmt::format("C_{:010}", m_id); } std::string element::alias() const { return fmt::format("C_{:010}", m_id); }
void element::add_relationship(class_relationship &&cr)
{
if (cr.destination.empty()) {
LOG_WARN("Skipping relationship '{}' - {} - '{}' due empty "
"destination",
cr.destination, to_string(cr.type), full_name(true));
return;
}
auto it = std::find(relationships_.begin(), relationships_.end(), cr);
if (it == relationships_.end())
relationships_.emplace_back(std::move(cr));
}
void element::set_using_namespaces(const std::vector<std::string> &un)
{
using_namespaces_ = un;
}
const std::vector<std::string> &element::using_namespaces() const
{
return using_namespaces_;
}
std::vector<class_relationship> &element::relationships()
{
return relationships_;
}
const std::vector<class_relationship> &element::relationships() const
{
return relationships_;
}
// //
// method_parameter // method_parameter
// //
@@ -152,7 +187,7 @@ bool operator==(const class_template &l, const class_template &r)
bool operator==(const class_ &l, const class_ &r) bool operator==(const class_ &l, const class_ &r)
{ {
return (l.usr == r.usr) && (l.templates == r.templates); return l.full_name() == r.full_name();
} }
void class_::add_type_alias(type_alias &&ta) void class_::add_type_alias(type_alias &&ta)
@@ -161,38 +196,27 @@ void class_::add_type_alias(type_alias &&ta)
type_aliases[ta.alias] = std::move(ta); type_aliases[ta.alias] = std::move(ta);
} }
void class_::add_relationship(class_relationship &&cr) std::string class_::full_name(bool relative) const
{
if (cr.destination.empty()) {
LOG_WARN("Skipping relationship '{}' - {} - '{}' due empty destination",
cr.destination, to_string(cr.type), usr);
return;
}
auto it = std::find(relationships.begin(), relationships.end(), cr);
if (it == relationships.end())
relationships.emplace_back(std::move(cr));
}
std::string class_::full_name(
const std::vector<std::string> &using_namespaces) const
{ {
using namespace clanguml::util; using namespace clanguml::util;
std::ostringstream ostr; std::ostringstream ostr;
ostr << ns_relative(using_namespaces, name); if (relative)
ostr << ns_relative(using_namespaces(), name());
else
ostr << name();
if (!templates.empty()) { if (!templates.empty()) {
std::vector<std::string> tnames; std::vector<std::string> tnames;
std::transform(templates.cbegin(), templates.cend(), std::transform(templates.cbegin(), templates.cend(),
std::back_inserter(tnames), [&using_namespaces](const auto &tmplt) { std::back_inserter(tnames), [this](const auto &tmplt) {
std::vector<std::string> res; std::vector<std::string> res;
if (!tmplt.type.empty()) if (!tmplt.type.empty())
res.push_back(ns_relative(using_namespaces, tmplt.type)); res.push_back(ns_relative(using_namespaces(), tmplt.type));
if (!tmplt.name.empty()) if (!tmplt.name.empty())
res.push_back(ns_relative(using_namespaces, tmplt.name)); res.push_back(ns_relative(using_namespaces(), tmplt.name));
if (!tmplt.default_value.empty()) { if (!tmplt.default_value.empty()) {
res.push_back("="); res.push_back("=");
@@ -219,15 +243,17 @@ bool class_::is_abstract() const
// enum_ // enum_
// //
bool operator==(const enum_ &l, const enum_ &r) { return l.name == r.name; } bool operator==(const enum_ &l, const enum_ &r) { return l.name() == r.name(); }
std::string enum_::full_name( std::string enum_::full_name(bool relative) const
const std::vector<std::string> &using_namespaces) const
{ {
using namespace clanguml::util; using namespace clanguml::util;
std::ostringstream ostr; std::ostringstream ostr;
ostr << ns_relative(using_namespaces, name); if (relative)
ostr << ns_relative(using_namespaces(), name());
else
ostr << name();
return ostr.str(); return ostr.str();
} }
@@ -236,10 +262,10 @@ std::string enum_::full_name(
// diagram // diagram
// //
bool diagram::has_class(const std::string &usr) const bool diagram::has_class(const class_ &c) const
{ {
return std::any_of(classes.cbegin(), classes.cend(), return std::any_of(classes.cbegin(), classes.cend(),
[&usr](const auto &c) { return c.usr == usr; }); [&c](const auto &cc) { return cc.full_name() == c.full_name(); });
} }
void diagram::add_type_alias(type_alias &&ta) void diagram::add_type_alias(type_alias &&ta)
@@ -251,36 +277,35 @@ void diagram::add_type_alias(type_alias &&ta)
void diagram::add_class(class_ &&c) void diagram::add_class(class_ &&c)
{ {
LOG_DBG("Adding class: {}, {}", c.name, c.usr); LOG_DBG("Adding class: {}, {}", c.name(), c.full_name());
if (!has_class(c.usr)) if (!has_class(c))
classes.emplace_back(std::move(c)); classes.emplace_back(std::move(c));
else else
LOG_DBG("Class {} ({}) already in the model", c.name, c.usr); LOG_DBG("Class {} ({}) already in the model", c.name(), c.full_name());
} }
void diagram::add_enum(enum_ &&e) void diagram::add_enum(enum_ &&e)
{ {
LOG_DBG("Adding enum: {}", e.name); LOG_DBG("Adding enum: {}", e.name());
auto it = std::find(enums.begin(), enums.end(), e); auto it = std::find(enums.begin(), enums.end(), e);
if (it == enums.end()) if (it == enums.end())
enums.emplace_back(std::move(e)); enums.emplace_back(std::move(e));
else else
LOG_DBG("Enum {} already in the model", e.name); LOG_DBG("Enum {} already in the model", e.name());
} }
std::string diagram::to_alias(const std::vector<std::string> &using_namespaces, std::string diagram::to_alias(const std::string &full_name) const
const std::string &full_name) const
{ {
LOG_DBG("Looking for alias for {}", full_name); LOG_DBG("Looking for alias for {}", full_name);
for (const auto &c : classes) { for (const auto &c : classes) {
if (c.full_name(using_namespaces) == full_name) { if (c.full_name() == full_name) {
return c.alias(); return c.alias();
} }
} }
for (const auto &e : enums) { for (const auto &e : enums) {
if (e.full_name(using_namespaces) == full_name) { if (e.full_name() == full_name) {
return e.alias(); return e.alias();
} }
} }
@@ -289,21 +314,6 @@ std::string diagram::to_alias(const std::vector<std::string> &using_namespaces,
fmt::format("Missing alias for {}", full_name)); fmt::format("Missing alias for {}", full_name));
} }
std::string diagram::usr_to_name(
const std::vector<std::string> &using_namespaces,
const std::string &usr) const
{
if (usr.empty())
throw std::runtime_error("Empty USR");
for (const auto &c : classes) {
if (c.usr == usr)
return c.full_name(using_namespaces);
}
return "";
}
} }
} }
} }

View File

@@ -70,22 +70,6 @@ struct decorated_element {
std::string style_spec(); std::string style_spec();
}; };
class element : public decorated_element {
public:
element();
std::string alias() const;
std::string name;
std::vector<std::string> namespace_;
protected:
const uint64_t m_id{0};
private:
static std::atomic_uint64_t m_nextId;
};
struct class_element : public decorated_element { struct class_element : public decorated_element {
scope_t scope; scope_t scope;
std::string name; std::string name;
@@ -143,6 +127,44 @@ struct class_template {
friend bool operator==(const class_template &l, const class_template &r); friend bool operator==(const class_template &l, const class_template &r);
}; };
class element : public decorated_element {
public:
element(const std::vector<std::string> &using_namespaces);
std::string alias() const;
void set_name(const std::string &name) { name_ = name; }
std::string name() const { return name_; }
void set_namespace(const std::vector<std::string> &ns) { namespace_ = ns; }
std::vector<std::string> get_namespace() const { return namespace_; }
virtual std::string full_name(bool relative) const { return name(); }
void set_using_namespaces(const std::vector<std::string> &un);
const std::vector<std::string> &using_namespaces() const;
std::vector<class_relationship> &relationships();
const std::vector<class_relationship> &relationships() const;
void add_relationship(class_relationship &&cr);
protected:
const uint64_t m_id{0};
private:
std::string name_;
std::vector<std::string> namespace_;
std::vector<std::string> using_namespaces_;
std::vector<class_relationship> relationships_;
static std::atomic_uint64_t m_nextId;
};
struct type_alias { struct type_alias {
std::string alias; std::string alias;
std::string underlying_type; std::string underlying_type;
@@ -150,7 +172,11 @@ struct type_alias {
class class_ : public element, public stylable_element { class class_ : public element, public stylable_element {
public: public:
std::string usr; class_(const std::vector<std::string> &using_namespaces)
: element{using_namespaces}
{
}
bool is_struct{false}; bool is_struct{false};
bool is_template{false}; bool is_template{false};
bool is_template_instantiation{false}; bool is_template_instantiation{false};
@@ -158,31 +184,39 @@ public:
std::vector<class_method> methods; std::vector<class_method> methods;
std::vector<class_parent> bases; std::vector<class_parent> bases;
std::vector<std::string> inner_classes; std::vector<std::string> inner_classes;
std::vector<class_relationship> relationships;
std::vector<class_template> templates; std::vector<class_template> templates;
std::string base_template_usr; std::string base_template_full_name;
std::map<std::string, type_alias> type_aliases; std::map<std::string, type_alias> type_aliases;
friend bool operator==(const class_ &l, const class_ &r); friend bool operator==(const class_ &l, const class_ &r);
void add_type_alias(type_alias &&ta); void add_type_alias(type_alias &&ta);
void add_relationship(class_relationship &&cr); std::string full_name(bool relative = true) const override;
std::string full_name(
const std::vector<std::string> &using_namespaces) const;
bool is_abstract() const; bool is_abstract() const;
private:
std::string full_name_;
}; };
struct enum_ : public element, public stylable_element { struct enum_ : public element, public stylable_element {
std::vector<std::string> constants; public:
std::vector<class_relationship> relationships; enum_(const std::vector<std::string> &using_namespaces)
: element{using_namespaces}
{
}
friend bool operator==(const enum_ &l, const enum_ &r); friend bool operator==(const enum_ &l, const enum_ &r);
std::string full_name( std::string full_name(bool relative = true) const override;
const std::vector<std::string> &using_namespaces) const;
std::vector<std::string> &constants() { return constants_; }
const std::vector<std::string> &constants() const { return constants_; }
private:
std::vector<std::string> constants_;
}; };
struct diagram { struct diagram {
@@ -191,7 +225,7 @@ struct diagram {
std::vector<enum_> enums; std::vector<enum_> enums;
std::map<std::string, type_alias> type_aliases; std::map<std::string, type_alias> type_aliases;
bool has_class(const std::string &usr) const; bool has_class(const class_ &c) const;
void add_type_alias(type_alias &&ta); void add_type_alias(type_alias &&ta);
@@ -199,11 +233,7 @@ struct diagram {
void add_enum(enum_ &&e); void add_enum(enum_ &&e);
std::string to_alias(const std::vector<std::string> &using_namespaces, std::string to_alias(const std::string &full_name) const;
const std::string &full_name) const;
std::string usr_to_name(const std::vector<std::string> &using_namespaces,
const std::string &usr) const;
}; };
} }
} }

View File

@@ -279,8 +279,8 @@ void tu_visitor::process_enum_declaration(const cppast::cpp_enum &enm)
return; return;
} }
enum_ e; enum_ e{ctx.config.using_namespace};
e.name = cx::util::full_name(ctx.namespace_, enm); e.set_name(cx::util::full_name(ctx.namespace_, enm));
if (enm.comment().has_value()) if (enm.comment().has_value())
e.decorators = decorators::parse(enm.comment().value()); e.decorators = decorators::parse(enm.comment().value());
@@ -296,7 +296,7 @@ void tu_visitor::process_enum_declaration(const cppast::cpp_enum &enm)
for (const auto &ev : enm) { for (const auto &ev : enm) {
if (ev.kind() == cppast::cpp_entity_kind::enum_value_t) { if (ev.kind() == cppast::cpp_entity_kind::enum_value_t) {
e.constants.push_back(ev.name()); e.constants().push_back(ev.name());
} }
} }
@@ -309,9 +309,9 @@ void tu_visitor::process_enum_declaration(const cppast::cpp_enum &enm)
containment.destination = containment.destination =
cx::util::full_name(ctx.namespace_, cur.value()); cx::util::full_name(ctx.namespace_, cur.value());
containment.scope = scope_t::kNone; containment.scope = scope_t::kNone;
e.relationships.emplace_back(std::move(containment)); e.add_relationship(std::move(containment));
LOG_DBG("Added relationship {} +-- {}", e.name, LOG_DBG("Added relationship {} +-- {}", e.name(),
containment.destination); containment.destination);
break; break;
} }
@@ -323,9 +323,9 @@ void tu_visitor::process_enum_declaration(const cppast::cpp_enum &enm)
void tu_visitor::process_class_declaration(const cppast::cpp_class &cls, void tu_visitor::process_class_declaration(const cppast::cpp_class &cls,
type_safe::optional_ref<const cppast::cpp_template_specialization> tspec) type_safe::optional_ref<const cppast::cpp_template_specialization> tspec)
{ {
class_ c; class_ c{ctx.config.using_namespace};
c.is_struct = cls.class_kind() == cppast::cpp_class_kind::struct_t; c.is_struct = cls.class_kind() == cppast::cpp_class_kind::struct_t;
c.name = cx::util::full_name(ctx.namespace_, cls); c.set_name(cx::util::full_name(ctx.namespace_, cls));
if (cls.comment().has_value()) if (cls.comment().has_value())
c.decorators = decorators::parse(cls.comment().value()); c.decorators = decorators::parse(cls.comment().value());
@@ -438,7 +438,7 @@ void tu_visitor::process_class_declaration(const cppast::cpp_class &cls,
cp.access = class_parent::access_t::kPublic; cp.access = class_parent::access_t::kPublic;
} }
LOG_DBG("Found base class {} for class {}", cp.name, c.name); LOG_DBG("Found base class {} for class {}", cp.name, c.name());
c.bases.emplace_back(std::move(cp)); c.bases.emplace_back(std::move(cp));
} }
@@ -511,16 +511,17 @@ void tu_visitor::process_class_declaration(const cppast::cpp_class &cls,
.class_(); .class_();
if (primary_template_ref.user_data()) { if (primary_template_ref.user_data()) {
auto base_template_usr = static_cast<const char *>( auto base_template_full_name =
static_cast<const char *>(
primary_template_ref.user_data()); primary_template_ref.user_data());
LOG_DBG("Primary template ref set to: {}", LOG_DBG("Primary template ref set to: {}",
base_template_usr); base_template_full_name);
// Add template specialization/instantiation // Add template specialization/instantiation
// relationship // relationship
class_relationship r; class_relationship r;
r.type = relationship_t::kInstantiation; r.type = relationship_t::kInstantiation;
r.label = ""; r.label = "";
r.destination = base_template_usr; r.destination = base_template_full_name;
r.scope = scope_t::kNone; r.scope = scope_t::kNone;
c.add_relationship(std::move(r)); c.add_relationship(std::move(r));
} }
@@ -587,22 +588,19 @@ void tu_visitor::process_class_declaration(const cppast::cpp_class &cls,
cx::util::full_name(ctx.namespace_, cur.value()); cx::util::full_name(ctx.namespace_, cur.value());
c.add_relationship(std::move(containment)); c.add_relationship(std::move(containment));
LOG_DBG("Added relationship {} +-- {}", LOG_DBG("Added relationship {} +-- {}", c.full_name(),
c.full_name(ctx.config.using_namespace),
containment.destination); containment.destination);
break; break;
} }
} }
cls.set_user_data(strdup(c.full_name(ctx.config.using_namespace).c_str())); cls.set_user_data(strdup(c.full_name().c_str()));
LOG_DBG("Setting user data for class {}, {}", LOG_DBG("Setting user data for class {}, {}",
static_cast<const char *>(cls.user_data()), static_cast<const char *>(cls.user_data()),
fmt::ptr(reinterpret_cast<const void *>(&cls))); fmt::ptr(reinterpret_cast<const void *>(&cls)));
c.usr = c.full_name(ctx.config.using_namespace);
ctx.d.add_class(std::move(c)); ctx.d.add_class(std::move(c));
} }
@@ -623,12 +621,11 @@ bool tu_visitor::process_field_with_template_instantiation(
resolve_alias(template_instantiation_type)); resolve_alias(template_instantiation_type));
class_ tinst = build_template_instantiation(unaliased); class_ tinst = build_template_instantiation(unaliased);
tinst.usr = tinst.full_name(ctx.config.using_namespace);
// Infer the relationship of this field to the template // Infer the relationship of this field to the template
// instantiation // instantiation
class_relationship rr; class_relationship rr;
rr.destination = tinst.full_name(ctx.config.using_namespace); rr.destination = tinst.full_name();
if (mv.type().kind() == cppast::cpp_type_kind::pointer_t || if (mv.type().kind() == cppast::cpp_type_kind::pointer_t ||
mv.type().kind() == cppast::cpp_type_kind::reference_t) mv.type().kind() == cppast::cpp_type_kind::reference_t)
rr.type = relationship_t::kAssociation; rr.type = relationship_t::kAssociation;
@@ -649,17 +646,16 @@ bool tu_visitor::process_field_with_template_instantiation(
} }
} }
if (ctx.config.should_include(tinst.name)) { if (ctx.config.should_include(tinst.name())) {
LOG_DBG("Adding field instantiation relationship {} {} {} : {}", LOG_DBG("Adding field instantiation relationship {} {} {} : {}",
rr.destination, model::class_diagram::to_string(rr.type), c.usr, rr.destination, model::class_diagram::to_string(rr.type),
rr.label); c.full_name(), rr.label);
c.add_relationship(std::move(rr)); c.add_relationship(std::move(rr));
res = true; res = true;
LOG_DBG( LOG_DBG("Created template instantiation: {}", tinst.full_name());
"Created template instantiation: {}, {}", tinst.name, tinst.usr);
ctx.d.add_class(std::move(tinst)); ctx.d.add_class(std::move(tinst));
} }
@@ -736,9 +732,9 @@ void tu_visitor::process_field(const cppast::cpp_member_variable &mv, class_ &c,
LOG_DBG("Adding field relationship {} {} {} : {}", LOG_DBG("Adding field relationship {} {} {} : {}",
r.destination, model::class_diagram::to_string(r.type), r.destination, model::class_diagram::to_string(r.type),
c.usr, r.label); c.full_name(), r.label);
c.relationships.emplace_back(std::move(r)); c.add_relationship(std::move(r));
} }
} }
} }
@@ -966,7 +962,7 @@ void tu_visitor::process_function_parameter(
relationship_t::kDependency); relationship_t::kDependency);
for (const auto &[type, relationship_type] : relationships) { for (const auto &[type, relationship_type] : relationships) {
if ((relationship_type != relationship_t::kNone) && if ((relationship_type != relationship_t::kNone) &&
(type != c.name)) { (type != c.name())) {
class_relationship r; class_relationship r;
r.destination = type; r.destination = type;
r.type = relationship_t::kDependency; r.type = relationship_t::kDependency;
@@ -974,7 +970,7 @@ void tu_visitor::process_function_parameter(
LOG_DBG("Adding field relationship {} {} {} : {}", LOG_DBG("Adding field relationship {} {} {} : {}",
r.destination, model::class_diagram::to_string(r.type), r.destination, model::class_diagram::to_string(r.type),
c.usr, r.label); c.full_name(), r.label);
c.add_relationship(std::move(r)); c.add_relationship(std::move(r));
} }
@@ -1031,8 +1027,8 @@ void tu_visitor::process_function_parameter(
"{} {} {} " "{} {} {} "
": {}", ": {}",
rr.destination, rr.destination,
model::class_diagram::to_string(rr.type), c.usr, model::class_diagram::to_string(rr.type),
rr.label); c.full_name(), rr.label);
c.add_relationship(std::move(rr)); c.add_relationship(std::move(rr));
} }
else { else {
@@ -1041,14 +1037,16 @@ void tu_visitor::process_function_parameter(
template_instantiation_type); template_instantiation_type);
class_relationship rr; class_relationship rr;
rr.destination = tinst.usr; rr.destination = tinst.full_name();
rr.type = relationship_t::kDependency; rr.type = relationship_t::kDependency;
rr.label = ""; rr.label = "";
LOG_DBG("Adding field dependency relationship {} {} {} " LOG_DBG("Adding field dependency relationship {} {} {} "
": {}", ": {}",
rr.destination, rr.destination,
model::class_diagram::to_string(rr.type), c.usr, model::class_diagram::to_string(rr.type),
rr.label); c.full_name(), rr.label);
c.add_relationship(std::move(rr)); c.add_relationship(std::move(rr));
ctx.d.add_class(std::move(tinst)); ctx.d.add_class(std::move(tinst));
@@ -1304,7 +1302,7 @@ class_ tu_visitor::build_template_instantiation(
const cppast::cpp_template_instantiation_type &t, const cppast::cpp_template_instantiation_type &t,
std::optional<clanguml::model::class_diagram::class_ *> parent) std::optional<clanguml::model::class_diagram::class_ *> parent)
{ {
class_ tinst; class_ tinst{ctx.config.using_namespace};
std::string full_template_name; std::string full_template_name;
std::deque<std::tuple<std::string, int, bool>> template_base_params{}; std::deque<std::tuple<std::string, int, bool>> template_base_params{};
@@ -1317,8 +1315,7 @@ class_ tu_visitor::build_template_instantiation(
.class_(); .class_();
if (parent) if (parent)
LOG_DBG("Template parent is {}", LOG_DBG("Template parent is {}", (*parent)->full_name());
(*parent)->full_name(ctx.config.using_namespace));
else else
LOG_DBG("Template parent is empty"); LOG_DBG("Template parent is empty");
@@ -1331,8 +1328,9 @@ class_ tu_visitor::build_template_instantiation(
cppast::to_string(t), cppast::to_string(t.canonical()), cppast::to_string(t), cppast::to_string(t.canonical()),
t.primary_template().name(), full_template_name); t.primary_template().name(), full_template_name);
if (full_template_name.back() == ':') if (full_template_name.back() == ':') {
tinst.name = full_template_name + tinst.name; tinst.set_name(full_template_name + tinst.name());
}
std::vector<std::pair<std::string, bool>> template_parameter_names{}; std::vector<std::pair<std::string, bool>> template_parameter_names{};
if (primary_template_ref.scope_name().has_value()) { if (primary_template_ref.scope_name().has_value()) {
@@ -1383,9 +1381,10 @@ class_ tu_visitor::build_template_instantiation(
} }
if (primary_template_ref.user_data()) { if (primary_template_ref.user_data()) {
tinst.base_template_usr = tinst.base_template_full_name =
static_cast<const char *>(primary_template_ref.user_data()); static_cast<const char *>(primary_template_ref.user_data());
LOG_DBG("Primary template ref set to: {}", tinst.base_template_usr); LOG_DBG("Primary template ref set to: {}",
tinst.base_template_full_name);
} }
else else
LOG_WARN("No user data for base template {}", LOG_WARN("No user data for base template {}",
@@ -1413,14 +1412,13 @@ class_ tu_visitor::build_template_instantiation(
LOG_DBG("Template namespace is {}", ns); LOG_DBG("Template namespace is {}", ns);
tinst.name = ns + util::split(cppast::to_string(t), "<")[0]; tinst.set_name(ns + util::split(cppast::to_string(t), "<")[0]);
tinst.is_template_instantiation = true; tinst.is_template_instantiation = true;
tinst.usr = tinst.full_name(ctx.config.using_namespace); if (tinst.full_name().substr(0, tinst.full_name().find('<')).find("::") ==
if (tinst.usr.substr(0, tinst.usr.find('<')).find("::") ==
std::string::npos) { std::string::npos) {
tinst.usr = ns + tinst.usr; tinst.set_name(ns + tinst.full_name());
} }
// Process template argumetns // Process template argumetns
@@ -1450,28 +1448,26 @@ class_ tu_visitor::build_template_instantiation(
std::string nnn{"empty"}; std::string nnn{"empty"};
if (parent) if (parent)
nnn = (*parent)->name; nnn = (*parent)->name();
class_ nested_tinst = class_ nested_tinst =
build_template_instantiation(nested_template_parameter, build_template_instantiation(nested_template_parameter,
ctx.config.should_include(tinst.usr) ctx.config.should_include(tinst.full_name(false))
? std::make_optional(&tinst) ? std::make_optional(&tinst)
: parent); : parent);
tinst_dependency.destination = tinst_dependency.destination = nested_tinst.full_name();
nested_tinst.full_name(ctx.config.using_namespace);
auto nested_tinst_usr = nested_tinst.usr; auto nested_tinst_full_name = nested_tinst.full_name();
if (ctx.config.should_include(fn)) { if (ctx.config.should_include(fn)) {
ctx.d.add_class(std::move(nested_tinst)); ctx.d.add_class(std::move(nested_tinst));
} }
if (ctx.config.should_include(tinst.usr)) { if (ctx.config.should_include(tinst.full_name(false))) {
LOG_DBG("Creating nested template dependency to template " LOG_DBG("Creating nested template dependency to template "
"instantiation {}, {} -> {}", "instantiation {}, {} -> {}",
fn, tinst.full_name(ctx.config.using_namespace), fn, tinst.full_name(), tinst_dependency.destination);
tinst_dependency.destination);
tinst.add_relationship(std::move(tinst_dependency)); tinst.add_relationship(std::move(tinst_dependency));
} }
@@ -1479,7 +1475,7 @@ class_ tu_visitor::build_template_instantiation(
LOG_DBG("Creating nested template dependency to parent " LOG_DBG("Creating nested template dependency to parent "
"template " "template "
"instantiation {}, {} -> {}", "instantiation {}, {} -> {}",
fn, (*parent)->full_name(ctx.config.using_namespace), fn, (*parent)->full_name(),
tinst_dependency.destination); tinst_dependency.destination);
(*parent)->add_relationship(std::move(tinst_dependency)); (*parent)->add_relationship(std::move(tinst_dependency));
@@ -1487,8 +1483,7 @@ class_ tu_visitor::build_template_instantiation(
else { else {
LOG_DBG("No nested template dependency to template " LOG_DBG("No nested template dependency to template "
"instantiation: {}, {} -> {}", "instantiation: {}, {} -> {}",
fn, tinst.full_name(ctx.config.using_namespace), fn, tinst.full_name(), tinst_dependency.destination);
tinst_dependency.destination);
} }
} }
else if (targ.type().value().kind() == else if (targ.type().value().kind() ==
@@ -1504,8 +1499,7 @@ class_ tu_visitor::build_template_instantiation(
LOG_DBG("Creating nested template dependency to user defined " LOG_DBG("Creating nested template dependency to user defined "
"type {} -> {}", "type {} -> {}",
tinst.full_name(ctx.config.using_namespace), tinst.full_name(), tinst_dependency.destination);
tinst_dependency.destination);
if (ctx.config.should_include(fn)) { if (ctx.config.should_include(fn)) {
tinst.add_relationship(std::move(tinst_dependency)); tinst.add_relationship(std::move(tinst_dependency));
@@ -1560,16 +1554,6 @@ class_ tu_visitor::build_template_instantiation(
tinst.templates.emplace_back(std::move(ct)); tinst.templates.emplace_back(std::move(ct));
} }
// Now update usr with the template arguments of the
// instantiations... (there must be a better way)
tinst.usr = tinst.full_name(ctx.config.using_namespace);
if (tinst.usr.substr(0, tinst.usr.find('<')).find("::") ==
std::string::npos) {
tinst.usr = ns + tinst.usr;
}
LOG_DBG("Setting tinst usr to {}", tinst.usr);
// Add instantiation relationship to primary template of this // Add instantiation relationship to primary template of this
// instantiation // instantiation
class_relationship r; class_relationship r;
@@ -1584,7 +1568,7 @@ class_ tu_visitor::build_template_instantiation(
} }
else { else {
// Otherwise point to the base template // Otherwise point to the base template
r.destination = tinst.base_template_usr; r.destination = tinst.base_template_full_name;
} }
r.type = relationship_t::kInstantiation; r.type = relationship_t::kInstantiation;
r.label = ""; r.label = "";

View File

@@ -17,9 +17,9 @@
*/ */
#pragma once #pragma once
#include "config/config.h"
#include "cx/cursor.h" #include "cx/cursor.h"
#include "sequence_diagram_model.h" #include "sequence_diagram_model.h"
#include "config/config.h"
#include <clang-c/CXCompilationDatabase.h> #include <clang-c/CXCompilationDatabase.h>
#include <clang-c/Index.h> #include <clang-c/Index.h>