diff --git a/src/source_clang.cc b/src/source_clang.cc index 7159f77..4ae874e 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -9,6 +9,7 @@ #include "dialogs.h" #include "ctags.h" #include "selection_dialog.h" +#include "filesystem.h" namespace sigc { #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(); 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(client_data_); + if(client_data->found_include.empty() && include_len>0) { + auto source_location=clang::SourceLocation(inclusion_stack[0]); + if(static_cast(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(client_data_); + if(client_data->found_include.empty()) { + for(unsigned c=1;c(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"); return Offset(); };