From 082cee92ca939a7d729f2bf1cbc7008b3560e992 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sat, 10 Jun 2023 15:47:21 +0200 Subject: [PATCH] Cleanup of CompileCommands class --- src/cmake.cpp | 2 +- src/compile_commands.cpp | 142 ++++++------------ src/compile_commands.hpp | 4 +- src/meson.cpp | 2 +- tests/compile_commands_test.cpp | 16 +- .../build/compile_commands.json | 5 - 6 files changed, 56 insertions(+), 115 deletions(-) diff --git a/src/cmake.cpp b/src/cmake.cpp index 06efaf2..22fd0f5 100644 --- a/src/cmake.cpp +++ b/src/cmake.cpp @@ -160,7 +160,7 @@ boost::filesystem::path CMake::get_executable(const boost::filesystem::path &bui std::vector> source_files_and_maybe_executables; for(auto &command : compile_commands.commands) { auto source_file = filesystem::get_normal_path(command.file); - auto values = command.parameter_values("-o"); + auto values = command.get_argument_values("-o"); if(!values.empty()) { size_t pos; if((pos = values[0].find("CMakeFiles/")) != std::string::npos) diff --git a/src/compile_commands.cpp b/src/compile_commands.cpp index fdb7c73..e2d1634 100644 --- a/src/compile_commands.cpp +++ b/src/compile_commands.cpp @@ -8,78 +8,30 @@ #include #include -std::vector CompileCommands::Command::parameter_values(const std::string ¶meter_name) const { - std::vector parameter_values; +std::vector CompileCommands::Command::get_argument_values(const std::string &argument_name) const { + std::vector argument_values; bool found_argument = false; - for(auto ¶meter : parameters) { + for(auto &argument : arguments) { if(found_argument) { - parameter_values.emplace_back(parameter); + argument_values.emplace_back(argument); found_argument = false; } - else if(parameter == parameter_name) + else if(argument == argument_name) found_argument = true; } - return parameter_values; + return argument_values; } CompileCommands::CompileCommands(const boost::filesystem::path &build_path) { - try { - JSON compile_commands(build_path / "compile_commands.json"); - for(auto &command : compile_commands.array()) { - boost::filesystem::path directory = command.string("directory"); - auto parameters_str = command.string("command"); - boost::filesystem::path file = command.string("file"); - - std::vector parameters; - bool backslash = false; - bool single_quote = false; - bool double_quote = false; - size_t parameter_start_pos = std::string::npos; - size_t parameter_size = 0; - auto add_parameter = [¶meters, ¶meters_str, ¶meter_start_pos, ¶meter_size] { - auto parameter = parameters_str.substr(parameter_start_pos, parameter_size); - // Remove escaping - for(size_t c = 0; c < parameter.size() - 1; ++c) { - if(parameter[c] == '\\') - parameter.replace(c, 2, std::string() + parameter[c + 1]); - } - parameters.emplace_back(std::move(parameter)); - }; - for(size_t c = 0; c < parameters_str.size(); ++c) { - if(backslash) - backslash = false; - else if(parameters_str[c] == '\\') - backslash = true; - else if((parameters_str[c] == ' ' || parameters_str[c] == '\t') && !backslash && !single_quote && !double_quote) { - if(parameter_start_pos != std::string::npos) { - add_parameter(); - parameter_start_pos = std::string::npos; - parameter_size = 0; - } - continue; - } - else if(parameters_str[c] == '\'' && !backslash && !double_quote) { - single_quote = !single_quote; - continue; - } - else if(parameters_str[c] == '\"' && !backslash && !single_quote) { - double_quote = !double_quote; - continue; - } - - if(parameter_start_pos == std::string::npos) - parameter_start_pos = c; - ++parameter_size; - } - if(parameter_start_pos != std::string::npos) - add_parameter(); - - commands.emplace_back(Command{std::move(directory), std::move(parameters), filesystem::get_absolute_path(file, build_path)}); - } - } - catch(...) { + clangmm::CompilationDatabase db(build_path.string()); + if(db) { + clangmm::CompileCommands compile_commands({}, db); + for(auto &command : compile_commands.get_commands()) + commands.emplace_back(Command{clangmm::to_string(clang_CompileCommand_getDirectory(command.cx_command)), + command.get_arguments(), + filesystem::get_absolute_path(clangmm::to_string(clang_CompileCommand_getFilename(command.cx_command)), build_path)}); } } @@ -89,46 +41,46 @@ std::vector CompileCommands::get_arguments(const boost::filesystem: auto extension = file_path.extension().string(); bool is_header = CompileCommands::is_header(file_path) || extension.empty(); // Include std C++ headers that are without extensions - // If header file, use source file flags if they are in the same folder - std::vector file_paths; - if(is_header && !extension.empty()) { - auto parent_path = file_path.parent_path(); - CompileCommands compile_commands(build_path); - for(auto &command : compile_commands.commands) { - if(command.file.parent_path() == parent_path) - file_paths.emplace_back(command.file); - } - } - - if(file_paths.empty()) - file_paths.emplace_back(file_path); - std::vector arguments; + if(!build_path.empty()) { clangmm::CompilationDatabase db(build_path.string()); if(db) { - for(auto &file_path : file_paths) { + std::vector> compile_commands_arguments; + // If header file, use source file flags if they are in the same folder + if(is_header && !extension.empty()) { + auto parent_path = file_path.parent_path(); + clangmm::CompileCommands compile_commands({}, db); + for(auto &command : compile_commands.get_commands()) { + boost::filesystem::path file = filesystem::get_absolute_path(clangmm::to_string(clang_CompileCommand_getFilename(command.cx_command)), build_path); + if(file.parent_path() == parent_path) + compile_commands_arguments.emplace_back(command.get_arguments()); + } + } + + if(compile_commands_arguments.empty()) { clangmm::CompileCommands compile_commands(file_path.string(), db); - auto commands = compile_commands.get_commands(); - for(auto &command : commands) { - auto cmd_arguments = command.get_arguments(); - bool ignore_next = false; - for(size_t c = 1; c + 1 < cmd_arguments.size(); c++) { // Exclude first and last argument - if(ignore_next) - ignore_next = false; - else if(cmd_arguments[c] == "-o" || - cmd_arguments[c] == "-x" || // Remove language arguments since some tools add languages not understood by clang - (is_header && cmd_arguments[c] == "-include-pch") || // Header files should not use precompiled headers - cmd_arguments[c] == "-MF") { // Exclude dependency file generation - ignore_next = true; - } - else if(cmd_arguments[c] == "-c") { - } - else if(cmd_arguments[c] == "--") // End of command options - break; - else - arguments.emplace_back(cmd_arguments[c]); + for(auto &command : compile_commands.get_commands()) + compile_commands_arguments.emplace_back(command.get_arguments()); + } + + for(auto &command_arguments : compile_commands_arguments) { + bool ignore_next = false; + for(size_t i = 1; i + 1 < command_arguments.size(); i++) { // Exclude first and last argument + if(ignore_next) + ignore_next = false; + else if(command_arguments[i] == "-o" || + command_arguments[i] == "-x" || // Remove language arguments since some tools add languages not understood by clang + (is_header && command_arguments[i] == "-include-pch") || // Header files should not use precompiled headers + command_arguments[i] == "-MF") { // Exclude dependency file generation + ignore_next = true; + } + else if(command_arguments[i] == "-c") { } + else if(command_arguments[i] == "--") // End of command options + break; + else + arguments.emplace_back(command_arguments[i]); } } } diff --git a/src/compile_commands.hpp b/src/compile_commands.hpp index 54f6424..deffd4e 100644 --- a/src/compile_commands.hpp +++ b/src/compile_commands.hpp @@ -8,10 +8,10 @@ public: class Command { public: boost::filesystem::path directory; - std::vector parameters; + std::vector arguments; boost::filesystem::path file; - std::vector parameter_values(const std::string ¶meter_name) const; + std::vector get_argument_values(const std::string &argument_name) const; }; CompileCommands(const boost::filesystem::path &build_path); diff --git a/src/meson.cpp b/src/meson.cpp index 91f75b1..9ef1754 100644 --- a/src/meson.cpp +++ b/src/meson.cpp @@ -135,7 +135,7 @@ boost::filesystem::path Meson::get_executable(const boost::filesystem::path &bui for(auto &command : compile_commands.commands) { auto source_file = filesystem::get_normal_path(command.file); - auto values = command.parameter_values("-o"); + auto values = command.get_argument_values("-o"); if(!values.empty()) { size_t pos; if((pos = values[0].find('@')) != std::string::npos) { diff --git a/tests/compile_commands_test.cpp b/tests/compile_commands_test.cpp index 537bf5d..f6ffedf 100644 --- a/tests/compile_commands_test.cpp +++ b/tests/compile_commands_test.cpp @@ -14,17 +14,11 @@ int main() { g_assert(compile_commands.commands.at(0).directory == "jucipp/tests/meson_old_test_files/build"); - g_assert_cmpuint(compile_commands.commands.size(), ==, 5); + g_assert_cmpuint(compile_commands.commands.size(), ==, 4); - g_assert_cmpstr(compile_commands.commands.at(4).parameters.at(0).c_str(), ==, "te's\"t"); - g_assert_cmpstr(compile_commands.commands.at(4).parameters.at(1).c_str(), ==, "te st"); - g_assert_cmpstr(compile_commands.commands.at(4).parameters.at(2).c_str(), ==, "test"); - g_assert_cmpstr(compile_commands.commands.at(4).parameters.at(3).c_str(), ==, "te\\st"); - g_assert_cmpstr(compile_commands.commands.at(4).parameters.at(4).c_str(), ==, "te\\\\st"); - - auto parameter_values = compile_commands.commands.at(0).parameter_values("-o"); - g_assert_cmpuint(parameter_values.size(), ==, 1); - g_assert_cmpstr(parameter_values.at(0).c_str(), ==, "hello_lib@sta/main.cpp.o"); + auto argument_values = compile_commands.commands.at(0).get_argument_values("-o"); + g_assert_cmpuint(argument_values.size(), ==, 1); + g_assert_cmpstr(argument_values.at(0).c_str(), ==, "hello_lib@sta/main.cpp.o"); g_assert(boost::filesystem::canonical(compile_commands.commands.at(0).file) == tests_path / "meson_old_test_files" / "main.cpp"); } @@ -36,6 +30,6 @@ int main() { g_assert_cmpuint(compile_commands.commands.size(), ==, 1); - g_assert_cmpstr(compile_commands.commands.at(0).parameters.at(2).c_str(), ==, "-Wall"); + g_assert_cmpstr(compile_commands.commands.at(0).arguments.at(3).c_str(), ==, "-Wall"); } } diff --git a/tests/meson_old_test_files/build/compile_commands.json b/tests/meson_old_test_files/build/compile_commands.json index 06f1990..5d86064 100644 --- a/tests/meson_old_test_files/build/compile_commands.json +++ b/tests/meson_old_test_files/build/compile_commands.json @@ -18,10 +18,5 @@ "directory": "jucipp/tests/meson_old_test_files/build", "command": "c++ '-Ianother_executable@exe' '-I..' '-I.' '-Wall' '-Winvalid-pch' '-Wnon-virtual-dtor' '-std=c++11' '-Wall' '-Wextra' '-O0' '-g' '-MMD' '-MQ' 'another_executable@exe/another_file.cpp.o' '-MF' 'another_executable@exe/another_file.cpp.o.d' -o 'another_executable@exe/another_file.cpp.o' -c ../another_file.cpp", "file": "../another_file.cpp" - }, - { - "directory": "jucipp/tests/meson_old_test_files/build", - "command": "'te\\'s\"t' te\\ st test te\\\\st te\\\\\\\\st", - "file": "../parse_test.cpp" } ]