Order preprocessing entities relative to other entities

This commit is contained in:
Jonathan Müller 2017-02-22 20:30:26 +01:00
commit 8fdfd3a707
2 changed files with 35 additions and 7 deletions

View file

@ -158,6 +158,15 @@ namespace
return tu; return tu;
} }
unsigned get_line_no(const CXCursor& cursor)
{
auto loc = clang_getCursorLocation(cursor);
unsigned line;
clang_getPresumedLocation(loc, nullptr, &line, nullptr);
return line;
}
} }
std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx, std::string path, std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx, std::string path,
@ -172,21 +181,26 @@ std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx,
auto tu = get_cxunit(pimpl_->index, config, path.c_str(), preprocessed.source); auto tu = get_cxunit(pimpl_->index, config, path.c_str(), preprocessed.source);
auto file = clang_getFile(tu.get(), path.c_str()); auto file = clang_getFile(tu.get(), path.c_str());
// convert entity hierachies
cpp_file::builder builder(path); cpp_file::builder builder(path);
auto preprocessed_iter = preprocessed.entities.begin();
// add all preprocessor entities up-front // convert entity hierachies
// TODO: add them in the correct place
for (auto& e : preprocessed.entities)
builder.add_child(std::move(e.entity));
detail::parse_context context{tu.get(), file, type_safe::ref(logger()), type_safe::ref(idx)}; detail::parse_context context{tu.get(), file, type_safe::ref(logger()), type_safe::ref(idx)};
detail::visit_tu(tu, path.c_str(), [&](const CXCursor& cur) { detail::visit_tu(tu, path.c_str(), [&](const CXCursor& cur) {
// add macro if needed
for (auto line = get_line_no(cur);
preprocessed_iter != preprocessed.entities.end() && preprocessed_iter->line <= line;
++preprocessed_iter)
builder.add_child(std::move(preprocessed_iter->entity));
auto entity = detail::parse_entity(context, cur); auto entity = detail::parse_entity(context, cur);
if (entity) if (entity)
builder.add_child(std::move(entity)); builder.add_child(std::move(entity));
}); });
for (; preprocessed_iter != preprocessed.entities.end(); ++preprocessed_iter)
builder.add_child(std::move(preprocessed_iter->entity));
return builder.finish(idx); return builder.finish(idx);
} }
catch (detail::parse_error& ex) catch (detail::parse_error& ex)

View file

@ -15,13 +15,18 @@ TEST_CASE("cpp_macro_definition")
#define G #define G
#define A #define A
#define B hello #define B hello
namespace ns {}
#define C(x, y) x##_name #define C(x, y) x##_name
#define D(...) __VA_ARGS__ #define D(...) __VA_ARGS__
#define E() bar\ #define E() bar\
baz baz
namespace ns2
{
#define F () bar #define F () bar
#undef G #undef G
}
)"; )";
const char* order[] = {"A", "B", "ns", "C", "D", "E", "ns2", "F"};
auto check_macro = [](const cpp_macro_definition& macro, const char* replacement, auto check_macro = [](const cpp_macro_definition& macro, const char* replacement,
const char* args) { const char* args) {
@ -56,9 +61,18 @@ baz
REQUIRE(false); REQUIRE(false);
}); });
REQUIRE(count == 6u); REQUIRE(count == 6u);
auto index = 0u;
for (auto& child : *file)
{
if (child.kind() == cpp_entity_kind::include_directive_t)
continue;
REQUIRE(child.name() == order[index++]);
}
} }
// requires clang 4.0, currently not available for testing // requires clang 4.0, currently not available for testing
// TODO:
#if 0 #if 0
TEST_CASE("cpp_include_directive") TEST_CASE("cpp_include_directive")
{ {