Add semantic parent to forward declarable entities
This commit is contained in:
parent
cf7ea80768
commit
599f2bbff8
20 changed files with 260 additions and 109 deletions
|
|
@ -178,7 +178,8 @@ namespace cppast
|
||||||
/// \effects Registers the class in the [cppast::cpp_entity_index](),
|
/// \effects Registers the class in the [cppast::cpp_entity_index](),
|
||||||
/// using the given [cppast::cpp_entity_id]().
|
/// using the given [cppast::cpp_entity_id]().
|
||||||
/// \returns The finished class.
|
/// \returns The finished class.
|
||||||
std::unique_ptr<cpp_class> finish(const cpp_entity_index& idx, cpp_entity_id id);
|
std::unique_ptr<cpp_class> finish(const cpp_entity_index& idx, cpp_entity_id id,
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent);
|
||||||
|
|
||||||
/// \effects Marks the class as forward declaration.
|
/// \effects Marks the class as forward declaration.
|
||||||
/// \returns The finished class.
|
/// \returns The finished class.
|
||||||
|
|
@ -187,7 +188,7 @@ namespace cppast
|
||||||
|
|
||||||
/// \effects Returns the finished class without registering it.
|
/// \effects Returns the finished class without registering it.
|
||||||
/// \notes This is intended for templated classes only.
|
/// \notes This is intended for templated classes only.
|
||||||
std::unique_ptr<cpp_class> finish();
|
std::unique_ptr<cpp_class> finish(type_safe::optional<cpp_entity_ref> semantic_parent);
|
||||||
|
|
||||||
/// \effects Returns the finish class without registering it and marks it as forward declaration.
|
/// \effects Returns the finish class without registering it and marks it as forward declaration.
|
||||||
/// \notes This is intended for templated classes only.
|
/// \notes This is intended for templated classes only.
|
||||||
|
|
|
||||||
|
|
@ -85,8 +85,11 @@ namespace cppast
|
||||||
/// \effects Registers the enum in the [cppast::cpp_entity_index](),
|
/// \effects Registers the enum in the [cppast::cpp_entity_index](),
|
||||||
/// using the given [cppast::cpp_entity_id]().
|
/// using the given [cppast::cpp_entity_id]().
|
||||||
/// \returns The finished enum.
|
/// \returns The finished enum.
|
||||||
std::unique_ptr<cpp_enum> finish(const cpp_entity_index& idx, cpp_entity_id id) noexcept
|
std::unique_ptr<cpp_enum> finish(
|
||||||
|
const cpp_entity_index& idx, cpp_entity_id id,
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent) noexcept
|
||||||
{
|
{
|
||||||
|
enum_->set_semantic_parent(std::move(semantic_parent));
|
||||||
idx.register_definition(std::move(id), type_safe::ref(*enum_));
|
idx.register_definition(std::move(id), type_safe::ref(*enum_));
|
||||||
return std::move(enum_);
|
return std::move(enum_);
|
||||||
}
|
}
|
||||||
|
|
@ -96,7 +99,7 @@ namespace cppast
|
||||||
std::unique_ptr<cpp_enum> finish_declaration(const cpp_entity_index& idx,
|
std::unique_ptr<cpp_enum> finish_declaration(const cpp_entity_index& idx,
|
||||||
cpp_entity_id definition_id) noexcept
|
cpp_entity_id definition_id) noexcept
|
||||||
{
|
{
|
||||||
enum_->set_definition(definition_id);
|
enum_->mark_declaration(definition_id);
|
||||||
idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*enum_));
|
idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*enum_));
|
||||||
return std::move(enum_);
|
return std::move(enum_);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,22 @@ namespace cppast
|
||||||
return definition_;
|
return definition_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \returns A reference to the semantic parent of the entity.
|
||||||
|
/// This applies only to out-of-line definitions
|
||||||
|
/// and is the entity which owns the declaration.
|
||||||
|
const type_safe::optional<cpp_entity_ref>& semantic_parent() const noexcept
|
||||||
|
{
|
||||||
|
return semantic_parent_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \returns The name of the semantic parent, if it has own,
|
||||||
|
/// else the empty string.
|
||||||
|
/// \notes This may include template parameters.
|
||||||
|
std::string semantic_scope() const noexcept
|
||||||
|
{
|
||||||
|
return semantic_parent_.map(&cpp_entity_ref::name).value_or("");
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// \effects Marks the entity as definition.
|
/// \effects Marks the entity as definition.
|
||||||
/// \notes If it is not a definition,
|
/// \notes If it is not a definition,
|
||||||
|
|
@ -49,14 +65,21 @@ namespace cppast
|
||||||
|
|
||||||
~cpp_forward_declarable() noexcept = default;
|
~cpp_forward_declarable() noexcept = default;
|
||||||
|
|
||||||
/// \effects Sets the definition of the entity,
|
/// \effects Sets the definition entity,
|
||||||
/// marking it as a forward declaration.
|
/// marking it as a forward declaration.
|
||||||
void set_definition(cpp_entity_id def) noexcept
|
void mark_declaration(cpp_entity_id def) noexcept
|
||||||
{
|
{
|
||||||
definition_ = std::move(def);
|
definition_ = std::move(def);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \effects Sets the semantic parent of the entity.
|
||||||
|
void set_semantic_parent(type_safe::optional<cpp_entity_ref> semantic_parent) noexcept
|
||||||
|
{
|
||||||
|
semantic_parent_ = std::move(semantic_parent);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent_;
|
||||||
type_safe::optional<cpp_entity_id> definition_;
|
type_safe::optional<cpp_entity_id> definition_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -137,14 +137,16 @@ namespace cppast
|
||||||
/// Else marks it as a declaration.
|
/// Else marks it as a declaration.
|
||||||
/// \returns The finished function.
|
/// \returns The finished function.
|
||||||
std::unique_ptr<T> finish(const cpp_entity_index& idx, cpp_entity_id id,
|
std::unique_ptr<T> finish(const cpp_entity_index& idx, cpp_entity_id id,
|
||||||
cpp_function_body_kind body_kind)
|
cpp_function_body_kind body_kind,
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||||
{
|
{
|
||||||
function->body_ = body_kind;
|
function->body_ = body_kind;
|
||||||
|
function->set_semantic_parent(std::move(semantic_parent));
|
||||||
if (cppast::is_definition(body_kind))
|
if (cppast::is_definition(body_kind))
|
||||||
idx.register_definition(std::move(id), type_safe::ref(*function));
|
idx.register_definition(std::move(id), type_safe::ref(*function));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
function->set_definition(id);
|
function->mark_declaration(id);
|
||||||
idx.register_forward_declaration(std::move(id), type_safe::ref(*function));
|
idx.register_forward_declaration(std::move(id), type_safe::ref(*function));
|
||||||
}
|
}
|
||||||
return std::move(function);
|
return std::move(function);
|
||||||
|
|
@ -152,11 +154,13 @@ namespace cppast
|
||||||
|
|
||||||
/// \returns The finished function without registering it.
|
/// \returns The finished function without registering it.
|
||||||
/// \notes This is intended for templated functions only.
|
/// \notes This is intended for templated functions only.
|
||||||
std::unique_ptr<T> finish(cpp_entity_id id, cpp_function_body_kind body_kind)
|
std::unique_ptr<T> finish(cpp_entity_id id, cpp_function_body_kind body_kind,
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||||
{
|
{
|
||||||
if (!cppast::is_definition(body_kind))
|
|
||||||
function->set_definition(id);
|
|
||||||
function->body_ = body_kind;
|
function->body_ = body_kind;
|
||||||
|
function->set_semantic_parent(std::move(semantic_parent));
|
||||||
|
if (!cppast::is_definition(body_kind))
|
||||||
|
function->mark_declaration(id);
|
||||||
return std::move(function);
|
return std::move(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ namespace
|
||||||
output << keyword("enum");
|
output << keyword("enum");
|
||||||
if (e.is_scoped())
|
if (e.is_scoped())
|
||||||
output << whitespace << keyword("class");
|
output << whitespace << keyword("class");
|
||||||
output << whitespace << identifier(e.name());
|
output << whitespace << identifier(e.semantic_scope()) << identifier(e.name());
|
||||||
if (e.has_explicit_type())
|
if (e.has_explicit_type())
|
||||||
{
|
{
|
||||||
output << newl << punctuation(":");
|
output << newl << punctuation(":");
|
||||||
|
|
@ -285,6 +285,7 @@ namespace
|
||||||
output << keyword("friend") << whitespace;
|
output << keyword("friend") << whitespace;
|
||||||
output << keyword(to_string(c.class_kind())) << whitespace;
|
output << keyword(to_string(c.class_kind())) << whitespace;
|
||||||
|
|
||||||
|
output << identifier(c.semantic_scope());
|
||||||
if (spec)
|
if (spec)
|
||||||
{
|
{
|
||||||
output << spec.value().primary_template();
|
output << spec.value().primary_template();
|
||||||
|
|
@ -492,6 +493,7 @@ namespace
|
||||||
output << whitespace;
|
output << whitespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output << identifier(func.semantic_scope());
|
||||||
if (spec)
|
if (spec)
|
||||||
{
|
{
|
||||||
output << spec.value().primary_template();
|
output << spec.value().primary_template();
|
||||||
|
|
@ -585,6 +587,7 @@ namespace
|
||||||
output << whitespace;
|
output << whitespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output << identifier(func.semantic_scope());
|
||||||
if (spec)
|
if (spec)
|
||||||
{
|
{
|
||||||
output << spec.value().primary_template();
|
output << spec.value().primary_template();
|
||||||
|
|
@ -621,6 +624,8 @@ namespace
|
||||||
else
|
else
|
||||||
write_prefix_virtual(output, op.virtual_info());
|
write_prefix_virtual(output, op.virtual_info());
|
||||||
|
|
||||||
|
output << identifier(op.semantic_scope());
|
||||||
|
|
||||||
auto pos = op.name().find("operator");
|
auto pos = op.name().find("operator");
|
||||||
output << identifier(op.name().substr(0u, pos)) << keyword("operator") << whitespace;
|
output << identifier(op.name().substr(0u, pos)) << keyword("operator") << whitespace;
|
||||||
detail::write_type(output, op.return_type(), "");
|
detail::write_type(output, op.return_type(), "");
|
||||||
|
|
@ -645,7 +650,7 @@ namespace
|
||||||
if (ctor.is_constexpr())
|
if (ctor.is_constexpr())
|
||||||
output << keyword("constexpr") << whitespace;
|
output << keyword("constexpr") << whitespace;
|
||||||
|
|
||||||
output << identifier(ctor.name());
|
output << identifier(ctor.semantic_scope()) << identifier(ctor.name());
|
||||||
write_function_parameters(output, ctor);
|
write_function_parameters(output, ctor);
|
||||||
write_noexcept(output, ctor, false);
|
write_noexcept(output, ctor, false);
|
||||||
|
|
||||||
|
|
@ -661,7 +666,8 @@ namespace
|
||||||
if (is_friended(dtor))
|
if (is_friended(dtor))
|
||||||
output << keyword("friend") << whitespace;
|
output << keyword("friend") << whitespace;
|
||||||
write_prefix_virtual(output, dtor.virtual_info());
|
write_prefix_virtual(output, dtor.virtual_info());
|
||||||
output << identifier(dtor.name()) << punctuation("(") << punctuation(")");
|
output << identifier(dtor.semantic_scope()) << identifier(dtor.name())
|
||||||
|
<< punctuation("(") << punctuation(")");
|
||||||
write_noexcept(output, dtor, false);
|
write_noexcept(output, dtor, false);
|
||||||
|
|
||||||
write_suffix_virtual(output, dtor.virtual_info());
|
write_suffix_virtual(output, dtor.virtual_info());
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,11 @@
|
||||||
|
|
||||||
using namespace cppast;
|
using namespace cppast;
|
||||||
|
|
||||||
std::unique_ptr<cpp_class> cpp_class::builder::finish(const cpp_entity_index& idx, cpp_entity_id id)
|
std::unique_ptr<cpp_class> cpp_class::builder::finish(
|
||||||
|
const cpp_entity_index& idx, cpp_entity_id id,
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||||
{
|
{
|
||||||
|
class_->set_semantic_parent(std::move(semantic_parent));
|
||||||
idx.register_definition(std::move(id), type_safe::ref(*class_));
|
idx.register_definition(std::move(id), type_safe::ref(*class_));
|
||||||
return std::move(class_);
|
return std::move(class_);
|
||||||
}
|
}
|
||||||
|
|
@ -18,19 +21,21 @@ std::unique_ptr<cpp_class> cpp_class::builder::finish(const cpp_entity_index& id
|
||||||
std::unique_ptr<cpp_class> cpp_class::builder::finish_declaration(const cpp_entity_index& idx,
|
std::unique_ptr<cpp_class> cpp_class::builder::finish_declaration(const cpp_entity_index& idx,
|
||||||
cpp_entity_id definition_id)
|
cpp_entity_id definition_id)
|
||||||
{
|
{
|
||||||
class_->set_definition(definition_id);
|
class_->mark_declaration(definition_id);
|
||||||
idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*class_));
|
idx.register_forward_declaration(std::move(definition_id), type_safe::ref(*class_));
|
||||||
return std::move(class_);
|
return std::move(class_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_class> cpp_class::builder::finish()
|
std::unique_ptr<cpp_class> cpp_class::builder::finish(
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||||
{
|
{
|
||||||
|
class_->set_semantic_parent(std::move(semantic_parent));
|
||||||
return std::move(class_);
|
return std::move(class_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_class> cpp_class::builder::finish_declaration(cpp_entity_id definition_id)
|
std::unique_ptr<cpp_class> cpp_class::builder::finish_declaration(cpp_entity_id definition_id)
|
||||||
{
|
{
|
||||||
class_->set_definition(definition_id);
|
class_->mark_declaration(definition_id);
|
||||||
return std::move(class_);
|
return std::move(class_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ std::unique_ptr<cpp_variable> cpp_variable::build_declaration(cpp_entity_id defi
|
||||||
{
|
{
|
||||||
auto result = std::unique_ptr<cpp_variable>(
|
auto result = std::unique_ptr<cpp_variable>(
|
||||||
new cpp_variable(std::move(name), std::move(type), nullptr, spec, is_constexpr));
|
new cpp_variable(std::move(name), std::move(type), nullptr, spec, is_constexpr));
|
||||||
result->set_definition(definition_id);
|
result->mark_declaration(definition_id);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,33 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_class(const detail::parse_context&
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto builder = make_class_builder(cur);
|
auto builder = make_class_builder(cur);
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent;
|
||||||
if (!is_friend)
|
if (!is_friend)
|
||||||
{
|
{
|
||||||
|
if (!clang_equalCursors(clang_getCursorSemanticParent(cur),
|
||||||
|
clang_getCursorLexicalParent(cur)))
|
||||||
|
{
|
||||||
|
// out-of-line definition
|
||||||
|
detail::tokenizer tokenizer(context.tu, context.file, cur);
|
||||||
|
detail::token_stream stream(tokenizer, cur);
|
||||||
|
|
||||||
|
std::string name = detail::get_cursor_name(cur).c_str();
|
||||||
|
auto pos = name.find('<');
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
name.erase(pos, std::string::npos);
|
||||||
|
|
||||||
|
std::string scope;
|
||||||
|
while (!detail::skip_if(stream, name.c_str()))
|
||||||
|
{
|
||||||
|
if (!detail::append_scope(stream, scope))
|
||||||
|
stream.bump();
|
||||||
|
}
|
||||||
|
if (!scope.empty())
|
||||||
|
semantic_parent =
|
||||||
|
cpp_entity_ref(detail::get_entity_id(clang_getCursorSemanticParent(cur)),
|
||||||
|
std::move(scope));
|
||||||
|
}
|
||||||
|
|
||||||
context.comments.match(builder.get(), cur);
|
context.comments.match(builder.get(), cur);
|
||||||
detail::visit_children(cur, [&](const CXCursor& child) {
|
detail::visit_children(cur, [&](const CXCursor& child) {
|
||||||
auto kind = clang_getCursorKind(child);
|
auto kind = clang_getCursorKind(child);
|
||||||
|
|
@ -123,7 +148,9 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_class(const detail::parse_context&
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_friend && clang_isCursorDefinition(cur))
|
if (!is_friend && clang_isCursorDefinition(cur))
|
||||||
return is_templated ? builder.finish() : builder.finish(*context.idx, get_entity_id(cur));
|
return is_templated ?
|
||||||
|
builder.finish(std::move(semantic_parent)) :
|
||||||
|
builder.finish(*context.idx, get_entity_id(cur), std::move(semantic_parent));
|
||||||
else
|
else
|
||||||
return is_templated ? builder.finish_declaration(detail::get_entity_id(cur)) :
|
return is_templated ? builder.finish_declaration(detail::get_entity_id(cur)) :
|
||||||
builder.finish_declaration(*context.idx, get_entity_id(cur));
|
builder.finish_declaration(*context.idx, get_entity_id(cur));
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,10 @@ namespace
|
||||||
std::move(value));
|
std::move(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
cpp_enum::builder make_enum_builder(const detail::parse_context& context, const CXCursor& cur)
|
cpp_enum::builder make_enum_builder(const detail::parse_context& context, const CXCursor& cur,
|
||||||
|
type_safe::optional<cpp_entity_ref>& semantic_parent)
|
||||||
{
|
{
|
||||||
|
auto name = detail::get_cursor_name(cur);
|
||||||
detail::tokenizer tokenizer(context.tu, context.file, cur);
|
detail::tokenizer tokenizer(context.tu, context.file, cur);
|
||||||
detail::token_stream stream(tokenizer, cur);
|
detail::token_stream stream(tokenizer, cur);
|
||||||
|
|
||||||
|
|
@ -51,7 +53,15 @@ namespace
|
||||||
detail::skip(stream, "enum");
|
detail::skip(stream, "enum");
|
||||||
auto scoped = detail::skip_if(stream, "class");
|
auto scoped = detail::skip_if(stream, "class");
|
||||||
detail::skip_attribute(stream);
|
detail::skip_attribute(stream);
|
||||||
auto& name = stream.get().value();
|
std::string scope;
|
||||||
|
while (!detail::skip_if(stream, name.c_str()))
|
||||||
|
if (!detail::append_scope(stream, scope))
|
||||||
|
DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur,
|
||||||
|
"unexpected tokens in enum name");
|
||||||
|
if (!scope.empty())
|
||||||
|
semantic_parent =
|
||||||
|
cpp_entity_ref(detail::get_entity_id(clang_getCursorSemanticParent(cur)),
|
||||||
|
std::move(scope));
|
||||||
|
|
||||||
// parse type
|
// parse type
|
||||||
auto type = detail::parse_type(context, cur, clang_getEnumDeclIntegerType(cur));
|
auto type = detail::parse_type(context, cur, clang_getEnumDeclIntegerType(cur));
|
||||||
|
|
@ -66,7 +76,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_enum(const detail::parse_context&
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT(cur.kind == CXCursor_EnumDecl, detail::assert_handler{});
|
DEBUG_ASSERT(cur.kind == CXCursor_EnumDecl, detail::assert_handler{});
|
||||||
|
|
||||||
auto builder = make_enum_builder(context, cur);
|
type_safe::optional<cpp_entity_ref> semantic_parent;
|
||||||
|
auto builder = make_enum_builder(context, cur, semantic_parent);
|
||||||
context.comments.match(builder.get(), cur);
|
context.comments.match(builder.get(), cur);
|
||||||
detail::visit_children(cur, [&](const CXCursor& child) {
|
detail::visit_children(cur, [&](const CXCursor& child) {
|
||||||
try
|
try
|
||||||
|
|
@ -82,7 +93,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_enum(const detail::parse_context&
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (clang_isCursorDefinition(cur))
|
if (clang_isCursorDefinition(cur))
|
||||||
return builder.finish(*context.idx, get_entity_id(cur));
|
return builder.finish(*context.idx, get_entity_id(cur), std::move(semantic_parent));
|
||||||
else
|
else
|
||||||
return builder.finish_declaration(*context.idx, get_entity_id(cur));
|
return builder.finish_declaration(*context.idx, get_entity_id(cur));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -75,10 +75,13 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_friend(const detail::parse_context
|
||||||
else if (clang_isDeclaration(kind))
|
else if (clang_isDeclaration(kind))
|
||||||
{
|
{
|
||||||
entity = parse_entity(context, child);
|
entity = parse_entity(context, child);
|
||||||
|
if (entity)
|
||||||
|
{
|
||||||
// steal comment
|
// steal comment
|
||||||
comment = type_safe::copy(entity->comment()).value_or("");
|
comment = type_safe::copy(entity->comment()).value_or("");
|
||||||
entity->set_comment(type_safe::nullopt);
|
entity->set_comment(type_safe::nullopt);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if (inst_builder && clang_isExpression(kind))
|
else if (inst_builder && clang_isExpression(kind))
|
||||||
{
|
{
|
||||||
namespace_str.clear();
|
namespace_str.clear();
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ namespace
|
||||||
// just the tokens occurring in the prefix
|
// just the tokens occurring in the prefix
|
||||||
struct prefix_info
|
struct prefix_info
|
||||||
{
|
{
|
||||||
std::string scope_name;
|
type_safe::optional<cpp_entity_ref> semantic_parent;
|
||||||
bool is_constexpr = false;
|
bool is_constexpr = false;
|
||||||
bool is_virtual = false;
|
bool is_virtual = false;
|
||||||
bool is_explicit = false;
|
bool is_explicit = false;
|
||||||
|
|
@ -153,38 +153,18 @@ namespace
|
||||||
result.is_explicit = true;
|
result.is_explicit = true;
|
||||||
scope.clear();
|
scope.clear();
|
||||||
}
|
}
|
||||||
// add identifiers and "::" to current scope name,
|
else if (!detail::append_scope(stream, scope))
|
||||||
// clear if there is any other token in between, or mismatched combination
|
|
||||||
else if (stream.peek().kind() == CXToken_Identifier)
|
|
||||||
{
|
|
||||||
if (!scope.empty() && scope.back() != ':')
|
|
||||||
scope.clear();
|
|
||||||
scope += stream.get().c_str();
|
|
||||||
}
|
|
||||||
else if (stream.peek() == "::")
|
|
||||||
{
|
|
||||||
if (!scope.empty() && scope.back() == ':')
|
|
||||||
scope.clear();
|
|
||||||
scope += stream.get().c_str();
|
|
||||||
}
|
|
||||||
else if (stream.peek() == "<")
|
|
||||||
{
|
|
||||||
auto iter = detail::find_closing_bracket(stream);
|
|
||||||
scope += detail::to_string(stream, iter);
|
|
||||||
if (!detail::skip_if(stream, ">>"))
|
|
||||||
detail::skip(stream, ">");
|
|
||||||
scope += ">";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stream.bump();
|
stream.bump();
|
||||||
scope.clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
DEBUG_ASSERT(!stream.done(), detail::parse_error_handler{}, stream.cursor(),
|
DEBUG_ASSERT(!stream.done(), detail::parse_error_handler{}, stream.cursor(),
|
||||||
"unable to find end of function prefix");
|
"unable to find end of function prefix");
|
||||||
if (!scope.empty() && scope.back() == ':')
|
if (!scope.empty() && scope.back() == ':')
|
||||||
result.scope_name = std::move(scope);
|
{
|
||||||
|
result.semantic_parent =
|
||||||
|
cpp_entity_ref(detail::get_entity_id(
|
||||||
|
clang_getCursorSemanticParent(stream.cursor())),
|
||||||
|
std::move(scope));
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -392,7 +372,7 @@ namespace
|
||||||
DEBUG_ASSERT(!prefix.is_virtual && !prefix.is_explicit, detail::parse_error_handler{}, cur,
|
DEBUG_ASSERT(!prefix.is_virtual && !prefix.is_explicit, detail::parse_error_handler{}, cur,
|
||||||
"free function cannot be virtual or explicit");
|
"free function cannot be virtual or explicit");
|
||||||
|
|
||||||
cpp_function::builder builder(prefix.scope_name + name.c_str(),
|
cpp_function::builder builder(name.c_str(),
|
||||||
detail::parse_type(context, cur,
|
detail::parse_type(context, cur,
|
||||||
clang_getCursorResultType(cur)));
|
clang_getCursorResultType(cur)));
|
||||||
context.comments.match(builder.get(), cur);
|
context.comments.match(builder.get(), cur);
|
||||||
|
|
@ -413,9 +393,11 @@ namespace
|
||||||
builder.noexcept_condition(std::move(suffix.noexcept_condition));
|
builder.noexcept_condition(std::move(suffix.noexcept_condition));
|
||||||
|
|
||||||
if (is_templated_cursor(cur))
|
if (is_templated_cursor(cur))
|
||||||
return builder.finish(detail::get_entity_id(cur), suffix.body_kind);
|
return builder.finish(detail::get_entity_id(cur), suffix.body_kind,
|
||||||
|
std::move(prefix.semantic_parent));
|
||||||
else
|
else
|
||||||
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind);
|
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind,
|
||||||
|
std::move(prefix.semantic_parent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -425,6 +407,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_function(const detail::parse_conte
|
||||||
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_FunctionDecl
|
DEBUG_ASSERT(clang_getCursorKind(cur) == CXCursor_FunctionDecl
|
||||||
|| clang_getTemplateCursorKind(cur) == CXCursor_FunctionDecl,
|
|| clang_getTemplateCursorKind(cur) == CXCursor_FunctionDecl,
|
||||||
detail::assert_handler{});
|
detail::assert_handler{});
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent;
|
||||||
return parse_cpp_function_impl(context, cur, false);
|
return parse_cpp_function_impl(context, cur, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -510,7 +493,8 @@ namespace
|
||||||
template <class Builder>
|
template <class Builder>
|
||||||
std::unique_ptr<cpp_entity> handle_suffix(const detail::parse_context& context,
|
std::unique_ptr<cpp_entity> handle_suffix(const detail::parse_context& context,
|
||||||
const CXCursor& cur, Builder& builder,
|
const CXCursor& cur, Builder& builder,
|
||||||
detail::token_stream& stream, bool is_virtual)
|
detail::token_stream& stream, bool is_virtual,
|
||||||
|
type_safe::optional<cpp_entity_ref> semantic_parent)
|
||||||
{
|
{
|
||||||
auto allow_qualifiers = set_qualifier(0, builder, cpp_cv_none, cpp_ref_none);
|
auto allow_qualifiers = set_qualifier(0, builder, cpp_cv_none, cpp_ref_none);
|
||||||
|
|
||||||
|
|
@ -522,9 +506,11 @@ namespace
|
||||||
builder.virtual_info(virt.value());
|
builder.virtual_info(virt.value());
|
||||||
|
|
||||||
if (is_templated_cursor(cur))
|
if (is_templated_cursor(cur))
|
||||||
return builder.finish(detail::get_entity_id(cur), suffix.body_kind);
|
return builder.finish(detail::get_entity_id(cur), suffix.body_kind,
|
||||||
|
std::move(semantic_parent));
|
||||||
else
|
else
|
||||||
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind);
|
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind,
|
||||||
|
std::move(semantic_parent));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -543,7 +529,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_member_function(const detail::pars
|
||||||
DEBUG_ASSERT(!prefix.is_explicit, detail::parse_error_handler{}, cur,
|
DEBUG_ASSERT(!prefix.is_explicit, detail::parse_error_handler{}, cur,
|
||||||
"member function cannot be explicit");
|
"member function cannot be explicit");
|
||||||
|
|
||||||
cpp_member_function::builder builder(prefix.scope_name + name.c_str(),
|
cpp_member_function::builder builder(name.c_str(),
|
||||||
detail::parse_type(context, cur,
|
detail::parse_type(context, cur,
|
||||||
clang_getCursorResultType(cur)));
|
clang_getCursorResultType(cur)));
|
||||||
context.comments.match(builder.get(), cur);
|
context.comments.match(builder.get(), cur);
|
||||||
|
|
@ -555,7 +541,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_member_function(const detail::pars
|
||||||
builder.is_constexpr();
|
builder.is_constexpr();
|
||||||
|
|
||||||
skip_parameters(stream);
|
skip_parameters(stream);
|
||||||
return handle_suffix(context, cur, builder, stream, prefix.is_virtual);
|
return handle_suffix(context, cur, builder, stream, prefix.is_virtual,
|
||||||
|
std::move(prefix.semantic_parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_context& context,
|
std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_context& context,
|
||||||
|
|
@ -604,7 +591,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_
|
||||||
detail::skip(stream, ")");
|
detail::skip(stream, ")");
|
||||||
|
|
||||||
auto type = clang_getCursorResultType(cur);
|
auto type = clang_getCursorResultType(cur);
|
||||||
cpp_conversion_op::builder builder(prefix.scope_name + "operator " + type_spelling,
|
cpp_conversion_op::builder builder("operator " + type_spelling,
|
||||||
detail::parse_type(context, cur, type));
|
detail::parse_type(context, cur, type));
|
||||||
context.comments.match(builder.get(), cur);
|
context.comments.match(builder.get(), cur);
|
||||||
if (prefix.is_explicit)
|
if (prefix.is_explicit)
|
||||||
|
|
@ -612,7 +599,8 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_conversion_op(const detail::parse_
|
||||||
else if (prefix.is_constexpr)
|
else if (prefix.is_constexpr)
|
||||||
builder.is_constexpr();
|
builder.is_constexpr();
|
||||||
|
|
||||||
return handle_suffix(context, cur, builder, stream, prefix.is_virtual);
|
return handle_suffix(context, cur, builder, stream, prefix.is_virtual,
|
||||||
|
std::move(prefix.semantic_parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_context& context,
|
std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_context& context,
|
||||||
|
|
@ -633,7 +621,7 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_co
|
||||||
DEBUG_ASSERT(!prefix.is_virtual, detail::parse_error_handler{}, cur,
|
DEBUG_ASSERT(!prefix.is_virtual, detail::parse_error_handler{}, cur,
|
||||||
"constructor cannot be virtual");
|
"constructor cannot be virtual");
|
||||||
|
|
||||||
cpp_constructor::builder builder(prefix.scope_name + name.c_str());
|
cpp_constructor::builder builder(name.c_str());
|
||||||
context.comments.match(builder.get(), cur);
|
context.comments.match(builder.get(), cur);
|
||||||
add_parameters(context, builder, cur);
|
add_parameters(context, builder, cur);
|
||||||
if (clang_Cursor_isVariadic(cur))
|
if (clang_Cursor_isVariadic(cur))
|
||||||
|
|
@ -650,9 +638,11 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_constructor(const detail::parse_co
|
||||||
builder.noexcept_condition(std::move(suffix.noexcept_condition));
|
builder.noexcept_condition(std::move(suffix.noexcept_condition));
|
||||||
|
|
||||||
if (is_templated_cursor(cur))
|
if (is_templated_cursor(cur))
|
||||||
return builder.finish(detail::get_entity_id(cur), suffix.body_kind);
|
return builder.finish(detail::get_entity_id(cur), suffix.body_kind,
|
||||||
|
std::move(prefix.semantic_parent));
|
||||||
else
|
else
|
||||||
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind);
|
return builder.finish(*context.idx, detail::get_entity_id(cur), suffix.body_kind,
|
||||||
|
std::move(prefix.semantic_parent));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_entity> detail::parse_cpp_destructor(const detail::parse_context& context,
|
std::unique_ptr<cpp_entity> detail::parse_cpp_destructor(const detail::parse_context& context,
|
||||||
|
|
@ -671,5 +661,5 @@ std::unique_ptr<cpp_entity> detail::parse_cpp_destructor(const detail::parse_con
|
||||||
|
|
||||||
detail::skip(stream, "(");
|
detail::skip(stream, "(");
|
||||||
detail::skip(stream, ")");
|
detail::skip(stream, ")");
|
||||||
return handle_suffix(context, cur, builder, stream, is_virtual);
|
return handle_suffix(context, cur, builder, stream, is_virtual, type_safe::nullopt);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -389,3 +389,35 @@ std::string detail::to_string(token_stream& stream, token_iterator end)
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool detail::append_scope(detail::token_stream& stream, std::string& scope)
|
||||||
|
{
|
||||||
|
// add identifiers and "::" to current scope name,
|
||||||
|
// clear if there is any other token in between, or mismatched combination
|
||||||
|
if (stream.peek().kind() == CXToken_Identifier)
|
||||||
|
{
|
||||||
|
if (!scope.empty() && scope.back() != ':')
|
||||||
|
scope.clear();
|
||||||
|
scope += stream.get().c_str();
|
||||||
|
}
|
||||||
|
else if (stream.peek() == "::")
|
||||||
|
{
|
||||||
|
if (!scope.empty() && scope.back() == ':')
|
||||||
|
scope.clear();
|
||||||
|
scope += stream.get().c_str();
|
||||||
|
}
|
||||||
|
else if (stream.peek() == "<")
|
||||||
|
{
|
||||||
|
auto iter = detail::find_closing_bracket(stream);
|
||||||
|
scope += detail::to_string(stream, iter);
|
||||||
|
if (!detail::skip_if(stream, ">>"))
|
||||||
|
detail::skip(stream, ">");
|
||||||
|
scope += ">";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scope.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -191,6 +191,12 @@ namespace cppast
|
||||||
|
|
||||||
// converts a token range to a string, adding whitespace where necessary
|
// converts a token range to a string, adding whitespace where necessary
|
||||||
std::string to_string(token_stream& stream, token_iterator end);
|
std::string to_string(token_stream& stream, token_iterator end);
|
||||||
|
|
||||||
|
// appends token to scope, if it is still valid
|
||||||
|
// else clears it
|
||||||
|
// note: does not consume the token if it is not valid,
|
||||||
|
// returns false in that case
|
||||||
|
bool append_scope(token_stream& stream, std::string& scope);
|
||||||
}
|
}
|
||||||
} // namespace cppast::detail
|
} // namespace cppast::detail
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,14 @@ class e
|
||||||
|
|
||||||
namespace ns
|
namespace ns
|
||||||
{
|
{
|
||||||
/// struct base{
|
/// struct base;
|
||||||
/// };
|
struct base;
|
||||||
struct base {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// struct ns::base{
|
||||||
|
/// };
|
||||||
|
struct ns::base {};
|
||||||
|
|
||||||
/// struct f
|
/// struct f
|
||||||
/// :ns::base,virtual protected e{
|
/// :ns::base,virtual protected e{
|
||||||
/// };
|
/// };
|
||||||
|
|
@ -296,5 +299,5 @@ struct g
|
||||||
else
|
else
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
});
|
});
|
||||||
REQUIRE(count == 11u);
|
REQUIRE(count == 12u);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,9 +41,17 @@ enum class b : int
|
||||||
b_c
|
b_c
|
||||||
};
|
};
|
||||||
|
|
||||||
|
namespace ns
|
||||||
|
{
|
||||||
/// enum c
|
/// enum c
|
||||||
/// :int;
|
/// :int;
|
||||||
enum c : int;
|
enum c : int;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// enum ns::c
|
||||||
|
/// :int{
|
||||||
|
/// };
|
||||||
|
enum ns::c : int {};
|
||||||
)";
|
)";
|
||||||
|
|
||||||
cpp_entity_index idx;
|
cpp_entity_index idx;
|
||||||
|
|
@ -137,18 +145,21 @@ enum c : int;
|
||||||
}
|
}
|
||||||
else if (e.name() == "c")
|
else if (e.name() == "c")
|
||||||
{
|
{
|
||||||
|
if (e.semantic_scope() == "ns::")
|
||||||
|
REQUIRE(e.is_definition());
|
||||||
|
else
|
||||||
REQUIRE(e.is_declaration());
|
REQUIRE(e.is_declaration());
|
||||||
REQUIRE(!e.is_definition());
|
|
||||||
REQUIRE(!e.is_scoped());
|
REQUIRE(!e.is_scoped());
|
||||||
REQUIRE(e.has_explicit_type());
|
REQUIRE(e.has_explicit_type());
|
||||||
REQUIRE(equal_types(idx, e.underlying_type(), *cpp_builtin_type::build(cpp_int)));
|
REQUIRE(equal_types(idx, e.underlying_type(), *cpp_builtin_type::build(cpp_int)));
|
||||||
REQUIRE(count_children(e) == 0u);
|
REQUIRE(count_children(e) == 0u);
|
||||||
|
|
||||||
auto definition = get_definition(idx, e);
|
auto definition = get_definition(idx, e);
|
||||||
REQUIRE(!definition);
|
REQUIRE(definition);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
});
|
});
|
||||||
REQUIRE(count == 4u);
|
REQUIRE(count == 5u);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -170,20 +170,23 @@ int d() {}
|
||||||
}
|
}
|
||||||
else if (func.name() == "e")
|
else if (func.name() == "e")
|
||||||
REQUIRE(func.is_definition());
|
REQUIRE(func.is_definition());
|
||||||
else if (func.name() == "b::b")
|
else if (func.name() == "b")
|
||||||
{
|
{
|
||||||
|
REQUIRE(func.semantic_scope() == "b::");
|
||||||
REQUIRE(func.is_declaration());
|
REQUIRE(func.is_declaration());
|
||||||
REQUIRE(func.definition());
|
REQUIRE(func.definition());
|
||||||
check_definition(func.definition().value(), "b::b");
|
check_definition(func.definition().value(), "b::b");
|
||||||
}
|
}
|
||||||
else if (func.name() == "b::f")
|
else if (func.name() == "f")
|
||||||
{
|
{
|
||||||
|
REQUIRE(func.semantic_scope() == "b::");
|
||||||
REQUIRE(func.is_declaration());
|
REQUIRE(func.is_declaration());
|
||||||
REQUIRE(func.definition());
|
REQUIRE(func.definition());
|
||||||
check_definition(func.definition().value(), "b::f");
|
check_definition(func.definition().value(), "b::f");
|
||||||
}
|
}
|
||||||
else if (func.name() == "b::operator int")
|
else if (func.name() == "operator int")
|
||||||
{
|
{
|
||||||
|
REQUIRE(func.semantic_scope() == "b::");
|
||||||
REQUIRE(func.is_declaration());
|
REQUIRE(func.is_declaration());
|
||||||
REQUIRE(func.definition());
|
REQUIRE(func.definition());
|
||||||
check_definition(func.definition().value(), "operator int");
|
check_definition(func.definition().value(), "operator int");
|
||||||
|
|
|
||||||
|
|
@ -198,7 +198,7 @@ void ns::l()
|
||||||
REQUIRE(func.storage_class() == cpp_storage_class_static);
|
REQUIRE(func.storage_class() == cpp_storage_class_static);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (func.name() == "k" || func.name() == "l" || func.name() == "ns::l")
|
else if (func.name() == "k" || func.name() == "l")
|
||||||
{
|
{
|
||||||
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void)));
|
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void)));
|
||||||
REQUIRE(count_children(func.parameters()) == 0u);
|
REQUIRE(count_children(func.parameters()) == 0u);
|
||||||
|
|
@ -210,9 +210,12 @@ void ns::l()
|
||||||
if (func.name() == "k")
|
if (func.name() == "k")
|
||||||
check_body(func, cpp_function_deleted);
|
check_body(func, cpp_function_deleted);
|
||||||
else if (func.name() == "l")
|
else if (func.name() == "l")
|
||||||
check_body(func, cpp_function_declaration);
|
{
|
||||||
else if (func.name() == "ns::l")
|
if (func.semantic_scope() == "ns::")
|
||||||
check_body(func, cpp_function_definition);
|
check_body(func, cpp_function_definition);
|
||||||
|
else
|
||||||
|
check_body(func, cpp_function_declaration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
|
|
@ -247,16 +250,16 @@ void foo::a() {}
|
||||||
REQUIRE(count_children(func.parameters()) == 0u);
|
REQUIRE(count_children(func.parameters()) == 0u);
|
||||||
REQUIRE(func.storage_class() == cpp_storage_class_static);
|
REQUIRE(func.storage_class() == cpp_storage_class_static);
|
||||||
|
|
||||||
if (func.name() == "a" || func.name() == "foo::a")
|
if (func.name() == "a")
|
||||||
{
|
{
|
||||||
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void)));
|
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_void)));
|
||||||
REQUIRE(!func.noexcept_condition());
|
REQUIRE(!func.noexcept_condition());
|
||||||
REQUIRE(!func.is_constexpr());
|
REQUIRE(!func.is_constexpr());
|
||||||
|
|
||||||
if (func.name() == "a")
|
if (func.semantic_scope() == "foo::")
|
||||||
REQUIRE(func.body_kind() == cpp_function_declaration);
|
|
||||||
else
|
|
||||||
REQUIRE(func.body_kind() == cpp_function_definition);
|
REQUIRE(func.body_kind() == cpp_function_definition);
|
||||||
|
else
|
||||||
|
REQUIRE(func.body_kind() == cpp_function_declaration);
|
||||||
}
|
}
|
||||||
else if (func.name() == "b")
|
else if (func.name() == "b")
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -185,11 +185,12 @@ d::d(const int&);
|
||||||
REQUIRE(!tfunc.arguments_exposed());
|
REQUIRE(!tfunc.arguments_exposed());
|
||||||
|
|
||||||
auto templ = tfunc.primary_template();
|
auto templ = tfunc.primary_template();
|
||||||
if (tfunc.name() == "d::operator int")
|
if (tfunc.name() == "operator int")
|
||||||
REQUIRE(equal_ref(idx, templ, cpp_template_ref(cpp_entity_id(""), tfunc.name()),
|
REQUIRE(equal_ref(idx, templ, cpp_template_ref(cpp_entity_id(""), tfunc.name()),
|
||||||
"d::operator T"));
|
"d::operator T"));
|
||||||
else
|
else
|
||||||
REQUIRE(equal_ref(idx, templ, cpp_template_ref(cpp_entity_id(""), tfunc.name())));
|
REQUIRE(equal_ref(idx, templ, cpp_template_ref(cpp_entity_id(""), tfunc.name()),
|
||||||
|
(tfunc.function().semantic_scope() + tfunc.name()).c_str()));
|
||||||
|
|
||||||
if (tfunc.name() == "a")
|
if (tfunc.name() == "a")
|
||||||
{
|
{
|
||||||
|
|
@ -197,6 +198,7 @@ d::d(const int&);
|
||||||
|
|
||||||
REQUIRE(tfunc.function().kind() == cpp_entity_kind::function_t);
|
REQUIRE(tfunc.function().kind() == cpp_entity_kind::function_t);
|
||||||
auto& func = static_cast<const cpp_function&>(tfunc.function());
|
auto& func = static_cast<const cpp_function&>(tfunc.function());
|
||||||
|
REQUIRE(func.semantic_scope() == "");
|
||||||
|
|
||||||
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_int)));
|
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_int)));
|
||||||
|
|
||||||
|
|
@ -214,12 +216,13 @@ d::d(const int&);
|
||||||
}
|
}
|
||||||
REQUIRE(count == 1u);
|
REQUIRE(count == 1u);
|
||||||
}
|
}
|
||||||
else if (tfunc.name() == "d::b")
|
else if (tfunc.name() == "b")
|
||||||
{
|
{
|
||||||
REQUIRE(tfunc.unexposed_arguments() == "0,int");
|
REQUIRE(tfunc.unexposed_arguments() == "0,int");
|
||||||
|
|
||||||
REQUIRE(tfunc.function().kind() == cpp_entity_kind::function_t);
|
REQUIRE(tfunc.function().kind() == cpp_entity_kind::function_t);
|
||||||
auto& func = static_cast<const cpp_function&>(tfunc.function());
|
auto& func = static_cast<const cpp_function&>(tfunc.function());
|
||||||
|
REQUIRE(func.semantic_scope() == "d::");
|
||||||
|
|
||||||
cpp_template_instantiation_type::builder builder(
|
cpp_template_instantiation_type::builder builder(
|
||||||
cpp_template_ref(cpp_entity_id(""), "type"));
|
cpp_template_ref(cpp_entity_id(""), "type"));
|
||||||
|
|
@ -234,17 +237,18 @@ d::d(const int&);
|
||||||
}
|
}
|
||||||
REQUIRE(count == 1u);
|
REQUIRE(count == 1u);
|
||||||
}
|
}
|
||||||
else if (tfunc.name() == "d::c")
|
else if (tfunc.name() == "c")
|
||||||
{
|
{
|
||||||
REQUIRE(tfunc.unexposed_arguments() == "");
|
REQUIRE(tfunc.unexposed_arguments() == "");
|
||||||
|
|
||||||
REQUIRE(tfunc.function().kind() == cpp_entity_kind::member_function_t);
|
REQUIRE(tfunc.function().kind() == cpp_entity_kind::member_function_t);
|
||||||
auto& func = static_cast<const cpp_member_function&>(tfunc.function());
|
auto& func = static_cast<const cpp_member_function&>(tfunc.function());
|
||||||
|
REQUIRE(func.semantic_scope() == "d::");
|
||||||
REQUIRE(func.cv_qualifier() == cpp_cv_none);
|
REQUIRE(func.cv_qualifier() == cpp_cv_none);
|
||||||
|
|
||||||
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_int)));
|
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_int)));
|
||||||
}
|
}
|
||||||
else if (tfunc.name() == "d::operator int")
|
else if (tfunc.name() == "operator int")
|
||||||
{
|
{
|
||||||
REQUIRE(tfunc.unexposed_arguments() == "");
|
REQUIRE(tfunc.unexposed_arguments() == "");
|
||||||
|
|
||||||
|
|
@ -254,12 +258,13 @@ d::d(const int&);
|
||||||
|
|
||||||
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_int)));
|
REQUIRE(equal_types(idx, func.return_type(), *cpp_builtin_type::build(cpp_int)));
|
||||||
}
|
}
|
||||||
else if (tfunc.name() == "d::d")
|
else if (tfunc.name() == "d")
|
||||||
{
|
{
|
||||||
REQUIRE(tfunc.unexposed_arguments() == "");
|
REQUIRE(tfunc.unexposed_arguments() == "");
|
||||||
|
|
||||||
REQUIRE(tfunc.function().kind() == cpp_entity_kind::constructor_t);
|
REQUIRE(tfunc.function().kind() == cpp_entity_kind::constructor_t);
|
||||||
auto& func = static_cast<const cpp_constructor&>(tfunc.function());
|
auto& func = static_cast<const cpp_constructor&>(tfunc.function());
|
||||||
|
REQUIRE(func.semantic_scope() == "d::");
|
||||||
|
|
||||||
auto count = 0u;
|
auto count = 0u;
|
||||||
for (auto& param : func.parameters())
|
for (auto& param : func.parameters())
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ TEST_CASE("cpp_member_function")
|
||||||
{
|
{
|
||||||
auto code = R"(
|
auto code = R"(
|
||||||
// no need to test parameters/return types
|
// no need to test parameters/return types
|
||||||
|
template <typename T>
|
||||||
struct foo
|
struct foo
|
||||||
{
|
{
|
||||||
/// void a();
|
/// void a();
|
||||||
|
|
@ -39,7 +40,11 @@ struct foo
|
||||||
void j() = delete;
|
void j() = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bar : foo
|
/// void foo<T>::a();
|
||||||
|
template <typename T>
|
||||||
|
void foo<T>::a() {}
|
||||||
|
|
||||||
|
struct bar : foo<int>
|
||||||
{
|
{
|
||||||
/// virtual void g() override;
|
/// virtual void g() override;
|
||||||
void g();
|
void g();
|
||||||
|
|
@ -59,11 +64,13 @@ struct bar : foo
|
||||||
REQUIRE(!func.noexcept_condition());
|
REQUIRE(!func.noexcept_condition());
|
||||||
if (func.name() != "g" && func.name() != "h")
|
if (func.name() != "g" && func.name() != "h")
|
||||||
REQUIRE(!func.virtual_info());
|
REQUIRE(!func.virtual_info());
|
||||||
if (func.name() != "i" && func.name() != "j")
|
if (func.semantic_scope().empty() && func.name() != "i" && func.name() != "j")
|
||||||
REQUIRE(func.body_kind() == cpp_function_declaration);
|
REQUIRE(func.body_kind() == cpp_function_declaration);
|
||||||
|
|
||||||
if (func.name() == "a")
|
if (func.name() == "a")
|
||||||
{
|
{
|
||||||
|
if (func.semantic_scope() == "foo::")
|
||||||
|
REQUIRE(func.is_definition());
|
||||||
REQUIRE(func.cv_qualifier() == cpp_cv_none);
|
REQUIRE(func.cv_qualifier() == cpp_cv_none);
|
||||||
REQUIRE(func.ref_qualifier() == cpp_ref_none);
|
REQUIRE(func.ref_qualifier() == cpp_ref_none);
|
||||||
}
|
}
|
||||||
|
|
@ -140,7 +147,7 @@ struct bar : foo
|
||||||
else
|
else
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
});
|
});
|
||||||
REQUIRE(count == 12u);
|
REQUIRE(count == 13u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("cpp_conversion_op")
|
TEST_CASE("cpp_conversion_op")
|
||||||
|
|
@ -248,13 +255,14 @@ foo<T>::foo(int) {}
|
||||||
auto file = parse(idx, "cpp_constructor.cpp", code);
|
auto file = parse(idx, "cpp_constructor.cpp", code);
|
||||||
auto count = test_visit<cpp_constructor>(*file, [&](const cpp_constructor& cont) {
|
auto count = test_visit<cpp_constructor>(*file, [&](const cpp_constructor& cont) {
|
||||||
REQUIRE(!cont.is_variadic());
|
REQUIRE(!cont.is_variadic());
|
||||||
|
REQUIRE(cont.name() == "foo");
|
||||||
|
|
||||||
if (cont.is_definition() && count_children(cont.parameters()) == 1u)
|
if (cont.semantic_parent())
|
||||||
{
|
{
|
||||||
if (is_template)
|
if (is_template)
|
||||||
REQUIRE(cont.name() == "foo<T>::foo");
|
REQUIRE(cont.semantic_parent().value().name() == "foo<T>::");
|
||||||
else
|
else
|
||||||
REQUIRE(cont.name() == "foo::foo");
|
REQUIRE(cont.semantic_parent().value().name() == "foo::");
|
||||||
REQUIRE(!cont.noexcept_condition());
|
REQUIRE(!cont.noexcept_condition());
|
||||||
REQUIRE(!cont.is_constexpr());
|
REQUIRE(!cont.is_constexpr());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include <catch.hpp>
|
#include <catch.hpp>
|
||||||
|
|
||||||
#include <cppast/code_generator.hpp>
|
#include <cppast/code_generator.hpp>
|
||||||
|
#include <cppast/cpp_class.hpp>
|
||||||
#include <cppast/cpp_entity_kind.hpp>
|
#include <cppast/cpp_entity_kind.hpp>
|
||||||
#include <cppast/cpp_expression.hpp>
|
#include <cppast/cpp_expression.hpp>
|
||||||
#include <cppast/cpp_type.hpp>
|
#include <cppast/cpp_type.hpp>
|
||||||
|
|
@ -157,6 +158,12 @@ inline std::string full_name(const cppast::cpp_entity& e)
|
||||||
scopes = cur_scope.name() + "::" + scopes;
|
scopes = cur_scope.name() + "::" + scopes;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (e.kind() == cppast::cpp_entity_kind::class_t)
|
||||||
|
{
|
||||||
|
auto& c = static_cast<const cppast::cpp_class&>(e);
|
||||||
|
return scopes + c.semantic_scope() + c.name();
|
||||||
|
}
|
||||||
|
else
|
||||||
return scopes + e.name();
|
return scopes + e.name();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue