Refactored template argument relationship hints to configuration file option
This commit is contained in:
@@ -1487,30 +1487,9 @@ bool translation_unit_visitor::find_relationships_in_template_instantiation(
|
|||||||
|
|
||||||
auto full_name = fmt::format("{}", fmt::join(ns_and_name, "::"));
|
auto full_name = fmt::format("{}", fmt::join(ns_and_name, "::"));
|
||||||
|
|
||||||
// Try to match common containers
|
auto full_base_name = full_name.substr(0, full_name.find('<'));
|
||||||
// TODO: Refactor to a separate class with configurable
|
|
||||||
// container list
|
if (ctx.diagram().should_include(ns, name)) {
|
||||||
if (full_name.find("std::unique_ptr") == 0) {
|
|
||||||
found = find_relationships(args[0u].type().value(), relationships,
|
|
||||||
relationship_t::kAggregation);
|
|
||||||
}
|
|
||||||
else if (full_name.find("std::shared_ptr") == 0) {
|
|
||||||
found = find_relationships(args[0u].type().value(), relationships,
|
|
||||||
relationship_t::kAssociation);
|
|
||||||
}
|
|
||||||
else if (full_name.find("std::weak_ptr") == 0) {
|
|
||||||
found = find_relationships(args[0u].type().value(), relationships,
|
|
||||||
relationship_t::kAssociation);
|
|
||||||
}
|
|
||||||
else if (full_name.find("std::vector") == 0) {
|
|
||||||
if (args[0u].type().has_value())
|
|
||||||
found = find_relationships(args[0u].type().value(), relationships,
|
|
||||||
relationship_t::kAggregation);
|
|
||||||
else
|
|
||||||
LOG_DBG("Failed to process template argument of std::vector at: {}",
|
|
||||||
fn);
|
|
||||||
}
|
|
||||||
else if (ctx.diagram().should_include(ns, name)) {
|
|
||||||
LOG_DBG("User defined template instantiation: {} | {}",
|
LOG_DBG("User defined template instantiation: {} | {}",
|
||||||
cppast::to_string(t_), cppast::to_string(t_.canonical()));
|
cppast::to_string(t_), cppast::to_string(t_.canonical()));
|
||||||
|
|
||||||
@@ -1529,11 +1508,23 @@ bool translation_unit_visitor::find_relationships_in_template_instantiation(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
int argument_index = 0;
|
||||||
|
auto relationship_hint = relationship_type;
|
||||||
for (const auto &arg : args) {
|
for (const auto &arg : args) {
|
||||||
if (arg.type().has_value()) {
|
if (ctx.config().relationship_hints().count(full_base_name) > 0) {
|
||||||
found = find_relationships(
|
relationship_hint = ctx.config()
|
||||||
arg.type().value(), relationships, relationship_type);
|
.relationship_hints()
|
||||||
|
.at(full_base_name)
|
||||||
|
.get(argument_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg.type().has_value()) {
|
||||||
|
found = found ||
|
||||||
|
find_relationships(
|
||||||
|
arg.type().value(), relationships, relationship_hint);
|
||||||
|
}
|
||||||
|
|
||||||
|
argument_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1659,8 +1650,8 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
|||||||
bool t_is_alias = t_unaliased_declaration != tr_declaration;
|
bool t_is_alias = t_unaliased_declaration != tr_declaration;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Here we'll hold the template base params to replace with the instantiated
|
// Here we'll hold the template base params to replace with the
|
||||||
// values
|
// instantiated values
|
||||||
//
|
//
|
||||||
std::deque<std::tuple<std::string, int, bool>> template_base_params{};
|
std::deque<std::tuple<std::string, int, bool>> template_base_params{};
|
||||||
|
|
||||||
@@ -1669,8 +1660,9 @@ std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
|||||||
auto tinst_full_name = cppast::to_string(t);
|
auto tinst_full_name = cppast::to_string(t);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Typically, every template instantiation should have a primary_template()
|
// Typically, every template instantiation should have a
|
||||||
// which should also be generated here if it doesn't exist yet in the model
|
// primary_template() which should also be generated here if it doesn't
|
||||||
|
// exist yet in the model
|
||||||
//
|
//
|
||||||
if (t.primary_template().get(ctx.entity_index()).size()) {
|
if (t.primary_template().get(ctx.entity_index()).size()) {
|
||||||
auto size = t.primary_template().get(ctx.entity_index()).size();
|
auto size = t.primary_template().get(ctx.entity_index()).size();
|
||||||
|
|||||||
@@ -120,6 +120,34 @@ common::model::diagram_t include_diagram::type() const
|
|||||||
return common::model::diagram_t::kInclude;
|
return common::model::diagram_t::kInclude;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void class_diagram::initialize_relationship_hints()
|
||||||
|
{
|
||||||
|
using common::model::relationship_t;
|
||||||
|
|
||||||
|
if (!relationship_hints().count("std::vector")) {
|
||||||
|
relationship_hints().insert({"std::vector", {}});
|
||||||
|
}
|
||||||
|
if (!relationship_hints().count("std::unique_ptr")) {
|
||||||
|
relationship_hints().insert({"std::unique_ptr", {}});
|
||||||
|
}
|
||||||
|
if (!relationship_hints().count("std::shared_ptr")) {
|
||||||
|
relationship_hints().insert(
|
||||||
|
{"std::shared_ptr", {relationship_t::kAssociation}});
|
||||||
|
}
|
||||||
|
if (!relationship_hints().count("std::weak_ptr")) {
|
||||||
|
relationship_hints().insert(
|
||||||
|
{"std::weak_ptr", {relationship_t::kAssociation}});
|
||||||
|
}
|
||||||
|
if (!relationship_hints().count("std::tuple")) {
|
||||||
|
relationship_hints().insert({"std::tuple", {}});
|
||||||
|
}
|
||||||
|
if (!relationship_hints().count("std::map")) {
|
||||||
|
relationship_hint_t hint{relationship_t::kNone};
|
||||||
|
hint.argument_hints.insert({1, relationship_t::kAggregation});
|
||||||
|
relationship_hints().insert({"std::tuple", std::move(hint)});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template <> void append_value<plantuml>(plantuml &l, const plantuml &r)
|
template <> void append_value<plantuml>(plantuml &l, const plantuml &r)
|
||||||
{
|
{
|
||||||
l.append(r);
|
l.append(r);
|
||||||
@@ -141,6 +169,7 @@ using clanguml::config::layout_hint;
|
|||||||
using clanguml::config::method_arguments;
|
using clanguml::config::method_arguments;
|
||||||
using clanguml::config::package_diagram;
|
using clanguml::config::package_diagram;
|
||||||
using clanguml::config::plantuml;
|
using clanguml::config::plantuml;
|
||||||
|
using clanguml::config::relationship_hint_t;
|
||||||
using clanguml::config::sequence_diagram;
|
using clanguml::config::sequence_diagram;
|
||||||
using clanguml::config::source_location;
|
using clanguml::config::source_location;
|
||||||
|
|
||||||
@@ -459,6 +488,9 @@ template <> struct convert<class_diagram> {
|
|||||||
get_option(node, rhs.include_relations_also_as_members);
|
get_option(node, rhs.include_relations_also_as_members);
|
||||||
get_option(node, rhs.generate_method_arguments);
|
get_option(node, rhs.generate_method_arguments);
|
||||||
get_option(node, rhs.generate_packages);
|
get_option(node, rhs.generate_packages);
|
||||||
|
get_option(node, rhs.relationship_hints);
|
||||||
|
|
||||||
|
rhs.initialize_relationship_hints();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -551,6 +583,42 @@ template <> struct convert<layout_hint> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//
|
||||||
|
// relationship_hint_t Yaml decoder
|
||||||
|
//
|
||||||
|
template <> struct convert<relationship_hint_t> {
|
||||||
|
static bool decode(const Node &node, relationship_hint_t &rhs)
|
||||||
|
{
|
||||||
|
assert(node.Type() == NodeType::Map || node.Type() == NodeType::Scalar);
|
||||||
|
|
||||||
|
if (node.Type() == NodeType::Scalar) {
|
||||||
|
// This will be default relationship hint for all arguments
|
||||||
|
// of this template (useful for instance for tuples)
|
||||||
|
rhs.default_hint = node.as<relationship_t>();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (const auto &it : node) {
|
||||||
|
auto key = it.first.as<std::string>();
|
||||||
|
if (key == "default") {
|
||||||
|
rhs.default_hint = node["default"].as<relationship_t>();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
auto index = stoul(key);
|
||||||
|
rhs.argument_hints[index] =
|
||||||
|
it.second.as<relationship_t>();
|
||||||
|
}
|
||||||
|
catch (std::exception &e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
// config Yaml decoder
|
// config Yaml decoder
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -95,6 +95,27 @@ struct git_config {
|
|||||||
std::string toplevel;
|
std::string toplevel;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct relationship_hint_t {
|
||||||
|
std::map<unsigned int, common::model::relationship_t> argument_hints;
|
||||||
|
common::model::relationship_t default_hint;
|
||||||
|
|
||||||
|
relationship_hint_t(common::model::relationship_t def =
|
||||||
|
common::model::relationship_t::kAggregation)
|
||||||
|
: default_hint{def}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
common::model::relationship_t get(unsigned int argument_index) const
|
||||||
|
{
|
||||||
|
if (argument_hints.count(argument_index) > 0)
|
||||||
|
return argument_hints.at(argument_index);
|
||||||
|
|
||||||
|
return default_hint;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using relationship_hints_t = std::map<std::string, relationship_hint_t>;
|
||||||
|
|
||||||
std::string to_string(const hint_t t);
|
std::string to_string(const hint_t t);
|
||||||
|
|
||||||
struct inheritable_diagram_options {
|
struct inheritable_diagram_options {
|
||||||
@@ -113,6 +134,7 @@ struct inheritable_diagram_options {
|
|||||||
option<std::filesystem::path> base_directory{"__parent_path"};
|
option<std::filesystem::path> base_directory{"__parent_path"};
|
||||||
option<std::filesystem::path> relative_to{"relative_to"};
|
option<std::filesystem::path> relative_to{"relative_to"};
|
||||||
option<bool> generate_system_headers{"generate_system_headers", false};
|
option<bool> generate_system_headers{"generate_system_headers", false};
|
||||||
|
option<relationship_hints_t> relationship_hints{"relationship_hints"};
|
||||||
|
|
||||||
void inherit(const inheritable_diagram_options &parent);
|
void inherit(const inheritable_diagram_options &parent);
|
||||||
};
|
};
|
||||||
@@ -139,7 +161,7 @@ struct class_diagram : public diagram {
|
|||||||
option<std::vector<std::string>> classes{"classes"};
|
option<std::vector<std::string>> classes{"classes"};
|
||||||
option<layout_hints> layout{"layout"};
|
option<layout_hints> layout{"layout"};
|
||||||
|
|
||||||
bool has_class(std::string clazz);
|
void initialize_relationship_hints();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sequence_diagram : public diagram {
|
struct sequence_diagram : public diagram {
|
||||||
|
|||||||
@@ -68,6 +68,27 @@ TEST_CASE("Test config simple", "[unit-test]")
|
|||||||
contains(diagram.include().relationships, relationship_t::kOwnership));
|
contains(diagram.include().relationships, relationship_t::kOwnership));
|
||||||
|
|
||||||
CHECK(contains(diagram.exclude().relationships, relationship_t::kNone));
|
CHECK(contains(diagram.exclude().relationships, relationship_t::kNone));
|
||||||
|
|
||||||
|
CHECK(diagram.relationship_hints().at("std::vector").get(0) ==
|
||||||
|
relationship_t::kComposition);
|
||||||
|
CHECK(diagram.relationship_hints().at("std::tuple").get(10) ==
|
||||||
|
relationship_t::kAggregation);
|
||||||
|
CHECK(diagram.relationship_hints().at("std::map").get(0) ==
|
||||||
|
relationship_t::kNone);
|
||||||
|
CHECK(diagram.relationship_hints().at("std::map").get(1) ==
|
||||||
|
relationship_t::kComposition);
|
||||||
|
CHECK(diagram.relationship_hints().at("std::shared_ptr").get(0) ==
|
||||||
|
relationship_t::kAssociation);
|
||||||
|
CHECK(diagram.relationship_hints().at("std::weak_ptr").get(0) ==
|
||||||
|
relationship_t::kAssociation);
|
||||||
|
CHECK(diagram.relationship_hints().at("std::unique_ptr").get(0) ==
|
||||||
|
relationship_t::kAggregation);
|
||||||
|
CHECK(diagram.relationship_hints().at("ns1::n2::some_template").get(0) ==
|
||||||
|
relationship_t::kAssociation);
|
||||||
|
CHECK(diagram.relationship_hints().at("ns1::n2::some_template").get(2) ==
|
||||||
|
relationship_t::kComposition);
|
||||||
|
CHECK(diagram.relationship_hints().at("ns1::n2::some_template").get(10) ==
|
||||||
|
relationship_t::kAggregation);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("Test config inherited", "[unit-test]")
|
TEST_CASE("Test config inherited", "[unit-test]")
|
||||||
|
|||||||
@@ -33,4 +33,14 @@ diagrams:
|
|||||||
- dependency
|
- dependency
|
||||||
exclude:
|
exclude:
|
||||||
relationships:
|
relationships:
|
||||||
- none
|
- none
|
||||||
|
relationship_hints:
|
||||||
|
std::vector: composition
|
||||||
|
std::map:
|
||||||
|
default: none
|
||||||
|
1: composition
|
||||||
|
std::tuple: aggregation
|
||||||
|
ns1::n2::some_template:
|
||||||
|
default: association
|
||||||
|
2: composition
|
||||||
|
10: aggregation
|
||||||
|
|||||||
Reference in New Issue
Block a user