#include "cmake.h" #include "singletons.h" #include "filesystem.h" #include #include "dialogs.h" #include //TODO: remove using namespace std; //TODO: remove CMake::CMake(const boost::filesystem::path &path) { const auto find_cmake_project=[this](const boost::filesystem::path &cmake_path) { for(auto &line: filesystem::read_lines(cmake_path)) { const std::regex project_regex("^ *project *\\(.*$"); std::smatch sm; if(std::regex_match(line, sm, project_regex)) { return true; } } return false; }; auto search_path=path; auto search_cmake_path=search_path; search_cmake_path+="/CMakeLists.txt"; if(boost::filesystem::exists(search_cmake_path)) paths.emplace(paths.begin(), search_cmake_path); if(find_cmake_project(search_cmake_path)) project_path=search_path; else { do { search_path=search_path.parent_path(); search_cmake_path=search_path; search_cmake_path+="/CMakeLists.txt"; if(boost::filesystem::exists(search_cmake_path)) paths.emplace(paths.begin(), search_cmake_path); if(find_cmake_project(search_cmake_path)) { project_path=search_path; break; } } while(search_path!=search_path.root_directory()); } if(!project_path.empty()) { if(boost::filesystem::exists(project_path/"CMakeLists.txt") && !boost::filesystem::exists(project_path/"compile_commands.json")) create_compile_commands(project_path); } } bool CMake::create_compile_commands(const boost::filesystem::path &path) { auto message=Dialog::Message("Creating "+path.string()+"/compile_commands.json"); message.wait_until_drawn(); auto exit_code=Singleton::terminal->execute(Singleton::config->terminal.cmake_command+" . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON", path); message.hide(); if(exit_code==EXIT_SUCCESS) { #ifdef _WIN32 //Temporary fix to MSYS2's libclang auto compile_commands_path=path; compile_commands_path+="/compile_commands.json"; auto compile_commands_file=filesystem::read(compile_commands_path); size_t pos=0; while((pos=compile_commands_file.find("-I/", pos))!=std::string::npos) { if(pos+3start_line) { auto line=file.substr(start_line, end_line-start_line); const std::regex set_regex("^ *set *\\( *([A-Za-z_][A-Za-z_0-9]*) +(.*)\\) *$"); std::smatch sm; if(std::regex_match(line, sm, set_regex)) { auto data=sm[2].str(); while(data.size()>0 && data.back()==' ') data.pop_back(); parse_variable_parameters(data); variables[sm[1].str()]=data; } } pos=end_line+1; } } } void CMake::parse_variable_parameters(std::string &data) { size_t pos=0; bool inside_quote=false; char last_char=0; while(pos CMake::get_function_parameters(std::string &data) { std::vector parameters; size_t pos=0; size_t parameter_pos=0; bool inside_quote=false; char last_char=0; while(pos > > CMake::get_functions_parameters(const std::string &name) { if(!parsed) parse(); std::vector > > functions; size_t file_c=0; for(auto &file: files) { size_t pos=0; while(posstart_line) { auto line=file.substr(start_line, end_line-start_line); const std::regex function_regex("^ *"+name+" *\\( *(.*)\\) *$"); std::smatch sm; if(std::regex_match(line, sm, function_regex)) { auto data=sm[1].str(); while(data.size()>0 && data.back()==' ') data.pop_back(); auto parameters=get_function_parameters(data); functions.emplace(functions.begin(), paths[file_c], parameters); } } pos=end_line+1; } file_c++; } return functions; }