Store full path of header as well
This commit is contained in:
parent
6d261cef16
commit
fd449dde4a
6 changed files with 169 additions and 131 deletions
|
|
@ -80,9 +80,11 @@ namespace cppast
|
||||||
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index](),
|
/// \notes It is not meant to be registered in the [cppast::cpp_entity_index](),
|
||||||
/// as no other [cppast::cpp_entity]() can refer to it.
|
/// as no other [cppast::cpp_entity]() can refer to it.
|
||||||
static std::unique_ptr<cpp_include_directive> build(const cpp_file_ref& target,
|
static std::unique_ptr<cpp_include_directive> build(const cpp_file_ref& target,
|
||||||
cpp_include_kind kind)
|
cpp_include_kind kind,
|
||||||
|
std::string full_path)
|
||||||
{
|
{
|
||||||
return std::unique_ptr<cpp_include_directive>(new cpp_include_directive(target, kind));
|
return std::unique_ptr<cpp_include_directive>(
|
||||||
|
new cpp_include_directive(target, kind, std::move(full_path)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \returns A reference to the [cppast::cpp_file]() it includes.
|
/// \returns A reference to the [cppast::cpp_file]() it includes.
|
||||||
|
|
@ -97,17 +99,28 @@ namespace cppast
|
||||||
return kind_;
|
return kind_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// \returns The full path of the included file.
|
||||||
|
const std::string& full_path() const noexcept
|
||||||
|
{
|
||||||
|
return full_path_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
cpp_entity_kind do_get_entity_kind() const noexcept override;
|
||||||
|
|
||||||
cpp_include_directive(const cpp_file_ref& target, cpp_include_kind kind)
|
cpp_include_directive(const cpp_file_ref& target, cpp_include_kind kind,
|
||||||
: cpp_entity(target.name()), target_(target.id()[0u]), kind_(kind)
|
std::string full_path)
|
||||||
|
: cpp_entity(target.name()),
|
||||||
|
target_(target.id()[0u]),
|
||||||
|
kind_(kind),
|
||||||
|
full_path_(std::move(full_path))
|
||||||
{
|
{
|
||||||
DEBUG_ASSERT(!target.is_overloaded(), detail::precondition_error_handler{});
|
DEBUG_ASSERT(!target.is_overloaded(), detail::precondition_error_handler{});
|
||||||
}
|
}
|
||||||
|
|
||||||
cpp_entity_id target_;
|
cpp_entity_id target_;
|
||||||
cpp_include_kind kind_;
|
cpp_include_kind kind_;
|
||||||
|
std::string full_path_;
|
||||||
};
|
};
|
||||||
} // namespace cppast
|
} // namespace cppast
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -205,14 +205,16 @@ namespace
|
||||||
auto args = get_arguments(config);
|
auto args = get_arguments(config);
|
||||||
|
|
||||||
CXTranslationUnit tu;
|
CXTranslationUnit tu;
|
||||||
auto error =
|
auto flags = CXTranslationUnit_Incomplete | CXTranslationUnit_KeepGoing;
|
||||||
|
if (detail::libclang_compile_config_access::clang_version(config) >= 40000)
|
||||||
|
flags |= CXTranslationUnit_DetailedPreprocessingRecord;
|
||||||
|
|
||||||
|
auto error =
|
||||||
clang_parseTranslationUnit2(idx.get(), path, // index and path
|
clang_parseTranslationUnit2(idx.get(), path, // index and path
|
||||||
args.data(),
|
args.data(),
|
||||||
static_cast<int>(args.size()), // arguments (ptr + size)
|
static_cast<int>(args.size()), // arguments (ptr + size)
|
||||||
&file, 1, // unsaved files (ptr + size)
|
&file, 1, // unsaved files (ptr + size)
|
||||||
CXTranslationUnit_Incomplete
|
unsigned(flags), &tu);
|
||||||
| CXTranslationUnit_KeepGoing, // flags
|
|
||||||
&tu);
|
|
||||||
if (error != CXError_Success)
|
if (error != CXError_Success)
|
||||||
{
|
{
|
||||||
switch (error)
|
switch (error)
|
||||||
|
|
@ -259,25 +261,42 @@ std::unique_ptr<cpp_file> libclang_parser::do_parse(const cpp_entity_index& idx,
|
||||||
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(path);
|
||||||
auto preprocessed_iter = preprocessed.entities.begin();
|
auto macro_iter = preprocessed.macros.begin();
|
||||||
|
auto include_iter = preprocessed.includes.begin();
|
||||||
|
|
||||||
// convert entity hierachies
|
// convert entity hierachies
|
||||||
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::comment_context(preprocessed.comments)};
|
detail::comment_context(preprocessed.comments)};
|
||||||
detail::visit_tu(tu, path.c_str(), [&](const CXCursor& cur) {
|
detail::visit_tu(tu, path.c_str(), [&](const CXCursor& cur) {
|
||||||
// add macro if needed
|
if (clang_getCursorKind(cur) == CXCursor_InclusionDirective)
|
||||||
for (auto line = get_line_no(cur);
|
{
|
||||||
preprocessed_iter != preprocessed.entities.end() && preprocessed_iter->line <= line;
|
DEBUG_ASSERT(include_iter != preprocessed.includes.end()
|
||||||
++preprocessed_iter)
|
&& get_line_no(cur) >= include_iter->line,
|
||||||
builder.add_child(std::move(preprocessed_iter->entity));
|
detail::assert_handler{});
|
||||||
|
|
||||||
auto entity = detail::parse_entity(context, cur);
|
auto include =
|
||||||
if (entity)
|
cpp_include_directive::build(std::move(include_iter->file), include_iter->kind,
|
||||||
builder.add_child(std::move(entity));
|
detail::get_cursor_name(cur).c_str());
|
||||||
|
context.comments.match(*include, include_iter->line);
|
||||||
|
builder.add_child(std::move(include));
|
||||||
|
|
||||||
|
++include_iter;
|
||||||
|
}
|
||||||
|
else if (clang_getCursorKind(cur) != CXCursor_MacroDefinition)
|
||||||
|
{
|
||||||
|
// add macro if needed
|
||||||
|
for (auto line = get_line_no(cur);
|
||||||
|
macro_iter != preprocessed.macros.end() && macro_iter->line <= line; ++macro_iter)
|
||||||
|
builder.add_child(std::move(macro_iter->macro));
|
||||||
|
|
||||||
|
auto entity = detail::parse_entity(context, cur);
|
||||||
|
if (entity)
|
||||||
|
builder.add_child(std::move(entity));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (; preprocessed_iter != preprocessed.entities.end(); ++preprocessed_iter)
|
for (; macro_iter != preprocessed.macros.end(); ++macro_iter)
|
||||||
builder.add_child(std::move(preprocessed_iter->entity));
|
builder.add_child(std::move(macro_iter->macro));
|
||||||
|
|
||||||
for (auto& c : preprocessed.comments)
|
for (auto& c : preprocessed.comments)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -104,6 +104,11 @@ std::unique_ptr<cpp_entity> detail::parse_entity(const detail::parse_context& co
|
||||||
return entity;
|
return entity;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CXCursor_MacroDefinition:
|
||||||
|
case CXCursor_InclusionDirective:
|
||||||
|
DEBUG_UNREACHABLE(detail::assert_handler{}, "handle preprocessor in parser callback");
|
||||||
|
break;
|
||||||
|
|
||||||
case CXCursor_Namespace:
|
case CXCursor_Namespace:
|
||||||
return parse_cpp_namespace(context, cur);
|
return parse_cpp_namespace(context, cur);
|
||||||
case CXCursor_NamespaceAlias:
|
case CXCursor_NamespaceAlias:
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,89 @@ namespace
|
||||||
p.skip(std::strlen(str));
|
p.skip(std::strlen(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void skip_spaces(position& p, bool bump = false)
|
||||||
|
{
|
||||||
|
while (starts_with(p, " "))
|
||||||
|
if (bump)
|
||||||
|
p.bump();
|
||||||
|
else
|
||||||
|
p.skip();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct linemarker
|
||||||
|
{
|
||||||
|
std::string file;
|
||||||
|
unsigned line;
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
line_directive, // no change in file
|
||||||
|
enter_new, // open a new file
|
||||||
|
enter_old, // return to an old file
|
||||||
|
} flag = line_directive;
|
||||||
|
bool is_system = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
ts::optional<linemarker> parse_linemarker(position& p)
|
||||||
|
{
|
||||||
|
// format (at new line): # <line> "<filename>" <flags>
|
||||||
|
// flag 1: enter_new
|
||||||
|
// flag 2: enter_old
|
||||||
|
// flag 3: system file
|
||||||
|
// flag 4: ignored
|
||||||
|
if (!p.was_newl() || !starts_with(p, "#"))
|
||||||
|
return ts::nullopt;
|
||||||
|
p.skip();
|
||||||
|
DEBUG_ASSERT(!starts_with(p, "define") && !starts_with(p, "undef")
|
||||||
|
&& !starts_with(p, "pragma"),
|
||||||
|
detail::assert_handler{}, "handle macros first");
|
||||||
|
|
||||||
|
linemarker result;
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
for (skip_spaces(p); std::isdigit(*p.ptr()); p.skip())
|
||||||
|
line += *p.ptr();
|
||||||
|
result.line = unsigned(std::stoi(line));
|
||||||
|
|
||||||
|
skip_spaces(p);
|
||||||
|
DEBUG_ASSERT(*p.ptr() == '"', detail::assert_handler{});
|
||||||
|
p.skip();
|
||||||
|
|
||||||
|
std::string file_name;
|
||||||
|
for (; !starts_with(p, "\""); p.skip())
|
||||||
|
file_name += *p.ptr();
|
||||||
|
p.skip();
|
||||||
|
result.file = std::move(file_name);
|
||||||
|
|
||||||
|
for (; !starts_with(p, "\n"); p.skip())
|
||||||
|
{
|
||||||
|
skip_spaces(p);
|
||||||
|
|
||||||
|
switch (*p.ptr())
|
||||||
|
{
|
||||||
|
case '1':
|
||||||
|
DEBUG_ASSERT(result.flag == linemarker::line_directive, detail::assert_handler{});
|
||||||
|
result.flag = linemarker::enter_new;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
DEBUG_ASSERT(result.flag == linemarker::line_directive, detail::assert_handler{});
|
||||||
|
result.flag = linemarker::enter_old;
|
||||||
|
break;
|
||||||
|
case '3':
|
||||||
|
result.is_system = true;
|
||||||
|
break;
|
||||||
|
case '4':
|
||||||
|
break; // ignored
|
||||||
|
|
||||||
|
default:
|
||||||
|
DEBUG_UNREACHABLE(detail::assert_handler{}, "invalid line marker");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.skip();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
detail::pp_doc_comment parse_c_doc_comment(position& p)
|
detail::pp_doc_comment parse_c_doc_comment(position& p)
|
||||||
{
|
{
|
||||||
detail::pp_doc_comment result;
|
detail::pp_doc_comment result;
|
||||||
|
|
@ -423,15 +506,6 @@ namespace
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void skip_spaces(position& p, bool bump = false)
|
|
||||||
{
|
|
||||||
while (starts_with(p, " "))
|
|
||||||
if (bump)
|
|
||||||
p.bump();
|
|
||||||
else
|
|
||||||
p.skip();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<cpp_macro_definition> parse_macro(position& p,
|
std::unique_ptr<cpp_macro_definition> parse_macro(position& p,
|
||||||
detail::preprocessor_output& output,
|
detail::preprocessor_output& output,
|
||||||
bool in_main_file)
|
bool in_main_file)
|
||||||
|
|
@ -504,15 +578,13 @@ namespace
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<cpp_include_directive> parse_include(position& p,
|
type_safe::optional<detail::pp_include> parse_include(position& p, bool in_main_file)
|
||||||
detail::preprocessor_output& output,
|
|
||||||
bool in_main_file)
|
|
||||||
{
|
{
|
||||||
// format (at new line, literal <>): #include <filename>
|
// format (at new line, literal <>): #include <filename>
|
||||||
// or: #include "filename"
|
// or: #include "filename"
|
||||||
// note: don't write include back
|
// note: don't write include back
|
||||||
if (!p.was_newl() || !starts_with(p, "#include"))
|
if (!p.was_newl() || !starts_with(p, "#include"))
|
||||||
return nullptr;
|
return type_safe::nullopt;
|
||||||
p.skip(std::strlen("#include"));
|
p.skip(std::strlen("#include"));
|
||||||
if (starts_with(p, "_next"))
|
if (starts_with(p, "_next"))
|
||||||
p.skip(std::strlen("_next"));
|
p.skip(std::strlen("_next"));
|
||||||
|
|
@ -544,16 +616,10 @@ namespace
|
||||||
// don't skip newline
|
// don't skip newline
|
||||||
|
|
||||||
if (!in_main_file)
|
if (!in_main_file)
|
||||||
return nullptr;
|
return type_safe::nullopt;
|
||||||
|
|
||||||
auto result = cpp_include_directive::build(cpp_file_ref(cpp_entity_id(filename), filename),
|
return detail::pp_include{cpp_file_ref(cpp_entity_id(filename), filename), include_kind,
|
||||||
include_kind);
|
p.cur_line()};
|
||||||
if (!output.comments.empty() && output.comments.back().matches(*result, p.cur_line()))
|
|
||||||
{
|
|
||||||
result->set_comment(std::move(output.comments.back().comment));
|
|
||||||
output.comments.pop_back();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bump_pragma(position& p)
|
bool bump_pragma(position& p)
|
||||||
|
|
@ -568,80 +634,6 @@ namespace
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct linemarker
|
|
||||||
{
|
|
||||||
std::string file;
|
|
||||||
unsigned line;
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
line_directive, // no change in file
|
|
||||||
enter_new, // open a new file
|
|
||||||
enter_old, // return to an old file
|
|
||||||
} flag = line_directive;
|
|
||||||
bool is_system = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
ts::optional<linemarker> parse_linemarker(position& p)
|
|
||||||
{
|
|
||||||
// format (at new line): # <line> "<filename>" <flags>
|
|
||||||
// flag 1: enter_new
|
|
||||||
// flag 2: enter_old
|
|
||||||
// flag 3: system file
|
|
||||||
// flag 4: ignored
|
|
||||||
if (!p.was_newl() || !starts_with(p, "#"))
|
|
||||||
return ts::nullopt;
|
|
||||||
p.skip();
|
|
||||||
DEBUG_ASSERT(!starts_with(p, "define") && !starts_with(p, "undef")
|
|
||||||
&& !starts_with(p, "pragma"),
|
|
||||||
detail::assert_handler{}, "handle macros first");
|
|
||||||
|
|
||||||
linemarker result;
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
for (skip_spaces(p); std::isdigit(*p.ptr()); p.skip())
|
|
||||||
line += *p.ptr();
|
|
||||||
result.line = unsigned(std::stoi(line));
|
|
||||||
|
|
||||||
skip_spaces(p);
|
|
||||||
DEBUG_ASSERT(*p.ptr() == '"', detail::assert_handler{});
|
|
||||||
p.skip();
|
|
||||||
|
|
||||||
std::string file_name;
|
|
||||||
for (; !starts_with(p, "\""); p.skip())
|
|
||||||
file_name += *p.ptr();
|
|
||||||
p.skip();
|
|
||||||
result.file = std::move(file_name);
|
|
||||||
|
|
||||||
for (; !starts_with(p, "\n"); p.skip())
|
|
||||||
{
|
|
||||||
skip_spaces(p);
|
|
||||||
|
|
||||||
switch (*p.ptr())
|
|
||||||
{
|
|
||||||
case '1':
|
|
||||||
DEBUG_ASSERT(result.flag == linemarker::line_directive, detail::assert_handler{});
|
|
||||||
result.flag = linemarker::enter_new;
|
|
||||||
break;
|
|
||||||
case '2':
|
|
||||||
DEBUG_ASSERT(result.flag == linemarker::line_directive, detail::assert_handler{});
|
|
||||||
result.flag = linemarker::enter_old;
|
|
||||||
break;
|
|
||||||
case '3':
|
|
||||||
result.is_system = true;
|
|
||||||
break;
|
|
||||||
case '4':
|
|
||||||
break; // ignored
|
|
||||||
|
|
||||||
default:
|
|
||||||
DEBUG_UNREACHABLE(detail::assert_handler{}, "invalid line marker");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p.skip();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
detail::preprocessor_output detail::preprocess(const libclang_compile_config& config,
|
detail::preprocessor_output detail::preprocess(const libclang_compile_config& config,
|
||||||
|
|
@ -682,7 +674,7 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co
|
||||||
severity::debug});
|
severity::debug});
|
||||||
}
|
}
|
||||||
|
|
||||||
result.entities.push_back({std::move(macro), p.cur_line()});
|
result.macros.push_back({std::move(macro), p.cur_line()});
|
||||||
}
|
}
|
||||||
else if (auto undef = parse_undef(p))
|
else if (auto undef = parse_undef(p))
|
||||||
{
|
{
|
||||||
|
|
@ -695,26 +687,24 @@ detail::preprocessor_output detail::preprocess(const libclang_compile_config& co
|
||||||
diagnostic{std::move(message), source_location::make_file(path),
|
diagnostic{std::move(message), source_location::make_file(path),
|
||||||
severity::debug});
|
severity::debug});
|
||||||
}
|
}
|
||||||
result.entities
|
result.macros.erase(std::remove_if(result.macros.begin(), result.macros.end(),
|
||||||
.erase(std::remove_if(result.entities.begin(), result.entities.end(),
|
[&](const pp_macro& e) {
|
||||||
[&](const pp_entity& e) {
|
return e.macro->name() == undef.value();
|
||||||
return e.entity->kind()
|
}),
|
||||||
== cpp_entity_kind::macro_definition_t
|
result.macros.end());
|
||||||
&& e.entity->name() == undef.value();
|
|
||||||
}),
|
|
||||||
result.entities.end());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (auto include = parse_include(p, result, file_depth == 0u))
|
else if (auto include = parse_include(p, file_depth == 0u))
|
||||||
{
|
{
|
||||||
if (logger.is_verbose())
|
if (logger.is_verbose())
|
||||||
{
|
{
|
||||||
auto message = detail::format("parsing include '", include->name(), "'");
|
auto message =
|
||||||
|
detail::format("parsing include '", include.value().file.name(), "'");
|
||||||
logger.log("preprocessor",
|
logger.log("preprocessor",
|
||||||
diagnostic{std::move(message), source_location::make_file(path),
|
diagnostic{std::move(message), source_location::make_file(path),
|
||||||
severity::debug});
|
severity::debug});
|
||||||
}
|
}
|
||||||
result.entities.push_back({std::move(include), p.cur_line()});
|
result.includes.push_back(std::move(include.value()));
|
||||||
}
|
}
|
||||||
else if (bump_pragma(p))
|
else if (bump_pragma(p))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,17 @@ namespace cppast
|
||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
struct pp_entity
|
struct pp_macro
|
||||||
{
|
{
|
||||||
std::unique_ptr<cpp_entity> entity;
|
std::unique_ptr<cpp_macro_definition> macro;
|
||||||
unsigned line;
|
unsigned line;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct pp_include
|
||||||
|
{
|
||||||
|
cpp_file_ref file;
|
||||||
|
cpp_include_kind kind;
|
||||||
|
unsigned line;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pp_doc_comment
|
struct pp_doc_comment
|
||||||
|
|
@ -35,7 +42,8 @@ namespace cppast
|
||||||
struct preprocessor_output
|
struct preprocessor_output
|
||||||
{
|
{
|
||||||
std::string source;
|
std::string source;
|
||||||
std::vector<pp_entity> entities;
|
std::vector<pp_include> includes;
|
||||||
|
std::vector<pp_macro> macros;
|
||||||
std::vector<pp_doc_comment> comments;
|
std::vector<pp_doc_comment> comments;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,12 +107,14 @@ TEST_CASE("cpp_include_directive", "[!hide][clang4]")
|
||||||
REQUIRE(include.target().name() == include.name());
|
REQUIRE(include.target().name() == include.name());
|
||||||
REQUIRE(include.include_kind() == cppast::cpp_include_kind::system);
|
REQUIRE(include.include_kind() == cppast::cpp_include_kind::system);
|
||||||
REQUIRE(include.target().get(idx).empty());
|
REQUIRE(include.target().get(idx).empty());
|
||||||
|
REQUIRE_THAT(include.full_path(), Catch::EndsWith("iostream"));
|
||||||
}
|
}
|
||||||
else if (include.name() == "cpp_include_directive-header.hpp")
|
else if (include.name() == "cpp_include_directive-header.hpp")
|
||||||
{
|
{
|
||||||
REQUIRE(include.target().name() == include.name());
|
REQUIRE(include.target().name() == include.name());
|
||||||
REQUIRE(include.include_kind() == cppast::cpp_include_kind::local);
|
REQUIRE(include.include_kind() == cppast::cpp_include_kind::local);
|
||||||
REQUIRE(include.target().get(idx).empty());
|
REQUIRE(include.target().get(idx).empty());
|
||||||
|
REQUIRE(include.full_path() == "./cpp_include_directive-header.hpp");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
|
|
@ -126,6 +128,7 @@ TEST_CASE("cpp_include_directive", "[!hide][clang4]")
|
||||||
REQUIRE(include.include_kind() == cppast::cpp_include_kind::local);
|
REQUIRE(include.include_kind() == cppast::cpp_include_kind::local);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
equal_ref(idx, include.target(), cpp_file_ref(cpp_entity_id(""), "header_a.hpp")));
|
equal_ref(idx, include.target(), cpp_file_ref(cpp_entity_id(""), "header_a.hpp")));
|
||||||
|
REQUIRE(include.full_path() == "./header_a.hpp");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue