Better handling of include refs

This commit is contained in:
Jonathan Müller 2018-01-11 15:29:15 +01:00
commit 3e8b2b429c
3 changed files with 30 additions and 9 deletions

View file

@ -116,9 +116,15 @@ namespace
return file.size() > 2 && file[1] == ':';
}
bool is_absolute(const std::string& file)
{
return !file.empty()
&& (has_drive_prefix(file) || file.front() == '/' || file.front() == '\\');
}
std::string get_full_path(const detail::cxstring& dir, const std::string& file)
{
if (has_drive_prefix(file) || file.front() == '/' || file.front() == '\\')
if (is_absolute(file))
// absolute file
return file;
else if (dir[dir.length() - 1] != '/' && dir[dir.length() - 1] != '\\')
@ -466,7 +472,7 @@ std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx,
auto tu = get_cxunit(logger(), pimpl_->index, config, path.c_str(), preprocessed.source);
auto file = clang_getFile(tu.get(), path.c_str());
cpp_file::builder builder(path);
cpp_file::builder builder(detail::cxstring(clang_getFileName(file)).std_str());
auto macro_iter = preprocessed.macros.begin();
auto include_iter = preprocessed.includes.begin();
@ -486,9 +492,22 @@ std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx,
&& get_line_no(cur) >= include_iter->line,
detail::assert_handler{});
// create an include directive
auto full_path = detail::get_cursor_name(cur);
// if we got an absolute file path for the current file,
// also use an absolute file path for the id
// otherwise just use the file name as written in the source file
// note: this is a hack around lack of `fs::canonical()`
cpp_entity_id id("");
if (is_absolute(builder.get().name()))
id = cpp_entity_id(full_path.c_str());
else
id = cpp_entity_id(include_iter->file_name.c_str());
auto include =
cpp_include_directive::build(std::move(include_iter->file), include_iter->kind,
detail::get_cursor_name(cur).c_str());
cpp_include_directive::build(cpp_file_ref(id,
std::move(include_iter->file_name)),
include_iter->kind, full_path.std_str());
context.comments.match(*include, include_iter->line,
false); // must not skip comments,
// includes are not reported in order

View file

@ -694,8 +694,11 @@ namespace
if (!in_main_file)
return type_safe::nullopt;
return detail::pp_include{cpp_file_ref(cpp_entity_id(filename), filename), include_kind,
p.cur_line()};
if (filename.size() > 2u && filename[0] == '.'
&& (filename[1] == '/' || filename[1] == '\\'))
filename = filename.substr(2);
return detail::pp_include{std::move(filename), include_kind, p.cur_line()};
}
bool bump_pragma(position& p)
@ -777,8 +780,7 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co
logger.log("preprocessor",
format_diagnostic(severity::debug,
source_location::make_file(path, p.cur_line()),
"parsing include '", include.value().file.name(),
"'"));
"parsing include '", include.value().file_name, "'"));
result.includes.push_back(std::move(include.value()));
}

View file

@ -20,7 +20,7 @@ namespace cppast
struct pp_include
{
cpp_file_ref file;
std::string file_name;
cpp_include_kind kind;
unsigned line;
};