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. 38
      src/source_clang.cc
  5. 51
      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;
}
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
size_t c=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);
result.second->seekg(0, std::ios::end);
if(result.second->tellg()==0)
return Location();
return std::vector<Location>();
result.second->seekg(0, std::ios::beg);
std::string line;
size_t best_score=0;
Location best_location;
std::vector<Location> best_locations;
while(std::getline(*result.second, line)) {
if(line.find(name)==std::string::npos)
continue;
@ -163,9 +163,12 @@ Ctags::Location Ctags::get_location(const boost::filesystem::path &path, const s
}
if(score>best_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 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_

2
src/source.h

@ -60,7 +60,7 @@ namespace Source {
std::function<void()> auto_indent;
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::string()> get_method;
std::function<std::vector<std::pair<Offset, std::string> >()> get_methods;

38
src/source_clang.cc

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

51
src/window.cc

@ -547,22 +547,57 @@ void Window::set_menu_actions() {
});
menu.add_action("source_goto_implementation", [this]() {
if(auto view=Notebook::get().get_current_view()) {
if(view->get_implementation_location) {
auto location=view->get_implementation_location(Notebook::get().get_views());
if(location) {
if(view->get_implementation_locations) {
auto locations=view->get_implementation_locations(Notebook::get().get_views());
if(!locations.empty()) {
auto dialog_iter=view->get_iter_for_dialog();
view->selection_dialog=std::unique_ptr<SelectionDialog>(new SelectionDialog(*view, view->get_buffer()->create_mark(dialog_iter), true, true));
auto rows=std::make_shared<std::unordered_map<std::string, Source::Offset> >();
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)
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;
Notebook::get().open(implementation_path);
else if(rows->size()==1) {
auto location=*rows->begin();
Notebook::get().open(location.second.file_path);
auto view=Notebook::get().get_current_view();
auto line=static_cast<int>(location.line);
auto index=static_cast<int>(location.index);
auto line=static_cast<int>(location.second.line);
auto index=static_cast<int>(location.second.index);
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_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_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_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);

5
tests/source_clang_test.cc

@ -40,8 +40,9 @@ int main() {
g_assert_cmpuint(location.line, ==, 4);
clang_view->place_cursor_at_line_index(location.line, location.index);
location=clang_view->get_implementation_location({clang_view});
g_assert_cmpuint(location.line, ==, 9);
auto impl_locations=clang_view->get_implementation_locations({clang_view});
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);
location=clang_view->get_declaration_location();

Loading…
Cancel
Save