Browse Source

Go to Implementation: now shows a selection dialog if more than one implementation was found

merge-requests/365/head
eidheim 10 years ago
parent
commit
a2c4880429
  1. 13
      src/ctags.cc
  2. 2
      src/ctags.h
  3. 2
      src/source.h
  4. 54
      src/source_clang.cc
  5. 65
      src/window.cc
  6. 5
      tests/source_clang_test.cc

13
src/ctags.cc

@ -103,7 +103,7 @@ Ctags::Location Ctags::get_location(const std::string &line, bool markup) {
return location; return location;
} }
Ctags::Location Ctags::get_location(const boost::filesystem::path &path, const std::string &name, const std::string &type) { std::vector<Ctags::Location> Ctags::get_locations(const boost::filesystem::path &path, const std::string &name, const std::string &type) {
//insert name into type //insert name into type
size_t c=0; size_t c=0;
size_t bracket_count=0; size_t bracket_count=0;
@ -139,12 +139,12 @@ Ctags::Location Ctags::get_location(const boost::filesystem::path &path, const s
auto result=get_result(path); auto result=get_result(path);
result.second->seekg(0, std::ios::end); result.second->seekg(0, std::ios::end);
if(result.second->tellg()==0) if(result.second->tellg()==0)
return Location(); return std::vector<Location>();
result.second->seekg(0, std::ios::beg); result.second->seekg(0, std::ios::beg);
std::string line; std::string line;
size_t best_score=0; size_t best_score=0;
Location best_location; std::vector<Location> best_locations;
while(std::getline(*result.second, line)) { while(std::getline(*result.second, line)) {
if(line.find(name)==std::string::npos) if(line.find(name)==std::string::npos)
continue; continue;
@ -163,9 +163,12 @@ Ctags::Location Ctags::get_location(const boost::filesystem::path &path, const s
} }
if(score>best_score) { if(score>best_score) {
best_score=score; best_score=score;
best_location=location; best_locations.clear();
best_locations.emplace_back(location);
} }
else if(score==best_score)
best_locations.emplace_back(location);
} }
return best_location; return best_locations;
} }

2
src/ctags.h

@ -20,7 +20,7 @@ public:
static Location get_location(const std::string &line, bool markup); static Location get_location(const std::string &line, bool markup);
static Location get_location(const boost::filesystem::path &path, const std::string &name, const std::string &type); static std::vector<Location> get_locations(const boost::filesystem::path &path, const std::string &name, const std::string &type);
}; };
#endif //JUCI_CTAGS_H_ #endif //JUCI_CTAGS_H_

2
src/source.h

@ -60,7 +60,7 @@ namespace Source {
std::function<void()> auto_indent; std::function<void()> auto_indent;
std::function<Offset()> get_declaration_location; std::function<Offset()> get_declaration_location;
std::function<Offset(const std::vector<Source::View*> &views)> get_implementation_location; 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;
std::function<std::vector<std::pair<Offset, std::string> >()> get_methods; std::function<std::vector<std::pair<Offset, std::string> >()> get_methods;

54
src/source_clang.cc

@ -923,47 +923,53 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
return Offset(); return Offset();
}; };
get_implementation_location=[this](const std::vector<Source::View*> &views){ get_implementation_locations=[this](const std::vector<Source::View*> &views){
Offset location; std::vector<Offset> locations;
if(!parsed) { if(!parsed) {
Info::get().print("Buffer is parsing"); Info::get().print("Buffer is parsing");
return location; return locations;
} }
auto identifier=get_identifier(); auto identifier=get_identifier();
if(identifier) { if(identifier) {
wait_parsing(views); wait_parsing(views);
for(auto &view: views) { for(auto &view: views) {
if(auto clang_view=dynamic_cast<Source::ClangView*>(view)) { if(auto clang_view=dynamic_cast<Source::ClangView*>(view)) {
if(clang_view->language && clang_view->language->get_id()!="chdr" && clang_view->language->get_id()!="cpphdr") { for(auto &token: *clang_view->clang_tokens) {
for(auto token_it=clang_view->clang_tokens->rbegin();token_it!=clang_view->clang_tokens->rend();++token_it) { auto cursor=token.get_cursor();
auto cursor=token_it->get_cursor(); auto kind=cursor.get_kind();
auto kind=cursor.get_kind(); if((kind==clang::CursorKind::FunctionDecl || kind==clang::CursorKind::CXXMethod ||
if((kind==clang::CursorKind::FunctionDecl || kind==clang::CursorKind::CXXMethod || kind==clang::CursorKind::Constructor || kind==clang::CursorKind::Destructor) &&
kind==clang::CursorKind::Constructor || kind==clang::CursorKind::Destructor) && token.get_kind()==clang::TokenKind::Token_Identifier && cursor.has_type()) {
token_it->get_kind()==clang::TokenKind::Token_Identifier && cursor.has_type()) { auto referenced=cursor.get_referenced();
auto referenced=cursor.get_referenced(); 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_it->get_spelling() && identifier.usr==referenced.get_usr()) { if(clang_isCursorDefinition(referenced.cx_cursor)) {
Offset location;
location.file_path=cursor.get_source_location().get_path(); location.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; location.line=clang_offset.line-1;
location.index=clang_offset.index-1; location.index=clang_offset.index-1;
return location; locations.emplace_back(location);
} }
} }
} }
} }
} }
} }
if(!locations.empty())
return locations;
//If no implementation was found, try using clang_getCursorDefinition //If no implementation was found, try using clang_getCursorDefinition
auto definition=clang::Cursor(clang_getCursorDefinition(identifier.cursor.cx_cursor)); auto definition=clang::Cursor(clang_getCursorDefinition(identifier.cursor.cx_cursor));
if(definition) { if(definition) {
auto definition_location=definition.get_source_location(); auto definition_location=definition.get_source_location();
Offset location;
location.file_path=definition_location.get_path(); location.file_path=definition_location.get_path();
auto offset=definition_location.get_offset(); auto offset=definition_location.get_offset();
location.line=offset.line-1; location.line=offset.line-1;
location.index=offset.index-1; location.index=offset.index-1;
return location; locations.emplace_back(location);
return locations;
} }
//If no implementation was found, try using Ctags //If no implementation was found, try using Ctags
@ -974,17 +980,21 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
name.insert(0, spelling); name.insert(0, spelling);
parent=parent.get_semantic_parent(); parent=parent.get_semantic_parent();
} }
auto ctags_location=Ctags::get_location(this->file_path, name, identifier.cursor.get_type()); auto ctags_locations=Ctags::get_locations(this->file_path, name, identifier.cursor.get_type());
if(ctags_location) { if(!ctags_locations.empty()) {
location.file_path=ctags_location.file_path; for(auto &ctags_location: ctags_locations) {
location.line=ctags_location.line; Offset location;
location.index=ctags_location.index; location.file_path=ctags_location.file_path;
return location; location.line=ctags_location.line;
location.index=ctags_location.index;
locations.emplace_back(location);
}
return locations;
} }
Info::get().print("Could not find implementation"); Info::get().print("Could not find implementation");
} }
return location; return locations;
}; };
get_usages=[this](const std::vector<Source::View*> &views) { get_usages=[this](const std::vector<Source::View*> &views) {

65
src/window.cc

@ -547,21 +547,56 @@ void Window::set_menu_actions() {
}); });
menu.add_action("source_goto_implementation", [this]() { menu.add_action("source_goto_implementation", [this]() {
if(auto view=Notebook::get().get_current_view()) { if(auto view=Notebook::get().get_current_view()) {
if(view->get_implementation_location) { if(view->get_implementation_locations) {
auto location=view->get_implementation_location(Notebook::get().get_views()); auto locations=view->get_implementation_locations(Notebook::get().get_views());
if(location) { if(!locations.empty()) {
boost::filesystem::path implementation_path; auto dialog_iter=view->get_iter_for_dialog();
boost::system::error_code ec; view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(dialog_iter), true, true));
implementation_path=boost::filesystem::canonical(location.file_path, ec); auto rows=std::make_shared<std::unordered_map<std::string, Source::Offset> >();
if(ec) auto project_path=Project::Build::create(view->file_path)->project_path;
if(project_path.empty()) {
if(!Directories::get().path.empty())
project_path=Directories::get().path;
else
project_path=view->file_path.parent_path();
}
for(auto &location: locations) {
boost::filesystem::path implementation_path;
boost::system::error_code ec;
implementation_path=boost::filesystem::canonical(location.file_path, ec);
if(!ec) {
location.file_path=implementation_path;
auto path=filesystem::get_relative_path(location.file_path, project_path);
if(path.empty())
path=location.file_path.filename();
auto row=path.string()+":"+std::to_string(location.line+1);
(*rows)[row]=location;
view->selection_dialog->add_row(row);
}
}
if(rows->size()==0)
return; return;
Notebook::get().open(implementation_path); else if(rows->size()==1) {
auto view=Notebook::get().get_current_view(); auto location=*rows->begin();
auto line=static_cast<int>(location.line); Notebook::get().open(location.second.file_path);
auto index=static_cast<int>(location.index); auto view=Notebook::get().get_current_view();
view->place_cursor_at_line_index(line, index); auto line=static_cast<int>(location.second.line);
view->scroll_to_cursor_delayed(view, true, false); auto index=static_cast<int>(location.second.index);
return; view->place_cursor_at_line_index(line, index);
view->scroll_to_cursor_delayed(view, true, false);
return;
}
view->selection_dialog->on_select=[this, rows](const std::string &selected, bool hide_window) {
auto location=rows->at(selected);
Notebook::get().open(location.file_path);
auto view=Notebook::get().get_current_view();
view->place_cursor_at_line_index(location.line, location.index);
view->scroll_to_cursor_delayed(view, true, false);
view->hide_tooltips();
};
view->hide_tooltips();
view->selection_dialog->show();
} }
} }
} }
@ -969,7 +1004,7 @@ void Window::activate_menu_items(bool activate) {
menu.actions["source_find_symbol_ctags"]->set_enabled(activate); menu.actions["source_find_symbol_ctags"]->set_enabled(activate);
menu.actions["source_find_documentation"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_token_data) : false); menu.actions["source_find_documentation"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_token_data) : false);
menu.actions["source_goto_declaration"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_declaration_location) : false); menu.actions["source_goto_declaration"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_declaration_location) : false);
menu.actions["source_goto_implementation"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_implementation_location) : false); menu.actions["source_goto_implementation"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_implementation_locations) : false);
menu.actions["source_goto_usage"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_usages) : false); menu.actions["source_goto_usage"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_usages) : false);
menu.actions["source_goto_method"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_methods) : false); menu.actions["source_goto_method"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->get_methods) : false);
menu.actions["source_rename"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->rename_similar_tokens) : false); menu.actions["source_rename"]->set_enabled(activate ? static_cast<bool>(notebook.get_current_view()->rename_similar_tokens) : false);

5
tests/source_clang_test.cc

@ -40,8 +40,9 @@ int main() {
g_assert_cmpuint(location.line, ==, 4); g_assert_cmpuint(location.line, ==, 4);
clang_view->place_cursor_at_line_index(location.line, location.index); clang_view->place_cursor_at_line_index(location.line, location.index);
location=clang_view->get_implementation_location({clang_view}); auto impl_locations=clang_view->get_implementation_locations({clang_view});
g_assert_cmpuint(location.line, ==, 9); g_assert_cmpuint(impl_locations.size(), ==, 1);
g_assert_cmpuint(impl_locations[0].line, ==, 9);
clang_view->place_cursor_at_line_index(location.line, location.index); clang_view->place_cursor_at_line_index(location.line, location.index);
location=clang_view->get_declaration_location(); location=clang_view->get_declaration_location();

Loading…
Cancel
Save