Added support for template type aliases only available as unexposed arguments
This commit is contained in:
@@ -175,11 +175,20 @@ void translation_unit_visitor::operator()(const cppast::cpp_entity &file)
|
|||||||
|
|
||||||
auto &at = static_cast<const cppast::cpp_alias_template &>(e);
|
auto &at = static_cast<const cppast::cpp_alias_template &>(e);
|
||||||
|
|
||||||
class_ tinst = build_template_instantiation(static_cast<
|
if (at.type_alias().underlying_type().kind() ==
|
||||||
const cppast::cpp_template_instantiation_type &>(
|
cppast::cpp_type_kind::unexposed_t) {
|
||||||
at.type_alias().underlying_type()));
|
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));
|
ctx.diagram().add_class(std::move(tinst));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -408,6 +417,18 @@ void translation_unit_visitor::process_class_declaration(
|
|||||||
for (const auto &t : toks) {
|
for (const auto &t : toks) {
|
||||||
c.add_template({t});
|
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 =
|
const auto &primary_template_ref =
|
||||||
static_cast<const cppast::cpp_class_template &>(
|
static_cast<const cppast::cpp_class_template &>(
|
||||||
tspec.value()
|
tspec.value()
|
||||||
@@ -886,16 +907,28 @@ void translation_unit_visitor::process_function_parameter(
|
|||||||
// not an instantiation but just a reference to an existing
|
// not an instantiation but just a reference to an existing
|
||||||
// template
|
// template
|
||||||
bool template_is_not_instantiation{false};
|
bool template_is_not_instantiation{false};
|
||||||
for (const auto &template_argument :
|
if (template_instantiation_type.arguments_exposed()) {
|
||||||
template_instantiation_type.arguments().value()) {
|
LOG_DBG("Processing template method argument exposed "
|
||||||
const auto template_argument_name =
|
"parameters...");
|
||||||
cppast::to_string(template_argument.type().value());
|
|
||||||
if (template_parameter_names.count(template_argument_name) >
|
for (const auto &template_argument :
|
||||||
0) {
|
template_instantiation_type.arguments().value()) {
|
||||||
template_is_not_instantiation = true;
|
const auto template_argument_name =
|
||||||
break;
|
cppast::to_string(template_argument.type().value());
|
||||||
|
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: {}",
|
LOG_DBG("Maybe building instantiation for: {}",
|
||||||
primary_template_name);
|
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{};
|
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()) {
|
if (t.primary_template().get(ctx.entity_index()).size()) {
|
||||||
const auto &primary_template_ref =
|
const auto &primary_template_ref =
|
||||||
static_cast<const cppast::cpp_class_template &>(
|
static_cast<const cppast::cpp_class_template &>(
|
||||||
@@ -1293,129 +1325,141 @@ class_ translation_unit_visitor::build_template_instantiation(
|
|||||||
// Process template argumetns
|
// Process template argumetns
|
||||||
int arg_index{0};
|
int arg_index{0};
|
||||||
bool variadic_params{false};
|
bool variadic_params{false};
|
||||||
for (const auto &targ : t.arguments().value()) {
|
if (t.arguments_exposed()) {
|
||||||
bool add_template_argument_as_base_class{false};
|
for (const auto &targ : t.arguments().value()) {
|
||||||
class_template ct;
|
bool add_template_argument_as_base_class{false};
|
||||||
if (targ.type()) {
|
class_template ct;
|
||||||
ct.set_type(cppast::to_string(targ.type().value()));
|
if (targ.type()) {
|
||||||
|
ct.set_type(cppast::to_string(targ.type().value()));
|
||||||
|
|
||||||
LOG_DBG("Template argument is a type {}", ct.type());
|
LOG_DBG("Template argument is a type {}", ct.type());
|
||||||
auto fn = cx::util::full_name(
|
auto fn = cx::util::full_name(
|
||||||
cppast::remove_cv(cx::util::unreferenced(targ.type().value())),
|
cppast::remove_cv(
|
||||||
ctx.entity_index(), false);
|
cx::util::unreferenced(targ.type().value())),
|
||||||
|
ctx.entity_index(), false);
|
||||||
|
|
||||||
if (targ.type().value().kind() ==
|
if (targ.type().value().kind() ==
|
||||||
cppast::cpp_type_kind::template_instantiation_t) {
|
cppast::cpp_type_kind::template_instantiation_t) {
|
||||||
|
|
||||||
const auto &nested_template_parameter = static_cast<
|
const auto &nested_template_parameter = static_cast<
|
||||||
const cppast::cpp_template_instantiation_type &>(
|
const cppast::cpp_template_instantiation_type &>(
|
||||||
targ.type().value());
|
targ.type().value());
|
||||||
|
|
||||||
std::string nnn{"empty"};
|
std::string nnn{"empty"};
|
||||||
if (parent)
|
if (parent)
|
||||||
nnn = (*parent)->name();
|
nnn = (*parent)->name();
|
||||||
|
|
||||||
class_ nested_tinst =
|
class_ nested_tinst =
|
||||||
build_template_instantiation(nested_template_parameter,
|
build_template_instantiation(nested_template_parameter,
|
||||||
ctx.config().should_include(tinst.full_name(false))
|
ctx.config().should_include(tinst.full_name(false))
|
||||||
? std::make_optional(&tinst)
|
? std::make_optional(&tinst)
|
||||||
: parent);
|
: parent);
|
||||||
|
|
||||||
class_relationship tinst_dependency{
|
class_relationship tinst_dependency{
|
||||||
relationship_t::kDependency, nested_tinst.full_name()};
|
relationship_t::kDependency, nested_tinst.full_name()};
|
||||||
|
|
||||||
auto nested_tinst_full_name = nested_tinst.full_name();
|
auto nested_tinst_full_name = nested_tinst.full_name();
|
||||||
|
|
||||||
if (ctx.config().should_include(fn)) {
|
if (ctx.config().should_include(fn)) {
|
||||||
ctx.diagram().add_class(std::move(nested_tinst));
|
ctx.diagram().add_class(std::move(nested_tinst));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.config().should_include(tinst.full_name(false))) {
|
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 {}, {} -> {}",
|
"instantiation {}, {} -> {}",
|
||||||
fn, tinst.full_name(), tinst_dependency.destination());
|
fn, tinst.full_name(),
|
||||||
|
tinst_dependency.destination());
|
||||||
|
|
||||||
tinst.add_relationship(std::move(tinst_dependency));
|
tinst.add_relationship(std::move(tinst_dependency));
|
||||||
}
|
}
|
||||||
else if (parent) {
|
else if (parent) {
|
||||||
LOG_DBG("Creating nested template dependency to parent "
|
LOG_DBG("Creating nested template dependency to parent "
|
||||||
"template "
|
"template "
|
||||||
"instantiation {}, {} -> {}",
|
"instantiation {}, {} -> {}",
|
||||||
fn, (*parent)->full_name(),
|
fn, (*parent)->full_name(),
|
||||||
tinst_dependency.destination());
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else if (targ.type().value().kind() ==
|
||||||
LOG_DBG("No nested template dependency to template "
|
cppast::cpp_type_kind::user_defined_t) {
|
||||||
"instantiation: {}, {} -> {}",
|
class_relationship tinst_dependency{
|
||||||
fn, tinst.full_name(), tinst_dependency.destination());
|
relationship_t::kDependency,
|
||||||
}
|
cx::util::full_name(
|
||||||
}
|
cppast::remove_cv(
|
||||||
else if (targ.type().value().kind() ==
|
cx::util::unreferenced(targ.type().value())),
|
||||||
cppast::cpp_type_kind::user_defined_t) {
|
ctx.entity_index(), false)};
|
||||||
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 {} -> {}",
|
"type {} -> {}",
|
||||||
tinst.full_name(), tinst_dependency.destination());
|
tinst.full_name(), tinst_dependency.destination());
|
||||||
|
|
||||||
if (ctx.config().should_include(fn)) {
|
if (ctx.config().should_include(fn)) {
|
||||||
tinst.add_relationship(std::move(tinst_dependency));
|
tinst.add_relationship(std::move(tinst_dependency));
|
||||||
}
|
}
|
||||||
else if (parent) {
|
else if (parent) {
|
||||||
(*parent)->add_relationship(std::move(tinst_dependency));
|
(*parent)->add_relationship(
|
||||||
|
std::move(tinst_dependency));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (targ.expression()) {
|
||||||
else if (targ.expression()) {
|
const auto &exp = targ.expression().value();
|
||||||
const auto &exp = targ.expression().value();
|
if (exp.kind() == cppast::cpp_expression_kind::literal_t)
|
||||||
if (exp.kind() == cppast::cpp_expression_kind::literal_t)
|
ct.set_type(
|
||||||
ct.set_type(
|
static_cast<const cppast::cpp_literal_expression &>(exp)
|
||||||
static_cast<const cppast::cpp_literal_expression &>(exp)
|
.value());
|
||||||
.value());
|
else if (exp.kind() == cppast::cpp_expression_kind::unexposed_t)
|
||||||
else if (exp.kind() == cppast::cpp_expression_kind::unexposed_t)
|
ct.set_type(
|
||||||
ct.set_type(
|
static_cast<const cppast::cpp_unexposed_expression &>(
|
||||||
static_cast<const cppast::cpp_unexposed_expression &>(exp)
|
exp)
|
||||||
.expression()
|
.expression()
|
||||||
.as_string());
|
.as_string());
|
||||||
|
|
||||||
LOG_DBG("Template argument is an expression {}", ct.type());
|
LOG_DBG("Template argument is an expression {}", ct.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case any of the template arguments are base classes, add
|
// In case any of the template arguments are base classes, add
|
||||||
// them as parents of the current template instantiation class
|
// them as parents of the current template instantiation class
|
||||||
if (template_base_params.size() > 0) {
|
if (template_base_params.size() > 0) {
|
||||||
auto [arg_name, is_variadic, index] = template_base_params.front();
|
auto [arg_name, is_variadic, index] =
|
||||||
if (variadic_params)
|
template_base_params.front();
|
||||||
add_template_argument_as_base_class = true;
|
if (variadic_params)
|
||||||
else {
|
|
||||||
variadic_params = is_variadic;
|
|
||||||
if (arg_index == index) {
|
|
||||||
add_template_argument_as_base_class = true;
|
add_template_argument_as_base_class = true;
|
||||||
template_base_params.pop_front();
|
else {
|
||||||
|
variadic_params = is_variadic;
|
||||||
|
if (arg_index == index) {
|
||||||
|
add_template_argument_as_base_class = true;
|
||||||
|
template_base_params.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (add_template_argument_as_base_class) {
|
||||||
|
LOG_DBG("Adding template argument '{}' as base class",
|
||||||
|
ct.type());
|
||||||
|
|
||||||
|
class_parent cp;
|
||||||
|
cp.set_access(access_t::kPublic);
|
||||||
|
cp.set_name(ct.type());
|
||||||
|
|
||||||
|
tinst.add_parent(std::move(cp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (add_template_argument_as_base_class) {
|
LOG_DBG("Adding template argument '{}'", ct.type());
|
||||||
LOG_DBG(
|
|
||||||
"Adding template argument '{}' as base class", ct.type());
|
|
||||||
|
|
||||||
class_parent cp;
|
tinst.add_template(std::move(ct));
|
||||||
cp.set_access(access_t::kPublic);
|
|
||||||
cp.set_name(ct.type());
|
|
||||||
|
|
||||||
tinst.add_parent(std::move(cp));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_DBG("Adding template argument '{}'", ct.type());
|
|
||||||
|
|
||||||
tinst.add_template(std::move(ct));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add instantiation relationship to primary template of this
|
// Add instantiation relationship to primary template of this
|
||||||
@@ -1452,5 +1496,4 @@ const cppast::cpp_type &translation_unit_visitor::resolve_alias(
|
|||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,10 +150,15 @@ std::string ns(const cppast::cpp_type &t, const cppast::cpp_entity_index &idx)
|
|||||||
else {
|
else {
|
||||||
// This is a bug/feature in libclang, where canonical representation
|
// This is a bug/feature in libclang, where canonical representation
|
||||||
// of a template type with incomplete specialization doesn't have a
|
// 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 =
|
const auto &primary_template =
|
||||||
static_cast<const cppast::cpp_template_instantiation_type &>(t)
|
static_cast<const cppast::cpp_template_instantiation_type &>(t)
|
||||||
.primary_template();
|
.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());
|
return ns(primary_template.get(idx)[0].get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user