Browse Source

Improvements to Go to Method: improved parsing of C++ system headers, and now shows namespace for each symbol if any

pipelines/235045657
eidheim 6 years ago
parent
commit
c53d927483
  1. 6
      src/ctags.cpp
  2. 2
      src/ctags.hpp
  3. 20
      src/source.cpp
  4. 57
      src/source_clang.cpp

6
src/ctags.cpp

@ -30,7 +30,7 @@ Ctags::Ctags(const boost::filesystem::path &path, bool enable_scope, bool enable
}
else {
project_path = path.parent_path();
command = Config::get().project.ctags_command + fields + " --sort=foldcase -I \"override noexcept\" -f - " + filesystem::escape_argument(path.string());
command = Config::get().project.ctags_command + fields + " --c-kinds=+p --c++-kinds=+p --sort=foldcase -I \"override noexcept\" -f - " + filesystem::escape_argument(path.string());
}
std::stringstream stdin_stream;
@ -45,7 +45,7 @@ Ctags::operator bool() {
return true;
}
Ctags::Location Ctags::get_location(const std::string &line_, bool add_markup) const {
Ctags::Location Ctags::get_location(const std::string &line_, bool add_markup, bool symbol_ends_with_open_parenthesis) const {
Location location;
#ifdef _WIN32
@ -148,6 +148,8 @@ Ctags::Location Ctags::get_location(const std::string &line_, bool add_markup) c
if(add_markup) {
location.source = Glib::Markup::escape_text(location.source);
std::string symbol = Glib::Markup::escape_text(location.symbol);
if(symbol_ends_with_open_parenthesis)
symbol += '(';
bool first = true;
bool escaped = false;
for(size_t i = 0; i < location.source.size(); i++) {

2
src/ctags.hpp

@ -22,7 +22,7 @@ public:
operator bool();
Location get_location(const std::string &line, bool add_markup = false) const;
Location get_location(const std::string &line, bool add_markup = false, bool symbol_ends_with_open_parenthesis = false) const;
boost::filesystem::path project_path;
std::stringstream output;

20
src/source.cpp

@ -313,8 +313,9 @@ Source::View::View(const boost::filesystem::path &file_path, const Glib::RefPtr<
boost::filesystem::path file_path;
boost::system::error_code ec;
bool use_tmp_file = false;
bool is_cpp_standard_header = is_cpp && this->file_path.extension().empty();
if(this->get_buffer()->get_modified()) {
if(this->get_buffer()->get_modified() || is_cpp_standard_header) {
use_tmp_file = true;
file_path = boost::filesystem::temp_directory_path(ec);
if(ec) {
@ -327,13 +328,13 @@ Source::View::View(const boost::filesystem::path &file_path, const Glib::RefPtr<
Terminal::get().print("Error: could not create temporary folder\n", true);
return methods;
}
file_path /= this->file_path.filename();
file_path /= this->file_path.filename().string() + (is_cpp_standard_header ? ".hpp" : "");
filesystem::write(file_path, this->get_buffer()->get_text().raw());
}
else
file_path = this->file_path;
Ctags ctags(file_path, false, true);
Ctags ctags(file_path, true, true);
if(use_tmp_file)
boost::filesystem::remove_all(file_path.parent_path(), ec);
if(!ctags) {
@ -343,7 +344,7 @@ Source::View::View(const boost::filesystem::path &file_path, const Glib::RefPtr<
std::string line;
while(std::getline(ctags.output, line)) {
auto location = ctags.get_location(line, true);
auto location = ctags.get_location(line, true, is_cpp);
std::transform(location.kind.begin(), location.kind.end(), location.kind.begin(),
[](char c) { return std::tolower(c); });
std::vector<std::string> ignore_kinds = {"variable", "local", "constant", "global", "property", "member", "enum",
@ -352,8 +353,15 @@ Source::View::View(const boost::filesystem::path &file_path, const Glib::RefPtr<
"typedef", "using", "alias",
"project", "option"};
if(std::none_of(ignore_kinds.begin(), ignore_kinds.end(), [&location](const std::string &e) { return location.kind.find(e) != std::string::npos; }) &&
location.source.find("<b>") != std::string::npos)
methods.emplace_back(Offset(location.line, location.index), std::to_string(location.line + 1) + ": " + location.source);
location.source.find("<b>") != std::string::npos) {
std::string scope = !location.scope.empty() ? Glib::Markup::escape_text(location.scope) : "";
if(is_cpp && !scope.empty()) { // Remove namespace from location.source in C++ source files
auto pos = location.source.find(scope + "::<b>");
if(pos != std::string::npos)
location.source.erase(pos, scope.size() + 2);
}
methods.emplace_back(Offset(location.line, location.index), (!scope.empty() ? scope + ":" : "") + std::to_string(location.line + 1) + ": " + location.source);
}
}
std::sort(methods.begin(), methods.end(), [](const std::pair<Offset, std::string> &e1, const std::pair<Offset, std::string> &e2) {
return e1.first < e2.first;

57
src/source_clang.cpp

@ -1695,63 +1695,6 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
return std::string();
};
if(language && (language->get_id() == "chdr" || language->get_id() == "cpphdr")) {
get_methods = [this]() {
std::vector<std::pair<Offset, std::string>> methods;
if(!parsed) {
Info::get().print("Buffer is parsing");
return methods;
}
clangmm::Offset last_offset{static_cast<unsigned>(-1), static_cast<unsigned>(-1)};
for(auto &token : *clang_tokens) {
if(token.is_identifier()) {
auto cursor = token.get_cursor();
auto kind = cursor.get_kind();
if(kind == clangmm::Cursor::Kind::FunctionDecl || kind == clangmm::Cursor::Kind::CXXMethod ||
kind == clangmm::Cursor::Kind::Constructor || kind == clangmm::Cursor::Kind::Destructor ||
kind == clangmm::Cursor::Kind::FunctionTemplate || kind == clangmm::Cursor::Kind::ConversionFunction) {
auto offset = cursor.get_source_location().get_offset();
if(offset == last_offset)
continue;
last_offset = offset;
std::string scope;
auto parent = cursor.get_semantic_parent();
while(parent && parent.get_kind() != clangmm::Cursor::Kind::TranslationUnit) {
scope.insert(0, parent.get_display_name() + (scope.empty() ? "" : "::"));
parent = parent.get_semantic_parent();
}
if(!scope.empty())
scope += "::";
scope = Glib::Markup::escape_text(scope);
std::string ret;
if(kind != clangmm::Cursor::Kind::Constructor && kind != clangmm::Cursor::Kind::Destructor) {
ret += cursor.get_type().get_result().get_spelling();
if(!ret.empty() && ret.back() != '&' && ret.back() != '*')
ret += ' ';
}
ret = Glib::Markup::escape_text(ret);
auto method = Glib::Markup::escape_text(cursor.get_display_name());
// Add bold method token
auto end = method.find('(');
if(end == std::string::npos)
continue;
method.insert(end, "</b>");
method.insert(0, "<b>");
methods.emplace_back(Offset(offset.line - 1, offset.index - 1), std::to_string(offset.line) + ": " + ret + scope + method);
}
}
}
if(methods.empty())
Info::get().print("No methods found in current buffer");
return methods;
};
}
get_token_data = [this]() -> std::vector<std::string> {
clangmm::Cursor cursor;

Loading…
Cancel
Save