Added handling of nontype template parameters
This commit is contained in:
@@ -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()
|
||||
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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, ", "));
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ struct class_relationship {
|
||||
|
||||
struct class_template {
|
||||
std::string name;
|
||||
std::string type;
|
||||
std::string default_value;
|
||||
};
|
||||
|
||||
struct class_ : public element {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user