Fix code generation bugs
This commit is contained in:
commit
b924d8f8d5
3 changed files with 58 additions and 57 deletions
|
|
@ -157,6 +157,7 @@ namespace cppast
|
||||||
/// Flags that control the generation.
|
/// Flags that control the generation.
|
||||||
enum generation_flags
|
enum generation_flags
|
||||||
{
|
{
|
||||||
|
custom, //< A custom output is written.
|
||||||
exclude, //< Exclude the entire entity.
|
exclude, //< Exclude the entire entity.
|
||||||
exclude_return, //< Exclude the return type of a function entity.
|
exclude_return, //< Exclude the return type of a function entity.
|
||||||
exclude_target, //< Exclude the underlying entity of an alias (e.g. typedef).
|
exclude_target, //< Exclude the underlying entity of an alias (e.g. typedef).
|
||||||
|
|
@ -193,12 +194,10 @@ namespace cppast
|
||||||
|
|
||||||
output& operator=(const output&) = delete;
|
output& operator=(const output&) = delete;
|
||||||
|
|
||||||
/// \returns Whether or not the `on_XXX` function returned something other than `exclude`.
|
/// \returns Whether or not the `on_XXX` function returned something other than `exclude` or `custom`.
|
||||||
/// \notes If this returns `false`,
|
|
||||||
/// the other functions have no effects.
|
|
||||||
explicit operator bool() const noexcept
|
explicit operator bool() const noexcept
|
||||||
{
|
{
|
||||||
return !options_.is_set(exclude);
|
return !options_.is_set(exclude) && !options_.is_set(custom);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns The generation options.
|
/// \returns The generation options.
|
||||||
|
|
@ -234,19 +233,15 @@ namespace cppast
|
||||||
/// \effects Call `do_indent()` followed by `do_write_newline()` (if `print_newline` is `true`).
|
/// \effects Call `do_indent()` followed by `do_write_newline()` (if `print_newline` is `true`).
|
||||||
void indent(bool print_newline = true) const noexcept
|
void indent(bool print_newline = true) const noexcept
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_indent();
|
||||||
{
|
if (print_newline)
|
||||||
gen_->do_indent();
|
gen_->do_write_newline();
|
||||||
if (print_newline)
|
|
||||||
gen_->do_write_newline();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_unindent()`.
|
/// \effects Calls `do_unindent()`.
|
||||||
void unindent() const noexcept
|
void unindent() const noexcept
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_unindent();
|
||||||
gen_->do_unindent();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `func(*this)`.
|
/// \effects Calls `func(*this)`.
|
||||||
|
|
@ -259,16 +254,14 @@ namespace cppast
|
||||||
/// \effects Calls `do_write_keyword()`.
|
/// \effects Calls `do_write_keyword()`.
|
||||||
const output& operator<<(const keyword& k) const
|
const output& operator<<(const keyword& k) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_keyword(k.str());
|
||||||
gen_->do_write_keyword(k.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_identifier()`.
|
/// \effects Calls `do_write_identifier()`.
|
||||||
const output& operator<<(const identifier& ident) const
|
const output& operator<<(const identifier& ident) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_identifier(ident.str());
|
||||||
gen_->do_write_identifier(ident.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,88 +269,77 @@ namespace cppast
|
||||||
template <typename T, class Predicate>
|
template <typename T, class Predicate>
|
||||||
const output& operator<<(const basic_cpp_entity_ref<T, Predicate>& ref) const
|
const output& operator<<(const basic_cpp_entity_ref<T, Predicate>& ref) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_reference(ref.id(), ref.name());
|
||||||
gen_->do_write_reference(ref.id(), ref.name());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_punctuation()`.
|
/// \effects Calls `do_write_punctuation()`.
|
||||||
const output& operator<<(const punctuation& punct) const
|
const output& operator<<(const punctuation& punct) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_punctuation(punct.str());
|
||||||
gen_->do_write_punctuation(punct.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_str_literal`.
|
/// \effects Calls `do_write_str_literal`.
|
||||||
const output& operator<<(const string_literal& lit) const
|
const output& operator<<(const string_literal& lit) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_str_literal(lit.str());
|
||||||
gen_->do_write_str_literal(lit.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_int_literal()`.
|
/// \effects Calls `do_write_int_literal()`.
|
||||||
const output& operator<<(const int_literal& lit) const
|
const output& operator<<(const int_literal& lit) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_int_literal(lit.str());
|
||||||
gen_->do_write_int_literal(lit.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_float_literal()`.
|
/// \effects Calls `do_write_float_literal()`.
|
||||||
const output& operator<<(const float_literal& lit) const
|
const output& operator<<(const float_literal& lit) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_float_literal(lit.str());
|
||||||
gen_->do_write_float_literal(lit.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_preprocessor()`.
|
/// \effects Calls `do_write_preprocessor()`.
|
||||||
const output& operator<<(const preprocessor_token& tok) const
|
const output& operator<<(const preprocessor_token& tok) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_preprocessor(tok.str());
|
||||||
gen_->do_write_preprocessor(tok.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_comment()`.
|
/// \effects Calls `do_write_comment()`.
|
||||||
const output& operator<<(const comment& c) const
|
const output& operator<<(const comment& c) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_comment(c.str());
|
||||||
gen_->do_write_comment(c.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_token_seq()`.
|
/// \effects Calls `do_write_token_seq()`.
|
||||||
const output& operator<<(const token_seq& seq) const
|
const output& operator<<(const token_seq& seq) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_token_seq(seq.str());
|
||||||
gen_->do_write_token_seq(seq.str());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_excluded()`.
|
/// \effects Calls `do_write_excluded()`.
|
||||||
const output& excluded(const cpp_entity& e) const
|
const output& excluded(const cpp_entity& e) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_excluded(e);
|
||||||
gen_->do_write_excluded(e);
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_newline()`.
|
/// \effects Calls `do_write_newline()`.
|
||||||
const output& operator<<(newl_t) const
|
const output& operator<<(newl_t) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_newline();
|
||||||
gen_->do_write_newline();
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \effects Calls `do_write_whitespace()`.
|
/// \effects Calls `do_write_whitespace()`.
|
||||||
const output& operator<<(whitespace_t) const
|
const output& operator<<(whitespace_t) const
|
||||||
{
|
{
|
||||||
if (*this)
|
gen_->do_write_whitespace();
|
||||||
gen_->do_write_whitespace();
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -376,6 +358,12 @@ namespace cppast
|
||||||
return main_entity_.value();
|
return main_entity_.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \effects Generates the code for the specified entity.
|
||||||
|
/// It can be used to generate additional entities while generating another one.
|
||||||
|
/// \returns Whether or not any code was generated.
|
||||||
|
/// \notes This does not affect the main entity, but otherwise behaves just like [cppast::generate_code()]().
|
||||||
|
bool generate_code(const cpp_entity& entity);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// \returns The formatting options that should be used.
|
/// \returns The formatting options that should be used.
|
||||||
/// The base class version has no flags set.
|
/// The base class version has no flags set.
|
||||||
|
|
|
||||||
|
|
@ -66,9 +66,13 @@ namespace
|
||||||
auto need_sep = false;
|
auto need_sep = false;
|
||||||
for (auto& child : cont)
|
for (auto& child : cont)
|
||||||
{
|
{
|
||||||
if (need_sep)
|
auto is_excluded = output.options(child, cur_access).is_set(code_generator::exclude);
|
||||||
output << s;
|
if (!is_excluded)
|
||||||
need_sep = generate_code_impl(*output.generator(), child, cur_access);
|
{
|
||||||
|
if (need_sep)
|
||||||
|
output << s;
|
||||||
|
need_sep = generate_code_impl(*output.generator(), child, cur_access);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return need_sep;
|
return need_sep;
|
||||||
}
|
}
|
||||||
|
|
@ -636,15 +640,15 @@ namespace
|
||||||
case cpp_cv_none:
|
case cpp_cv_none:
|
||||||
break;
|
break;
|
||||||
case cpp_cv_const:
|
case cpp_cv_const:
|
||||||
output << keyword("const");
|
output << operator_ws << keyword("const");
|
||||||
need_ws = true;
|
need_ws = true;
|
||||||
break;
|
break;
|
||||||
case cpp_cv_volatile:
|
case cpp_cv_volatile:
|
||||||
output << keyword("volatile");
|
output << operator_ws << keyword("volatile");
|
||||||
need_ws = true;
|
need_ws = true;
|
||||||
break;
|
break;
|
||||||
case cpp_cv_const_volatile:
|
case cpp_cv_const_volatile:
|
||||||
output << keyword("const") << whitespace << keyword("volatile");
|
output << operator_ws << keyword("const") << whitespace << keyword("volatile");
|
||||||
need_ws = true;
|
need_ws = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -654,11 +658,11 @@ namespace
|
||||||
case cpp_ref_none:
|
case cpp_ref_none:
|
||||||
break;
|
break;
|
||||||
case cpp_ref_lvalue:
|
case cpp_ref_lvalue:
|
||||||
output << operator_ws << punctuation("&") << operator_ws;
|
output << operator_ws << punctuation("&");
|
||||||
need_ws = false;
|
need_ws = false;
|
||||||
break;
|
break;
|
||||||
case cpp_ref_rvalue:
|
case cpp_ref_rvalue:
|
||||||
output << operator_ws << punctuation("&&") << operator_ws;
|
output << operator_ws << punctuation("&&");
|
||||||
need_ws = false;
|
need_ws = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -905,23 +909,25 @@ namespace
|
||||||
if (!hide_if_empty)
|
if (!hide_if_empty)
|
||||||
output << keyword("template") << operator_ws << punctuation("<") << bracket_ws;
|
output << keyword("template") << operator_ws << punctuation("<") << bracket_ws;
|
||||||
|
|
||||||
auto need_sep = false;
|
auto need_sep = false;
|
||||||
auto first = hide_if_empty;
|
auto need_header = hide_if_empty;
|
||||||
for (auto& param : templ.parameters())
|
for (auto& param : templ.parameters())
|
||||||
{
|
{
|
||||||
if (first
|
auto is_excluded = output.options(param, cpp_public).is_set(code_generator::exclude);
|
||||||
&& !output.options(*templ.parameters().begin(), cpp_public)
|
if (!is_excluded)
|
||||||
.is_set(code_generator::exclude))
|
|
||||||
{
|
{
|
||||||
first = false;
|
if (need_header)
|
||||||
output << keyword("template") << operator_ws << punctuation("<") << bracket_ws;
|
{
|
||||||
|
need_header = false;
|
||||||
|
output << keyword("template") << operator_ws << punctuation("<") << bracket_ws;
|
||||||
|
}
|
||||||
|
else if (need_sep)
|
||||||
|
output << comma;
|
||||||
|
need_sep = generate_code_impl(*output.generator(), param, cpp_public);
|
||||||
}
|
}
|
||||||
else if (need_sep)
|
|
||||||
output << comma;
|
|
||||||
need_sep = generate_code_impl(*output.generator(), param, cpp_public);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hide_if_empty || need_sep)
|
if (!need_header)
|
||||||
output << bracket_ws << punctuation(">") << newl;
|
output << bracket_ws << punctuation(">") << newl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1097,6 +1103,11 @@ namespace
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool code_generator::generate_code(const cpp_entity& entity)
|
||||||
|
{
|
||||||
|
return generate_code_impl(*this, entity, cpp_public);
|
||||||
|
}
|
||||||
|
|
||||||
bool cppast::generate_code(code_generator& generator, const cpp_entity& e)
|
bool cppast::generate_code(code_generator& generator, const cpp_entity& e)
|
||||||
{
|
{
|
||||||
generator.main_entity_ = type_safe::ref(e);
|
generator.main_entity_ = type_safe::ref(e);
|
||||||
|
|
|
||||||
|
|
@ -438,6 +438,8 @@ namespace
|
||||||
if (spelling.empty() || spelling.back() != '>')
|
if (spelling.empty() || spelling.back() != '>')
|
||||||
return nullptr;
|
return nullptr;
|
||||||
spelling.pop_back();
|
spelling.pop_back();
|
||||||
|
while (!spelling.empty() && spelling.back() == ' ')
|
||||||
|
spelling.pop_back();
|
||||||
builder.add_unexposed_arguments(ptr);
|
builder.add_unexposed_arguments(ptr);
|
||||||
|
|
||||||
return builder.finish();
|
return builder.finish();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue