diff --git a/src/source.h b/src/source.h index 97f78e4..e29a22f 100644 --- a/src/source.h +++ b/src/source.h @@ -76,7 +76,7 @@ namespace Source { std::function &views)> get_declaration_location; std::function &views)> get_implementation_location; std::function >(const std::vector &views)> get_usages; - std::function goto_method; + std::function >()> get_methods; std::function()> get_token_data; std::function get_token_spelling; std::function >(const std::vector &views, const std::string &text)> rename_similar_tokens; diff --git a/src/source_clang.cc b/src/source_clang.cc index 3a5f7a2..1353b39 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -1112,18 +1112,16 @@ Source::ClangViewAutocomplete(file_path, language) { return usages; }; - goto_method=[this](){ + get_methods=[this](){ + std::vector > methods; if(!parsed) { Info::get().print("Buffer is parsing"); - return; + return methods; } - auto iter=get_iter_for_dialog(); - selection_dialog=std::unique_ptr(new SelectionDialog(*this, get_buffer()->create_mark(iter), true, true)); - auto rows=std::make_shared >(); - auto methods=clang_tokens->get_cxx_methods(); - if(methods.size()==0) - return; - for(auto &method: methods) { + auto cxx_methods=clang_tokens->get_cxx_methods(); + if(cxx_methods.size()==0) + return methods; + for(auto &method: cxx_methods) { std::string row=std::to_string(method.second.line)+": "+Glib::Markup::escape_text(method.first); //Add bold method token size_t token_end_pos=row.find('('); @@ -1153,16 +1151,9 @@ Source::ClangViewAutocomplete(file_path, language) { (row[pos]>='0' && row[pos]<='9') || row[pos]=='_' || row[pos]=='~') && pos>0); row.insert(token_end_pos, ""); row.insert(pos+1, ""); - (*rows)[row]=method.second; - selection_dialog->add_row(row); + methods.emplace_back(Offset(method.second.line, method.second.index), row); } - selection_dialog->on_select=[this, rows](const std::string& selected, bool hide_window) { - auto offset=rows->at(selected); - get_buffer()->place_cursor(get_buffer()->get_iter_at_line_index(offset.line-1, offset.index-1)); - scroll_to(get_buffer()->get_insert(), 0.0, 1.0, 0.5); - delayed_tooltips_connection.disconnect(); - }; - selection_dialog->show(); + return methods; }; get_token_data=[this]() { diff --git a/src/window.cc b/src/window.cc index 48796b0..c459829 100644 --- a/src/window.cc +++ b/src/window.cc @@ -517,8 +517,25 @@ void Window::set_menu_actions() { }); menu.add_action("source_goto_method", [this]() { if(notebook.get_current_page()!=-1) { - if(notebook.get_current_view()->goto_method) { - notebook.get_current_view()->goto_method(); + auto view=notebook.get_current_view(); + if(view->get_methods) { + auto methods=notebook.get_current_view()->get_methods(); + if(!methods.empty()) { + auto iter=view->get_iter_for_dialog(); + view->selection_dialog=std::unique_ptr(new SelectionDialog(*view, view->get_buffer()->create_mark(iter), true, true)); + auto rows=std::make_shared >(); + for(auto &method: methods) { + (*rows)[method.second]=method.first; + view->selection_dialog->add_row(method.second); + } + view->selection_dialog->on_select=[view, rows](const std::string& selected, bool hide_window) { + auto offset=rows->at(selected); + view->get_buffer()->place_cursor(view->get_buffer()->get_iter_at_line_index(offset.line-1, offset.index-1)); + view->scroll_to(view->get_buffer()->get_insert(), 0.0, 1.0, 0.5); + view->delayed_tooltips_connection.disconnect(); + }; + view->selection_dialog->show(); + } } } }); @@ -790,7 +807,7 @@ void Window::activate_menu_items(bool activate) { menu.actions["source_goto_declaration"]->set_enabled(activate ? static_cast(notebook.get_current_view()->get_declaration_location) : false); menu.actions["source_goto_implementation"]->set_enabled(activate ? static_cast(notebook.get_current_view()->get_implementation_location) : false); menu.actions["source_goto_usage"]->set_enabled(activate ? static_cast(notebook.get_current_view()->get_usages) : false); - menu.actions["source_goto_method"]->set_enabled(activate ? static_cast(notebook.get_current_view()->goto_method) : false); + menu.actions["source_goto_method"]->set_enabled(activate ? static_cast(notebook.get_current_view()->get_methods) : false); menu.actions["source_rename"]->set_enabled(activate ? static_cast(notebook.get_current_view()->rename_similar_tokens) : false); menu.actions["source_goto_next_diagnostic"]->set_enabled(activate ? static_cast(notebook.get_current_view()->goto_next_diagnostic) : false); menu.actions["source_apply_fix_its"]->set_enabled(activate ? static_cast(notebook.get_current_view()->apply_fix_its) : false); diff --git a/tests/clang_project/main.cpp b/tests/clang_project/main.cpp index d1c3ab6..f4fe93a 100644 --- a/tests/clang_project/main.cpp +++ b/tests/clang_project/main.cpp @@ -1,11 +1,15 @@ -class Test { +class TestClass { public: + TestClass(); + ~TestClass() {} void function(); }; -void Test::function() {} +TestClass::TestClass() {} + +void TestClass::function() {} int main() { - Test test; + TestClass test; test.function(); } diff --git a/tests/source_clang_test.cc b/tests/source_clang_test.cc index f85197a..9acb5af 100644 --- a/tests/source_clang_test.cc +++ b/tests/source_clang_test.cc @@ -30,19 +30,55 @@ int main() { flush_events(); g_assert_cmpuint(clang_view->diagnostics.size(), ==, 0); - clang_view->place_cursor_at_line_index(10-1, 8-1); + //test get_declaration and get_implementation + clang_view->place_cursor_at_line_index(14-1, 8-1); flush_events(); auto location=clang_view->get_declaration_location({clang_view}); - g_assert_cmpuint(location.line, ==, 3); + g_assert_cmpuint(location.line, ==, 5); + clang_view->place_cursor_at_line_index(location.line-1, location.index-1); flush_events(); location=clang_view->get_implementation_location({clang_view}); - g_assert_cmpuint(location.line, ==, 6); + g_assert_cmpuint(location.line, ==, 10); + clang_view->place_cursor_at_line_index(location.line-1, location.index-1); flush_events(); location=clang_view->get_declaration_location({clang_view}); - g_assert_cmpuint(location.line, ==, 3); + g_assert_cmpuint(location.line, ==, 5); + + //test get_usages and get_methods + auto locations=clang_view->get_usages({clang_view}); + flush_events(); + g_assert_cmpuint(locations.size(), >, 0); + + locations=clang_view->get_methods(); + flush_events(); + g_assert_cmpuint(locations.size(), >, 0); + + //Test rename class (error if not constructor and destructor is renamed as well) + auto saved_main=clang_view->get_buffer()->get_text(); + clang_view->place_cursor_at_line_index(1-1, 7-1); + flush_events(); + auto token=clang_view->get_token(clang_view->get_buffer()->get_insert()->get_iter()); + g_assert_cmpstr(token.c_str(), ==, "TestClass"); + location=clang_view->get_declaration_location({clang_view}); + g_assert_cmpuint(location.line, ==, 1); + clang_view->rename_similar_tokens({clang_view}, "RenamedTestClass"); + flush_events(); + while(!clang_view->parsed) + flush_events(); + flush_events(); + auto iter=clang_view->get_buffer()->get_insert()->get_iter(); + iter.backward_char(); + token=clang_view->get_token(iter); + g_assert_cmpstr(token.c_str(), ==, "RenamedTestClass"); + flush_events(); + g_assert_cmpuint(clang_view->diagnostics.size(), ==, 0); + clang_view->get_buffer()->set_text(saved_main); + flush_events(); + clang_view->save({clang_view}); + //test error clang_view->get_buffer()->set_text(main_error); flush_events(); while(!clang_view->parsed)