From 8a006962bf782b8915e60fc39f0e3d01e9838fe7 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sat, 5 Aug 2017 13:18:56 +0200 Subject: [PATCH] Std headers are now parsed. Also moved Source::ClangViewParse::get_compilation_commands to CompileCommands::get_arguments and some cleanup." --- libclangmm | 2 +- src/compile_commands.cc | 63 +++++++ src/compile_commands.h | 3 + src/config.cc | 6 - src/config.h | 4 - src/ctags.cc | 9 +- src/source.cc | 8 + src/source_clang.cc | 158 ++---------------- src/source_clang.h | 3 - tests/source_clang_test.cc | 22 +-- .../build/compile_commands.json | 4 +- 11 files changed, 109 insertions(+), 173 deletions(-) diff --git a/libclangmm b/libclangmm index e687e95..955c113 160000 --- a/libclangmm +++ b/libclangmm @@ -1 +1 @@ -Subproject commit e687e95fa62b26fa3d6e930ffbbec8fb389cf30e +Subproject commit 955c113c73ecdfbf5fecc1c0b8fef537693c2f25 diff --git a/src/compile_commands.cc b/src/compile_commands.cc index 18846be..0c3731a 100644 --- a/src/compile_commands.cc +++ b/src/compile_commands.cc @@ -1,5 +1,7 @@ #include "compile_commands.h" +#include "clangmm.h" #include +#include std::vector CompileCommands::Command::parameter_values(const std::string ¶meter_name) const { std::vector parameter_values; @@ -77,3 +79,64 @@ CompileCommands::CompileCommands(const boost::filesystem::path &build_path) { } catch(...) {} } + +std::vector CompileCommands::get_arguments(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path) { + clangmm::CompilationDatabase db(build_path.string()); + clangmm::CompileCommands commands(file_path.string(), db); + std::vector cmds = commands.get_commands(); + std::vector arguments; + for (auto &cmd : cmds) { + auto cmd_arguments = cmd.get_arguments(); + bool ignore_next=false; + for (size_t c = 1; c < cmd_arguments.size(); c++) { + if(ignore_next) { + ignore_next=false; + continue; + } + else if(cmd_arguments[c]=="-o" || cmd_arguments[c]=="-c") { + ignore_next=true; + continue; + } + arguments.emplace_back(cmd_arguments[c]); + } + } + auto clang_version_string=clangmm::to_string(clang_getClangVersion()); + const static std::regex clang_version_regex("^[A-Za-z ]+([0-9.]+).*$"); + std::smatch sm; + if(std::regex_match(clang_version_string, sm, clang_version_regex)) { + auto clang_version=sm[1].str(); + arguments.emplace_back("-I/usr/lib/clang/"+clang_version+"/include"); + arguments.emplace_back("-I/usr/lib64/clang/"+clang_version+"/include"); // For Fedora +#if defined(__APPLE__) && CINDEX_VERSION_MAJOR==0 && CINDEX_VERSION_MINOR<32 // TODO: remove during 2018 if llvm3.7 is no longer in homebrew (CINDEX_VERSION_MINOR=32 equals clang-3.8 I think) + arguments.emplace_back("-I/usr/local/Cellar/llvm/"+clang_version+"/lib/clang/"+clang_version+"/include"); + arguments.emplace_back("-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1"); + arguments.emplace_back("-I/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1"); //Added for OS X 10.11 +#endif +#ifdef _WIN32 + auto env_msystem_prefix=std::getenv("MSYSTEM_PREFIX"); + if(env_msystem_prefix!=nullptr) + arguments.emplace_back("-I"+(boost::filesystem::path(env_msystem_prefix)/"lib/clang"/clang_version/"include").string()); +#endif + } + arguments.emplace_back("-fretain-comments-from-system-headers"); + + auto extension=file_path.extension().string(); + if(extension==".h" || //TODO: temporary fix for .h-files (parse as c++) + extension!=".c") + arguments.emplace_back("-xc++"); + + if(extension.empty()) { // For std headers + arguments.emplace_back("-xc++"); + arguments.emplace_back("-w"); // Disable all warnings + } + + if((extension.size()>1 && extension[1]=='h') || extension==".tcc") + arguments.emplace_back("-Wno-pragma-once-outside-header"); + + if(!build_path.empty()) { + arguments.emplace_back("-working-directory"); + arguments.emplace_back(build_path.string()); + } + + return arguments; +} diff --git a/src/compile_commands.h b/src/compile_commands.h index 50526eb..4dc77f9 100644 --- a/src/compile_commands.h +++ b/src/compile_commands.h @@ -18,6 +18,9 @@ public: CompileCommands(const boost::filesystem::path &build_path); std::vector commands; + + /// Return arguments for the given file using libclangmm + static std::vector get_arguments(const boost::filesystem::path &build_path, const boost::filesystem::path &file_path); }; #endif // JUCI_COMPILE_COMMANDS_H_ diff --git a/src/config.cc b/src/config.cc index f8de208..10c97f7 100644 --- a/src/config.cc +++ b/src/config.cc @@ -11,12 +11,6 @@ Config::Config() { if(home_path.empty()) throw std::runtime_error("Could not find home path"); home_juci_path=home_path/".juci"; - -#ifdef _WIN32 - auto env_MSYSTEM_PREFIX=std::getenv("MSYSTEM_PREFIX"); - if(env_MSYSTEM_PREFIX!=nullptr) - terminal.msys2_mingw_path=boost::filesystem::path(env_MSYSTEM_PREFIX); -#endif } void Config::load() { diff --git a/src/config.h b/src/config.h index b8c7941..4f5cdee 100644 --- a/src/config.h +++ b/src/config.h @@ -29,10 +29,6 @@ public: int history_size; std::string font; bool show_progress; - -#ifdef _WIN32 - boost::filesystem::path msys2_mingw_path; -#endif }; class Project { diff --git a/src/ctags.cc b/src/ctags.cc index 8e76fa5..31a0845 100644 --- a/src/ctags.cc +++ b/src/ctags.cc @@ -21,8 +21,13 @@ std::pair > Ctags::g if(!relative_debug_path.empty()) exclude+=" --exclude="+relative_debug_path.string(); } - else - run_path=path; + else { + boost::system::error_code ec; + if(boost::filesystem::is_directory(path, ec) || ec) + run_path=path; + else + run_path=path.parent_path(); + } std::stringstream stdin_stream; //TODO: when debian stable gets newer g++ version that supports move on streams, remove unique_ptr below diff --git a/src/source.cc b/src/source.cc index 0e436ad..3214bb7 100644 --- a/src/source.cc +++ b/src/source.cc @@ -32,6 +32,14 @@ Glib::RefPtr Source::guess_language(const boost::filesystem::path language=language_manager->get_language("makefile"); else if(file_path.extension()==".tcc") language=language_manager->get_language("cpphdr"); + else if(!file_path.has_extension()) { + for(auto &part: file_path) { + if(part=="include") { + language=language_manager->get_language("cpphdr"); + break; + } + } + } } return language; } diff --git a/src/source_clang.cc b/src/source_clang.cc index 0ca7ed5..16fdc34 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -10,6 +10,7 @@ #include "ctags.h" #include "selection_dialog.h" #include "filesystem.h" +#include "compile_commands.h" clangmm::Index Source::ClangViewParse::clang_index(0, 0); @@ -93,8 +94,15 @@ void Source::ClangViewParse::parse_initialize() { pos++; } auto &buffer_raw=const_cast(buffer.raw()); - remove_include_guard(buffer_raw); - clang_tu = std::make_unique(clang_index, file_path.string(), get_compilation_commands(), buffer_raw); + if(this->language && (this->language->get_id()=="chdr" || this->language->get_id()=="cpphdr")) + clangmm::remove_include_guard(buffer_raw); + + auto build=Project::Build::create(file_path); + if(build->project_path.empty()) + Info::get().print(file_path.filename().string()+": could not find a supported build system"); + build->update_default(); + auto arguments=CompileCommands::get_arguments(build->get_default_path(), file_path); + clang_tu = std::make_unique(clang_index, file_path.string(), arguments, buffer_raw); clang_tokens=clang_tu->get_tokens(0, buffer.bytes()-1); update_syntax(); @@ -124,7 +132,8 @@ void Source::ClangViewParse::parse_initialize() { } else if (parse_process_state==ParseProcessState::PROCESSING && parse_lock.try_lock()) { auto &parse_thread_buffer_raw=const_cast(parse_thread_buffer.raw()); - remove_include_guard(parse_thread_buffer_raw); + if(this->language && (this->language->get_id()=="chdr" || this->language->get_id()=="cpphdr")) + clangmm::remove_include_guard(parse_thread_buffer_raw); auto status=clang_tu->ReparseTranslationUnit(parse_thread_buffer_raw); parsing_in_progress->done("done"); if(status==0) { @@ -190,146 +199,6 @@ void Source::ClangViewParse::soft_reparse() { }, 1000); } -std::vector Source::ClangViewParse::get_compilation_commands() { - auto build=Project::Build::create(file_path); - if(build->project_path.empty()) - Info::get().print(file_path.filename().string()+": could not find a supported build system"); - auto default_build_path=build->get_default_path(); - build->update_default(); - clangmm::CompilationDatabase db(default_build_path.string()); - clangmm::CompileCommands commands(file_path.string(), db); - std::vector cmds = commands.get_commands(); - std::vector arguments; - for (auto &i : cmds) { - std::vector lol = i.get_command_as_args(); - for (size_t a = 1; a < lol.size()-4; a++) { - arguments.emplace_back(lol[a]); - } - } - auto clang_version_string=clangmm::to_string(clang_getClangVersion()); - const static std::regex clang_version_regex("^[A-Za-z ]+([0-9.]+).*$"); - std::smatch sm; - if(std::regex_match(clang_version_string, sm, clang_version_regex)) { - auto clang_version=sm[1].str(); - arguments.emplace_back("-I/usr/lib/clang/"+clang_version+"/include"); - arguments.emplace_back("-I/usr/lib64/clang/"+clang_version+"/include"); // For Fedora -#if defined(__APPLE__) && CINDEX_VERSION_MAJOR==0 && CINDEX_VERSION_MINOR<32 // TODO: remove during 2018 if llvm3.7 is no longer in homebrew (CINDEX_VERSION_MINOR=32 equals clang-3.8 I think) - arguments.emplace_back("-I/usr/local/Cellar/llvm/"+clang_version+"/lib/clang/"+clang_version+"/include"); - arguments.emplace_back("-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1"); - arguments.emplace_back("-I/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1"); //Added for OS X 10.11 -#endif -#ifdef _WIN32 - if(!Config::get().terminal.msys2_mingw_path.empty()) - arguments.emplace_back("-I"+(Config::get().terminal.msys2_mingw_path/"lib/clang"/clang_version/"include").string()); -#endif - } - arguments.emplace_back("-fretain-comments-from-system-headers"); - - if(file_path.extension()==".h" || //TODO: temporary fix for .h-files (parse as c++) - (language && (language->get_id()=="cpp" || language->get_id()=="cpphdr"))) - arguments.emplace_back("-xc++"); - - if(language && (language->get_id()=="chdr" || language->get_id()=="cpphdr")) - arguments.emplace_back("-Wno-pragma-once-outside-header"); - - if(!default_build_path.empty()) { - arguments.emplace_back("-working-directory"); - arguments.emplace_back(default_build_path.string()); - } - - return arguments; -} - -void Source::ClangViewParse::remove_include_guard(std::string &buffer) { - if(!(language && (language->get_id()=="chdr" || language->get_id()=="cpphdr"))) - return; - - static std::regex ifndef_regex1("^[ \t]*#ifndef[ \t]+([A-Za-z0-9_]+).*$"); - static std::regex ifndef_regex2("^[ \t]*#if[ \t]+![ \t]*defined[ \t]*\\([ \t]*([A-Za-z0-9_]+).*$"); - static std::regex define_regex("^[ \t]*#define[ \t]+([A-Za-z0-9_]+).*$"); - static std::regex endif_regex("^[ \t]*#endif.*$"); - std::vector> ranges; - bool found_ifndef=false, found_define=false; - bool line_comment=false, multiline_comment=false; - size_t start_of_line=0; - std::string line; - std::string preprocessor_identifier; - for(size_t c=0;c &offsets, int type) { @@ -642,7 +511,8 @@ Source::ClangViewAutocomplete::ClangViewAutocomplete(const boost::filesystem::pa autocomplete.get_suggestions=[this](std::string &buffer, int line_number, int column) { auto suggestions=std::make_shared>(); - remove_include_guard(buffer); + if(this->language && (this->language->get_id()=="chdr" || this->language->get_id()=="cpphdr")) + clangmm::remove_include_guard(buffer); auto results=clang_tu->get_code_completions(buffer, line_number, column); if(results.cx_results==nullptr) { auto expected=ParseState::PROCESSING; diff --git a/src/source_clang.h b/src/source_clang.h index 71b0903..26572d7 100644 --- a/src/source_clang.h +++ b/src/source_clang.h @@ -33,8 +33,6 @@ namespace Source { std::shared_ptr parsing_in_progress; - void remove_include_guard(std::string &buffer); - void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) override; void show_type_tooltips(const Gdk::Rectangle &rectangle) override; @@ -55,7 +53,6 @@ namespace Source { std::vector clang_diagnostics; static clangmm::Index clang_index; - std::vector get_compilation_commands(); }; class ClangViewAutocomplete : public virtual ClangViewParse { diff --git a/tests/source_clang_test.cc b/tests/source_clang_test.cc index 44c0e3c..71190e0 100644 --- a/tests/source_clang_test.cc +++ b/tests/source_clang_test.cc @@ -84,50 +84,50 @@ int main() { { clang_view->language=Gsv::LanguageManager::get_default()->get_language("chdr"); std::string source="#ifndef F\n#define F\n#endif // F"; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(source.c_str(),==," \n \n "); source="#ifndef F\n#define F\n#endif // F\n"; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(source.c_str(),==," \n \n \n"); source="/*test*/\n#ifndef F\n#define F\n#endif // F\n"; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(source.c_str(),==,"/*test*/\n \n \n \n"); source="//test\n#ifndef F\n#define F\n#endif // F\n"; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(source.c_str(),==,"//test\n \n \n \n"); source="#ifndef F /*test*/\n#define F\n#endif // F"; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(source.c_str(),==," \n \n "); source="#ifndef F //test\n#define F\n#endif // F"; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(source.c_str(),==," \n \n "); source="#ifndef F\n//test\n#define F\n#endif // F\n"; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(source.c_str(),==," \n//test\n \n \n"); source="#if !defined(F)\n#define F\n#endif\n"; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(source.c_str(),==," \n \n \n"); source="#ifndef F\ntest\n#define F\n#endif // F\n"; auto old_source=source; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(old_source.c_str(),==,source.c_str()); source="test\n#ifndef F\n#define F\n#endif // F\n"; old_source=source; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(old_source.c_str(),==,source.c_str()); source="#ifndef F\n#define F\n#endif // F\ntest\n"; old_source=source; - clang_view->remove_include_guard(source); + clangmm::remove_include_guard(source); g_assert_cmpstr(old_source.c_str(),==,source.c_str()); } diff --git a/tests/source_clang_test_files/build/compile_commands.json b/tests/source_clang_test_files/build/compile_commands.json index 829dcc1..f03ce43 100644 --- a/tests/source_clang_test_files/build/compile_commands.json +++ b/tests/source_clang_test_files/build/compile_commands.json @@ -1,7 +1,7 @@ [ { "directory": ".", - "command": "c++ -std=c++1y -Wall -Wextra -Wno-unused-parameter -o CMakeFiles/test.dir/main.cpp.o main.cpp", + "command": "c++ -std=c++1y -Wall -Wextra -Wno-unused-parameter -o CMakeFiles/test.dir/main.cpp.o -c main.cpp", "file": "../main.cpp" } -] \ No newline at end of file +]