Fixed template instantiations generation without known primary template

This commit is contained in:
Bartek Kryza
2021-07-20 19:35:47 +02:00
parent 0563a251fa
commit 524cf36ecd
10 changed files with 63 additions and 27 deletions

View File

@@ -13,11 +13,16 @@ diagrams:
include: include:
namespaces: namespaces:
- clanguml::t00014 - clanguml::t00014
exclude:
namespaces:
- std
- clanguml::t00014::std
``` ```
## Source code ## Source code
```cpp ```cpp
#include <algorithm> #include <algorithm>
#include <functional>
#include <ios> #include <ios>
#include <map> #include <map>
#include <numeric> #include <numeric>
@@ -46,6 +51,9 @@ template <typename T, typename P> struct A {
template <typename T> using AString = A<T, std::string>; template <typename T> using AString = A<T, std::string>;
template <typename... T> using GeneralCallback = std::function<void(T..., int)>;
using VoidCallback = GeneralCallback<>;
struct B { struct B {
std::string value; std::string value;
}; };
@@ -65,6 +73,8 @@ class R {
AStringString stringstring; AStringString stringstring;
BVector bs; BVector bs;
BVector2 bs2; BVector2 bs2;
GeneralCallback<AIntString> cb;
VoidCallback vcb;
}; };
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View File

