Added template overload pattern test case
This commit is contained in:
@@ -31,6 +31,8 @@
|
|||||||
#include <cppast/cpp_variable.hpp>
|
#include <cppast/cpp_variable.hpp>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
namespace clanguml {
|
namespace clanguml {
|
||||||
namespace visitor {
|
namespace visitor {
|
||||||
namespace class_diagram {
|
namespace class_diagram {
|
||||||
@@ -1185,7 +1187,7 @@ class_ tu_visitor::build_template_instantiation(
|
|||||||
class_ tinst;
|
class_ tinst;
|
||||||
std::string full_template_name;
|
std::string full_template_name;
|
||||||
|
|
||||||
std::vector<std::tuple<std::string, int, bool>> template_base_params{};
|
std::deque<std::tuple<std::string, int, bool>> template_base_params{};
|
||||||
|
|
||||||
if (t.primary_template().get(ctx.entity_index).size()) {
|
if (t.primary_template().get(ctx.entity_index).size()) {
|
||||||
const auto &primary_template_ref =
|
const auto &primary_template_ref =
|
||||||
@@ -1223,7 +1225,7 @@ class_ tu_visitor::build_template_instantiation(
|
|||||||
const auto base_class_name =
|
const auto base_class_name =
|
||||||
cppast::to_string(base_class.type());
|
cppast::to_string(base_class.type());
|
||||||
|
|
||||||
LOG_ERROR("FOUND TEMPLATE INSTANTIATION BASE: {}, {}, {}",
|
LOG_DBG("Found template instantiation base: {}, {}, {}",
|
||||||
cppast::to_string(base.kind()), base_class_name,
|
cppast::to_string(base.kind()), base_class_name,
|
||||||
base_index);
|
base_index);
|
||||||
|
|
||||||
@@ -1236,8 +1238,8 @@ class_ tu_visitor::build_template_instantiation(
|
|||||||
|
|
||||||
if (it != template_parameter_names.end()) {
|
if (it != template_parameter_names.end()) {
|
||||||
// Found base class which is a template parameter
|
// Found base class which is a template parameter
|
||||||
LOG_ERROR("FOUND BASE CLASS WHICH IS A TEMPLATE PARAMETER "
|
LOG_DBG("Found base class which is a template parameter "
|
||||||
"{}, {}, {}",
|
"{}, {}, {}",
|
||||||
it->first, it->second,
|
it->first, it->second,
|
||||||
std::distance(template_parameter_names.begin(), it));
|
std::distance(template_parameter_names.begin(), it));
|
||||||
template_base_params.emplace_back(it->first, it->second,
|
template_base_params.emplace_back(it->first, it->second,
|
||||||
@@ -1283,7 +1285,10 @@ class_ tu_visitor::build_template_instantiation(
|
|||||||
tinst.is_template_instantiation = true;
|
tinst.is_template_instantiation = true;
|
||||||
|
|
||||||
// Process template argumetns
|
// Process template argumetns
|
||||||
|
int arg_index{0};
|
||||||
|
bool variadic_params{false};
|
||||||
for (const auto &targ : t.arguments().value()) {
|
for (const auto &targ : t.arguments().value()) {
|
||||||
|
bool add_template_argument_as_base_class{false};
|
||||||
class_template ct;
|
class_template ct;
|
||||||
if (targ.type()) {
|
if (targ.type()) {
|
||||||
ct.type = cppast::to_string(targ.type().value());
|
ct.type = cppast::to_string(targ.type().value());
|
||||||
@@ -1301,13 +1306,36 @@ class_ tu_visitor::build_template_instantiation(
|
|||||||
.as_string();
|
.as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// In case any of the template arguments are base classes, add
|
||||||
|
// them as parents of the current template instantiation class
|
||||||
|
if (template_base_params.size() > 0) {
|
||||||
|
auto [arg_name, is_variadic, index] = template_base_params.front();
|
||||||
|
if (variadic_params)
|
||||||
|
add_template_argument_as_base_class = true;
|
||||||
|
else {
|
||||||
|
variadic_params = is_variadic;
|
||||||
|
if (arg_index == index) {
|
||||||
|
add_template_argument_as_base_class = true;
|
||||||
|
template_base_params.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_template_argument_as_base_class) {
|
||||||
|
LOG_DBG("Adding template argument '{}' as base class", ct.type);
|
||||||
|
|
||||||
|
class_parent cp;
|
||||||
|
cp.access = class_parent::access_t::kPublic;
|
||||||
|
cp.name = ct.type;
|
||||||
|
|
||||||
|
tinst.bases.emplace_back(std::move(cp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_DBG("Adding template argument '{}'", ct.type);
|
LOG_DBG("Adding template argument '{}'", ct.type);
|
||||||
|
|
||||||
tinst.templates.emplace_back(std::move(ct));
|
tinst.templates.emplace_back(std::move(ct));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if template inherits from any of the template arguments
|
|
||||||
|
|
||||||
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("::") ==
|
if (tinst.usr.substr(0, tinst.usr.find('<')).find("::") ==
|
||||||
std::string::npos) {
|
std::string::npos) {
|
||||||
|
|||||||
@@ -22,15 +22,16 @@ struct C {
|
|||||||
void operator()() { }
|
void operator()() { }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename... Ts>
|
template <typename T, typename L, typename... Ts>
|
||||||
struct Overload : public Base, public T, public Ts... {
|
struct Overload : public Base, public T, public Ts... {
|
||||||
using Ts::operator()...;
|
using Ts::operator()...;
|
||||||
|
L counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class... Ts> Overload(Ts...) -> Overload<Ts...>;
|
template <class... Ts> Overload(Ts...) -> Overload<Ts...>;
|
||||||
|
|
||||||
struct R {
|
struct R {
|
||||||
Overload<TBase, A, B, C> overload;
|
Overload<TBase, int, A, B, C> overload;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace t00032
|
} // namespace t00032
|
||||||
|
|||||||
@@ -42,7 +42,21 @@ TEST_CASE("t00032", "[test-case][class]")
|
|||||||
REQUIRE_THAT(puml, StartsWith("@startuml"));
|
REQUIRE_THAT(puml, StartsWith("@startuml"));
|
||||||
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml, IsClass(_A("Base")));
|
||||||
|
REQUIRE_THAT(puml, IsClass(_A("TBase")));
|
||||||
REQUIRE_THAT(puml, IsClass(_A("A")));
|
REQUIRE_THAT(puml, IsClass(_A("A")));
|
||||||
|
REQUIRE_THAT(puml, IsClass(_A("B")));
|
||||||
|
REQUIRE_THAT(puml, IsClass(_A("C")));
|
||||||
|
REQUIRE_THAT(puml, IsClass(_A("R")));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml, IsClassTemplate("Overload", "T,L,Ts..."));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml, IsBaseClass(_A("Base"), _A("Overload<T,L,Ts...>")));
|
||||||
|
REQUIRE_THAT(
|
||||||
|
puml, IsBaseClass(_A("TBase"), _A("Overload<TBase,int,A,B,C>")));
|
||||||
|
REQUIRE_THAT(puml, IsBaseClass(_A("A"), _A("Overload<TBase,int,A,B,C>")));
|
||||||
|
REQUIRE_THAT(puml, IsBaseClass(_A("B"), _A("Overload<TBase,int,A,B,C>")));
|
||||||
|
REQUIRE_THAT(puml, IsBaseClass(_A("C"), _A("Overload<TBase,int,A,B,C>")));
|
||||||
|
|
||||||
save_puml(
|
save_puml(
|
||||||
"./" + config.output_directory + "/" + diagram->name + ".puml", puml);
|
"./" + config.output_directory + "/" + diagram->name + ".puml", puml);
|
||||||
|
|||||||
Reference in New Issue
Block a user