Add parse_database() function
This commit is contained in:
parent
38831db073
commit
7092946091
2 changed files with 66 additions and 18 deletions
|
|
@ -12,6 +12,7 @@
|
|||
namespace cppast
|
||||
{
|
||||
class libclang_compile_config;
|
||||
class libclang_compilation_database;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
|
@ -23,6 +24,9 @@ namespace cppast
|
|||
|
||||
static const std::vector<std::string>& flags(const libclang_compile_config& config);
|
||||
};
|
||||
|
||||
void for_each_file(const libclang_compilation_database& database, void* user_data,
|
||||
void (*callback)(void*, std::string));
|
||||
} // namespace detail
|
||||
|
||||
/// The exception thrown when a fatal parse error occurs.
|
||||
|
|
@ -77,6 +81,8 @@ namespace cppast
|
|||
database database_;
|
||||
|
||||
friend libclang_compile_config;
|
||||
friend void detail::for_each_file(const libclang_compilation_database& database,
|
||||
void* user_data, void (*callback)(void*, std::string));
|
||||
};
|
||||
|
||||
/// Compilation config for the [cppast::libclang_parser]().
|
||||
|
|
@ -168,7 +174,7 @@ namespace cppast
|
|||
///
|
||||
/// \throws [cppast::libclang_error]() if no configuration for a given file could be found in the database.
|
||||
///
|
||||
/// \requires `FileParser` must use [cppast::libclang_parser](),
|
||||
/// \requires `FileParser` must use the libclang parser.
|
||||
/// i.e. `FileParser::parser` must be an alias of [cppast::libclang_parser]().
|
||||
template <class FileParser, class Range>
|
||||
void parse_files(FileParser& parser, Range&& file_names,
|
||||
|
|
@ -183,6 +189,32 @@ namespace cppast
|
|||
return config.value();
|
||||
});
|
||||
}
|
||||
|
||||
/// Parses the files specified in a compilation database using a [cppast::libclang_parser]().
|
||||
///
|
||||
/// \effects For each file specified in a compilation database,
|
||||
/// uses the `FileParser` to parse the file with the configuration specified in the database.
|
||||
///
|
||||
/// \requires `FileParser` must have the same requirements as for [cppast::parse_files](standardese://parse_files_basic/).
|
||||
/// It must also use the libclang parser,
|
||||
/// i.e. `FileParser::parser` must be an alias of [cppast::libclang_parser]().
|
||||
template <class FileParser>
|
||||
void parse_database(FileParser& parser, const libclang_compilation_database& database)
|
||||
{
|
||||
static_assert(std::is_same<typename FileParser::parser, libclang_parser>::value,
|
||||
"must use the libclang parser");
|
||||
struct data_t
|
||||
{
|
||||
FileParser& parser;
|
||||
const libclang_compilation_database& database;
|
||||
} data{parser, database};
|
||||
detail::for_each_file(database, &data, [](void* ptr, std::string file) {
|
||||
auto& data = *static_cast<data_t*>(ptr);
|
||||
|
||||
libclang_compile_config config(data.database, file);
|
||||
data.parser.parse(std::move(file), std::move(config));
|
||||
});
|
||||
}
|
||||
} // namespace cppast
|
||||
|
||||
#endif // CPPAST_LIBCLANG_PARSER_HPP_INCLUDED
|
||||
|
|
|
|||
|
|
@ -103,6 +103,35 @@ namespace
|
|||
};
|
||||
|
||||
using cxcompile_commands = detail::raii_wrapper<CXCompileCommands, cxcompile_commands_deleter>;
|
||||
|
||||
std::string get_full_path(const detail::cxstring& dir, const std::string& file)
|
||||
{
|
||||
if (file.front() == '/' || file.front() == '\\')
|
||||
// absolute file
|
||||
return file;
|
||||
else if (dir[dir.length() - 1] != '/' && dir[dir.length() - 1] != '\\')
|
||||
// relative needing separator
|
||||
return dir.std_str() + '/' + file;
|
||||
else
|
||||
// relative w/o separator
|
||||
return dir.std_str() + file;
|
||||
}
|
||||
}
|
||||
|
||||
void detail::for_each_file(const libclang_compilation_database& database, void* user_data,
|
||||
void (*callback)(void*, std::string))
|
||||
{
|
||||
cxcompile_commands commands(
|
||||
clang_CompilationDatabase_getAllCompileCommands(database.database_));
|
||||
auto no = clang_CompileCommands_getSize(commands.get());
|
||||
for (auto i = 0u; i != no; ++i)
|
||||
{
|
||||
auto cmd = clang_CompileCommands_getCommand(commands.get(), i);
|
||||
|
||||
auto dir = cxstring(clang_CompileCommand_getDirectory(cmd));
|
||||
callback(user_data,
|
||||
get_full_path(dir, cxstring(clang_CompileCommand_getFilename(cmd)).std_str()));
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
@ -182,29 +211,16 @@ libclang_compile_config::libclang_compile_config(const libclang_compilation_data
|
|||
auto dir = detail::cxstring(clang_CompileCommand_getDirectory(cmd));
|
||||
parse_flags(cmd, [&](std::string flag, std::string args) {
|
||||
if (flag == "-I")
|
||||
{
|
||||
if (args.front() == '/' || args.front() == '\\')
|
||||
{
|
||||
add_flag(std::move(flag) + std::move(args));
|
||||
}
|
||||
else
|
||||
{
|
||||
// path relative to the directory
|
||||
if (dir[dir.length() - 1] != '/' && dir[dir.length() - 1] != '\\')
|
||||
add_flag(std::move(flag) + dir.std_str() + '/' + std::move(args));
|
||||
else
|
||||
add_flag(std::move(flag) + dir.std_str() + std::move(args));
|
||||
}
|
||||
}
|
||||
add_flag(std::move(flag) + get_full_path(dir, args));
|
||||
else if (flag == "-D" || flag == "-U")
|
||||
// preprocessor options
|
||||
this->add_flag(std::move(flag) + std::move(args));
|
||||
add_flag(std::move(flag) + std::move(args));
|
||||
else if (flag == "-std")
|
||||
// standard
|
||||
this->add_flag(std::move(flag) + "=" + std::move(args));
|
||||
add_flag(std::move(flag) + "=" + std::move(args));
|
||||
else if (flag == "-f" && (args == "ms-compatibility" || args == "ms-extensions"))
|
||||
// other options
|
||||
this->add_flag(std::move(flag) + std::move(args));
|
||||
add_flag(std::move(flag) + std::move(args));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue