Refactored find_relationships method
This commit is contained in:
@@ -405,10 +405,10 @@ bool translation_unit_visitor::process_template_parameters(
|
|||||||
// Add specialization arguments
|
// Add specialization arguments
|
||||||
if (tspec) {
|
if (tspec) {
|
||||||
if (!tspec.value().arguments_exposed()) {
|
if (!tspec.value().arguments_exposed()) {
|
||||||
process_unexposed_template_specialization_arguments(tspec, c);
|
process_unexposed_template_specialization_parameters(tspec, c);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
process_exposed_template_specialization_arguments(tspec, c);
|
process_exposed_template_specialization_parameters(tspec, c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -451,7 +451,7 @@ void translation_unit_visitor::process_scope_template_parameters(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void translation_unit_visitor::
|
void translation_unit_visitor::
|
||||||
process_exposed_template_specialization_arguments(
|
process_exposed_template_specialization_parameters(
|
||||||
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
||||||
&tspec,
|
&tspec,
|
||||||
class_ &c)
|
class_ &c)
|
||||||
@@ -488,7 +488,7 @@ void translation_unit_visitor::
|
|||||||
}
|
}
|
||||||
|
|
||||||
void translation_unit_visitor::
|
void translation_unit_visitor::
|
||||||
process_unexposed_template_specialization_arguments(
|
process_unexposed_template_specialization_parameters(
|
||||||
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
||||||
&tspec,
|
&tspec,
|
||||||
class_ &c) const
|
class_ &c) const
|
||||||
@@ -505,7 +505,7 @@ void translation_unit_visitor::
|
|||||||
.primary_template()
|
.primary_template()
|
||||||
.get(ctx.entity_index())
|
.get(ctx.entity_index())
|
||||||
.size() == 0) {
|
.size() == 0) {
|
||||||
LOG_WARN("Template {} has no exposed arguments",
|
LOG_WARN("Template {} has no exposed parameters",
|
||||||
tspec.value().name());
|
tspec.value().name());
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
@@ -1211,8 +1211,7 @@ 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_,
|
||||||
std::vector<std::pair<std::string, relationship_t>> &relationships,
|
found_relationships_t &relationships, relationship_t relationship_hint)
|
||||||
relationship_t relationship_hint)
|
|
||||||
{
|
{
|
||||||
bool found{false};
|
bool found{false};
|
||||||
|
|
||||||
@@ -1227,35 +1226,92 @@ bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
|||||||
relationship_t relationship_type = relationship_hint;
|
relationship_t relationship_type = relationship_hint;
|
||||||
const auto &t = cppast::remove_cv(cx::util::unreferenced(t_));
|
const auto &t = cppast::remove_cv(cx::util::unreferenced(t_));
|
||||||
|
|
||||||
|
auto name = cppast::to_string(t);
|
||||||
|
|
||||||
if (t.kind() == cppast::cpp_type_kind::array_t) {
|
if (t.kind() == cppast::cpp_type_kind::array_t) {
|
||||||
auto &a = static_cast<const cppast::cpp_array_type &>(t);
|
found = find_relationships_in_array(relationships, t);
|
||||||
found = find_relationships(
|
|
||||||
a.value_type(), relationships, relationship_t::kAggregation);
|
|
||||||
return found;
|
|
||||||
}
|
}
|
||||||
|
else if (t_.kind() == cppast::cpp_type_kind::pointer_t) {
|
||||||
|
found =
|
||||||
|
find_relationships_in_pointer(t_, relationships, relationship_hint);
|
||||||
|
}
|
||||||
|
else if (t_.kind() == cppast::cpp_type_kind::reference_t) {
|
||||||
|
found = find_relationships_in_reference(
|
||||||
|
t_, relationships, relationship_hint);
|
||||||
|
}
|
||||||
|
else if (cppast::remove_cv(t_).kind() ==
|
||||||
|
cppast::cpp_type_kind::user_defined_t) {
|
||||||
|
found = find_relationships_in_user_defined_type(
|
||||||
|
t_, relationships, fn, relationship_type, t);
|
||||||
|
}
|
||||||
|
else if (t.kind() == cppast::cpp_type_kind::template_instantiation_t) {
|
||||||
|
found = find_relationships_in_template_instantiation(
|
||||||
|
t, fn, relationships, relationship_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool translation_unit_visitor::find_relationships_in_template_instantiation(
|
||||||
|
const cppast::cpp_type &t_, const std::string &fn,
|
||||||
|
found_relationships_t &relationships, relationship_t relationship_type)
|
||||||
|
{
|
||||||
|
const auto &t = cppast::remove_cv(cx::util::unreferenced(t_));
|
||||||
|
|
||||||
|
const auto &tinst =
|
||||||
|
static_cast<const cppast::cpp_template_instantiation_type &>(t);
|
||||||
|
|
||||||
auto name = cppast::to_string(t);
|
auto name = cppast::to_string(t);
|
||||||
|
|
||||||
if (t_.kind() == cppast::cpp_type_kind::pointer_t) {
|
bool found = false;
|
||||||
auto &p = static_cast<const cppast::cpp_pointer_type &>(t_);
|
|
||||||
auto rt = relationship_t::kAssociation;
|
if (!tinst.arguments_exposed()) {
|
||||||
if (relationship_hint == relationship_t::kDependency)
|
LOG_DBG("Template instantiation {} has no exposed arguments", name);
|
||||||
rt = relationship_hint;
|
|
||||||
found = find_relationships(p.pointee(), relationships, rt);
|
return found;
|
||||||
}
|
}
|
||||||
else if (t_.kind() == cppast::cpp_type_kind::reference_t) {
|
|
||||||
auto &r = static_cast<const cppast::cpp_reference_type &>(t_);
|
assert(tinst.arguments().has_value());
|
||||||
auto rt = relationship_t::kAssociation;
|
assert(tinst.arguments().value().size() > 0u);
|
||||||
if (r.reference_kind() == cppast::cpp_reference::cpp_ref_rvalue) {
|
|
||||||
rt = relationship_t::kAggregation;
|
[[maybe_unused]] const auto args_count = tinst.arguments().value().size();
|
||||||
}
|
|
||||||
if (relationship_hint == relationship_t::kDependency)
|
const auto args = tinst.arguments().value();
|
||||||
rt = relationship_hint;
|
|
||||||
found = find_relationships(r.referee(), relationships, rt);
|
const auto [ns, base_name] = cx::util::split_ns(fn);
|
||||||
|
|
||||||
|
auto ns_and_name = ns;
|
||||||
|
ns_and_name.push_back(base_name);
|
||||||
|
|
||||||
|
auto full_name = fmt::format("{}", fmt::join(ns_and_name, "::"));
|
||||||
|
|
||||||
|
// Try to match common containers
|
||||||
|
// TODO: Refactor to a separate class with configurable
|
||||||
|
// container list
|
||||||
|
if (full_name.find("std::unique_ptr") == 0) {
|
||||||
|
found = find_relationships(args[0u].type().value(), relationships,
|
||||||
|
relationship_t::kAggregation);
|
||||||
}
|
}
|
||||||
if (cppast::remove_cv(t_).kind() == cppast::cpp_type_kind::user_defined_t) {
|
else if (full_name.find("std::shared_ptr") == 0) {
|
||||||
LOG_DBG("User defined type: {} | {}", cppast::to_string(t_),
|
found = find_relationships(args[0u].type().value(), relationships,
|
||||||
cppast::to_string(t_.canonical()));
|
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_WARN(
|
||||||
|
"Failed to process template argument of std::vector at: {}",
|
||||||
|
fn);
|
||||||
|
}
|
||||||
|
else if (ctx.config().should_include(ns, name)) {
|
||||||
|
LOG_DBG("User defined template instantiation: {} | {}",
|
||||||
|
cppast::to_string(t_), cppast::to_string(t_.canonical()));
|
||||||
|
|
||||||
if (relationship_type != relationship_t::kNone)
|
if (relationship_type != relationship_t::kNone)
|
||||||
relationships.emplace_back(cppast::to_string(t), relationship_type);
|
relationships.emplace_back(cppast::to_string(t), relationship_type);
|
||||||
@@ -1269,94 +1325,13 @@ bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
|||||||
cppast::to_string(ctx.get_type_alias(fn).get()));
|
cppast::to_string(ctx.get_type_alias(fn).get()));
|
||||||
found = find_relationships(
|
found = find_relationships(
|
||||||
ctx.get_type_alias(fn).get(), relationships, relationship_type);
|
ctx.get_type_alias(fn).get(), relationships, relationship_type);
|
||||||
if (found)
|
|
||||||
return found;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (t.kind() == cppast::cpp_type_kind::template_instantiation_t) {
|
else {
|
||||||
// class_relationship r;
|
for (const auto &arg : args) {
|
||||||
|
if (arg.type().has_value()) {
|
||||||
const auto &tinst =
|
found = find_relationships(
|
||||||
static_cast<const cppast::cpp_template_instantiation_type &>(t);
|
arg.type().value(), relationships, relationship_type);
|
||||||
|
|
||||||
if (!tinst.arguments_exposed()) {
|
|
||||||
LOG_DBG("Template instantiation {} has no exposed arguments", name);
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(tinst.arguments().has_value());
|
|
||||||
assert(tinst.arguments().value().size() > 0u);
|
|
||||||
|
|
||||||
[[maybe_unused]] const auto args_count =
|
|
||||||
tinst.arguments().value().size();
|
|
||||||
|
|
||||||
const auto args = tinst.arguments().value();
|
|
||||||
|
|
||||||
const auto [ns, base_name] = cx::util::split_ns(fn);
|
|
||||||
|
|
||||||
auto ns_and_name = ns;
|
|
||||||
ns_and_name.push_back(base_name);
|
|
||||||
|
|
||||||
auto full_name = fmt::format("{}", fmt::join(ns_and_name, "::"));
|
|
||||||
|
|
||||||
// Try to match common containers
|
|
||||||
// TODO: Refactor to a separate class with configurable
|
|
||||||
// container list
|
|
||||||
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) {
|
|
||||||
assert(args.size() == 1u);
|
|
||||||
if (args[0u].type().has_value())
|
|
||||||
found = find_relationships(args[0u].type().value(),
|
|
||||||
relationships, relationship_t::kAggregation);
|
|
||||||
else
|
|
||||||
LOG_WARN(
|
|
||||||
"Failed to process template argument of std::vector at: {}",
|
|
||||||
fn);
|
|
||||||
}
|
|
||||||
else if (ctx.config().should_include(ns, name)) {
|
|
||||||
LOG_DBG("User defined template instantiation: {} | {}",
|
|
||||||
cppast::to_string(t_), cppast::to_string(t_.canonical()));
|
|
||||||
|
|
||||||
if (relationship_type != relationship_t::kNone)
|
|
||||||
relationships.emplace_back(
|
|
||||||
cppast::to_string(t), relationship_type);
|
|
||||||
else
|
|
||||||
relationships.emplace_back(
|
|
||||||
cppast::to_string(t), relationship_t::kAggregation);
|
|
||||||
|
|
||||||
// Check if t_ has an alias in the alias index
|
|
||||||
if (ctx.has_type_alias(fn)) {
|
|
||||||
LOG_DBG("Find relationship in alias of {} | {}", fn,
|
|
||||||
cppast::to_string(ctx.get_type_alias(fn).get()));
|
|
||||||
found = find_relationships(ctx.get_type_alias(fn).get(),
|
|
||||||
relationships, relationship_type);
|
|
||||||
if (found)
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
|
|
||||||
return found;
|
|
||||||
}
|
|
||||||
// ???
|
|
||||||
else {
|
|
||||||
for (const auto &arg : args) {
|
|
||||||
if (arg.type().has_value()) {
|
|
||||||
LOG_DBG("########## PROCESSING PARAMETER TYPE: {}",
|
|
||||||
cppast::to_string(arg.type().value()));
|
|
||||||
found = find_relationships(
|
|
||||||
arg.type().value(), relationships, relationship_type);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1364,6 +1339,70 @@ bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
|||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool translation_unit_visitor::find_relationships_in_user_defined_type(
|
||||||
|
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
||||||
|
const std::string &fn, relationship_t &relationship_type,
|
||||||
|
const cppast::cpp_type &t)
|
||||||
|
{
|
||||||
|
bool found;
|
||||||
|
LOG_DBG("Finding relationships in user defined type: {} | {}",
|
||||||
|
cppast::to_string(t_), cppast::to_string(t_.canonical()));
|
||||||
|
|
||||||
|
if (relationship_type != relationship_t::kNone)
|
||||||
|
relationships.emplace_back(cppast::to_string(t), relationship_type);
|
||||||
|
else
|
||||||
|
relationships.emplace_back(
|
||||||
|
cppast::to_string(t), relationship_t::kAggregation);
|
||||||
|
|
||||||
|
// Check if t_ has an alias in the alias index
|
||||||
|
if (ctx.has_type_alias(fn)) {
|
||||||
|
LOG_DBG("Find relationship in alias of {} | {}", fn,
|
||||||
|
cppast::to_string(ctx.get_type_alias(fn).get()));
|
||||||
|
found = find_relationships(
|
||||||
|
ctx.get_type_alias(fn).get(), relationships, relationship_type);
|
||||||
|
}
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool translation_unit_visitor::find_relationships_in_reference(
|
||||||
|
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
||||||
|
const relationship_t &relationship_hint)
|
||||||
|
{
|
||||||
|
bool found;
|
||||||
|
auto &r = static_cast<const cppast::cpp_reference_type &>(t_);
|
||||||
|
auto rt = relationship_t::kAssociation;
|
||||||
|
if (r.reference_kind() == cppast::cpp_ref_rvalue) {
|
||||||
|
rt = relationship_t::kAggregation;
|
||||||
|
}
|
||||||
|
if (relationship_hint == relationship_t::kDependency)
|
||||||
|
rt = relationship_hint;
|
||||||
|
found = find_relationships(r.referee(), relationships, rt);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool translation_unit_visitor::find_relationships_in_pointer(
|
||||||
|
const cppast::cpp_type &t_, found_relationships_t &relationships,
|
||||||
|
const relationship_t &relationship_hint)
|
||||||
|
{
|
||||||
|
bool found;
|
||||||
|
auto &p = static_cast<const cppast::cpp_pointer_type &>(t_);
|
||||||
|
auto rt = relationship_t::kAssociation;
|
||||||
|
if (relationship_hint == relationship_t::kDependency)
|
||||||
|
rt = relationship_hint;
|
||||||
|
found = find_relationships(p.pointee(), relationships, rt);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool translation_unit_visitor::find_relationships_in_array(
|
||||||
|
found_relationships_t &relationships, const cppast::cpp_type &t)
|
||||||
|
{
|
||||||
|
bool found;
|
||||||
|
auto &a = static_cast<const cppast::cpp_array_type &>(t);
|
||||||
|
found = find_relationships(
|
||||||
|
a.value_type(), relationships, relationship_t::kAggregation);
|
||||||
|
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)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include <cppast/visitor.hpp>
|
#include <cppast/visitor.hpp>
|
||||||
#include <type_safe/reference.hpp>
|
#include <type_safe/reference.hpp>
|
||||||
|
|
||||||
|
#include <common/model/enums.h>
|
||||||
#include <cppast/cpp_alias_template.hpp>
|
#include <cppast/cpp_alias_template.hpp>
|
||||||
#include <cppast/cpp_type_alias.hpp>
|
#include <cppast/cpp_type_alias.hpp>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -43,6 +44,9 @@
|
|||||||
|
|
||||||
namespace clanguml::class_diagram::visitor {
|
namespace clanguml::class_diagram::visitor {
|
||||||
|
|
||||||
|
using found_relationships_t =
|
||||||
|
std::vector<std::pair<std::string, common::model::relationship_t>>;
|
||||||
|
|
||||||
class translation_unit_visitor {
|
class translation_unit_visitor {
|
||||||
public:
|
public:
|
||||||
translation_unit_visitor(cppast::cpp_entity_index &idx,
|
translation_unit_visitor(cppast::cpp_entity_index &idx,
|
||||||
@@ -101,8 +105,7 @@ public:
|
|||||||
const std::set<std::string> &template_parameter_names = {});
|
const std::set<std::string> &template_parameter_names = {});
|
||||||
|
|
||||||
bool find_relationships(const cppast::cpp_type &t,
|
bool find_relationships(const cppast::cpp_type &t,
|
||||||
std::vector<std::pair<std::string,
|
found_relationships_t &relationships,
|
||||||
clanguml::common::model::relationship_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);
|
||||||
|
|
||||||
@@ -133,12 +136,12 @@ public:
|
|||||||
void process_class_bases(
|
void process_class_bases(
|
||||||
const cppast::cpp_class &cls, model::class_ &c) const;
|
const cppast::cpp_class &cls, model::class_ &c) const;
|
||||||
|
|
||||||
void process_unexposed_template_specialization_arguments(
|
void process_unexposed_template_specialization_parameters(
|
||||||
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
||||||
&tspec,
|
&tspec,
|
||||||
model::class_ &c) const;
|
model::class_ &c) const;
|
||||||
|
|
||||||
void process_exposed_template_specialization_arguments(
|
void process_exposed_template_specialization_parameters(
|
||||||
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
||||||
&tspec,
|
&tspec,
|
||||||
model::class_ &c);
|
model::class_ &c);
|
||||||
@@ -165,9 +168,30 @@ private:
|
|||||||
* If t does not represent an alias, returns t.
|
* If t does not represent an alias, returns t.
|
||||||
*/
|
*/
|
||||||
const cppast::cpp_type &resolve_alias(const cppast::cpp_type &t);
|
const cppast::cpp_type &resolve_alias(const cppast::cpp_type &t);
|
||||||
|
|
||||||
const cppast::cpp_type &resolve_alias_template(
|
const cppast::cpp_type &resolve_alias_template(
|
||||||
const cppast::cpp_type &type);
|
const cppast::cpp_type &type);
|
||||||
|
|
||||||
|
bool find_relationships_in_array(
|
||||||
|
found_relationships_t &relationships, const cppast::cpp_type &t);
|
||||||
|
|
||||||
|
bool find_relationships_in_pointer(const cppast::cpp_type &t_,
|
||||||
|
found_relationships_t &relationships,
|
||||||
|
const common::model::relationship_t &relationship_hint);
|
||||||
|
|
||||||
|
bool find_relationships_in_reference(const cppast::cpp_type &t_,
|
||||||
|
found_relationships_t &relationships,
|
||||||
|
const common::model::relationship_t &relationship_hint);
|
||||||
|
|
||||||
|
bool find_relationships_in_user_defined_type(const cppast::cpp_type &t_,
|
||||||
|
found_relationships_t &relationships, const std::string &fn,
|
||||||
|
common::model::relationship_t &relationship_type,
|
||||||
|
const cppast::cpp_type &t);
|
||||||
|
|
||||||
|
bool find_relationships_in_template_instantiation(const cppast::cpp_type &t,
|
||||||
|
const std::string &fn, found_relationships_t &relationships,
|
||||||
|
common::model::relationship_t relationship_type);
|
||||||
|
|
||||||
// ctx allows to track current visitor context, e.g. current namespace
|
// ctx allows to track current visitor context, e.g. current namespace
|
||||||
translation_unit_context ctx;
|
translation_unit_context ctx;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user