Browse Source

Fixes to #317: Use primary-left click to move to implementation or declaration

merge-requests/365/head
eidheim 9 years ago
parent
commit
cfeef6c618
  1. 27
      src/source.cc
  2. 2
      src/source.h
  3. 118
      src/source_clang.cc

27
src/source.cc

@ -2213,6 +2213,7 @@ bool Source::View::on_key_press_event_smart_inserts(GdkEventKey *key) {
} }
bool Source::View::on_button_press_event(GdkEventButton *event) { bool Source::View::on_button_press_event(GdkEventButton *event) {
// Select range when double clicking
if(event->type==GDK_2BUTTON_PRESS) { if(event->type==GDK_2BUTTON_PRESS) {
Gtk::TextIter start, end; Gtk::TextIter start, end;
get_buffer()->get_selection_bounds(start, end); get_buffer()->get_selection_bounds(start, end);
@ -2230,14 +2231,32 @@ bool Source::View::on_button_press_event(GdkEventButton *event) {
return true; return true;
} }
// Go to implementation or declaration
if((event->type == GDK_BUTTON_PRESS) && (event->button == 1)){ if((event->type == GDK_BUTTON_PRESS) && (event->button == 1)){
if(event->state & GDK_CONTROL_MASK) { #ifdef __APPLE__
hide_tooltips(); GdkModifierType mask=GDK_MOD2_MASK;
Menu::get().actions["source_goto_implementation"]->activate(); #else
return true; GdkModifierType mask=GDK_CONTROL_MASK;
#endif
if(event->state & mask) {
int x, y;
window_to_buffer_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, event->x, event->y, x, y);
Gtk::TextIter iter;
get_iter_at_location(iter, x, y);
if(iter)
get_buffer()->place_cursor(iter);
if(is_implementation_location) {
if(is_implementation_location())
Menu::get().actions["source_goto_declaration"]->activate();
else
Menu::get().actions["source_goto_implementation"]->activate();
return true;
}
} }
} }
// Open right click menu
if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)){ if((event->type == GDK_BUTTON_PRESS) && (event->button == 3)){
hide_tooltips(); hide_tooltips();
if(!get_buffer()->get_has_selection()){ if(!get_buffer()->get_has_selection()){

2
src/source.h

@ -68,7 +68,7 @@ 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; 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<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;

118
src/source_clang.cc

@ -1012,7 +1012,60 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
} }
}); });
get_declaration_location=[this](){ auto get_header_location=[this]() {
// If cursor is at an include line, return offset to included file
const static std::regex include_regex("^[ \t]*#[ \t]*include[ \t]*[<\"](.+)[>\"][ \t]*$");
std::smatch sm;
auto line=get_line();
if(std::regex_match(line, sm, include_regex)) {
struct ClientData {
boost::filesystem::path &file_path;
std::string found_include;
int line_nr;
std::string sm_str;
};
ClientData client_data{this->file_path, std::string(), get_buffer()->get_insert()->get_iter().get_line(), sm[1].str()};
// Attempt to find the 100% correct include file first
clang_getInclusions(clang_tu->cx_tu, [](CXFile included_file, CXSourceLocation *inclusion_stack, unsigned include_len, CXClientData client_data_) {
auto client_data=static_cast<ClientData*>(client_data_);
if(client_data->found_include.empty() && include_len>0) {
auto source_location=clang::SourceLocation(inclusion_stack[0]);
if(static_cast<int>(source_location.get_offset().line)-1==client_data->line_nr &&
filesystem::get_normal_path(source_location.get_path())==client_data->file_path)
client_data->found_include=clang::to_string(clang_getFileName(included_file));
}
}, &client_data);
if(!client_data.found_include.empty())
return Offset(0, 0, client_data.found_include);
// Find a matching include file if no include was found previously
clang_getInclusions(clang_tu->cx_tu, [](CXFile included_file, CXSourceLocation *inclusion_stack, unsigned include_len, CXClientData client_data_) {
auto client_data=static_cast<ClientData*>(client_data_);
if(client_data->found_include.empty()) {
for(unsigned c=1;c<include_len;++c) {
auto source_location=clang::SourceLocation(inclusion_stack[c]);
if(static_cast<int>(source_location.get_offset().line)-1<=client_data->line_nr &&
filesystem::get_normal_path(source_location.get_path())==client_data->file_path) {
auto included_file_str=clang::to_string(clang_getFileName(included_file));
if(included_file_str.size()>=client_data->sm_str.size() &&
included_file_str.compare(included_file_str.size()-client_data->sm_str.size(), client_data->sm_str.size(), client_data->sm_str)==0) {
client_data->found_include=included_file_str;
break;
}
}
}
}
}, &client_data);
if(!client_data.found_include.empty())
return Offset(0, 0, client_data.found_include);
}
return Offset();
};
get_declaration_location=[this, get_header_location](){
if(!parsed) { if(!parsed) {
Info::get().print("Buffer is parsing"); Info::get().print("Buffer is parsing");
return Offset(); return Offset();
@ -1024,61 +1077,15 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
return Offset(offset.line-1, offset.index-1, source_location.get_path()); return Offset(offset.line-1, offset.index-1, source_location.get_path());
} }
else { else {
// If cursor is at an include line, return offset to included file auto location=get_header_location();
const static std::regex include_regex("^[ \t]*#[ \t]*include[ \t]*[<\"](.+)[>\"][ \t]*$"); if(location)
std::smatch sm; return location;
auto line=get_line();
if(std::regex_match(line, sm, include_regex)) {
struct ClientData {
boost::filesystem::path &file_path;
std::string found_include;
int line_nr;
std::string sm_str;
};
ClientData client_data{this->file_path, std::string(), get_buffer()->get_insert()->get_iter().get_line(), sm[1].str()};
// Attempt to find the 100% correct include file first
clang_getInclusions(clang_tu->cx_tu, [](CXFile included_file, CXSourceLocation *inclusion_stack, unsigned include_len, CXClientData client_data_) {
auto client_data=static_cast<ClientData*>(client_data_);
if(client_data->found_include.empty() && include_len>0) {
auto source_location=clang::SourceLocation(inclusion_stack[0]);
if(static_cast<int>(source_location.get_offset().line)-1==client_data->line_nr &&
filesystem::get_normal_path(source_location.get_path())==client_data->file_path)
client_data->found_include=clang::to_string(clang_getFileName(included_file));
}
}, &client_data);
if(!client_data.found_include.empty())
return Offset(0, 0, client_data.found_include);
// Find a matching include file if no include was found previously
clang_getInclusions(clang_tu->cx_tu, [](CXFile included_file, CXSourceLocation *inclusion_stack, unsigned include_len, CXClientData client_data_) {
auto client_data=static_cast<ClientData*>(client_data_);
if(client_data->found_include.empty()) {
for(unsigned c=1;c<include_len;++c) {
auto source_location=clang::SourceLocation(inclusion_stack[c]);
if(static_cast<int>(source_location.get_offset().line)-1<=client_data->line_nr &&
filesystem::get_normal_path(source_location.get_path())==client_data->file_path) {
auto included_file_str=clang::to_string(clang_getFileName(included_file));
if(included_file_str.size()>=client_data->sm_str.size() &&
included_file_str.compare(included_file_str.size()-client_data->sm_str.size(), client_data->sm_str.size(), client_data->sm_str)==0) {
client_data->found_include=included_file_str;
break;
}
}
}
}
}, &client_data);
if(!client_data.found_include.empty())
return Offset(0, 0, client_data.found_include);
}
} }
Info::get().print("No declaration found"); Info::get().print("No declaration found");
return Offset(); return Offset();
}; };
is_implementation=[this]() { is_implementation_location=[this]() {
if(!parsed) if(!parsed)
return false; return false;
auto iter=get_buffer()->get_insert()->get_iter(); auto iter=get_buffer()->get_insert()->get_iter();
@ -1093,7 +1100,7 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
return false; return false;
}; };
get_implementation_locations=[this](const std::vector<Source::View*> &views){ get_implementation_locations=[this, get_header_location](const std::vector<Source::View*> &views){
std::vector<Offset> locations; std::vector<Offset> locations;
if(!parsed) { if(!parsed) {
Info::get().print("Buffer is parsing"); Info::get().print("Buffer is parsing");
@ -1163,6 +1170,13 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
return locations; return locations;
} }
} }
else {
auto location=get_header_location();
if(location) {
locations.emplace_back(location);
return locations;
}
}
Info::get().print("No implementation found"); Info::get().print("No implementation found");
return locations; return locations;
}; };

Loading…
Cancel
Save