Add signature() to cpp_function_base

This commit is contained in:
Jonathan Müller 2017-07-10 19:26:55 +02:00
commit 93d2c58f7f
8 changed files with 112 additions and 22 deletions

View file

@ -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<cpp_function_parameter> parameters_;
std::unique_ptr<cpp_expression> noexcept_expr_;

View file

@ -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<cppast::cpp_virtual_flags> : 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<cpp_type> return_type_;
cpp_virtual virtual_;

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -9,6 +9,7 @@
#include <cppast/cpp_entity.hpp>
#include <cppast/cpp_entity_kind.hpp>
#include <cppast/cpp_function_type.hpp>
#include <cppast/cpp_type_alias.hpp>
#include <cppast/cpp_template.hpp>
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();
}

View file

@ -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<cpp_function>(*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")

View file

@ -57,10 +57,10 @@ struct bar : foo<int>
cpp_entity_index idx;
auto file = parse(idx, "cpp_member_function.cpp", code);
auto count = test_visit<cpp_member_function>(*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<int>
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<int>
"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<cpp_virtual_flags>{});
@ -124,6 +131,7 @@ struct bar : foo<int>
{
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<int>
{
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<int>")
{
REQUIRE(op.return_type().kind() == cpp_type_kind::template_instantiation_t);
@ -316,6 +329,7 @@ foo<T>::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<T>::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<T>::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<cpp_destructor>(*file, [&](const cpp_destructor& dtor) {
REQUIRE(count_children(dtor.parameters()) == 0u);
REQUIRE(dtor.signature() == "()");
REQUIRE(!dtor.is_variadic());
if (dtor.name() == "~a")