Added detection of dependency relationships from unexposed template params
This commit is contained in:
@@ -178,6 +178,17 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
|
|||||||
|
|
||||||
process_type_alias_template(at);
|
process_type_alias_template(at);
|
||||||
}
|
}
|
||||||
|
else if (e.kind() == cppast::cpp_entity_kind::using_directive_t) {
|
||||||
|
|
||||||
|
const auto &using_directive =
|
||||||
|
static_cast<const cppast::cpp_using_directive &>(e);
|
||||||
|
|
||||||
|
const auto ns_ref = using_directive.target();
|
||||||
|
if (ns_ref.get(ctx.entity_index()).size() > 0) {
|
||||||
|
auto full_ns = cx::util::full_name(ctx.get_namespace(),
|
||||||
|
ns_ref.get(ctx.entity_index()).at(0).get());
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,10 +502,17 @@ void translation_unit_visitor::
|
|||||||
auto ua = tspec.value().unexposed_arguments().as_string();
|
auto ua = tspec.value().unexposed_arguments().as_string();
|
||||||
|
|
||||||
auto template_params = cx::util::parse_unexposed_template_params(ua);
|
auto template_params = cx::util::parse_unexposed_template_params(ua);
|
||||||
|
|
||||||
|
found_relationships_t relationships;
|
||||||
for (const auto ¶m : template_params) {
|
for (const auto ¶m : template_params) {
|
||||||
|
find_relationships_in_unexposed_template_params(param, relationships);
|
||||||
c.add_template(param);
|
c.add_template(param);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto &r : relationships) {
|
||||||
|
c.add_relationship({std::get<1>(r), std::get<0>(r)});
|
||||||
|
}
|
||||||
|
|
||||||
const auto &primary_template_ref =
|
const auto &primary_template_ref =
|
||||||
static_cast<const cppast::cpp_class_template &>(
|
static_cast<const cppast::cpp_class_template &>(
|
||||||
tspec.value().primary_template().get(ctx.entity_index())[0].get())
|
tspec.value().primary_template().get(ctx.entity_index())[0].get())
|
||||||
@@ -1193,7 +1211,8 @@ void translation_unit_visitor::process_friend(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
||||||
found_relationships_t &relationships, relationship_t relationship_hint)
|
found_relationships_t &relationships,
|
||||||
|
relationship_t relationship_hint) const
|
||||||
{
|
{
|
||||||
bool found{false};
|
bool found{false};
|
||||||
|
|
||||||
@@ -1234,7 +1253,8 @@ bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
|||||||
|
|
||||||
bool translation_unit_visitor::find_relationships_in_template_instantiation(
|
bool translation_unit_visitor::find_relationships_in_template_instantiation(
|
||||||
const cppast::cpp_type &t_, const std::string &fn,
|
const cppast::cpp_type &t_, const std::string &fn,
|
||||||
found_relationships_t &relationships, relationship_t relationship_type)
|
found_relationships_t &relationships,
|
||||||
|
relationship_t relationship_type) const
|
||||||
{
|
{
|
||||||
const auto &t = cppast::remove_cv(cx::util::unreferenced(t_));
|
const auto &t = cppast::remove_cv(cx::util::unreferenced(t_));
|
||||||
|
|
||||||
@@ -1321,7 +1341,7 @@ bool translation_unit_visitor::find_relationships_in_template_instantiation(
|
|||||||
bool translation_unit_visitor::find_relationships_in_user_defined_type(
|
bool translation_unit_visitor::find_relationships_in_user_defined_type(
|
||||||
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
||||||
const std::string &fn, relationship_t &relationship_type,
|
const std::string &fn, relationship_t &relationship_type,
|
||||||
const cppast::cpp_type &t)
|
const cppast::cpp_type &t) const
|
||||||
{
|
{
|
||||||
bool found;
|
bool found;
|
||||||
LOG_DBG("Finding relationships in user defined type: {} | {}",
|
LOG_DBG("Finding relationships in user defined type: {} | {}",
|
||||||
@@ -1348,7 +1368,7 @@ bool translation_unit_visitor::find_relationships_in_user_defined_type(
|
|||||||
|
|
||||||
bool translation_unit_visitor::find_relationships_in_reference(
|
bool translation_unit_visitor::find_relationships_in_reference(
|
||||||
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
||||||
const relationship_t &relationship_hint)
|
const relationship_t &relationship_hint) const
|
||||||
{
|
{
|
||||||
bool found;
|
bool found;
|
||||||
auto &r = static_cast<const cppast::cpp_reference_type &>(t_);
|
auto &r = static_cast<const cppast::cpp_reference_type &>(t_);
|
||||||
@@ -1364,7 +1384,7 @@ bool translation_unit_visitor::find_relationships_in_reference(
|
|||||||
|
|
||||||
bool translation_unit_visitor::find_relationships_in_pointer(
|
bool translation_unit_visitor::find_relationships_in_pointer(
|
||||||
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
||||||
const relationship_t &relationship_hint)
|
const relationship_t &relationship_hint) const
|
||||||
{
|
{
|
||||||
bool found;
|
bool found;
|
||||||
auto &p = static_cast<const cppast::cpp_pointer_type &>(t_);
|
auto &p = static_cast<const cppast::cpp_pointer_type &>(t_);
|
||||||
@@ -1376,7 +1396,7 @@ bool translation_unit_visitor::find_relationships_in_pointer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool translation_unit_visitor::find_relationships_in_array(
|
bool translation_unit_visitor::find_relationships_in_array(
|
||||||
found_relationships_t &relationships, const cppast::cpp_type &t)
|
found_relationships_t &relationships, const cppast::cpp_type &t) const
|
||||||
{
|
{
|
||||||
bool found;
|
bool found;
|
||||||
auto &a = static_cast<const cppast::cpp_array_type &>(t);
|
auto &a = static_cast<const cppast::cpp_array_type &>(t);
|
||||||
@@ -1385,6 +1405,48 @@ bool translation_unit_visitor::find_relationships_in_array(
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool translation_unit_visitor::find_relationships_in_unexposed_template_params(
|
||||||
|
const class_template &ct, found_relationships_t &relationships) const
|
||||||
|
{
|
||||||
|
bool found{false};
|
||||||
|
LOG_DBG("Finding relationships in user defined type: {}",
|
||||||
|
ct.to_string(ctx.config().using_namespace()));
|
||||||
|
|
||||||
|
if (!util::contains(ct.type(), "::")) {
|
||||||
|
// The type name has no namespace - assume it is in the current
|
||||||
|
// namespace
|
||||||
|
// TODO: try also all namespaces declared through 'using namespace'
|
||||||
|
// directive in the current scope
|
||||||
|
if (ctx.config().should_include(ctx.get_namespace(), ct.type())) {
|
||||||
|
relationships.emplace_back(ct.type(), relationship_t::kDependency);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Calculate the complete namespace of the type
|
||||||
|
auto type_ns = common::model::namespace_{ct.type()};
|
||||||
|
auto type_name = type_ns.name();
|
||||||
|
type_ns.pop_back();
|
||||||
|
|
||||||
|
auto current_ns = ctx.get_namespace();
|
||||||
|
if (current_ns.ends_with(type_ns)) {
|
||||||
|
if (ctx.config().should_include(current_ns, type_name)) {
|
||||||
|
auto full_name = (current_ns | type_name).to_string();
|
||||||
|
relationships.emplace_back(
|
||||||
|
full_name, relationship_t::kDependency);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &nested_template_params : ct.template_params_) {
|
||||||
|
found = find_relationships_in_unexposed_template_params(
|
||||||
|
nested_template_params, relationships) ||
|
||||||
|
found;
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
std::unique_ptr<class_> translation_unit_visitor::build_template_instantiation(
|
||||||
const cppast::cpp_template_instantiation_type &t,
|
const cppast::cpp_template_instantiation_type &t,
|
||||||
std::optional<clanguml::class_diagram::model::class_ *> parent)
|
std::optional<clanguml::class_diagram::model::class_ *> parent)
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ public:
|
|||||||
bool find_relationships(const cppast::cpp_type &t,
|
bool find_relationships(const cppast::cpp_type &t,
|
||||||
found_relationships_t &relationships,
|
found_relationships_t &relationships,
|
||||||
clanguml::common::model::relationship_t relationship_hint =
|
clanguml::common::model::relationship_t relationship_hint =
|
||||||
clanguml::common::model::relationship_t::kNone);
|
clanguml::common::model::relationship_t::kNone) const;
|
||||||
|
|
||||||
void process_template_type_parameter(
|
void process_template_type_parameter(
|
||||||
const cppast::cpp_template_type_parameter &t,
|
const cppast::cpp_template_type_parameter &t,
|
||||||
@@ -175,24 +175,28 @@ private:
|
|||||||
const cppast::cpp_type &type);
|
const cppast::cpp_type &type);
|
||||||
|
|
||||||
bool find_relationships_in_array(
|
bool find_relationships_in_array(
|
||||||
found_relationships_t &relationships, const cppast::cpp_type &t);
|
found_relationships_t &relationships, const cppast::cpp_type &t) const;
|
||||||
|
|
||||||
bool find_relationships_in_pointer(const cppast::cpp_type &t_,
|
bool find_relationships_in_pointer(const cppast::cpp_type &t_,
|
||||||
found_relationships_t &relationships,
|
found_relationships_t &relationships,
|
||||||
const common::model::relationship_t &relationship_hint);
|
const common::model::relationship_t &relationship_hint) const;
|
||||||
|
|
||||||
bool find_relationships_in_reference(const cppast::cpp_type &t_,
|
bool find_relationships_in_reference(const cppast::cpp_type &t_,
|
||||||
found_relationships_t &relationships,
|
found_relationships_t &relationships,
|
||||||
const common::model::relationship_t &relationship_hint);
|
const common::model::relationship_t &relationship_hint) const;
|
||||||
|
|
||||||
bool find_relationships_in_user_defined_type(const cppast::cpp_type &t_,
|
bool find_relationships_in_user_defined_type(const cppast::cpp_type &t_,
|
||||||
found_relationships_t &relationships, const std::string &fn,
|
found_relationships_t &relationships, const std::string &fn,
|
||||||
common::model::relationship_t &relationship_type,
|
common::model::relationship_t &relationship_type,
|
||||||
const cppast::cpp_type &t);
|
const cppast::cpp_type &t) const;
|
||||||
|
|
||||||
bool find_relationships_in_template_instantiation(const cppast::cpp_type &t,
|
bool find_relationships_in_template_instantiation(const cppast::cpp_type &t,
|
||||||
const std::string &fn, found_relationships_t &relationships,
|
const std::string &fn, found_relationships_t &relationships,
|
||||||
common::model::relationship_t relationship_type);
|
common::model::relationship_t relationship_type) const;
|
||||||
|
|
||||||
|
bool find_relationships_in_unexposed_template_params(
|
||||||
|
const model::class_template &ct,
|
||||||
|
found_relationships_t &relationships) const;
|
||||||
|
|
||||||
void build_template_instantiation_primary_template(
|
void build_template_instantiation_primary_template(
|
||||||
const cppast::cpp_template_instantiation_type &t,
|
const cppast::cpp_template_instantiation_type &t,
|
||||||
|
|||||||
@@ -129,9 +129,15 @@ const std::string &namespace_::operator[](const int index) const
|
|||||||
|
|
||||||
bool namespace_::starts_with(const namespace_ &right) const
|
bool namespace_::starts_with(const namespace_ &right) const
|
||||||
{
|
{
|
||||||
|
|
||||||
return util::starts_with(namespace_path_, right.namespace_path_);
|
return util::starts_with(namespace_path_, right.namespace_path_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool namespace_::ends_with(const namespace_ &right) const
|
||||||
|
{
|
||||||
|
return util::ends_with(namespace_path_, right.namespace_path_);
|
||||||
|
}
|
||||||
|
|
||||||
namespace_ namespace_::common_path(const namespace_ &right) const
|
namespace_ namespace_::common_path(const namespace_ &right) const
|
||||||
{
|
{
|
||||||
namespace_ res{};
|
namespace_ res{};
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ public:
|
|||||||
void pop_back();
|
void pop_back();
|
||||||
|
|
||||||
bool starts_with(const namespace_ &right) const;
|
bool starts_with(const namespace_ &right) const;
|
||||||
|
bool ends_with(const namespace_ &right) const;
|
||||||
namespace_ common_path(const namespace_ &right) const;
|
namespace_ common_path(const namespace_ &right) const;
|
||||||
namespace_ relative_to(const namespace_ &right) const;
|
namespace_ relative_to(const namespace_ &right) const;
|
||||||
std::string relative(const std::string &name) const;
|
std::string relative(const std::string &name) const;
|
||||||
|
|||||||
@@ -158,6 +158,16 @@ bool starts_with(const std::vector<T> &col, const std::vector<T> &prefix)
|
|||||||
std::vector<std::string>(col.begin(), col.begin() + prefix.size());
|
std::vector<std::string>(col.begin(), col.begin() + prefix.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool ends_with(const std::vector<T> &col, const std::vector<T> &suffix)
|
||||||
|
{
|
||||||
|
if (suffix.size() > col.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return std::vector<std::string>(suffix.rbegin(), suffix.rend()) ==
|
||||||
|
std::vector<std::string>(col.rbegin(), col.rbegin() + suffix.size());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Removes prefix sequence of elements from the beggining of col.
|
* @brief Removes prefix sequence of elements from the beggining of col.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -22,12 +22,13 @@ struct key_t {
|
|||||||
template <typename T> struct map;
|
template <typename T> struct map;
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct map<std::integral_constant<property_t, property_t::property_a>> : A {
|
struct map<std::integral_constant<clanguml::t00038::property_t,
|
||||||
|
clanguml::t00038::property_t::property_a>> : A {
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
struct map<
|
struct map<std::vector<
|
||||||
std::vector<std::integral_constant<property_t, property_t::property_b>>>
|
std::integral_constant<t00038::property_t, t00038::property_t::property_b>>>
|
||||||
: B {
|
: B {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,8 @@ TEST_CASE("t00038", "[test-case][class]")
|
|||||||
"std::integral_constant<property_t,property_t::property_a>"));
|
"std::integral_constant<property_t,property_t::property_a>"));
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
IsClassTemplate("map",
|
IsClassTemplate("map",
|
||||||
"std::vector<std::integral_constant<property_t,property_t::"
|
"std::vector<std::integral_constant<t00038::property_t,t00038::"
|
||||||
|
"property_t::"
|
||||||
"property_b>>"));
|
"property_b>>"));
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
IsClassTemplate("map",
|
IsClassTemplate("map",
|
||||||
@@ -61,17 +62,28 @@ TEST_CASE("t00038", "[test-case][class]")
|
|||||||
|
|
||||||
// TODO: Add parsing of unexposed template arguments to infer
|
// TODO: Add parsing of unexposed template arguments to infer
|
||||||
// additional relationships
|
// additional relationships
|
||||||
/*
|
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
IsDependency(_A("map<std::integral_constant<property_t,property_t::"
|
IsDependency(_A("map<std::integral_constant<property_t,property_t::"
|
||||||
"property_a>>"),
|
"property_a>>"),
|
||||||
_A("property_t")));
|
_A("property_t")));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml,
|
||||||
|
IsDependency(_A("map<"
|
||||||
|
"std::vector<std::integral_constant<t00038::property_t,"
|
||||||
|
"t00038::property_t::"
|
||||||
|
"property_b>>>"),
|
||||||
|
_A("property_t")));
|
||||||
|
|
||||||
|
REQUIRE_THAT(puml,
|
||||||
|
IsDependency(_A("map<std::map<key_t,std::vector<std::integral_constant<"
|
||||||
|
"property_t,property_t::property_c>>>>"),
|
||||||
|
_A("property_t")));
|
||||||
|
|
||||||
REQUIRE_THAT(puml,
|
REQUIRE_THAT(puml,
|
||||||
IsDependency(_A("map<std::map<key_t,std::vector<std::integral_constant<"
|
IsDependency(_A("map<std::map<key_t,std::vector<std::integral_constant<"
|
||||||
"property_t,property_t::property_c>>>>"),
|
"property_t,property_t::property_c>>>>"),
|
||||||
_A("key_t")));
|
_A("key_t")));
|
||||||
*/
|
|
||||||
|
|
||||||
save_puml(
|
save_puml(
|
||||||
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
|
"./" + config.output_directory() + "/" + diagram->name + ".puml", puml);
|
||||||
|
|||||||
Reference in New Issue
Block a user