Added handling of class template specializations
This commit is contained in:
@@ -106,7 +106,8 @@ void tu_visitor::operator()(const cppast::cpp_entity &file)
|
||||
auto &tspec = static_cast<
|
||||
const cppast::cpp_class_template_specialization &>(e);
|
||||
|
||||
process_class_declaration(tspec.class_(), tspec);
|
||||
process_class_declaration(
|
||||
tspec.class_(), type_safe::ref(tspec));
|
||||
}
|
||||
else if (e.kind() == cppast::cpp_entity_kind::class_t) {
|
||||
LOG_DBG("========== Visiting '{}' - {}",
|
||||
@@ -358,8 +359,97 @@ void tu_visitor::process_class_declaration(const cppast::cpp_class &cls,
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_WARN("Class {} is templated but it's scope {} is not :-|",
|
||||
LOG_WARN("Class {} is templated but it's scope {} is not - "
|
||||
"probably this is a specialization",
|
||||
cls.name(), scope.name());
|
||||
|
||||
// Add specialization arguments
|
||||
if (tspec) {
|
||||
if (!tspec.value().arguments_exposed()) {
|
||||
// Create template specialization with unexposed arguments
|
||||
auto ua = tspec.value().unexposed_arguments().as_string();
|
||||
|
||||
// Naive parse of template arguments:
|
||||
auto toks = util::split(ua, ",");
|
||||
for (const auto &t : toks) {
|
||||
class_template ct;
|
||||
ct.type = t;
|
||||
ct.default_value = "";
|
||||
ct.is_variadic = false;
|
||||
ct.name = "";
|
||||
c.templates.emplace_back(std::move(ct));
|
||||
|
||||
const auto &primary_template_ref =
|
||||
static_cast<const cppast::cpp_class_template &>(
|
||||
tspec.value()
|
||||
.primary_template()
|
||||
.get(ctx.entity_index)[0]
|
||||
.get())
|
||||
.class_();
|
||||
|
||||
if (primary_template_ref.user_data()) {
|
||||
auto base_template_usr = static_cast<const char *>(
|
||||
primary_template_ref.user_data());
|
||||
LOG_DBG("Primary template ref set to: {}",
|
||||
base_template_usr);
|
||||
// Add template specialization/instantiation
|
||||
// relationship
|
||||
class_relationship r;
|
||||
r.type = relationship_t::kInstantiation;
|
||||
r.label = "";
|
||||
r.destination = base_template_usr;
|
||||
c.add_relationship(std::move(r));
|
||||
}
|
||||
else {
|
||||
LOG_WARN("No user data for base template {}",
|
||||
primary_template_ref.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (auto &tp : tspec.value().parameters()) {
|
||||
switch (tp.kind()) {
|
||||
case cppast::cpp_entity_kind::
|
||||
template_type_parameter_t: {
|
||||
LOG_DBG("Processing template type parameter {}",
|
||||
tp.name());
|
||||
process_template_type_parameter(
|
||||
static_cast<const cppast::
|
||||
cpp_template_type_parameter &>(tp),
|
||||
c);
|
||||
} break;
|
||||
case cppast::cpp_entity_kind::
|
||||
non_type_template_parameter_t: {
|
||||
LOG_DBG("Processing template nontype parameter {}",
|
||||
tp.name());
|
||||
process_template_nontype_parameter(
|
||||
static_cast<const cppast::
|
||||
cpp_non_type_template_parameter &>(tp),
|
||||
c);
|
||||
} break;
|
||||
case cppast::cpp_entity_kind::
|
||||
template_template_parameter_t: {
|
||||
LOG_DBG("Processing template template parameter {}",
|
||||
tp.name());
|
||||
process_template_template_parameter(
|
||||
static_cast<const cppast::
|
||||
cpp_template_template_parameter &>(tp),
|
||||
c);
|
||||
} break;
|
||||
default:
|
||||
LOG_DBG("Unhandled template parameter "
|
||||
"type {}",
|
||||
cppast::to_string(tp.kind()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
LOG_DBG("Skipping template class declaration which has only "
|
||||
"unexposed arguments but no tspec provided");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -810,7 +900,7 @@ void tu_visitor::process_friend(const cppast::cpp_friend &f, class_ &parent)
|
||||
r.destination = name;
|
||||
}
|
||||
else if (f.entity()) {
|
||||
std::string name {};
|
||||
std::string name{};
|
||||
|
||||
if (f.entity().value().kind() ==
|
||||
cppast::cpp_entity_kind::class_template_t) {
|
||||
|
||||
@@ -45,9 +45,9 @@ struct tu_context {
|
||||
tu_context(cppast::cpp_entity_index &idx,
|
||||
clanguml::model::class_diagram::diagram &d_,
|
||||
const clanguml::config::class_diagram &config_)
|
||||
: entity_index {idx}
|
||||
, d {d_}
|
||||
, config {config_}
|
||||
: entity_index{idx}
|
||||
, d{d_}
|
||||
, config{config_}
|
||||
{
|
||||
}
|
||||
|
||||
@@ -128,13 +128,13 @@ struct tu_context {
|
||||
template <typename T> struct element_visitor_context {
|
||||
element_visitor_context(clanguml::model::class_diagram::diagram &d_, T &e)
|
||||
: element(e)
|
||||
, d {d_}
|
||||
, d{d_}
|
||||
{
|
||||
}
|
||||
tu_context *ctx;
|
||||
|
||||
T &element;
|
||||
clanguml::model::class_diagram::class_ *parent_class {};
|
||||
clanguml::model::class_diagram::class_ *parent_class{};
|
||||
clanguml::model::class_diagram::diagram &d;
|
||||
};
|
||||
|
||||
@@ -143,7 +143,7 @@ public:
|
||||
tu_visitor(cppast::cpp_entity_index &idx_,
|
||||
clanguml::model::class_diagram::diagram &d_,
|
||||
const clanguml::config::class_diagram &config_)
|
||||
: ctx {idx_, d_, config_}
|
||||
: ctx{idx_, d_, config_}
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace clanguml {
|
||||
namespace t00016 {
|
||||
|
||||
template <typename T> struct is_numeric {
|
||||
template <typename> struct is_numeric {
|
||||
enum { value = false };
|
||||
};
|
||||
|
||||
|
||||
@@ -41,7 +41,20 @@ TEST_CASE("t00016", "[test-case][class]")
|
||||
|
||||
REQUIRE_THAT(puml, StartsWith("@startuml"));
|
||||
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
||||
REQUIRE_THAT(puml, IsClass(_A("is_numeric")));
|
||||
REQUIRE_THAT(puml, IsClassTemplate("is_numeric", ""));
|
||||
REQUIRE_THAT(puml, IsClassTemplate("is_numeric", "int"));
|
||||
REQUIRE_THAT(puml, IsClassTemplate("is_numeric", "bool"));
|
||||
REQUIRE_THAT(puml, IsClassTemplate("is_numeric", "char"));
|
||||
REQUIRE_THAT(puml, IsClassTemplate("is_numeric", "unsigned char"));
|
||||
|
||||
REQUIRE_THAT(
|
||||
puml, IsInstantiation(_A("is_numeric<>"), _A("is_numeric<int>")));
|
||||
REQUIRE_THAT(
|
||||
puml, IsInstantiation(_A("is_numeric<>"), _A("is_numeric<bool>")));
|
||||
REQUIRE_THAT(
|
||||
puml, IsInstantiation(_A("is_numeric<>"), _A("is_numeric<char>")));
|
||||
REQUIRE_THAT(puml,
|
||||
IsInstantiation(_A("is_numeric<>"), _A("is_numeric<unsigned char>")));
|
||||
|
||||
save_puml(
|
||||
"./" + config.output_directory + "/" + diagram->name + ".puml", puml);
|
||||
|
||||
Reference in New Issue
Block a user