From df684694ccd6d958bc0454e0df184494a2ee371a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Thu, 30 Mar 2017 12:04:18 +0200 Subject: [PATCH] Add and parse unexposed entity --- include/cppast/cpp_entity.hpp | 34 ++++++++++++++++++++++++++++++ include/cppast/cpp_entity_kind.hpp | 2 ++ src/code_generator.cpp | 11 ++++++++++ src/cpp_entity.cpp | 26 +++++++++++++++++++++++ src/cpp_entity_kind.cpp | 8 +++++++ src/libclang/parse_functions.cpp | 11 +++++++++- src/visitor.cpp | 1 + test/code_generator.cpp | 3 ++- 8 files changed, 94 insertions(+), 2 deletions(-) diff --git a/include/cppast/cpp_entity.hpp b/include/cppast/cpp_entity.hpp index 942e9d2..4273444 100644 --- a/include/cppast/cpp_entity.hpp +++ b/include/cppast/cpp_entity.hpp @@ -119,6 +119,40 @@ namespace cppast friend detail::intrusive_list_node; }; + /// A [cppast::cpp_entity]() that isn't exposed directly. + /// + /// The only information available is the raw source code. + class cpp_unexposed_entity final : public cpp_entity + { + public: + static cpp_entity_kind kind() noexcept; + + /// \returns A newly built and registered unexposed entity. + /// \notes It will be registered as a declaration. + static std::unique_ptr build(const cpp_entity_index& index, cpp_entity_id id, + std::string name, std::string spelling); + + /// \returns A newly built unnamed unexposed entity. + /// It will not be registered. + static std::unique_ptr build(std::string spelling); + + /// \returns The spelling of that entity. + const std::string& spelling() const noexcept + { + return spelling_; + } + + private: + cpp_unexposed_entity(std::string name, std::string spelling) + : cpp_entity(std::move(name)), spelling_(std::move(spelling)) + { + } + + cpp_entity_kind do_get_entity_kind() const noexcept override; + + std::string spelling_; + }; + /// \returns Whether or not the entity is templated. /// If this function returns `true` that means the entity is not the "real" entity, /// but contains just the information for the template which is the parent entity. diff --git a/include/cppast/cpp_entity_kind.hpp b/include/cppast/cpp_entity_kind.hpp index 5c9e298..8480a86 100644 --- a/include/cppast/cpp_entity_kind.hpp +++ b/include/cppast/cpp_entity_kind.hpp @@ -55,6 +55,8 @@ namespace cppast class_template_t, class_template_specialization_t, + unexposed_t, + count, }; diff --git a/src/code_generator.cpp b/src/code_generator.cpp index a9a4525..8df1254 100644 --- a/src/code_generator.cpp +++ b/src/code_generator.cpp @@ -810,6 +810,13 @@ namespace generate_class(generator, templ.class_(), type_safe::ref(templ)); } } + + void generate_unexposed(code_generator& generator, const cpp_unexposed_entity& entity) + { + code_generator::output output(type_safe::ref(generator), type_safe::ref(entity), false); + if (output) + output << token_seq(entity.spelling()); + } } void cppast::generate_code(code_generator& generator, const cpp_entity& e) @@ -863,6 +870,10 @@ void cppast::generate_code(code_generator& generator, const cpp_entity& e) CPPAST_DETAIL_HANDLE(class_template) CPPAST_DETAIL_HANDLE(class_template_specialization) + case cpp_entity_kind::unexposed_t: + generate_unexposed(generator, static_cast(e)); + break; + #undef CPPAST_DETAIL_HANDLE case cpp_entity_kind::count: diff --git a/src/cpp_entity.cpp b/src/cpp_entity.cpp index 20ef888..47ea237 100644 --- a/src/cpp_entity.cpp +++ b/src/cpp_entity.cpp @@ -4,10 +4,36 @@ #include +#include #include using namespace cppast; +cpp_entity_kind cpp_unexposed_entity::kind() noexcept +{ + return cpp_entity_kind::unexposed_t; +} + +std::unique_ptr cpp_unexposed_entity::build(const cpp_entity_index& index, + cpp_entity_id id, std::string name, + std::string spelling) +{ + std::unique_ptr result( + new cpp_unexposed_entity(std::move(name), std::move(spelling))); + index.register_forward_declaration(id, type_safe::ref(*result)); + return result; +} + +std::unique_ptr cpp_unexposed_entity::build(std::string spelling) +{ + return std::unique_ptr(new cpp_unexposed_entity("", std::move(spelling))); +} + +cpp_entity_kind cpp_unexposed_entity::do_get_entity_kind() const noexcept +{ + return kind(); +} + bool cppast::is_templated(const cpp_entity& e) noexcept { if (!e.parent()) diff --git a/src/cpp_entity_kind.cpp b/src/cpp_entity_kind.cpp index 8a4fdea..74db712 100644 --- a/src/cpp_entity_kind.cpp +++ b/src/cpp_entity_kind.cpp @@ -85,6 +85,9 @@ const char* cppast::to_string(cpp_entity_kind kind) noexcept case cpp_entity_kind::class_template_specialization_t: return "class tempalte specialization"; + case cpp_entity_kind::unexposed_t: + return "unexposed entity"; + case cpp_entity_kind::count: break; } @@ -130,6 +133,7 @@ bool cppast::is_type(cpp_entity_kind kind) noexcept case cpp_entity_kind::function_template_specialization_t: case cpp_entity_kind::class_template_t: case cpp_entity_kind::class_template_specialization_t: + case cpp_entity_kind::unexposed_t: case cpp_entity_kind::count: break; } @@ -175,6 +179,7 @@ bool cppast::is_function(cpp_entity_kind kind) noexcept case cpp_entity_kind::function_template_specialization_t: case cpp_entity_kind::class_template_t: case cpp_entity_kind::class_template_specialization_t: + case cpp_entity_kind::unexposed_t: case cpp_entity_kind::count: break; } @@ -220,6 +225,7 @@ bool cppast::is_parameter(cpp_entity_kind kind) noexcept case cpp_entity_kind::function_template_specialization_t: case cpp_entity_kind::class_template_t: case cpp_entity_kind::class_template_specialization_t: + case cpp_entity_kind::unexposed_t: case cpp_entity_kind::count: break; } @@ -264,6 +270,7 @@ bool cppast::is_template(cpp_entity_kind kind) noexcept case cpp_entity_kind::template_type_parameter_t: case cpp_entity_kind::non_type_template_parameter_t: case cpp_entity_kind::template_template_parameter_t: + case cpp_entity_kind::unexposed_t: case cpp_entity_kind::count: break; } @@ -309,6 +316,7 @@ bool cppast::is_template_specialization(cpp_entity_kind kind) noexcept case cpp_entity_kind::variable_template_t: case cpp_entity_kind::function_template_t: case cpp_entity_kind::class_template_t: + case cpp_entity_kind::unexposed_t: case cpp_entity_kind::count: break; } diff --git a/src/libclang/parse_functions.cpp b/src/libclang/parse_functions.cpp index 5fbf3ec..2064378 100644 --- a/src/libclang/parse_functions.cpp +++ b/src/libclang/parse_functions.cpp @@ -148,7 +148,16 @@ std::unique_ptr detail::parse_entity(const detail::parse_context& co context.logger->log("libclang parser", diagnostic{std::move(msg), detail::make_location(cur), severity::warning}); - return nullptr; + // build unexposed entity + auto name = detail::get_cursor_name(cur); + detail::tokenizer tokenizer(context.tu, context.file, cur); + detail::token_stream stream(tokenizer, cur); + auto spelling = detail::to_string(stream, stream.end()); + if (name.empty()) + return cpp_unexposed_entity::build(std::move(spelling)); + else + return cpp_unexposed_entity::build(*context.idx, detail::get_entity_id(cur), name.c_str(), + std::move(spelling)); } catch (parse_error& ex) { diff --git a/src/visitor.cpp b/src/visitor.cpp index 4c9366e..86ca7c1 100644 --- a/src/visitor.cpp +++ b/src/visitor.cpp @@ -93,6 +93,7 @@ bool detail::visit(const cpp_entity& e, detail::visitor_callback_t cb, void* fun case cpp_entity_kind::destructor_t: case cpp_entity_kind::template_type_parameter_t: case cpp_entity_kind::non_type_template_parameter_t: + case cpp_entity_kind::unexposed_t: return cb(functor, e, visitor_info::leaf_entity); case cpp_entity_kind::count: diff --git a/test/code_generator.cpp b/test/code_generator.cpp index dc85be4..5c83b80 100644 --- a/test/code_generator.cpp +++ b/test/code_generator.cpp @@ -32,7 +32,8 @@ enum class bar void func(int(*)(int)); extern void(* ptr)(int(*)(int))=&func; -)"; + +templateint var;)"; auto file = parse({}, "code_generator.cpp", code); REQUIRE(get_code(*file) == code);