From 06cf090b353c527380a37de6e1501653830e141e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Thu, 13 Apr 2017 11:58:52 +0200 Subject: [PATCH] Add cpp_scope_name to support templated scopes --- include/cppast/cpp_class.hpp | 5 ++--- include/cppast/cpp_entity.hpp | 35 ++++++++++++++++++++++++++++++-- include/cppast/cpp_enum.hpp | 4 +--- include/cppast/cpp_namespace.hpp | 5 ++--- src/cpp_entity.cpp | 29 ++++++++++++++++++++++++++ src/cpp_enum.cpp | 6 ++++-- test/test_parser.hpp | 6 ++++-- 7 files changed, 75 insertions(+), 15 deletions(-) diff --git a/include/cppast/cpp_class.hpp b/include/cppast/cpp_class.hpp index e2465cb..043f99b 100644 --- a/include/cppast/cpp_class.hpp +++ b/include/cppast/cpp_class.hpp @@ -223,10 +223,9 @@ namespace cppast cpp_entity_kind do_get_entity_kind() const noexcept override; - /// \returns The name of the namespace. - type_safe::optional do_get_scope_name() const override + type_safe::optional do_get_scope_name() const override { - return name(); + return type_safe::ref(*this); } detail::intrusive_list bases_; diff --git a/include/cppast/cpp_entity.hpp b/include/cppast/cpp_entity.hpp index 181f9f7..4170e3c 100644 --- a/include/cppast/cpp_entity.hpp +++ b/include/cppast/cpp_entity.hpp @@ -11,9 +11,40 @@ namespace cppast { + class cpp_entity; enum class cpp_entity_kind; class cpp_entity_index; struct cpp_entity_id; + class cpp_template_parameter; + class cpp_template; + + /// The name of a scope. + /// + /// It is a combination of a name and optional template parameters. + class cpp_scope_name + { + public: + /// \effects Creates a scope out of a given entity. + cpp_scope_name(type_safe::object_ref entity); + + /// \returns The name of the scope. + const std::string& name() const noexcept; + + /// \returns Whether or not the scope is templated. + bool is_templated() const noexcept + { + return templ_.has_value(); + } + + /// \returns An iteratable object iterating over the [cppast::cpp_template_parameter]() entities of the scope. + /// \requires The scope is templated. + detail::iteratable_intrusive_list template_parameters() const + noexcept; + + private: + type_safe::object_ref entity_; + type_safe::optional_ref templ_; + }; /// The base class for all entities in the C++ AST. class cpp_entity : detail::intrusive_list_node @@ -39,7 +70,7 @@ namespace cppast /// \returns The name of the new scope created by the entity, /// if there is any. - type_safe::optional scope_name() const + type_safe::optional scope_name() const { return do_get_scope_name(); } @@ -100,7 +131,7 @@ namespace cppast /// \returns The name of the new scope created by the entity, if any. /// By default, there is no scope created. - virtual type_safe::optional do_get_scope_name() const + virtual type_safe::optional do_get_scope_name() const { return type_safe::nullopt; } diff --git a/include/cppast/cpp_enum.hpp b/include/cppast/cpp_enum.hpp index e8b10d2..2ddbd45 100644 --- a/include/cppast/cpp_enum.hpp +++ b/include/cppast/cpp_enum.hpp @@ -134,9 +134,7 @@ namespace cppast cpp_entity_kind do_get_entity_kind() const noexcept override; - /// \returns If the enum is scoped, the name of the enum, - /// otherwise [ts::nullopt](). - type_safe::optional do_get_scope_name() const override; + type_safe::optional do_get_scope_name() const override; std::unique_ptr type_; bool scoped_, type_given_; diff --git a/include/cppast/cpp_namespace.hpp b/include/cppast/cpp_namespace.hpp index 90b5f8d..ee419f8 100644 --- a/include/cppast/cpp_namespace.hpp +++ b/include/cppast/cpp_namespace.hpp @@ -74,10 +74,9 @@ namespace cppast cpp_entity_kind do_get_entity_kind() const noexcept override; - /// \returns The name of the namespace. - type_safe::optional do_get_scope_name() const override + type_safe::optional do_get_scope_name() const override { - return name(); + return type_safe::ref(*this); } bool inline_; diff --git a/src/cpp_entity.cpp b/src/cpp_entity.cpp index bb00a11..4f7aa31 100644 --- a/src/cpp_entity.cpp +++ b/src/cpp_entity.cpp @@ -6,9 +6,38 @@ #include #include +#include using namespace cppast; +cpp_scope_name::cpp_scope_name(type_safe::object_ref entity) : entity_(entity) +{ + if (cppast::is_templated(*entity)) + { + auto& templ = static_cast(entity->parent().value()); + if (!templ.parameters().empty()) + templ_ = type_safe::ref(templ); + } + else if (is_template(entity->kind())) + { + auto& templ = static_cast(*entity); + if (!templ.parameters().empty()) + templ_ = type_safe::ref(templ); + } +} + +const std::string& cpp_scope_name::name() const noexcept +{ + return entity_->name(); +} + +detail::iteratable_intrusive_list cpp_scope_name::template_parameters() + const noexcept +{ + DEBUG_ASSERT(is_templated(), detail::precondition_error_handler{}); + return templ_.value().parameters(); +} + cpp_entity_kind cpp_unexposed_entity::kind() noexcept { return cpp_entity_kind::unexposed_t; diff --git a/src/cpp_enum.cpp b/src/cpp_enum.cpp index 355b977..f8c2f57 100644 --- a/src/cpp_enum.cpp +++ b/src/cpp_enum.cpp @@ -38,7 +38,9 @@ cpp_entity_kind cpp_enum::do_get_entity_kind() const noexcept return kind(); } -type_safe::optional cpp_enum::do_get_scope_name() const +type_safe::optional cpp_enum::do_get_scope_name() const { - return scoped_ ? type_safe::make_optional(name()) : type_safe::nullopt; + if (scoped_) + return type_safe::ref(*this); + return type_safe::nullopt; } diff --git a/test/test_parser.hpp b/test/test_parser.hpp index 0b95ff2..3d545a7 100644 --- a/test/test_parser.hpp +++ b/test/test_parser.hpp @@ -140,6 +140,7 @@ unsigned count_children(const Entity& cont) return std::distance(cont.begin(), cont.end()); } +// ignores templated scopes inline std::string full_name(const cppast::cpp_entity& e) { if (e.name().empty()) @@ -152,8 +153,9 @@ inline std::string full_name(const cppast::cpp_entity& e) for (auto cur = e.parent(); cur; cur = cur.value().parent()) // prepend each scope, if there is any - type_safe::with(cur.value().scope_name(), - [&](const std::string& cur_scope) { scopes = cur_scope + "::" + scopes; }); + type_safe::with(cur.value().scope_name(), [&](const cppast::cpp_scope_name& cur_scope) { + scopes = cur_scope.name() + "::" + scopes; + }); return scopes + e.name(); }