From 93d2c58f7f283d840e7ece090c78de6a14e518a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Mon, 10 Jul 2017 19:26:55 +0200 Subject: [PATCH] Add signature() to cpp_function_base --- include/cppast/cpp_function.hpp | 12 +++++++++ include/cppast/cpp_member_function.hpp | 19 +++----------- include/cppast/cpp_type.hpp | 3 +++ src/cpp_function.cpp | 16 ++++++++++++ src/cpp_member_function.cpp | 17 +++++++++++++ src/cpp_type.cpp | 35 ++++++++++++++++++++++++++ test/cpp_function.cpp | 12 +++++---- test/cpp_member_function.cpp | 20 +++++++++++++-- 8 files changed, 112 insertions(+), 22 deletions(-) diff --git a/include/cppast/cpp_function.hpp b/include/cppast/cpp_function.hpp index 61dce82..0bfc47b 100644 --- a/include/cppast/cpp_function.hpp +++ b/include/cppast/cpp_function.hpp @@ -94,6 +94,14 @@ namespace cppast return variadic_; } + /// \returns The signature of the function, + /// i.e. parameters and cv/ref-qualifiers if a member function. + /// It has the form `(int,char,...) const`. + std::string signature() const + { + return do_get_signature(); + } + protected: /// Builder class for functions. /// @@ -176,6 +184,10 @@ namespace cppast { } + protected: + /// \returns The signature, it is called by [*signature()](). + virtual std::string do_get_signature() const; + private: detail::intrusive_list parameters_; std::unique_ptr noexcept_expr_; diff --git a/include/cppast/cpp_member_function.hpp b/include/cppast/cpp_member_function.hpp index c6dec70..c743d7f 100644 --- a/include/cppast/cpp_member_function.hpp +++ b/include/cppast/cpp_member_function.hpp @@ -23,24 +23,10 @@ namespace cppast pure, //< Set if the function is pure. override, //< Set if the function overrides a base class function. final, //< Set if the function is marked `final`. - }; -} // namespace cppast -/// \exclude -namespace type_safe -{ - template <> - struct flag_set_traits : std::true_type - { - static constexpr std::size_t size() noexcept - { - return 3u; - } + _flag_set_size, //< \exclude }; -} // namespace type_safe -namespace cppast -{ /// The `virtual` information of a member function. /// /// This is an optional of the combination of the [cppast::cpp_virtual_flags](). @@ -161,6 +147,9 @@ namespace cppast { } + protected: + std::string do_get_signature() const override; + private: std::unique_ptr return_type_; cpp_virtual virtual_; diff --git a/include/cppast/cpp_type.hpp b/include/cppast/cpp_type.hpp index 7da60ed..6db6695 100644 --- a/include/cppast/cpp_type.hpp +++ b/include/cppast/cpp_type.hpp @@ -434,6 +434,9 @@ namespace cppast // write prefix, variadic, name, suffix void write_type(code_generator::output& output, const cpp_type& type, std::string name, bool is_variadic = false); + + // simple to_string() for types + std::string to_string(const cpp_type& type); } // namespace detail } // namespace cppast diff --git a/src/cpp_function.cpp b/src/cpp_function.cpp index dec9e98..f3f492b 100644 --- a/src/cpp_function.cpp +++ b/src/cpp_function.cpp @@ -35,6 +35,22 @@ cpp_entity_kind cpp_function_parameter::do_get_entity_kind() const noexcept return kind(); } +std::string cpp_function_base::do_get_signature() const +{ + std::string result = "("; + for (auto& param : parameters()) + result += detail::to_string(param.type()) + ','; + if (is_variadic()) + result += "..."; + + if (result.back() == ',') + result.back() = ')'; + else + result.push_back(')'); + + return result; +} + cpp_entity_kind cpp_function::kind() noexcept { return cpp_entity_kind::function_t; diff --git a/src/cpp_member_function.cpp b/src/cpp_member_function.cpp index 1cf8fd4..dcfdbc9 100644 --- a/src/cpp_member_function.cpp +++ b/src/cpp_member_function.cpp @@ -8,6 +8,23 @@ using namespace cppast; +std::string cpp_member_function_base::do_get_signature() const +{ + auto result = cpp_function_base::do_get_signature(); + + if (is_const(cv_qualifier())) + result += " const"; + if (is_volatile(cv_qualifier())) + result += " volatile"; + + if (ref_qualifier() == cpp_ref_lvalue) + result += " &"; + else if (ref_qualifier() == cpp_ref_rvalue) + result += " &&"; + + return result; +} + cpp_entity_kind cpp_member_function::kind() noexcept { return cpp_entity_kind::member_function_t; diff --git a/src/cpp_type.cpp b/src/cpp_type.cpp index efd8d7a..53684af 100644 --- a/src/cpp_type.cpp +++ b/src/cpp_type.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include using namespace cppast; @@ -545,3 +546,37 @@ void detail::write_type(code_generator::output& output, const cpp_type& type, st output << operator_ws << punctuation("...") << operator_ws; write_type_suffix(output, type); } + +std::string detail::to_string(const cpp_type& type) +{ + class to_string_generator : public code_generator + { + public: + std::string get() + { + return std::move(result_); + } + + private: + void do_indent() override + { + } + + void do_unindent() override + { + } + + void do_write_token_seq(string_view tokens) override + { + result_ += tokens.c_str(); + } + + std::string result_; + } generator; + + // just a dummy type for the output + static auto dummy_entity = cpp_type_alias::build("foo", cpp_builtin_type::build(cpp_int)); + to_string_generator::output output(type_safe::ref(generator), type_safe::ref(*dummy_entity)); + write_type(output, type, ""); + return generator.get(); +} diff --git a/test/cpp_function.cpp b/test/cpp_function.cpp index a08b0cb..8789951 100644 --- a/test/cpp_function.cpp +++ b/test/cpp_function.cpp @@ -77,12 +77,13 @@ void ns::l() if (func.name() == "a") { REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void))); - REQUIRE(count_children(func.parameters()) == 0u); + REQUIRE(func.signature() == "()"); REQUIRE(!func.is_variadic()); } else if (func.name() == "b") { REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_int))); + REQUIRE(func.signature() == "(int,float*)"); auto count = 0u; for (auto& param : func.parameters()) @@ -122,6 +123,7 @@ void ns::l() cpp_ulonglong), "10")), cpp_ref_lvalue))); + REQUIRE(func.signature() == "(decltype(42),...)"); auto count = 0u; for (auto& param : func.parameters()) @@ -147,7 +149,7 @@ void ns::l() else if (func.name() == "d" || func.name() == "e" || func.name() == "f") { REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void))); - REQUIRE(count_children(func.parameters()) == 0u); + REQUIRE(func.signature() == "()"); REQUIRE(!func.is_variadic()); REQUIRE(func.storage_class() == cpp_storage_class_none); REQUIRE(!func.is_constexpr()); @@ -172,7 +174,7 @@ void ns::l() || func.name() == "j") { REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void))); - REQUIRE(count_children(func.parameters()) == 0u); + REQUIRE(func.signature() == "()"); REQUIRE(!func.is_variadic()); REQUIRE(!func.noexcept_condition()); check_body(func, cpp_function_declaration); @@ -201,7 +203,7 @@ void ns::l() else if (func.name() == "k" || func.name() == "l") { REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void))); - REQUIRE(count_children(func.parameters()) == 0u); + REQUIRE(func.signature() == "()"); REQUIRE(!func.is_variadic()); REQUIRE(!func.noexcept_condition()); REQUIRE(!func.is_constexpr()); @@ -247,7 +249,7 @@ void foo::a() {} auto file = parse(idx, "static_cpp_function.cpp", code); auto count = test_visit(*file, [&](const cpp_function& func) { REQUIRE(!func.is_variadic()); - REQUIRE(count_children(func.parameters()) == 0u); + REQUIRE(func.signature() == "()"); REQUIRE(func.storage_class() == cpp_storage_class_static); if (func.name() == "a") diff --git a/test/cpp_member_function.cpp b/test/cpp_member_function.cpp index f44b506..1f84780 100644 --- a/test/cpp_member_function.cpp +++ b/test/cpp_member_function.cpp @@ -57,10 +57,10 @@ struct bar : foo cpp_entity_index idx; auto file = parse(idx, "cpp_member_function.cpp", code); auto count = test_visit(*file, [&](const cpp_member_function& func) { - REQUIRE(count_children(func.parameters()) == 0u); REQUIRE(!func.is_variadic()); REQUIRE(!func.is_constexpr()); REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void))); + if (func.name() != "b" && func.name() != "d") REQUIRE(!func.noexcept_condition()); if (func.name() != "g" && func.name() != "h") @@ -74,6 +74,7 @@ struct bar : foo REQUIRE(func.is_definition()); REQUIRE(func.cv_qualifier() == cpp_cv_none); REQUIRE(func.ref_qualifier() == cpp_ref_none); + REQUIRE(func.signature() == "()"); } else if (func.name() == "b") { @@ -84,31 +85,37 @@ struct bar : foo "true"))); REQUIRE(func.cv_qualifier() == cpp_cv_none); REQUIRE(func.ref_qualifier() == cpp_ref_none); + REQUIRE(func.signature() == "()"); } else if (func.name() == "c") { REQUIRE(func.cv_qualifier() == cpp_cv_const); REQUIRE(func.ref_qualifier() == cpp_ref_none); + REQUIRE(func.signature() == "() const"); } else if (func.name() == "d") { REQUIRE(func.cv_qualifier() == cpp_cv_const_volatile); REQUIRE(func.ref_qualifier() == cpp_ref_none); + REQUIRE(func.signature() == "() const volatile"); } else if (func.name() == "e") { REQUIRE(func.cv_qualifier() == cpp_cv_none); REQUIRE(func.ref_qualifier() == cpp_ref_lvalue); + REQUIRE(func.signature() == "() &"); } else if (func.name() == "f") { REQUIRE(func.cv_qualifier() == cpp_cv_const_volatile); REQUIRE(func.ref_qualifier() == cpp_ref_rvalue); + REQUIRE(func.signature() == "() const volatile &&"); } else if (func.name() == "g") { REQUIRE(func.cv_qualifier() == cpp_cv_none); REQUIRE(func.ref_qualifier() == cpp_ref_none); + REQUIRE(func.signature() == "()"); REQUIRE(func.virtual_info()); if (func.parent().value().name() == "foo") REQUIRE(func.virtual_info().value() == type_safe::flag_set{}); @@ -124,6 +131,7 @@ struct bar : foo { REQUIRE(func.cv_qualifier() == cpp_cv_none); REQUIRE(func.ref_qualifier() == cpp_ref_none); + REQUIRE(func.signature() == "()"); REQUIRE(func.virtual_info()); if (func.parent().value().name() == "foo") REQUIRE(func.virtual_info().value() == cpp_virtual_flags::pure); @@ -137,12 +145,14 @@ struct bar : foo { REQUIRE(func.cv_qualifier() == cpp_cv_none); REQUIRE(func.ref_qualifier() == cpp_ref_none); + REQUIRE(func.signature() == "()"); REQUIRE(func.body_kind() == cpp_function_definition); } else if (func.name() == "j") { REQUIRE(func.cv_qualifier() == cpp_cv_none); REQUIRE(func.ref_qualifier() == cpp_ref_none); + REQUIRE(func.signature() == "()"); REQUIRE(func.body_kind() == cpp_function_deleted); } else @@ -207,16 +217,19 @@ struct foo *cpp_reference_type::build(cpp_builtin_type::build(cpp_int), cpp_ref_lvalue))); REQUIRE(op.cv_qualifier() == cpp_cv_none); + REQUIRE(op.signature() == "()"); } else if (op.is_explicit() && !op.is_constexpr()) { REQUIRE(op.name() == "operator bool"); REQUIRE(equal_types(idx, op.return_type(), *cpp_builtin_type::build(cpp_bool))); REQUIRE(op.cv_qualifier() == cpp_cv_const); + REQUIRE(op.signature() == "() const"); } else if (!op.is_explicit() && op.is_constexpr()) { REQUIRE(op.cv_qualifier() == cpp_cv_none); + REQUIRE(op.signature() == "()"); if (op.name() == "operator ns::type") { REQUIRE(op.return_type().kind() == cpp_type_kind::template_instantiation_t); @@ -316,6 +329,7 @@ foo::foo(int) {} REQUIRE(!cont.is_explicit()); REQUIRE(!cont.is_constexpr()); REQUIRE(cont.body_kind() == cpp_function_defaulted); + REQUIRE(cont.signature() == "()"); } else if (count_children(cont.parameters()) == 1u) { @@ -323,6 +337,7 @@ foo::foo(int) {} REQUIRE(cont.is_explicit()); REQUIRE(!cont.is_constexpr()); REQUIRE(cont.body_kind() == cpp_function_declaration); + REQUIRE(cont.signature() == "(int)"); } else if (count_children(cont.parameters()) == 2u) { @@ -330,6 +345,7 @@ foo::foo(int) {} REQUIRE(!cont.is_explicit()); REQUIRE(cont.is_constexpr()); REQUIRE(cont.body_kind() == cpp_function_deleted); + REQUIRE(cont.signature() == "(int,char)"); } else REQUIRE(false); @@ -372,7 +388,7 @@ d::~d() {} auto file = parse({}, "cpp_destructor.cpp", code); auto count = test_visit(*file, [&](const cpp_destructor& dtor) { - REQUIRE(count_children(dtor.parameters()) == 0u); + REQUIRE(dtor.signature() == "()"); REQUIRE(!dtor.is_variadic()); if (dtor.name() == "~a")