Refactored find_relationships method
This commit is contained in:
@@ -405,10 +405,10 @@ bool translation_unit_visitor::process_template_parameters(
|
||||
// Add specialization arguments
|
||||
if (tspec) {
|
||||
if (!tspec.value().arguments_exposed()) {
|
||||
process_unexposed_template_specialization_arguments(tspec, c);
|
||||
process_unexposed_template_specialization_parameters(tspec, c);
|
||||
}
|
||||
else {
|
||||
process_exposed_template_specialization_arguments(tspec, c);
|
||||
process_exposed_template_specialization_parameters(tspec, c);
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -451,7 +451,7 @@ void translation_unit_visitor::process_scope_template_parameters(
|
||||
}
|
||||
|
||||
void translation_unit_visitor::
|
||||
process_exposed_template_specialization_arguments(
|
||||
process_exposed_template_specialization_parameters(
|
||||
const type_safe::optional_ref<const cppast::cpp_template_specialization>
|
||||
&tspec,
|
||||
class_ &c)
|
||||
@@ -488,7 +488,7 @@ 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>
|
||||
&tspec,
|
||||
class_ &c) const
|
||||
@@ -505,7 +505,7 @@ void translation_unit_visitor::
|
||||
.primary_template()
|
||||
.get(ctx.entity_index())
|
||||
.size() == 0) {
|
||||
LOG_WARN("Template {} has no exposed arguments",
|
||||
LOG_WARN("Template {} has no exposed parameters",
|
||||
tspec.value().name());
|
||||
|
||||
continue;
|
||||
@@ -1211,8 +1211,7 @@ void translation_unit_visitor::process_friend(
|
||||
}
|
||||
|
||||
bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
||||
std::vector<std::pair<std::string, relationship_t>> &relationships,
|
||||
relationship_t relationship_hint)
|
||||
found_relationships_t &relationships, relationship_t relationship_hint)
|
||||
{
|
||||
bool found{false};
|
||||
|
||||
@@ -1227,35 +1226,92 @@ bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
||||
relationship_t relationship_type = relationship_hint;
|
||||
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) {
|
||||
auto &a = static_cast<const cppast::cpp_array_type &>(t);
|
||||
found = find_relationships(
|
||||
a.value_type(), relationships, relationship_t::kAggregation);
|
||||
return found;
|
||||
found = find_relationships_in_array(relationships, t);
|
||||
}
|
||||
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);
|
||||
|
||||
if (t_.kind() == cppast::cpp_type_kind::pointer_t) {
|
||||
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);
|
||||
bool found = false;
|
||||
|
||||
if (!tinst.arguments_exposed()) {
|
||||
LOG_DBG("Template instantiation {} has no exposed arguments", name);
|
||||
|
||||
return found;
|
||||
}
|
||||
else if (t_.kind() == cppast::cpp_type_kind::reference_t) {
|
||||
auto &r = static_cast<const cppast::cpp_reference_type &>(t_);
|
||||
auto rt = relationship_t::kAssociation;
|
||||
if (r.reference_kind() == cppast::cpp_reference::cpp_ref_rvalue) {
|
||||
rt = relationship_t::kAggregation;
|
||||
}
|
||||
if (relationship_hint == relationship_t::kDependency)
|
||||
rt = relationship_hint;
|
||||
found = find_relationships(r.referee(), relationships, rt);
|
||||
|
||||
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);
|
||||
}
|
||||
if (cppast::remove_cv(t_).kind() == cppast::cpp_type_kind::user_defined_t) {
|
||||
LOG_DBG("User defined type: {} | {}", cppast::to_string(t_),
|
||||
cppast::to_string(t_.canonical()));
|
||||
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_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);
|
||||
@@ -1269,94 +1325,13 @@ bool translation_unit_visitor::find_relationships(const cppast::cpp_type &t_,
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if (t.kind() == cppast::cpp_type_kind::template_instantiation_t) {
|
||||
// class_relationship r;
|
||||
|
||||
const auto &tinst =
|
||||
static_cast<const cppast::cpp_template_instantiation_type &>(t);
|
||||
|
||||
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);
|
||||
}
|
||||
else {
|
||||
for (const auto &arg : args) {
|
||||
if (arg.type().has_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;
|
||||
}
|
||||
|
||||
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(
|
||||
const cppast::cpp_template_instantiation_type &t,
|
||||
std::optional<clanguml::class_diagram::model::class_ *> parent)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <cppast/visitor.hpp>
|
||||
#include <type_safe/reference.hpp>
|
||||
|
||||
#include <common/model/enums.h>
|
||||
#include <cppast/cpp_alias_template.hpp>
|
||||
#include <cppast/cpp_type_alias.hpp>
|
||||
#include <functional>
|
||||
@@ -43,6 +44,9 @@
|
||||
|
||||
namespace clanguml::class_diagram::visitor {
|
||||
|
||||
using found_relationships_t =
|
||||
std::vector<std::pair<std::string, common::model::relationship_t>>;
|
||||
|
||||
class translation_unit_visitor {
|
||||
public:
|
||||
translation_unit_visitor(cppast::cpp_entity_index &idx,
|
||||
@@ -101,8 +105,7 @@ public:
|
||||
const std::set<std::string> &template_parameter_names = {});
|
||||
|
||||
bool find_relationships(const cppast::cpp_type &t,
|
||||
std::vector<std::pair<std::string,
|
||||
clanguml::common::model::relationship_t>> &relationships,
|
||||
found_relationships_t &relationships,
|
||||
clanguml::common::model::relationship_t relationship_hint =
|
||||
clanguml::common::model::relationship_t::kNone);
|
||||
|
||||
@@ -133,12 +136,12 @@ public:
|
||||
void process_class_bases(
|
||||
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>
|
||||
&tspec,
|
||||
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>
|
||||
&tspec,
|
||||
model::class_ &c);
|
||||
@@ -165,9 +168,30 @@ private:
|
||||
* 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_template(
|
||||
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
|
||||
translation_unit_context ctx;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user