Fixed template instantiation with mixed type and non-type parameters
This commit is contained in:
@@ -268,36 +268,29 @@ public:
|
|||||||
|
|
||||||
std::vector<std::string> tokenize_template_parameters() const
|
std::vector<std::string> tokenize_template_parameters() const
|
||||||
{
|
{
|
||||||
const auto &toks = tokenize();
|
auto toks = tokenize();
|
||||||
std::vector<std::string> res;
|
std::vector<std::string> res;
|
||||||
bool inside_template{false};
|
bool inside_template{false};
|
||||||
bool is_namespace{false};
|
bool is_namespace{false};
|
||||||
for (const auto &tok : toks) {
|
|
||||||
auto t = clanguml::util::trim(tok);
|
|
||||||
if (t == ">") {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (inside_template) {
|
|
||||||
if (t == ",")
|
|
||||||
continue;
|
|
||||||
if (t == "::") {
|
|
||||||
is_namespace = true;
|
|
||||||
res.back() += t;
|
|
||||||
}
|
|
||||||
else if (is_namespace) {
|
|
||||||
is_namespace = false;
|
|
||||||
res.back() += t;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
res.push_back(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (t == "<") {
|
|
||||||
inside_template = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
for (int i = 0; i < toks.size(); i++) {
|
||||||
|
// libclang returns ">..>>" in template as a single token...
|
||||||
|
auto t = toks[i];
|
||||||
|
if (std::all_of(t.begin(), t.end(),
|
||||||
|
[](const char &c) { return c == '>'; })) {
|
||||||
|
toks[i] = ">";
|
||||||
|
for (int j = 0; j < t.size() - 1; j++)
|
||||||
|
toks.insert(toks.begin() + i, ">");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto template_start = std::find(toks.begin(), toks.end(), "<");
|
||||||
|
auto template_end = std::find(toks.rbegin(), toks.rend(), ">");
|
||||||
|
|
||||||
|
decltype(res) template_contents(
|
||||||
|
template_start + 1, template_end.base() - 1);
|
||||||
|
|
||||||
|
return clanguml::util::split(
|
||||||
|
fmt::format("{}", fmt::join(template_contents, "")), ",");
|
||||||
}
|
}
|
||||||
|
|
||||||
const CXCursor &get() const { return m_cursor; }
|
const CXCursor &get() const { return m_cursor; }
|
||||||
|
|||||||
@@ -462,21 +462,6 @@ static enum CXChildVisitResult class_visitor(
|
|||||||
tinst.usr = tr.type_declaration().usr();
|
tinst.usr = tr.type_declaration().usr();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tr.template_argument_type(0).is_invalid()) {
|
|
||||||
for (int i = 0;
|
|
||||||
i < tr.template_arguments_count(); i++) {
|
|
||||||
auto template_param =
|
|
||||||
tr.template_argument_type(i);
|
|
||||||
class_template ct;
|
|
||||||
ct.type = template_param.spelling();
|
|
||||||
tinst.templates.emplace_back(std::move(ct));
|
|
||||||
|
|
||||||
spdlog::info(
|
|
||||||
"Adding template argument '{}'",
|
|
||||||
template_param);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const auto &instantiation_params =
|
const auto &instantiation_params =
|
||||||
cursor.tokenize_template_parameters();
|
cursor.tokenize_template_parameters();
|
||||||
|
|
||||||
@@ -487,11 +472,9 @@ static enum CXChildVisitResult class_visitor(
|
|||||||
ct.type = template_param;
|
ct.type = template_param;
|
||||||
tinst.templates.emplace_back(std::move(ct));
|
tinst.templates.emplace_back(std::move(ct));
|
||||||
|
|
||||||
spdlog::info(
|
spdlog::info("Adding template argument '{}'",
|
||||||
"Adding template argument '{}'",
|
|
||||||
template_param);
|
template_param);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (partial_specialization) {
|
if (partial_specialization) {
|
||||||
tinst.base_template_usr = template_type.usr();
|
tinst.base_template_usr = template_type.usr();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
|
||||||
@@ -14,12 +15,20 @@ template <int... Is> class B {
|
|||||||
std::array<int, sizeof...(Is)> ints;
|
std::array<int, sizeof...(Is)> ints;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename T, int... Is> class C {
|
||||||
|
std::array<T, sizeof...(Is)> ints;
|
||||||
|
};
|
||||||
|
|
||||||
class R {
|
class R {
|
||||||
A<int, std::string, float> a1;
|
A<int, std::string, float> a1;
|
||||||
A<int, std::string, bool> a2;
|
A<int, std::string, bool> a2;
|
||||||
|
|
||||||
B<3, 2, 1> b1;
|
B<3, 2, 1> b1;
|
||||||
B<1, 1, 1, 1> b2;
|
B<1, 1, 1, 1> b2;
|
||||||
|
|
||||||
|
C<std::map<int, std::vector<std::vector<std::vector<std::string>>>>, 3, 3,
|
||||||
|
3>
|
||||||
|
c1;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,15 @@ TEST_CASE("Test t00012", "[unit-test]")
|
|||||||
REQUIRE_THAT(puml, IsClassTemplate("A", "T, Ts..."));
|
REQUIRE_THAT(puml, IsClassTemplate("A", "T, Ts..."));
|
||||||
REQUIRE_THAT(puml, IsClassTemplate("B", "int Is..."));
|
REQUIRE_THAT(puml, IsClassTemplate("B", "int Is..."));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml, IsInstantiation(_A("B<int Is...>"), _A("B<3, 2, 1>")));
|
||||||
|
REQUIRE_THAT(
|
||||||
|
puml, IsInstantiation(_A("B<int Is...>"), _A("B<1, 1, 1, 1>")));
|
||||||
|
REQUIRE_THAT(puml,
|
||||||
|
IsInstantiation(_A("C<T, int Is...>"),
|
||||||
|
_A("C<std::map<int, "
|
||||||
|
"std::vector<std::vector<std::vector<std::string>>>>, 3, 3, "
|
||||||
|
"3>")));
|
||||||
|
|
||||||
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