Added support for template type aliases only available as unexposed arguments

This commit is contained in:
Bartek Kryza
2021-10-07 20:36:26 +02:00
parent b10dc5e732
commit 7728eb68a6
2 changed files with 160 additions and 112 deletions

View File

@@ -175,12 +175,21 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
auto &at = static_cast<const cppast::cpp_alias_template &>(e);
if (at.type_alias().underlying_type().kind() ==
cppast::cpp_type_kind::unexposed_t) {
LOG_WARN("Template alias has unexposed underlying type: {}",
static_cast<const cppast::cpp_unexposed_type &>(
at.type_alias().underlying_type())
.name());
}
else {
class_ tinst = build_template_instantiation(static_cast<
const cppast::cpp_template_instantiation_type &>(
at.type_alias().underlying_type()));
ctx.diagram().add_class(std::move(tinst));
}
}
});
}
@@ -408,6 +417,18 @@ void translation_unit_visitor::process_class_declaration(
for (const auto &t : toks) {
c.add_template({t});
if (!tspec.value().primary_template().is_overloaded()) {
if (tspec.value()
.primary_template()
.get(ctx.entity_index())
.size() == 0) {
LOG_WARN("Template {} has no exposed arguments",
tspec.value().name());
continue;
}
}
const auto &primary_template_ref =
static_cast<const cppast::cpp_class_template &>(
tspec.value()
@@ -886,16 +907,28 @@ void translation_unit_visitor::process_function_parameter(
// not an instantiation but just a reference to an existing
// template
bool template_is_not_instantiation{false};
if (template_instantiation_type.arguments_exposed()) {
LOG_DBG("Processing template method argument exposed "
"parameters...");
for (const auto &template_argument :
template_instantiation_type.arguments().value()) {
const auto template_argument_name =
cppast::to_string(template_argument.type().value());
if (template_parameter_names.count(template_argument_name) >
0) {
if (template_parameter_names.count(
template_argument_name) > 0) {
template_is_not_instantiation = true;
break;
}
}
}
else {
LOG_DBG("Processing template method argument unexposed "
"parameters: ",
template_instantiation_type.unexposed_arguments());
// TODO: Process unexposed arguments by manually parsing the
// arguments string
}
LOG_DBG("Maybe building instantiation for: {}",
primary_template_name);
@@ -1177,7 +1210,6 @@ class_ translation_unit_visitor::build_template_instantiation(
std::deque<std::tuple<std::string, int, bool>> template_base_params{};
// Determine the full template name
if (t.primary_template().get(ctx.entity_index()).size()) {
const auto &primary_template_ref =
static_cast<const cppast::cpp_class_template &>(
@@ -1293,6 +1325,7 @@ class_ translation_unit_visitor::build_template_instantiation(
// Process template argumetns
int arg_index{0};
bool variadic_params{false};
if (t.arguments_exposed()) {
for (const auto &targ : t.arguments().value()) {
bool add_template_argument_as_base_class{false};
class_template ct;
@@ -1301,7 +1334,8 @@ class_ translation_unit_visitor::build_template_instantiation(
LOG_DBG("Template argument is a type {}", ct.type());
auto fn = cx::util::full_name(
cppast::remove_cv(cx::util::unreferenced(targ.type().value())),
cppast::remove_cv(
cx::util::unreferenced(targ.type().value())),
ctx.entity_index(), false);
if (targ.type().value().kind() ==
@@ -1331,9 +1365,11 @@ class_ translation_unit_visitor::build_template_instantiation(
}
if (ctx.config().should_include(tinst.full_name(false))) {
LOG_DBG("Creating nested template dependency to template "
LOG_DBG(
"Creating nested template dependency to template "
"instantiation {}, {} -> {}",
fn, tinst.full_name(), tinst_dependency.destination());
fn, tinst.full_name(),
tinst_dependency.destination());
tinst.add_relationship(std::move(tinst_dependency));
}
@@ -1344,23 +1380,27 @@ class_ translation_unit_visitor::build_template_instantiation(
fn, (*parent)->full_name(),
tinst_dependency.destination());
(*parent)->add_relationship(std::move(tinst_dependency));
(*parent)->add_relationship(
std::move(tinst_dependency));
}
else {
LOG_DBG("No nested template dependency to template "
"instantiation: {}, {} -> {}",
fn, tinst.full_name(), tinst_dependency.destination());
fn, tinst.full_name(),
tinst_dependency.destination());
}
}
else if (targ.type().value().kind() ==
cppast::cpp_type_kind::user_defined_t) {
class_relationship tinst_dependency{relationship_t::kDependency,
class_relationship tinst_dependency{
relationship_t::kDependency,
cx::util::full_name(
cppast::remove_cv(
cx::util::unreferenced(targ.type().value())),
ctx.entity_index(), false)};
LOG_DBG("Creating nested template dependency to user defined "
LOG_DBG(
"Creating nested template dependency to user defined "
"type {} -> {}",
tinst.full_name(), tinst_dependency.destination());
@@ -1368,7 +1408,8 @@ class_ translation_unit_visitor::build_template_instantiation(
tinst.add_relationship(std::move(tinst_dependency));
}
else if (parent) {
(*parent)->add_relationship(std::move(tinst_dependency));
(*parent)->add_relationship(
std::move(tinst_dependency));
}
}
}
@@ -1380,7 +1421,8 @@ class_ translation_unit_visitor::build_template_instantiation(
.value());
else if (exp.kind() == cppast::cpp_expression_kind::unexposed_t)
ct.set_type(
static_cast<const cppast::cpp_unexposed_expression &>(exp)
static_cast<const cppast::cpp_unexposed_expression &>(
exp)
.expression()
.as_string());
@@ -1390,7 +1432,8 @@ class_ translation_unit_visitor::build_template_instantiation(
// In case any of the template arguments are base classes, add
// them as parents of the current template instantiation class
if (template_base_params.size() > 0) {
auto [arg_name, is_variadic, index] = template_base_params.front();
auto [arg_name, is_variadic, index] =
template_base_params.front();
if (variadic_params)
add_template_argument_as_base_class = true;
else {
@@ -1402,8 +1445,8 @@ class_ translation_unit_visitor::build_template_instantiation(
}
if (add_template_argument_as_base_class) {
LOG_DBG(
"Adding template argument '{}' as base class", ct.type());
LOG_DBG("Adding template argument '{}' as base class",
ct.type());
class_parent cp;
cp.set_access(access_t::kPublic);
@@ -1417,6 +1460,7 @@ class_ translation_unit_visitor::build_template_instantiation(
tinst.add_template(std::move(ct));
}
}
// Add instantiation relationship to primary template of this
// instantiation
@@ -1452,5 +1496,4 @@ const cppast::cpp_type &translation_unit_visitor::resolve_alias(
return type;
}
}

View File

@@ -150,10 +150,15 @@ std::string ns(const cppast::cpp_type &t, const cppast::cpp_entity_index &idx)
else {
// This is a bug/feature in libclang, where canonical representation
// of a template type with incomplete specialization doesn't have a
// full namespace. We have to extract it from te primary template
// full namespace. We have to extract it from the primary template
const auto &primary_template =
static_cast<const cppast::cpp_template_instantiation_type &>(t)
.primary_template();
if (!primary_template.is_overloaded()) {
LOG_WARN(
"Cannot establish namespace for ", cppast::to_string(t));
return "";
}
return ns(primary_template.get(idx)[0].get());
}
}