Fixed generating relationships from function template arguments

This commit is contained in:
Bartek Kryza
2022-06-05 12:16:44 +02:00
parent 891caa8ecb
commit fdd5495940
4 changed files with 39 additions and 14 deletions

View File

@@ -18,6 +18,7 @@
#include "translation_unit_visitor.h"
#include "cppast/cpp_function_type.hpp"
#include "cx/util.h"
#include <cppast/cpp_alias_template.hpp>
@@ -26,6 +27,7 @@
#include <cppast/cpp_entity_kind.hpp>
#include <cppast/cpp_enum.hpp>
#include <cppast/cpp_friend.hpp>
#include <cppast/cpp_function_type.hpp>
#include <cppast/cpp_member_function.hpp>
#include <cppast/cpp_member_variable.hpp>
#include <cppast/cpp_namespace.hpp>
@@ -719,11 +721,12 @@ bool translation_unit_visitor::process_field_with_template_instantiation(
found_relationships_t nested_relationships;
if (tr_declaration == tr_unaliased_declaration)
tinst_ptr = build_template_instantiation(unaliased);
tinst_ptr = build_template_instantiation(unaliased, {&c});
else
tinst_ptr = build_template_instantiation(
static_cast<const cppast::cpp_template_instantiation_type &>(
type.canonical()));
type.canonical()),
{&c});
auto &tinst = *tinst_ptr;
@@ -1707,7 +1710,7 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
template_parameter ct;
if (targ.type()) {
build_template_instantiation_process_type_argument(
parent, tinst, targ, ct);
parent, tinst, targ.type().value(), ct);
}
else if (targ.expression()) {
build_template_instantiation_process_expression_argument(
@@ -1824,15 +1827,15 @@ void translation_unit_visitor::
void translation_unit_visitor::
build_template_instantiation_process_type_argument(
const std::optional<clanguml::class_diagram::model::class_ *> &parent,
class_ &tinst, const cppast::cpp_template_argument &targ,
class_ &tinst, const cppast::cpp_type &targ_type,
template_parameter &ct)
{
auto full_name = cx::util::full_name(
cppast::remove_cv(cx::util::unreferenced(targ.type().value())),
cppast::remove_cv(cx::util::unreferenced(targ_type)),
ctx.entity_index(), false);
auto [fn_ns, fn_name] = cx::util::split_ns(full_name);
auto template_argument_kind = targ.type().value().kind();
auto template_argument_kind = targ_type.kind();
if (template_argument_kind == cppast::cpp_type_kind::unexposed_t) {
// Here we're on our own - just make a best guess
@@ -1858,14 +1861,14 @@ void translation_unit_visitor::
// Check if this template should be simplified (e.g. system
// template aliases such as std:basic_string<char> should be simply
// std::string
// std::string)
if (simplify_system_template(ct, full_name)) {
return;
}
const auto &nested_template_parameter =
static_cast<const cppast::cpp_template_instantiation_type &>(
targ.type().value());
targ_type);
auto [tinst_ns, tinst_name] =
cx::util::split_ns(tinst.full_name(false));
@@ -1924,10 +1927,27 @@ void translation_unit_visitor::
full_name, tinst.full_name(), tinst_dependency.destination());
}
}
else if (template_argument_kind == cppast::cpp_type_kind::function_t) {
const auto &function_argument =
static_cast<const cppast::cpp_function_type &>(targ_type);
const auto &rt = function_argument.return_type();
// Search for relationships in argument return type
// TODO...
// Build instantiations of each of the arguments
for (const auto &arg : function_argument.parameter_types()) {
template_parameter ctt;
build_template_instantiation_process_type_argument(
parent, tinst, arg, ctt);
}
}
else if (template_argument_kind == cppast::cpp_type_kind::user_defined_t) {
relationship tinst_dependency{relationship_t::kDependency,
cx::util::full_name(
cppast::remove_cv(cx::util::unreferenced(targ.type().value())),
cppast::remove_cv(cx::util::unreferenced(targ_type)),
ctx.entity_index(), false)};
LOG_DBG("Creating nested template dependency to user defined "

View File

@@ -213,7 +213,7 @@ private:
void build_template_instantiation_process_type_argument(
const std::optional<clanguml::class_diagram::model::class_ *> &parent,
model::class_ &tinst, const cppast::cpp_template_argument &targ,
model::class_ &tinst, const cppast::cpp_type &targ_type,
class_diagram::model::template_parameter &ct);
void build_template_instantiation_process_expression_argument(

View File

@@ -39,13 +39,14 @@ template <class T> using ASharedPtr = std::shared_ptr<A<double, T>>;
template <class T, class U>
using AAPtr = std::unique_ptr<std::pair<A<double, T>, A<long, U>>>;
template <typename... T> using GeneralCallback = std::function<void(T..., int)>;
using VoidCallback = GeneralCallback<>;
template <typename T> using GeneralCallback = std::function<void(T, int)>;
using VoidCallback = GeneralCallback<void *>;
using BVector = std::vector<B>;
using BVector2 = BVector;
using AIntString = AString<int>;
using ACharString = AString<char>;
using AStringString = AString<std::string>;
using BStringString = AStringString;
@@ -66,7 +67,7 @@ protected:
public:
BVector2 bs2;
GeneralCallback<AIntString> cb;
GeneralCallback<ACharString> cb;
VoidCallback vcb;
VectorPtr<B> vps;
};

View File

@@ -45,6 +45,7 @@ TEST_CASE("t00014", "[test-case][class]")
REQUIRE_THAT(puml, IsClassTemplate("A", "long,float"));
REQUIRE_THAT(puml, IsClassTemplate("A", "double,float"));
REQUIRE_THAT(puml, IsClassTemplate("A", "bool,std::string"));
REQUIRE_THAT(puml, IsClassTemplate("A", "char,std::string"));
REQUIRE_THAT(puml, IsClass(_A("B")));
REQUIRE_THAT(puml, IsField<Private>("bapair", "PairPairBA<bool>"));
@@ -59,7 +60,7 @@ TEST_CASE("t00014", "[test-case][class]")
REQUIRE_THAT(puml, IsField<Protected>("bs", "BVector"));
REQUIRE_THAT(puml, IsField<Public>("cb", "GeneralCallback<AIntString>"));
REQUIRE_THAT(puml, IsField<Public>("cb", "GeneralCallback<ACharString>"));
REQUIRE_THAT(puml, IsField<Public>("vcb", "VoidCallback"));
REQUIRE_THAT(
@@ -79,6 +80,8 @@ TEST_CASE("t00014", "[test-case][class]")
REQUIRE_THAT(puml, IsInstantiation(_A("A<T,P>"), _A("A<T,std::string>")));
REQUIRE_THAT(puml,
IsInstantiation(_A("A<T,std::string>"), _A("A<bool,std::string>")));
REQUIRE_THAT(puml,
IsInstantiation(_A("A<T,std::string>"), _A("A<char,std::string>")));
REQUIRE_THAT(puml,
IsInstantiation(_A("A<T,std::unique_ptr<std::string>>"),
@@ -100,6 +103,7 @@ TEST_CASE("t00014", "[test-case][class]")
REQUIRE_THAT(puml,
IsAggregation(_A("R"), _A("A<float,std::unique_ptr<std::string>>"),
"-floatstring"));
REQUIRE_THAT(puml, IsDependency(_A("R"), _A("A<char,std::string>")));
save_puml(
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);