Browse Source

Fixes #310: can now use Go to Declaration on include directive to jump to included file

merge-requests/365/head
eidheim 9 years ago
parent
commit
61be493b9c
  1. 52
      src/source_clang.cc

52
src/source_clang.cc

@ -9,6 +9,7 @@
#include "dialogs.h" #include "dialogs.h"
#include "ctags.h" #include "ctags.h"
#include "selection_dialog.h" #include "selection_dialog.h"
#include "filesystem.h"
namespace sigc { namespace sigc {
#ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE #ifndef SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
@ -1022,6 +1023,57 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
auto offset=source_location.get_offset(); auto offset=source_location.get_offset();
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 {
// 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);
}
}
Info::get().print("No declaration found"); Info::get().print("No declaration found");
return Offset(); return Offset();
}; };

Loading…
Cancel
Save