Fixed nested namespace handling
This commit is contained in:
@@ -24,6 +24,8 @@
|
|||||||
#include <cppast/cpp_template.hpp>
|
#include <cppast/cpp_template.hpp>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
namespace clanguml {
|
namespace clanguml {
|
||||||
namespace cx {
|
namespace cx {
|
||||||
namespace util {
|
namespace util {
|
||||||
@@ -35,7 +37,8 @@ std::string to_string(CXString &&cxs)
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string full_name(const cppast::cpp_entity &e)
|
std::string full_name(
|
||||||
|
const std::vector<std::string> ¤t_ns, const cppast::cpp_entity &e)
|
||||||
{
|
{
|
||||||
if (e.name().empty())
|
if (e.name().empty())
|
||||||
return "";
|
return "";
|
||||||
@@ -43,25 +46,16 @@ std::string full_name(const cppast::cpp_entity &e)
|
|||||||
// parameters don't have a full name
|
// parameters don't have a full name
|
||||||
return e.name();
|
return e.name();
|
||||||
|
|
||||||
std::string scopes;
|
std::vector<std::string> fn;
|
||||||
|
|
||||||
for (auto cur = e.parent(); cur; cur = cur.value().parent())
|
for (const auto &ns : current_ns) {
|
||||||
// prepend each scope, if there is any
|
if (!ns.empty())
|
||||||
if (cur.value().kind() == cppast::cpp_entity_kind::namespace_t)
|
fn.push_back(ns);
|
||||||
type_safe::with(cur.value().scope_name(),
|
}
|
||||||
[&](const cppast::cpp_scope_name &cur_scope) {
|
|
||||||
scopes = cur_scope.name() + "::" + scopes;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (e.kind() == cppast::cpp_entity_kind::class_t) {
|
fn.push_back(e.name());
|
||||||
auto &c = static_cast<const cppast::cpp_class &>(e);
|
|
||||||
return scopes /*+ c.semantic_scope()*/ + c.name();
|
return fmt::format("{}", fmt::join(fn, "::"));
|
||||||
}
|
|
||||||
else if (e.kind() == cppast::cpp_entity_kind::class_template_t) {
|
|
||||||
return scopes;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return scopes + e.name();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string full_name(const cppast::cpp_type &t,
|
std::string full_name(const cppast::cpp_type &t,
|
||||||
@@ -87,7 +81,8 @@ std::string ns(const cppast::cpp_entity &e)
|
|||||||
auto it = e.parent();
|
auto it = e.parent();
|
||||||
while (it) {
|
while (it) {
|
||||||
if (it.value().kind() == cppast::cpp_entity_kind::namespace_t) {
|
if (it.value().kind() == cppast::cpp_entity_kind::namespace_t) {
|
||||||
res.push_back(it.value().name());
|
if (!it.value().name().empty())
|
||||||
|
res.push_back(it.value().name());
|
||||||
}
|
}
|
||||||
it = it.value().parent();
|
it = it.value().parent();
|
||||||
}
|
}
|
||||||
@@ -162,14 +157,40 @@ std::string ns(const cppast::cpp_type &t, const cppast::cpp_entity_index &idx)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string fully_prefixed(const cppast::cpp_entity &e)
|
std::string fully_prefixed(
|
||||||
|
const std::vector<std::string> ¤t_ns, const cppast::cpp_entity &e)
|
||||||
{
|
{
|
||||||
|
if (e.name().find("::") != std::string::npos) {
|
||||||
|
// the name already contains namespace, but it could be not
|
||||||
|
// absolute, i.e. relative to some supernamespace of current
|
||||||
|
// namespace context
|
||||||
|
std::list<std::string> res;
|
||||||
|
|
||||||
|
for (const auto &n : clanguml::util::split(e.name(), "::"))
|
||||||
|
res.push_back(n);
|
||||||
|
|
||||||
|
std::list<std::string> prefix_ns;
|
||||||
|
for (const auto &n : current_ns) {
|
||||||
|
if (!n.empty() && n != res.front())
|
||||||
|
prefix_ns.push_back(n);
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
prefix_ns.reverse();
|
||||||
|
for (const auto &n : prefix_ns)
|
||||||
|
res.push_front(n);
|
||||||
|
|
||||||
|
return fmt::format("{}", fmt::join(res, "::"));
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<std::string> res{e.name()};
|
std::vector<std::string> res{e.name()};
|
||||||
|
|
||||||
auto it = e.parent();
|
auto it = e.parent();
|
||||||
while (it) {
|
while (it) {
|
||||||
if (it.value().kind() == cppast::cpp_entity_kind::namespace_t) {
|
if (it.value().kind() == cppast::cpp_entity_kind::namespace_t) {
|
||||||
res.push_back(it.value().name());
|
if (!it.value().name().empty())
|
||||||
|
res.push_back(it.value().name());
|
||||||
}
|
}
|
||||||
it = it.value().parent();
|
it = it.value().parent();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,12 +40,14 @@ namespace util {
|
|||||||
*/
|
*/
|
||||||
std::string to_string(CXString &&cxs);
|
std::string to_string(CXString &&cxs);
|
||||||
|
|
||||||
std::string full_name(const cppast::cpp_entity &e);
|
std::string full_name(
|
||||||
|
const std::vector<std::string> ¤t_ns, const cppast::cpp_entity &e);
|
||||||
|
|
||||||
std::string full_name(const cppast::cpp_type &t,
|
std::string full_name(const cppast::cpp_type &t,
|
||||||
const cppast::cpp_entity_index &idx, bool inside_class);
|
const cppast::cpp_entity_index &idx, bool inside_class);
|
||||||
|
|
||||||
std::string fully_prefixed(const cppast::cpp_entity &e);
|
std::string fully_prefixed(
|
||||||
|
const std::vector<std::string> ¤t_ns, const cppast::cpp_entity &e);
|
||||||
|
|
||||||
const cppast::cpp_type &unreferenced(const cppast::cpp_type &t);
|
const cppast::cpp_type &unreferenced(const cppast::cpp_type &t);
|
||||||
|
|
||||||
|
|||||||
@@ -216,6 +216,10 @@ public:
|
|||||||
r.destination.find("@") != std::string::npos) {
|
r.destination.find("@") != std::string::npos) {
|
||||||
destination = m_model.usr_to_name(
|
destination = m_model.usr_to_name(
|
||||||
m_config.using_namespace, r.destination);
|
m_config.using_namespace, r.destination);
|
||||||
|
|
||||||
|
// If something went wrong and we have an empty destination
|
||||||
|
// generate the relationship but comment it out for
|
||||||
|
// debugging
|
||||||
if (destination.empty()) {
|
if (destination.empty()) {
|
||||||
ostr << "' ";
|
ostr << "' ";
|
||||||
destination = r.destination;
|
destination = r.destination;
|
||||||
|
|||||||
@@ -73,8 +73,22 @@ void tu_visitor::operator()(const cppast::cpp_entity &file)
|
|||||||
{
|
{
|
||||||
cppast::visit(file,
|
cppast::visit(file,
|
||||||
[&, this](const cppast::cpp_entity &e, cppast::visitor_info info) {
|
[&, this](const cppast::cpp_entity &e, cppast::visitor_info info) {
|
||||||
if (e.kind() == cppast::cpp_entity_kind::class_t) {
|
if (e.kind() == cppast::cpp_entity_kind::namespace_t) {
|
||||||
LOG_DBG("========== Visiting '{}' - {}", cx::util::full_name(e),
|
if (info.event ==
|
||||||
|
cppast::visitor_info::container_entity_enter) {
|
||||||
|
LOG_DBG("========== Visiting '{}' - {}", e.name(),
|
||||||
|
cppast::to_string(e.kind()));
|
||||||
|
ctx.namespace_.push_back(e.name());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
LOG_DBG("========== Leaving '{}' - {}", e.name(),
|
||||||
|
cppast::to_string(e.kind()));
|
||||||
|
ctx.namespace_.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (e.kind() == cppast::cpp_entity_kind::class_t) {
|
||||||
|
LOG_DBG("========== Visiting '{}' - {}",
|
||||||
|
cx::util::full_name(ctx.namespace_, e),
|
||||||
cppast::to_string(e.kind()));
|
cppast::to_string(e.kind()));
|
||||||
|
|
||||||
auto &cls = static_cast<const cppast::cpp_class &>(e);
|
auto &cls = static_cast<const cppast::cpp_class &>(e);
|
||||||
@@ -87,35 +101,40 @@ void tu_visitor::operator()(const cppast::cpp_entity &file)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctx.config.should_include(cx::util::fully_prefixed(cls)))
|
if (ctx.config.should_include(
|
||||||
|
cx::util::fully_prefixed(ctx.namespace_, cls)))
|
||||||
process_class_declaration(cls);
|
process_class_declaration(cls);
|
||||||
}
|
}
|
||||||
else if (e.kind() == cppast::cpp_entity_kind::enum_t) {
|
else if (e.kind() == cppast::cpp_entity_kind::enum_t) {
|
||||||
LOG_DBG("========== Visiting '{}' - {}", cx::util::full_name(e),
|
LOG_DBG("========== Visiting '{}' - {}",
|
||||||
|
cx::util::full_name(ctx.namespace_, e),
|
||||||
cppast::to_string(e.kind()));
|
cppast::to_string(e.kind()));
|
||||||
|
|
||||||
auto &enm = static_cast<const cppast::cpp_enum &>(e);
|
auto &enm = static_cast<const cppast::cpp_enum &>(e);
|
||||||
|
|
||||||
if (ctx.config.should_include(cx::util::fully_prefixed(enm)))
|
if (ctx.config.should_include(
|
||||||
|
cx::util::fully_prefixed(ctx.namespace_, enm)))
|
||||||
process_enum_declaration(enm);
|
process_enum_declaration(enm);
|
||||||
}
|
}
|
||||||
else if (e.kind() == cppast::cpp_entity_kind::type_alias_t) {
|
else if (e.kind() == cppast::cpp_entity_kind::type_alias_t) {
|
||||||
LOG_DBG("========== Visiting '{}' - {}", cx::util::full_name(e),
|
LOG_DBG("========== Visiting '{}' - {}",
|
||||||
|
cx::util::full_name(ctx.namespace_, e),
|
||||||
cppast::to_string(e.kind()));
|
cppast::to_string(e.kind()));
|
||||||
|
|
||||||
auto &ta = static_cast<const cppast::cpp_type_alias &>(e);
|
auto &ta = static_cast<const cppast::cpp_type_alias &>(e);
|
||||||
type_alias t;
|
type_alias t;
|
||||||
t.alias = cx::util::full_name(ta);
|
t.alias = cx::util::full_name(ctx.namespace_, ta);
|
||||||
t.underlying_type = cx::util::full_name(ta.underlying_type(),
|
t.underlying_type = cx::util::full_name(ta.underlying_type(),
|
||||||
ctx.entity_index, cx::util::is_inside_class(e));
|
ctx.entity_index, cx::util::is_inside_class(e));
|
||||||
|
|
||||||
ctx.add_type_alias(cx::util::full_name(ta),
|
ctx.add_type_alias(cx::util::full_name(ctx.namespace_, ta),
|
||||||
type_safe::ref(ta.underlying_type()));
|
type_safe::ref(ta.underlying_type()));
|
||||||
|
|
||||||
ctx.d.add_type_alias(std::move(t));
|
ctx.d.add_type_alias(std::move(t));
|
||||||
}
|
}
|
||||||
else if (e.kind() == cppast::cpp_entity_kind::alias_template_t) {
|
else if (e.kind() == cppast::cpp_entity_kind::alias_template_t) {
|
||||||
LOG_DBG("========== Visiting '{}' - {}", cx::util::full_name(e),
|
LOG_DBG("========== Visiting '{}' - {}",
|
||||||
|
cx::util::full_name(ctx.namespace_, e),
|
||||||
cppast::to_string(e.kind()));
|
cppast::to_string(e.kind()));
|
||||||
|
|
||||||
auto &at = static_cast<const cppast::cpp_alias_template &>(e);
|
auto &at = static_cast<const cppast::cpp_alias_template &>(e);
|
||||||
@@ -141,7 +160,7 @@ void tu_visitor::operator()(const cppast::cpp_entity &file)
|
|||||||
void tu_visitor::process_enum_declaration(const cppast::cpp_enum &enm)
|
void tu_visitor::process_enum_declaration(const cppast::cpp_enum &enm)
|
||||||
{
|
{
|
||||||
enum_ e;
|
enum_ e;
|
||||||
e.name = cx::util::full_name(enm);
|
e.name = cx::util::full_name(ctx.namespace_, 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) {
|
||||||
@@ -155,7 +174,8 @@ void tu_visitor::process_enum_declaration(const cppast::cpp_enum &enm)
|
|||||||
if (cur.value().kind() == cppast::cpp_entity_kind::class_t) {
|
if (cur.value().kind() == cppast::cpp_entity_kind::class_t) {
|
||||||
class_relationship containment;
|
class_relationship containment;
|
||||||
containment.type = relationship_t::kContainment;
|
containment.type = relationship_t::kContainment;
|
||||||
containment.destination = cx::util::full_name(cur.value());
|
containment.destination =
|
||||||
|
cx::util::full_name(ctx.namespace_, cur.value());
|
||||||
e.relationships.emplace_back(std::move(containment));
|
e.relationships.emplace_back(std::move(containment));
|
||||||
|
|
||||||
LOG_DBG("Added relationship {} +-- {}", e.name,
|
LOG_DBG("Added relationship {} +-- {}", e.name,
|
||||||
@@ -171,7 +191,7 @@ void tu_visitor::process_class_declaration(const cppast::cpp_class &cls)
|
|||||||
{
|
{
|
||||||
class_ c;
|
class_ c;
|
||||||
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(cls);
|
c.name = cx::util::full_name(ctx.namespace_, cls);
|
||||||
|
|
||||||
cppast::cpp_access_specifier_kind last_access_specifier =
|
cppast::cpp_access_specifier_kind last_access_specifier =
|
||||||
cppast::cpp_access_specifier_kind::cpp_private;
|
cppast::cpp_access_specifier_kind::cpp_private;
|
||||||
@@ -241,7 +261,7 @@ void tu_visitor::process_class_declaration(const cppast::cpp_class &cls)
|
|||||||
// Process class bases
|
// Process class bases
|
||||||
for (auto &base : cls.bases()) {
|
for (auto &base : cls.bases()) {
|
||||||
class_parent cp;
|
class_parent cp;
|
||||||
cp.name = clanguml::cx::util::fully_prefixed(base);
|
cp.name = clanguml::cx::util::fully_prefixed(ctx.namespace_, base);
|
||||||
cp.is_virtual = base.is_virtual();
|
cp.is_virtual = base.is_virtual();
|
||||||
|
|
||||||
switch (base.access_specifier()) {
|
switch (base.access_specifier()) {
|
||||||
@@ -299,7 +319,8 @@ void tu_visitor::process_class_declaration(const cppast::cpp_class &cls)
|
|||||||
if (cur.value().kind() == cppast::cpp_entity_kind::class_t) {
|
if (cur.value().kind() == cppast::cpp_entity_kind::class_t) {
|
||||||
class_relationship containment;
|
class_relationship containment;
|
||||||
containment.type = relationship_t::kContainment;
|
containment.type = relationship_t::kContainment;
|
||||||
containment.destination = cx::util::full_name(cur.value());
|
containment.destination =
|
||||||
|
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 {} +-- {}",
|
||||||
@@ -335,10 +356,10 @@ void tu_visitor::process_field_with_template_instantiation(
|
|||||||
.size()) {
|
.size()) {
|
||||||
// Here we need the name of the primary template with full namespace
|
// Here we need the name of the primary template with full namespace
|
||||||
// prefix to apply config inclusion filters
|
// prefix to apply config inclusion filters
|
||||||
auto primary_template_name =
|
auto primary_template_name = cx::util::full_name(ctx.namespace_,
|
||||||
cx::util::full_name(template_instantiation_type.primary_template()
|
template_instantiation_type.primary_template()
|
||||||
.get(ctx.entity_index)[0]
|
.get(ctx.entity_index)[0]
|
||||||
.get());
|
.get());
|
||||||
|
|
||||||
LOG_DBG("Maybe building instantiation for: {}{}", primary_template_name,
|
LOG_DBG("Maybe building instantiation for: {}{}", primary_template_name,
|
||||||
cppast::to_string(tr));
|
cppast::to_string(tr));
|
||||||
@@ -564,7 +585,27 @@ void tu_visitor::process_function_parameter(
|
|||||||
{
|
{
|
||||||
method_parameter mp;
|
method_parameter mp;
|
||||||
mp.name = param.name();
|
mp.name = param.name();
|
||||||
mp.type = cppast::to_string(param.type());
|
const auto ¶m_type =
|
||||||
|
cppast::remove_cv(cx::util::unreferenced(param.type()));
|
||||||
|
if (param_type.kind() == cppast::cpp_type_kind::template_instantiation_t) {
|
||||||
|
// Template instantiation parameters are not fully prefixed
|
||||||
|
// so we have to deduce the correct namespace prefix of the
|
||||||
|
// template which is being instantiated
|
||||||
|
mp.type = cppast::to_string(param.type());
|
||||||
|
|
||||||
|
auto &template_instantiation_type =
|
||||||
|
static_cast<const cppast::cpp_template_instantiation_type &>(
|
||||||
|
param_type);
|
||||||
|
auto &primary_template_entity =
|
||||||
|
template_instantiation_type.primary_template();
|
||||||
|
|
||||||
|
auto trawname = cppast::to_string(template_instantiation_type);
|
||||||
|
auto pte = cx::util::fully_prefixed(ctx.namespace_,
|
||||||
|
primary_template_entity.get(ctx.entity_index)[0].get());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
mp.type = cppast::to_string(param.type());
|
||||||
|
}
|
||||||
|
|
||||||
auto dv = param.default_value();
|
auto dv = param.default_value();
|
||||||
if (dv)
|
if (dv)
|
||||||
@@ -613,7 +654,7 @@ void tu_visitor::process_function_parameter(
|
|||||||
.size()) {
|
.size()) {
|
||||||
// Here we need the name of the primary template with full
|
// Here we need the name of the primary template with full
|
||||||
// namespace prefix to apply config inclusion filters
|
// namespace prefix to apply config inclusion filters
|
||||||
auto primary_template_name = cx::util::full_name(
|
auto primary_template_name = cx::util::full_name(ctx.namespace_,
|
||||||
template_instantiation_type.primary_template()
|
template_instantiation_type.primary_template()
|
||||||
.get(ctx.entity_index)[0]
|
.get(ctx.entity_index)[0]
|
||||||
.get());
|
.get());
|
||||||
@@ -638,7 +679,7 @@ void tu_visitor::process_function_parameter(
|
|||||||
rr.destination = tinst.usr;
|
rr.destination = tinst.usr;
|
||||||
rr.type = relationship_t::kDependency;
|
rr.type = relationship_t::kDependency;
|
||||||
rr.label = "";
|
rr.label = "";
|
||||||
LOG_DBG("Adding field instantiation relationship {} {} {} : {}",
|
LOG_DBG("Adding field dependency relationship {} {} {} : {}",
|
||||||
rr.destination, model::class_diagram::to_string(rr.type),
|
rr.destination, model::class_diagram::to_string(rr.type),
|
||||||
c.usr, rr.label);
|
c.usr, rr.label);
|
||||||
c.add_relationship(std::move(rr));
|
c.add_relationship(std::move(rr));
|
||||||
@@ -731,7 +772,7 @@ void tu_visitor::process_friend(const cppast::cpp_friend &f, class_ &parent)
|
|||||||
cppast::is_templated(f.entity().value()),
|
cppast::is_templated(f.entity().value()),
|
||||||
cppast::to_string(f.entity().value().kind()));
|
cppast::to_string(f.entity().value().kind()));
|
||||||
|
|
||||||
name = cx::util::full_name(f.entity().value());
|
name = cx::util::full_name(ctx.namespace_, f.entity().value());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx.config.should_include(name))
|
if (!ctx.config.should_include(name))
|
||||||
@@ -849,24 +890,23 @@ void tu_visitor::find_relationships(const cppast::cpp_type &t_,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class_ tu_visitor::build_template_instantiation(/*const cppast::cpp_entity &e,*/
|
class_ tu_visitor::build_template_instantiation(
|
||||||
const cppast::cpp_template_instantiation_type &t)
|
const cppast::cpp_template_instantiation_type &t)
|
||||||
{
|
{
|
||||||
auto full_template_name = cx::util::full_name(
|
const auto &primary_template_ref =
|
||||||
t.primary_template().get(ctx.entity_index)[0].get());
|
static_cast<const cppast::cpp_class_template &>(
|
||||||
|
t.primary_template().get(ctx.entity_index)[0].get())
|
||||||
|
.class_();
|
||||||
|
|
||||||
|
auto full_template_name =
|
||||||
|
cx::util::full_name(ctx.namespace_, primary_template_ref);
|
||||||
|
|
||||||
LOG_DBG("Found template instantiation: {} ({}) ..|> {}, {}",
|
LOG_DBG("Found 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);
|
||||||
|
|
||||||
class_ tinst;
|
class_ tinst;
|
||||||
const auto &primary_template_ref =
|
|
||||||
static_cast<const cppast::cpp_class_template &>(
|
|
||||||
t.primary_template().get(ctx.entity_index)[0].get())
|
|
||||||
.class_();
|
|
||||||
|
|
||||||
tinst.name = util::split(
|
|
||||||
cppast::to_string(t), "<")[0]; // primary_template_ref.name();
|
|
||||||
if (full_template_name.back() == ':')
|
if (full_template_name.back() == ':')
|
||||||
tinst.name = full_template_name + tinst.name;
|
tinst.name = full_template_name + tinst.name;
|
||||||
|
|
||||||
@@ -879,6 +919,19 @@ class_ tu_visitor::build_template_instantiation(/*const cppast::cpp_entity &e,*/
|
|||||||
LOG_WARN(
|
LOG_WARN(
|
||||||
"No user data for base template {}", primary_template_ref.name());
|
"No user data for base template {}", primary_template_ref.name());
|
||||||
|
|
||||||
|
// Extract namespace from base template name
|
||||||
|
auto ns_toks = clanguml::util::split(
|
||||||
|
tinst.base_template_usr.substr(0, tinst.base_template_usr.find('<')),
|
||||||
|
"::");
|
||||||
|
|
||||||
|
std::string ns;
|
||||||
|
if (ns_toks.size() > 1) {
|
||||||
|
ns = fmt::format(
|
||||||
|
"{}::", fmt::join(ns_toks.begin(), ns_toks.end() - 1, "::"));
|
||||||
|
}
|
||||||
|
|
||||||
|
tinst.name = ns + util::split(cppast::to_string(t), "<")[0];
|
||||||
|
|
||||||
tinst.is_template_instantiation = true;
|
tinst.is_template_instantiation = true;
|
||||||
|
|
||||||
for (const auto &targ : t.arguments().value()) {
|
for (const auto &targ : t.arguments().value()) {
|
||||||
@@ -905,6 +958,10 @@ class_ tu_visitor::build_template_instantiation(/*const cppast::cpp_entity &e,*/
|
|||||||
}
|
}
|
||||||
|
|
||||||
tinst.usr = tinst.full_name(ctx.config.using_namespace);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
return tinst;
|
return tinst;
|
||||||
}
|
}
|
||||||
|
|||||||
12
tests/t00015/.clanguml
Normal file
12
tests/t00015/.clanguml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
compilation_database_dir: ..
|
||||||
|
output_directory: puml
|
||||||
|
diagrams:
|
||||||
|
t00015_class:
|
||||||
|
type: class
|
||||||
|
glob:
|
||||||
|
- ../../tests/t00015/t00015.cc
|
||||||
|
using_namespace:
|
||||||
|
- clanguml::t00015
|
||||||
|
include:
|
||||||
|
namespaces:
|
||||||
|
- clanguml::t00015
|
||||||
25
tests/t00015/t00015.cc
Normal file
25
tests/t00015/t00015.cc
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
namespace clanguml {
|
||||||
|
namespace t00015 {
|
||||||
|
|
||||||
|
namespace ns1::ns2 {
|
||||||
|
class A {
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
class Anon final : public A {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ns3 {
|
||||||
|
|
||||||
|
namespace ns1::ns2 {
|
||||||
|
class Anon : public t00015::ns1::ns2::A {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class B : public ns1::ns2::Anon {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
50
tests/t00015/test_case.h
Normal file
50
tests/t00015/test_case.h
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* tests/t00015/test_case.cc
|
||||||
|
*
|
||||||
|
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TEST_CASE("t00015", "[test-case][class]")
|
||||||
|
{
|
||||||
|
auto [config, db] = load_config("t00015");
|
||||||
|
|
||||||
|
auto diagram = config.diagrams["t00015_class"];
|
||||||
|
|
||||||
|
REQUIRE(diagram->name == "t00015_class");
|
||||||
|
|
||||||
|
REQUIRE(diagram->include.namespaces.size() == 1);
|
||||||
|
REQUIRE_THAT(diagram->include.namespaces,
|
||||||
|
VectorContains(std::string{"clanguml::t00015"}));
|
||||||
|
|
||||||
|
REQUIRE(diagram->exclude.namespaces.size() == 0);
|
||||||
|
|
||||||
|
REQUIRE(diagram->should_include("clanguml::t00015::ns1::ns2::A"));
|
||||||
|
|
||||||
|
auto model = generate_class_diagram(db, diagram);
|
||||||
|
|
||||||
|
REQUIRE(model.name == "t00015_class");
|
||||||
|
|
||||||
|
auto puml = generate_class_puml(diagram, model);
|
||||||
|
AliasMatcher _A(puml);
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml, StartsWith("@startuml"));
|
||||||
|
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
||||||
|
REQUIRE_THAT(puml, IsClass(_A("ns1::ns2::A")));
|
||||||
|
REQUIRE_THAT(puml, IsClass(_A("ns1::ns2::Anon")));
|
||||||
|
REQUIRE_THAT(puml, IsClass(_A("ns3::B")));
|
||||||
|
|
||||||
|
save_puml(
|
||||||
|
"./" + config.output_directory + "/" + diagram->name + ".puml", puml);
|
||||||
|
}
|
||||||
@@ -118,6 +118,7 @@ using namespace clanguml::test::matchers;
|
|||||||
#include "t00012/test_case.h"
|
#include "t00012/test_case.h"
|
||||||
#include "t00013/test_case.h"
|
#include "t00013/test_case.h"
|
||||||
#include "t00014/test_case.h"
|
#include "t00014/test_case.h"
|
||||||
|
#include "t00015/test_case.h"
|
||||||
|
|
||||||
//
|
//
|
||||||
// Sequence diagram tests
|
// Sequence diagram tests
|
||||||
|
|||||||
@@ -39,6 +39,9 @@ test_cases:
|
|||||||
- name: t00014
|
- name: t00014
|
||||||
title: Alias template instantiation
|
title: Alias template instantiation
|
||||||
description:
|
description:
|
||||||
|
- name: t00015
|
||||||
|
title: Namespace fun
|
||||||
|
description:
|
||||||
Sequence diagrams:
|
Sequence diagrams:
|
||||||
- name: t20001
|
- name: t20001
|
||||||
title: Basic sequence diagram
|
title: Basic sequence diagram
|
||||||
|
|||||||
Reference in New Issue
Block a user