@@ -111,9 +111,11 @@ struct diagram {
auto name = clanguml::util::unqualify(name_); auto name = clanguml::util::unqualify(name_);
for (const auto &ex : exclude.namespaces) { for (const auto &ex : exclude.namespaces) {
if (name.find(ex) == 0) if (name.find(ex) == 0) {
spdlog::debug("Skipping from diagram: {}", name);
return false; return false;
} }
}
// If no inclusive namespaces are provided, // If no inclusive namespaces are provided,
// allow all // allow all

View File

@@ -341,16 +341,24 @@ public:
if (m_config.should_include_entities("classes")) { if (m_config.should_include_entities("classes")) {
for (const auto &c : m_model.classes) { for (const auto &c : m_model.classes) {
if (!c.is_template_instantiation &&
!m_config.should_include(c.name))
continue;
generate_alias(c, ostr); generate_alias(c, ostr);
ostr << std::endl; ostr << std::endl;
} }
for (const auto &e : m_model.enums) { for (const auto &e : m_model.enums) {
if (!m_config.should_include(e.name))
continue;
generate_alias(e, ostr); generate_alias(e, ostr);
ostr << std::endl; ostr << std::endl;
} }
for (const auto &c : m_model.classes) { for (const auto &c : m_model.classes) {
if (!c.is_template_instantiation &&
!m_config.should_include(c.name))
continue;
generate(c, ostr); generate(c, ostr);
ostr << std::endl; ostr << std::endl;
} }

View File

@@ -1048,20 +1048,22 @@ void tu_visitor::find_relationships(const cppast::cpp_type &t_,
class_ tu_visitor::build_template_instantiation( class_ tu_visitor::build_template_instantiation(
const cppast::cpp_template_instantiation_type &t) const cppast::cpp_template_instantiation_type &t)
{ {
class_ tinst;
std::string full_template_name;
if (t.primary_template().get(ctx.entity_index).size()) {
const auto &primary_template_ref = const auto &primary_template_ref =
static_cast<const cppast::cpp_class_template &>( static_cast<const cppast::cpp_class_template &>(
t.primary_template().get(ctx.entity_index)[0].get()) t.primary_template().get(ctx.entity_index)[0].get())
.class_(); .class_();
auto full_template_name = full_template_name =
cx::util::full_name(ctx.namespace_, primary_template_ref); cx::util::full_name(ctx.namespace_, primary_template_ref);
LOG_DBG("Found template instantiation: {} ({}) ..|> {}, {}", LOG_DBG("Found template instantiation: {} ({}) ..|> {}, {}",
cppast::to_string(t), cppast::to_string(t.canonical()), cppast::to_string(t), cppast::to_string(t.canonical()),
t.primary_template().name(), full_template_name); t.primary_template().name(), full_template_name);
class_ tinst;
if (full_template_name.back() == ':') if (full_template_name.back() == ':')
tinst.name = full_template_name + tinst.name; tinst.name = full_template_name + tinst.name;
@@ -1071,8 +1073,15 @@ class_ tu_visitor::build_template_instantiation(
LOG_DBG("Primary template ref set to: {}", tinst.base_template_usr); LOG_DBG("Primary template ref set to: {}", tinst.base_template_usr);
} }
else else
LOG_WARN( LOG_WARN("No user data for base template {}",
"No user data for base template {}", primary_template_ref.name()); primary_template_ref.name());
}
else {
LOG_WARN("Template instantiation {} has no primary template",
cppast::to_string(t));
full_template_name = cppast::to_string(t);
}
// Extract namespace from base template name // Extract namespace from base template name
auto ns_toks = clanguml::util::split( auto ns_toks = clanguml::util::split(

View File

@@ -10,3 +10,7 @@ diagrams:
include: include:
namespaces: namespaces:
- clanguml::t00014 - clanguml::t00014
exclude:
namespaces:
- std
- clanguml::t00014::std

View File

@@ -1,4 +1,5 @@
#include <algorithm> #include <algorithm>
#include <functional>
#include <ios> #include <ios>
#include <map> #include <map>
#include <numeric> #include <numeric>
@@ -27,6 +28,9 @@ template <typename T, typename P> struct A {
template <typename T> using AString = A<T, std::string>; template <typename T> using AString = A<T, std::string>;
template <typename... T> using GeneralCallback = std::function<void(T..., int)>;
using VoidCallback = GeneralCallback<>;
struct B { struct B {
std::string value; std::string value;
}; };
@@ -46,6 +50,8 @@ class R {
AStringString stringstring; AStringString stringstring;
BVector bs; BVector bs;
BVector2 bs2; BVector2 bs2;
GeneralCallback<AIntString> cb;
VoidCallback vcb;
}; };
} }
} }

View File

@@ -1,5 +1,5 @@
/** /**
* tests/t00014/test_case.cc * tests/t00014/test_case.h
* *
* Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com> * Copyright (c) 2021 Bartek Kryza <bkryza@gmail.com>
* *
@@ -27,7 +27,7 @@ TEST_CASE("t00014", "[test-case][class]")
REQUIRE_THAT(diagram->include.namespaces, REQUIRE_THAT(diagram->include.namespaces,
VectorContains(std::string{"clanguml::t00014"})); VectorContains(std::string{"clanguml::t00014"}));
REQUIRE(diagram->exclude.namespaces.size() == 0); REQUIRE(diagram->exclude.namespaces.size() == 2);
REQUIRE(diagram->should_include("clanguml::t00014::S")); REQUIRE(diagram->should_include("clanguml::t00014::S"));
@@ -46,9 +46,6 @@ TEST_CASE("t00014", "[test-case][class]")
REQUIRE_THAT(puml, IsClassTemplate("AString", "float")); REQUIRE_THAT(puml, IsClassTemplate("AString", "float"));
REQUIRE_THAT(puml, IsInstantiation(_A("A<T,P>"), _A("A<T,std::string>"))); REQUIRE_THAT(puml, IsInstantiation(_A("A<T,P>"), _A("A<T,std::string>")));
// TODO
// REQUIRE_THAT(puml, IsInstantiation(_A("A<T,std::string>"),
// _A("A<bool,std::string>")));
REQUIRE_THAT( REQUIRE_THAT(
puml, IsInstantiation(_A("A<T,std::string>"), _A("AString<float>"))); puml, IsInstantiation(_A("A<T,std::string>"), _A("AString<float>")));
REQUIRE_THAT( REQUIRE_THAT(