Browse Source

Improvement of primary-right click: now goes to declaration if no implementation was found (related to #317)

merge-requests/365/head
eidheim 9 years ago
parent
commit
30e0eace01
  1. 7
      src/source.cc
  2. 2
      src/source.h
  3. 150
      src/source_clang.cc
  4. 18
      src/window.cc

7
src/source.cc

@ -2246,15 +2246,10 @@ bool Source::View::on_button_press_event(GdkEventButton *event) {
if(iter) if(iter)
get_buffer()->place_cursor(iter); get_buffer()->place_cursor(iter);
if(is_implementation_location) { Menu::get().actions["source_goto_declaration_or_implementation"]->activate();
if(is_implementation_location())
Menu::get().actions["source_goto_declaration"]->activate();
else
Menu::get().actions["source_goto_implementation"]->activate();
return true; return true;
} }
} }
}
// Open right click menu // Open right click menu
if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)){ if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)){

2
src/source.h

@ -68,8 +68,8 @@ namespace Source {
std::function<void()> non_interactive_completion; std::function<void()> non_interactive_completion;
std::function<void()> format_style; std::function<void()> format_style;
std::function<Offset()> get_declaration_location; std::function<Offset()> get_declaration_location;
std::function<bool()> is_implementation_location;
std::function<std::vector<Offset>(const std::vector<Source::View*> &views)> get_implementation_locations; std::function<std::vector<Offset>(const std::vector<Source::View*> &views)> get_implementation_locations;
std::function<std::vector<Offset>(const std::vector<Source::View*> &views)> get_declaration_or_implementation_locations;
std::function<std::vector<std::pair<Offset, std::string> >(const std::vector<Source::View*> &views)> get_usages; std::function<std::vector<std::pair<Offset, std::string> >(const std::vector<Source::View*> &views)> get_usages;
std::function<std::string()> get_method; std::function<std::string()> get_method;
std::function<std::vector<std::pair<Offset, std::string> >()> get_methods; std::function<std::vector<std::pair<Offset, std::string> >()> get_methods;

150
src/source_clang.cc

@ -1012,7 +1012,14 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
} }
}); });
auto get_header_location=[this]() { auto declaration_location=[this]() {
auto identifier=get_identifier();
if(identifier) {
auto source_location=identifier.cursor.get_canonical().get_source_location();
auto offset=source_location.get_offset();
return Offset(offset.line-1, offset.index-1, source_location.get_path());
}
else {
// If cursor is at an include line, return offset to included file // If cursor is at an include line, return offset to included file
const static std::regex include_regex("^[ \t]*#[ \t]*include[ \t]*[<\"]([^<>\"]+)[>\"].*$"); const static std::regex include_regex("^[ \t]*#[ \t]*include[ \t]*[<\"]([^<>\"]+)[>\"].*$");
std::smatch sm; std::smatch sm;
@ -1062,50 +1069,23 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
if(!client_data.found_include.empty()) if(!client_data.found_include.empty())
return Offset(0, 0, client_data.found_include); return Offset(0, 0, client_data.found_include);
} }
}
return Offset(); return Offset();
}; };
get_declaration_location=[this, get_header_location](){ get_declaration_location=[this, declaration_location](){
if(!parsed) { if(!parsed) {
Info::get().print("Buffer is parsing"); Info::get().print("Buffer is parsing");
return Offset(); return Offset();
} }
auto identifier=get_identifier(); auto offset=declaration_location();
if(identifier) { if(!offset)
auto source_location=identifier.cursor.get_canonical().get_source_location();
auto offset=source_location.get_offset();
return Offset(offset.line-1, offset.index-1, source_location.get_path());
}
else {
auto location=get_header_location();
if(location)
return location;
}
Info::get().print("No declaration found"); Info::get().print("No declaration found");
return Offset(); return offset;
}; };
is_implementation_location=[this]() { auto implementation_locations=[this](const std::vector<Source::View*> &views) {
if(!parsed) std::vector<Offset> offsets;
return false;
auto iter=get_buffer()->get_insert()->get_iter();
auto line=static_cast<unsigned>(iter.get_line());
auto index=static_cast<unsigned>(iter.get_line_index());
for(auto &token: *clang_tokens) {
if(token.is_identifier()) {
if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index <=token.offsets.second.index-1)
return clang_isCursorDefinition(token.get_cursor().cx_cursor)>0;
}
}
return false;
};
get_implementation_locations=[this, get_header_location](const std::vector<Source::View*> &views){
std::vector<Offset> locations;
if(!parsed) {
Info::get().print("Buffer is parsing");
return locations;
}
auto identifier=get_identifier(); auto identifier=get_identifier();
if(identifier) { if(identifier) {
wait_parsing(views); wait_parsing(views);
@ -1122,32 +1102,32 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
if(referenced && identifier.kind==referenced.get_kind() && if(referenced && identifier.kind==referenced.get_kind() &&
identifier.spelling==token.get_spelling() && identifier.usr==referenced.get_usr()) { identifier.spelling==token.get_spelling() && identifier.usr==referenced.get_usr()) {
if(clang_isCursorDefinition(referenced.cx_cursor)) { if(clang_isCursorDefinition(referenced.cx_cursor)) {
Offset location; Offset offset;
location.file_path=cursor.get_source_location().get_path(); offset.file_path=cursor.get_source_location().get_path();
auto clang_offset=cursor.get_source_location().get_offset(); auto clang_offset=cursor.get_source_location().get_offset();
location.line=clang_offset.line-1; offset.line=clang_offset.line-1;
location.index=clang_offset.index-1; offset.index=clang_offset.index-1;
locations.emplace_back(location); offsets.emplace_back(offset);
} }
} }
} }
} }
} }
} }
if(!locations.empty()) if(!offsets.empty())
return locations; return offsets;
//If no implementation was found, try using clang_getCursorDefinition //If no implementation was found, try using clang_getCursorDefinition
auto definition=identifier.cursor.get_definition(); auto definition=identifier.cursor.get_definition();
if(definition) { if(definition) {
auto definition_location=definition.get_source_location(); auto definition_location=definition.get_source_location();
Offset location; Offset offset;
location.file_path=definition_location.get_path(); offset.file_path=definition_location.get_path();
auto offset=definition_location.get_offset(); auto definition_offset=definition_location.get_offset();
location.line=offset.line-1; offset.line=definition_offset.line-1;
location.index=offset.index-1; offset.index=definition_offset.index-1;
locations.emplace_back(location); offsets.emplace_back(offset);
return locations; return offsets;
} }
//If no implementation was found, try using Ctags //If no implementation was found, try using Ctags
@ -1161,24 +1141,72 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
auto ctags_locations=Ctags::get_locations(this->file_path, name, identifier.cursor.get_type_description()); auto ctags_locations=Ctags::get_locations(this->file_path, name, identifier.cursor.get_type_description());
if(!ctags_locations.empty()) { if(!ctags_locations.empty()) {
for(auto &ctags_location: ctags_locations) { for(auto &ctags_location: ctags_locations) {
Offset location; Offset offset;
location.file_path=ctags_location.file_path; offset.file_path=ctags_location.file_path;
location.line=ctags_location.line; offset.line=ctags_location.line;
location.index=ctags_location.index; offset.index=ctags_location.index;
locations.emplace_back(location); offsets.emplace_back(offset);
}
return offsets;
}
}
return offsets;
};
get_implementation_locations=[this, implementation_locations](const std::vector<Source::View*> &views){
if(!parsed) {
Info::get().print("Buffer is parsing");
return std::vector<Offset>();
}
auto offsets=implementation_locations(views);
if(offsets.empty())
Info::get().print("No implementation found");
return offsets;
};
get_declaration_or_implementation_locations=[this, declaration_location, implementation_locations](const std::vector<Source::View*> &views) {
if(!parsed) {
Info::get().print("Buffer is parsing");
return std::vector<Offset>();
}
std::vector<Offset> offsets;
bool is_implementation=false;
auto iter=get_buffer()->get_insert()->get_iter();
auto line=static_cast<unsigned>(iter.get_line());
auto index=static_cast<unsigned>(iter.get_line_index());
for(auto &token: *clang_tokens) {
if(token.is_identifier()) {
if(line==token.offsets.first.line-1 && index>=token.offsets.first.index-1 && index<=token.offsets.second.index-1) {
if(clang_isCursorDefinition(token.get_cursor().cx_cursor)>0)
is_implementation=true;
break;
}
} }
return locations;
} }
// If cursor is at implementation, return declaration_location
if(is_implementation) {
auto offset=declaration_location();
if(offset)
offsets.emplace_back(offset);
} }
else { else {
auto location=get_header_location(); auto implementation_offsets=implementation_locations(views);
if(location) { if(!implementation_offsets.empty()) {
locations.emplace_back(location); offsets=std::move(implementation_offsets);
return locations;
} }
else {
auto offset=declaration_location();
if(offset)
offsets.emplace_back(offset);
} }
Info::get().print("No implementation found"); }
return locations;
if(offsets.empty())
Info::get().print("No declaration or implementation found");
return offsets;
}; };
get_usages=[this](const std::vector<Source::View*> &views) { get_usages=[this](const std::vector<Source::View*> &views) {

18
src/window.cc

@ -741,10 +741,7 @@ void Window::set_menu_actions() {
} }
} }
}); });
menu.add_action("source_goto_implementation", [this]() { auto goto_selected_location=[](Source::View *view, const std::vector<Source::Offset> &locations) {
if(auto view=Notebook::get().get_current_view()) {
if(view->get_implementation_locations) {
auto locations=view->get_implementation_locations(Notebook::get().get_views());
if(!locations.empty()) { if(!locations.empty()) {
auto dialog_iter=view->get_iter_for_dialog(); auto dialog_iter=view->get_iter_for_dialog();
SelectionDialog::create(view, view->get_buffer()->create_mark(dialog_iter), true, true); SelectionDialog::create(view, view->get_buffer()->create_mark(dialog_iter), true, true);
@ -779,7 +776,7 @@ void Window::set_menu_actions() {
view->scroll_to_cursor_delayed(view, true, false); view->scroll_to_cursor_delayed(view, true, false);
return; return;
} }
SelectionDialog::get()->on_select=[this, rows](const std::string &selected, bool hide_window) { SelectionDialog::get()->on_select=[rows](const std::string &selected, bool hide_window) {
auto location=rows->at(selected); auto location=rows->at(selected);
if(!boost::filesystem::is_regular_file(location.file_path)) if(!boost::filesystem::is_regular_file(location.file_path))
return; return;
@ -792,7 +789,17 @@ void Window::set_menu_actions() {
view->hide_tooltips(); view->hide_tooltips();
SelectionDialog::get()->show(); SelectionDialog::get()->show();
} }
};
menu.add_action("source_goto_implementation", [this, goto_selected_location]() {
if(auto view=Notebook::get().get_current_view()) {
if(view->get_implementation_locations)
goto_selected_location(view, view->get_implementation_locations(Notebook::get().get_views()));
} }
});
menu.add_action("source_goto_declaration_or_implementation", [this, goto_selected_location]() {
if(auto view=Notebook::get().get_current_view()) {
if(view->get_declaration_or_implementation_locations)
goto_selected_location(view, view->get_declaration_or_implementation_locations(Notebook::get().get_views()));
} }
}); });
@ -1202,6 +1209,7 @@ void Window::activate_menu_items() {
menu.actions["source_find_documentation"]->set_enabled(view && view->get_token_data); menu.actions["source_find_documentation"]->set_enabled(view && view->get_token_data);
menu.actions["source_goto_declaration"]->set_enabled(view && view->get_declaration_location); menu.actions["source_goto_declaration"]->set_enabled(view && view->get_declaration_location);
menu.actions["source_goto_implementation"]->set_enabled(view && view->get_implementation_locations); menu.actions["source_goto_implementation"]->set_enabled(view && view->get_implementation_locations);
menu.actions["source_goto_declaration_or_implementation"]->set_enabled(view && view->get_declaration_or_implementation_locations);
menu.actions["source_goto_usage"]->set_enabled(view && view->get_usages); menu.actions["source_goto_usage"]->set_enabled(view && view->get_usages);
menu.actions["source_goto_method"]->set_enabled(view && view->get_methods); menu.actions["source_goto_method"]->set_enabled(view && view->get_methods);
menu.actions["source_rename"]->set_enabled(view && view->rename_similar_tokens); menu.actions["source_rename"]->set_enabled(view && view->rename_similar_tokens);

Loading…
Cancel
Save