Added handling of nontype template parameters

This commit is contained in:
Bartek Kryza
2021-03-06 20:41:29 +01:00
parent e267d295f6
commit 25254fc81d
6 changed files with 66 additions and 14 deletions

View File

@@ -223,3 +223,22 @@ private:
};
}
}
template <> struct fmt::formatter<clanguml::cx::cursor> {
template <typename ParseContext> constexpr auto parse(ParseContext &ctx)
{
return ctx.begin();
}
template <typename FormatContext>
auto format(const clanguml::cx::cursor &c, FormatContext &ctx)
{
return fmt::format_to(ctx.out(),
"(cx::cursor spelling={}, display_name={}, kind={}, "
"is_expression={}, template_argument_count={})",
c.spelling(), c.display_name(), c.kind_spelling(),
c.is_expression(), c.template_argument_count()
);
}
};

View File

@@ -105,8 +105,24 @@ public:
if (!c.templates.empty()) {
std::vector<std::string> tnames;
std::transform(c.templates.cbegin(), c.templates.cend(),
std::back_inserter(tnames),
[](const auto &tmplt) { return tmplt.name; });
std::back_inserter(tnames), [this](const auto &tmplt) {
std::vector<std::string> res;
if (!tmplt.type.empty())
res.push_back(
ns_relative(m_config.using_namespace, tmplt.type));
if (!tmplt.name.empty())
res.push_back(
ns_relative(m_config.using_namespace, tmplt.name));
if (!tmplt.default_value.empty()) {
res.push_back("=");
res.push_back(tmplt.default_value);
}
return fmt::format("{}", fmt::join(res, " "));
});
ostr << fmt::format("<{}>", fmt::join(tnames, ", "));
}

View File

@@ -89,6 +89,8 @@ struct class_relationship {
struct class_template {
std::string name;
std::string type;
std::string default_value;
};
struct class_ : public element {

View File

@@ -209,9 +209,8 @@ static enum CXChildVisitResult class_visitor(
std::string cursor_name_str = cursor.spelling();
spdlog::info("Visiting {}: {} - {}:{}",
ctx->element.is_struct ? "struct" : "class", ctx->element.name,
cursor_name_str, cursor.kind());
spdlog::info("Visiting {}: {} - {}",
ctx->element.is_struct ? "struct" : "class", ctx->element.name, cursor);
auto &config = ctx->ctx->config;
@@ -285,19 +284,27 @@ static enum CXChildVisitResult class_visitor(
ret = CXChildVisit_Continue;
break;
case CXCursor_TemplateTypeParameter: {
spdlog::info(
"Found template type parameter: {}", cursor.spelling());
spdlog::info("Found template type parameter: {}: {}",
cursor.spelling(), cursor.type());
class_template ct;
ct.type = "";
ct.name = cursor.spelling();
ct.default_value = "";
ctx->element.templates.emplace_back(std::move(ct));
ret = CXChildVisit_Continue;
} break;
case CXCursor_NonTypeTemplateParameter:
spdlog::info(
"Found template nontype parameter: {}", cursor.spelling());
case CXCursor_NonTypeTemplateParameter: {
spdlog::info("Found template nontype parameter: {}: {}",
cursor.spelling(), cursor.type());
class_template ct;
ct.type = cursor.type().canonical().spelling();
ct.name = cursor.spelling();
ct.default_value = "";
ctx->element.templates.emplace_back(std::move(ct));
ret = CXChildVisit_Continue;
break;
} break;
case CXCursor_TemplateTemplateParameter:
spdlog::info(
"Found template template parameter: {}", cursor.spelling());
@@ -468,7 +475,7 @@ static enum CXChildVisitResult translation_unit_visitor(
case CXCursor_ClassTemplate:
[[fallthrough]];
case CXCursor_ClassDecl: {
spdlog::debug("Found class or class template declaration: {}",
spdlog::info("Found class or class template declaration: {}",
cursor_name_str);
if (!ctx->config.should_include(cursor.fully_qualified())) {
ret = CXChildVisit_Continue;

View File

@@ -1,13 +1,19 @@
#include <array>
#include <vector>
namespace clanguml {
namespace t00008 {
template <typename T, typename P = T> class A {
using CMP = bool (*)(const int, const int);
template <typename T, typename P = T, CMP = nullptr, int N = 3> class A {
public:
T value;
T *pointer;
T &reference;
std::vector<P> values;
std::array<int, N> ints;
CMP comparator;
};
}
}

View File

@@ -43,12 +43,14 @@ TEST_CASE("Test t00008", "[unit-test]")
REQUIRE_THAT(puml, StartsWith("@startuml"));
REQUIRE_THAT(puml, EndsWith("@enduml\n"));
REQUIRE_THAT(puml, IsClassTemplate("A", "T, P"));
REQUIRE_THAT(puml, IsClassTemplate("A", "T, P, bool (*)(int, int), int N"));
REQUIRE_THAT(puml, IsField(Public("T value")));
REQUIRE_THAT(puml, IsField(Public("T * pointer")));
REQUIRE_THAT(puml, IsField(Public("T & reference")));
REQUIRE_THAT(puml, IsField(Public("std::vector<P> values")));
REQUIRE_THAT(puml, IsField(Public("std::array<int, N> ints")));
REQUIRE_THAT(puml, IsField(Public("bool (*)(int, int) comparator")));
save_puml(
"./" + config.output_directory + "/" + diagram->name + ".puml", puml);