Fixed unexposed template parameters namespace resolution
This commit is contained in:
@@ -41,9 +41,11 @@ std::string enum_::full_name(bool relative) const
|
||||
|
||||
std::ostringstream ostr;
|
||||
if (relative)
|
||||
ostr << namespace_{name()}.relative_to(using_namespace()).to_string();
|
||||
ostr << namespace_{name_and_ns()}
|
||||
.relative_to(using_namespace())
|
||||
.to_string();
|
||||
else
|
||||
ostr << name();
|
||||
ostr << name_and_ns();
|
||||
|
||||
return ostr.str();
|
||||
}
|
||||
|
||||
@@ -209,4 +209,59 @@ translation_unit_context::using_namespace_directive(
|
||||
return using_ns_declarations_.at(ns.to_string());
|
||||
}
|
||||
|
||||
type_safe::optional<common::model::namespace_>
|
||||
translation_unit_context::get_name_with_namespace(const std::string &name) const
|
||||
{
|
||||
using common::model::namespace_;
|
||||
|
||||
std::set<namespace_> possible_matches;
|
||||
possible_matches.emplace(name);
|
||||
|
||||
possible_matches.emplace(get_namespace() | namespace_{name});
|
||||
auto parent = get_namespace().parent();
|
||||
while (parent.has_value()) {
|
||||
possible_matches.emplace(parent.value() | namespace_{name});
|
||||
parent = parent.value().parent();
|
||||
}
|
||||
|
||||
if (using_ns_declarations_.find(get_namespace().to_string()) !=
|
||||
using_ns_declarations_.end()) {
|
||||
for (const auto &ns :
|
||||
using_ns_declarations_.at(get_namespace().to_string())) {
|
||||
possible_matches.emplace(ns | namespace_{name});
|
||||
auto parent = ns.parent();
|
||||
while (parent.has_value()) {
|
||||
possible_matches.emplace(parent.value() | namespace_{name});
|
||||
parent = parent.value().parent();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search classes
|
||||
for (const auto &c : diagram_.classes()) {
|
||||
auto c_ns = namespace_{c->name_and_ns()};
|
||||
for (const auto &possible_match : possible_matches) {
|
||||
if (c_ns == possible_match) {
|
||||
return possible_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search enums
|
||||
for (const auto &e : diagram_.enums()) {
|
||||
auto e_ns = namespace_{e->name_and_ns()};
|
||||
for (const auto &possible_match : possible_matches) {
|
||||
if (e_ns == possible_match) {
|
||||
return possible_match;
|
||||
}
|
||||
// Try to also match possible references to enum values
|
||||
else if (possible_match.starts_with(e_ns)) {
|
||||
return possible_match;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -83,6 +83,9 @@ public:
|
||||
const std::set<common::model::namespace_> &using_namespace_directive(
|
||||
const common::model::namespace_ &ns) const;
|
||||
|
||||
type_safe::optional<common::model::namespace_> get_name_with_namespace(
|
||||
const std::string &name) const;
|
||||
|
||||
private:
|
||||
// Current visitor namespace
|
||||
common::model::namespace_ ns_;
|
||||
@@ -90,6 +93,8 @@ private:
|
||||
// A map of 'using namespace' declared within a given namespace scope
|
||||
// This is necessary to properly establish the namespace of a given entity
|
||||
// for instance in unexposed template parameters
|
||||
// - key - namespace
|
||||
// - value - set of namespaces 'imported' within this namespace scope
|
||||
std::map<std::string, std::set<common::model::namespace_>>
|
||||
using_ns_declarations_;
|
||||
|
||||
|
||||
@@ -179,14 +179,15 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
|
||||
process_type_alias_template(at);
|
||||
}
|
||||
else if (e.kind() == cppast::cpp_entity_kind::using_directive_t) {
|
||||
using common::model::namespace_;
|
||||
|
||||
const auto &using_directive =
|
||||
static_cast<const cppast::cpp_using_directive &>(e);
|
||||
|
||||
const auto ns_ref = using_directive.target();
|
||||
const auto &ns = ns_ref.get(ctx.entity_index()).at(0).get();
|
||||
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());
|
||||
auto full_ns = namespace_{cx::util::ns(ns)} | ns.name();
|
||||
|
||||
ctx.add_using_namespace_directive(full_ns);
|
||||
}
|
||||
@@ -503,10 +504,16 @@ void translation_unit_visitor::
|
||||
{
|
||||
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, [this](const std::string &t) {
|
||||
auto full_type = ctx.get_name_with_namespace(t);
|
||||
if (full_type.has_value())
|
||||
return full_type.value().to_string();
|
||||
return t;
|
||||
});
|
||||
|
||||
found_relationships_t relationships;
|
||||
for (const auto ¶m : template_params) {
|
||||
for (auto ¶m : template_params) {
|
||||
find_relationships_in_unexposed_template_params(param, relationships);
|
||||
c.add_template(param);
|
||||
}
|
||||
@@ -1414,31 +1421,17 @@ bool translation_unit_visitor::find_relationships_in_unexposed_template_params(
|
||||
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 type_with_namespace = ctx.get_name_with_namespace(ct.type());
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (!type_with_namespace.has_value()) {
|
||||
// Couldn't find declaration of this type
|
||||
type_with_namespace = common::model::namespace_{ct.type()};
|
||||
}
|
||||
|
||||
if (ctx.config().should_include(type_with_namespace.value())) {
|
||||
relationships.emplace_back(type_with_namespace.value().to_string(),
|
||||
relationship_t::kDependency);
|
||||
found = true;
|
||||
}
|
||||
|
||||
for (const auto &nested_template_params : ct.template_params_) {
|
||||
|
||||
Reference in New Issue
Block a user