From 679fbcdcbc0f47b6bd1850b21d6944f4265b0f27 Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 17 Jul 2020 08:38:23 +0200 Subject: [PATCH] C/C++: can now cancel waiting for parsing buffers, and added check for crashed libclang processes in wait_parsing() --- src/source_clang.cpp | 51 +++++++++++++++++++++++++++----------------- src/source_clang.hpp | 2 +- src/usages_clang.cpp | 4 ++-- 3 files changed, 34 insertions(+), 23 deletions(-) diff --git a/src/source_clang.cpp b/src/source_clang.cpp index 0b1244a..01302b7 100644 --- a/src/source_clang.cpp +++ b/src/source_clang.cpp @@ -1088,7 +1088,8 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file } auto identifier = get_identifier(); if(identifier) { - wait_parsing(); + if(!wait_parsing()) + return; std::vector translation_units; translation_units.emplace_back(clang_tu.get()); @@ -1336,7 +1337,8 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file std::vector offsets; if(identifier) { if(parsed) { - wait_parsing(); // Wait for other views to finish parsing + if(!wait_parsing()) + return offsets; // First, look for a definition cursor that is equal auto identifier_usr = identifier.cursor.get_usr(); @@ -1528,7 +1530,8 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file } auto identifier = get_identifier(); if(identifier) { - wait_parsing(); + if(!wait_parsing()) + return usages; auto embolden_token = [](std::string &line, unsigned token_start_pos, unsigned token_end_pos) { //markup token as bold @@ -1844,36 +1847,44 @@ Source::ClangViewRefactor::Identifier Source::ClangViewRefactor::get_identifier( return Identifier(); } -void Source::ClangViewRefactor::wait_parsing() { +bool Source::ClangViewRefactor::wait_parsing() { hide_tooltips(); - std::unique_ptr message; - std::vector clang_views; + std::vector not_parsed_clang_views; for(auto &view : views) { if(auto clang_view = dynamic_cast(view)) { - if(!clang_view->parsed && !clang_view->selected_completion_string) { - clang_views.emplace_back(clang_view); - if(!message) - message = std::make_unique("Please wait while all buffers finish parsing"); - } + if(!clang_view->parsed && !clang_view->selected_completion_string) + not_parsed_clang_views.emplace_back(clang_view); } } - if(message) { + if(!not_parsed_clang_views.empty()) { + bool canceled = false; + auto message = std::make_unique("Please wait while all buffers finish parsing", [&canceled] { + canceled = true; + }, true); + ScopeGuard guard{[&message] { + message->hide(); + }}; while(true) { - bool all_parsed = true; - for(auto &clang_view : clang_views) { - if(!clang_view->parsed) { - all_parsed = false; - break; + size_t not_parsed = 0; + for(auto &clang_view : not_parsed_clang_views) { + if(clang_view->parse_state == ParseState::stop) { + Info::get().print("Canceled due to parsing error in " + clang_view->file_path.string()); + return false; } + if(!clang_view->parsed) + ++not_parsed; } - if(all_parsed) - break; + if(not_parsed == 0) + return true; + if(canceled) + return false; + message->set_fraction(static_cast(not_parsed_clang_views.size() - not_parsed) / not_parsed_clang_views.size()); while(Gtk::Main::events_pending()) Gtk::Main::iteration(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - message->hide(); } + return true; } void Source::ClangViewRefactor::apply_similar_symbol_tag() { diff --git a/src/source_clang.hpp b/src/source_clang.hpp index 36cbed6..c3ada0b 100644 --- a/src/source_clang.hpp +++ b/src/source_clang.hpp @@ -100,7 +100,7 @@ namespace Source { private: Identifier get_identifier(); - void wait_parsing(); + bool wait_parsing(); }; class ClangView : public ClangViewAutocomplete, public ClangViewRefactor { diff --git a/src/usages_clang.cpp b/src/usages_clang.cpp index 4766d4e..baf0f6e 100644 --- a/src/usages_clang.cpp +++ b/src/usages_clang.cpp @@ -171,16 +171,16 @@ std::vector Usages::Clang::get_usages(const boost::filesy std::atomic tasks_completed = {0}; if(tasks != 0) { message = create_message(); - while(cache_in_progress_count != 0) { + while(cache_in_progress_count != 0 && !canceled) { message->set_fraction((static_cast(tasks - cache_in_progress_count) / tasks) / 10.0); while(Gtk::Main::events_pending()) Gtk::Main::iteration(); std::this_thread::sleep_for(std::chrono::milliseconds(10)); } } - tasks_completed = tasks; if(canceled) return {}; + tasks_completed = tasks; // Use cache for(auto it = potential_paths.begin(); it != potential_paths.end();) {