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] == ':'; 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) 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 // absolute file
return file; return file;
else if (dir[dir.length() - 1] != '/' && dir[dir.length() - 1] != '\\') 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 tu = get_cxunit(logger(), 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());
cpp_file::builder builder(path); cpp_file::builder builder(detail::cxstring(clang_getFileName(file)).std_str());
auto macro_iter = preprocessed.macros.begin(); auto macro_iter = preprocessed.macros.begin();
auto include_iter = preprocessed.includes.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, && get_line_no(cur) >= include_iter->line,
detail::assert_handler{}); 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 = auto include =
cpp_include_directive::build(std::move(include_iter->file), include_iter->kind, cpp_include_directive::build(cpp_file_ref(id,
detail::get_cursor_name(cur).c_str()); std::move(include_iter->file_name)),
include_iter->kind, full_path.std_str());
context.comments.match(*include, include_iter->line, context.comments.match(*include, include_iter->line,
false); // must not skip comments, false); // must not skip comments,
// includes are not reported in order // includes are not reported in order

View file

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

View file

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