Add definition info to AST dump
This commit is contained in:
parent
0bc5097579
commit
599524a894
5 changed files with 162 additions and 43 deletions
|
|
@ -60,52 +60,36 @@ namespace cppast
|
|||
type_safe::optional<cpp_entity_id> definition_;
|
||||
};
|
||||
|
||||
/// \exclude
|
||||
namespace detail
|
||||
{
|
||||
template <typename T>
|
||||
auto get_definition_impl(const cpp_entity_index& idx, const T& entity) ->
|
||||
typename std::enable_if<std::is_base_of<cpp_forward_declarable, T>::value,
|
||||
type_safe::optional_ref<const T>>::type
|
||||
{
|
||||
if (!entity.definition())
|
||||
// entity is definition itself
|
||||
return type_safe::opt_cref(&entity);
|
||||
else
|
||||
// entity is not a definition
|
||||
// lookup the definition
|
||||
return idx
|
||||
.lookup_definition(entity.definition().value())
|
||||
// downcast
|
||||
.map([](const cpp_entity& e) {
|
||||
DEBUG_ASSERT(e.kind() == T::kind(), detail::assert_handler{});
|
||||
return type_safe::ref(static_cast<const T&>(e));
|
||||
});
|
||||
}
|
||||
/// \returns Whether or not the given entity is a definition.
|
||||
bool is_definition(const cpp_entity& e) noexcept;
|
||||
|
||||
template <typename T>
|
||||
auto get_definition_impl(const cpp_entity_index&, const T& entity) ->
|
||||
typename std::enable_if<!std::is_base_of<cpp_forward_declarable, T>::value,
|
||||
type_safe::optional_ref<const T>>::type
|
||||
{
|
||||
return type_safe::opt_cref(&entity);
|
||||
}
|
||||
} // namespace detail
|
||||
class cpp_enum;
|
||||
class cpp_class;
|
||||
class cpp_variable;
|
||||
class cpp_function_base;
|
||||
|
||||
/// Gets the definition of an entity.
|
||||
/// \returns A [ts::optional_ref]() to the entity that is the definition.
|
||||
/// If the entity is a definition or not derived from [cppast::cpp_forward_declarable](),
|
||||
/// If the entity is a definition or not derived from [cppast::cpp_forward_declarable]() (only valid for the generic entity overload),
|
||||
/// returns a reference to the entity itself.
|
||||
/// Otherwise lookups the definition id and returns it.
|
||||
/// \requires `entity` must be derived from [cppast::cpp_entity]().
|
||||
/// \param 1
|
||||
/// \exclude
|
||||
template <typename T,
|
||||
typename = typename std::enable_if<std::is_base_of<cpp_entity, T>::value>::type>
|
||||
type_safe::optional_ref<const T> get_definition(const cpp_entity_index& idx, const T& entity)
|
||||
{
|
||||
return detail::get_definition_impl(idx, entity);
|
||||
}
|
||||
/// \notes The return value will only be `nullptr`, if the definition is not registered.
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_entity> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_entity& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_enum> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_enum& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_class> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_class& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_variable> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_variable& e);
|
||||
/// \group get_definition
|
||||
type_safe::optional_ref<const cpp_function_base> get_definition(const cpp_entity_index& idx,
|
||||
const cpp_function_base& e);
|
||||
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_CPP_FORWARD_DECLARABLE_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ set(source
|
|||
cpp_enum.cpp
|
||||
cpp_expression.cpp
|
||||
cpp_file.cpp
|
||||
cpp_forward_declarable.cpp
|
||||
cpp_friend.cpp
|
||||
cpp_function.cpp
|
||||
cpp_function_template.cpp
|
||||
|
|
|
|||
129
src/cpp_forward_declarable.cpp
Normal file
129
src/cpp_forward_declarable.cpp
Normal file
|
|
@ -0,0 +1,129 @@
|
|||
// Copyright (C) 2017 Jonathan Müller <jonathanmueller.dev@gmail.com>
|
||||
// This file is subject to the license terms in the LICENSE file
|
||||
// found in the top-level directory of this distribution.
|
||||
|
||||
#include <cppast/cpp_forward_declarable.hpp>
|
||||
|
||||
#include <cppast/cpp_class.hpp>
|
||||
#include <cppast/cpp_entity_kind.hpp>
|
||||
#include <cppast/cpp_enum.hpp>
|
||||
#include <cppast/cpp_function.hpp>
|
||||
#include <cppast/cpp_variable.hpp>
|
||||
|
||||
using namespace cppast;
|
||||
|
||||
namespace
|
||||
{
|
||||
type_safe::optional_ref<const cpp_forward_declarable> get_declarable(const cpp_entity& e)
|
||||
{
|
||||
switch (e.kind())
|
||||
{
|
||||
case cpp_entity_kind::enum_t:
|
||||
return type_safe::ref(static_cast<const cpp_enum&>(e));
|
||||
case cpp_entity_kind::class_t:
|
||||
return type_safe::ref(static_cast<const cpp_class&>(e));
|
||||
case cpp_entity_kind::variable_t:
|
||||
return type_safe::ref(static_cast<const cpp_variable&>(e));
|
||||
case cpp_entity_kind::function_t:
|
||||
case cpp_entity_kind::member_function_t:
|
||||
case cpp_entity_kind::conversion_op_t:
|
||||
case cpp_entity_kind::constructor_t:
|
||||
case cpp_entity_kind::destructor_t:
|
||||
return type_safe::ref(static_cast<const cpp_function_base&>(e));
|
||||
|
||||
case cpp_entity_kind::file_t:
|
||||
case cpp_entity_kind::macro_definition_t:
|
||||
case cpp_entity_kind::include_directive_t:
|
||||
case cpp_entity_kind::language_linkage_t:
|
||||
case cpp_entity_kind::namespace_t:
|
||||
case cpp_entity_kind::namespace_alias_t:
|
||||
case cpp_entity_kind::using_directive_t:
|
||||
case cpp_entity_kind::using_declaration_t:
|
||||
case cpp_entity_kind::type_alias_t:
|
||||
case cpp_entity_kind::enum_value_t:
|
||||
case cpp_entity_kind::access_specifier_t:
|
||||
case cpp_entity_kind::base_class_t:
|
||||
case cpp_entity_kind::member_variable_t:
|
||||
case cpp_entity_kind::bitfield_t:
|
||||
case cpp_entity_kind::function_parameter_t:
|
||||
case cpp_entity_kind::friend_t:
|
||||
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::alias_template_t:
|
||||
case cpp_entity_kind::variable_template_t:
|
||||
case cpp_entity_kind::function_template_t:
|
||||
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:
|
||||
return nullptr;
|
||||
|
||||
case cpp_entity_kind::count:
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUG_UNREACHABLE(detail::assert_handler{});
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const cpp_entity> get_definition_impl(const cpp_entity_index& idx,
|
||||
const cpp_entity& e)
|
||||
{
|
||||
auto declarable = get_declarable(e);
|
||||
if (!declarable || declarable.value().is_definition())
|
||||
// not declarable or is a definition
|
||||
// return reference to entity itself
|
||||
return type_safe::ref(e);
|
||||
// else lookup definition
|
||||
return idx.lookup_definition(declarable.value().definition().value());
|
||||
}
|
||||
}
|
||||
|
||||
bool cppast::is_definition(const cpp_entity& e) noexcept
|
||||
{
|
||||
auto declarable = get_declarable(e);
|
||||
return declarable && declarable.value().is_definition();
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const cpp_entity> cppast::get_definition(const cpp_entity_index& idx,
|
||||
const cpp_entity& e)
|
||||
{
|
||||
return get_definition_impl(idx, e);
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const cpp_enum> cppast::get_definition(const cpp_entity_index& idx,
|
||||
const cpp_enum& e)
|
||||
{
|
||||
return get_definition_impl(idx, e).map([](const cpp_entity& e) {
|
||||
DEBUG_ASSERT(e.kind() == cpp_entity_kind::enum_t, detail::assert_handler{});
|
||||
return type_safe::ref(static_cast<const cpp_enum&>(e));
|
||||
});
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const cpp_class> cppast::get_definition(const cpp_entity_index& idx,
|
||||
const cpp_class& e)
|
||||
{
|
||||
return get_definition_impl(idx, e).map([](const cpp_entity& e) {
|
||||
DEBUG_ASSERT(e.kind() == cpp_entity_kind::class_t, detail::assert_handler{});
|
||||
return type_safe::ref(static_cast<const cpp_class&>(e));
|
||||
});
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const cpp_variable> cppast::get_definition(const cpp_entity_index& idx,
|
||||
const cpp_variable& e)
|
||||
{
|
||||
return get_definition_impl(idx, e).map([](const cpp_entity& e) {
|
||||
DEBUG_ASSERT(e.kind() == cpp_entity_kind::variable_t, detail::assert_handler{});
|
||||
return type_safe::ref(static_cast<const cpp_variable&>(e));
|
||||
});
|
||||
}
|
||||
|
||||
type_safe::optional_ref<const cpp_function_base> cppast::get_definition(const cpp_entity_index& idx,
|
||||
const cpp_function_base& e)
|
||||
{
|
||||
return get_definition_impl(idx, e).map([](const cpp_entity& e) {
|
||||
DEBUG_ASSERT(is_function(e.kind()), detail::assert_handler{});
|
||||
return type_safe::ref(static_cast<const cpp_function_base&>(e));
|
||||
});
|
||||
}
|
||||
|
|
@ -316,8 +316,8 @@ namespace
|
|||
}
|
||||
else if (detail::skip_if(stream, "final"))
|
||||
{
|
||||
"unexpected token");
|
||||
DEBUG_ASSERT(allow_virtual, detail::parse_error_handler{}, stream.cursor(),
|
||||
"unexpected token");
|
||||
if (result.virtual_keywords)
|
||||
result.virtual_keywords.value() |= cpp_virtual_flags::final;
|
||||
else
|
||||
|
|
|
|||
|
|
@ -9,8 +9,9 @@
|
|||
#include <cppast/libclang_parser.hpp> // for libclang_parser, libclang_compile_config, cpp_entity,...
|
||||
#include <cppast/visitor.hpp> // for visit()
|
||||
#include <cppast/code_generator.hpp> // for generate_code()
|
||||
#include <cppast/cpp_entity_kind.hpp> // for the cpp_entity_kind definition
|
||||
#include <cppast/cpp_namespace.hpp> // for cpp_namespace
|
||||
#include <cppast/cpp_entity_kind.hpp> // for the cpp_entity_kind definition
|
||||
#include <cppast/cpp_forward_declarable.hpp> // for is_definition()
|
||||
#include <cppast/cpp_namespace.hpp> // for cpp_namespace
|
||||
|
||||
// print help options
|
||||
void print_help(const cxxopts::Options& options)
|
||||
|
|
@ -31,6 +32,10 @@ void print_entity(std::ostream& out, const cppast::cpp_entity& e)
|
|||
// print name and the kind of the entity
|
||||
out << e.name() << " (" << cppast::to_string(e.kind()) << ")";
|
||||
|
||||
// print whether or not it is a definition
|
||||
if (cppast::is_definition(e))
|
||||
out << " [definition]";
|
||||
|
||||
if (e.kind() == cppast::cpp_entity_kind::language_linkage_t)
|
||||
// no need to print additional information for language linkages
|
||||
out << '\n';
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue