Browse Source

Optimized ctags parsing

merge-requests/399/head
eidheim 6 years ago
parent
commit
463cf1f973
  1. 125
      src/ctags.cc

125
src/ctags.cc

@ -32,64 +32,91 @@ std::pair<boost::filesystem::path, std::unique_ptr<std::stringstream>> Ctags::ge
return {run_path, std::move(stdout_stream)}; return {run_path, std::move(stdout_stream)};
} }
Ctags::Location Ctags::get_location(const std::string &line, bool markup) { Ctags::Location Ctags::get_location(const std::string &line_, bool markup) {
Location location; Location location;
#ifdef _WIN32 #ifdef _WIN32
auto line_fixed = line; auto line = line_;
if(!line_fixed.empty() && line_fixed.back() == '\r') if(!line.empty() && line.back() == '\r')
line_fixed.pop_back(); line.pop_back();
#else #else
auto &line_fixed = line; auto &line = line_;
#endif #endif
auto symbol_end = line.find('\t');
if(symbol_end == std::string::npos) {
std::cerr << "Warning (ctags): could not parse line: " << line << std::endl;
return location;
}
location.symbol = line.substr(0, symbol_end);
if(9 < location.symbol.size() && location.symbol[8] == ' ' && location.symbol.compare(0, 8, "operator") == 0) {
auto &chr = location.symbol[9];
if(!((chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr == '_'))
location.symbol.erase(8, 1);
}
const static std::regex regex(R"(^([^\t]+)\t([^\t]+)\t(?:/\^)?([ \t]*)(.+?)(\$/)?;"\tline:([0-9]+)\t?[a-zA-Z]*:?(.*)$)"); auto file_start = symbol_end + 1;
std::smatch sm; if(file_start >= line.size()) {
if(std::regex_match(line_fixed, sm, regex)) { std::cerr << "Warning (ctags): could not parse line: " << line << std::endl;
location.symbol = sm[1].str(); return location;
//fix location.symbol for operators }
if(9 < location.symbol.size() && location.symbol[8] == ' ' && location.symbol.compare(0, 8, "operator") == 0) { auto file_end = line.find('\t', file_start);
auto &chr = location.symbol[9]; if(file_end == std::string::npos) {
if(!((chr >= 'a' && chr <= 'z') || (chr >= 'A' && chr <= 'Z') || (chr >= '0' && chr <= '9') || chr == '_')) std::cerr << "Warning (ctags): could not parse line: " << line << std::endl;
location.symbol.erase(8, 1); return location;
} }
location.file_path = line.substr(file_start, file_end - file_start);
location.file_path = sm[2].str(); auto source_start = file_end + 3;
location.source = sm[4].str(); if(source_start >= line.size()) {
try { std::cerr << "Warning (ctags): could not parse line: " << line << std::endl;
location.line = std::stoul(sm[6]) - 1; return location;
} }
catch(const std::exception &) { location.index = 0;
location.line = 0; while(source_start < line.size() && (line[source_start] == ' ' || line[source_start] == '\t')) {
} ++source_start;
location.scope = sm[7].str(); ++location.index;
if(!sm[5].str().empty()) { }
location.index = sm[3].str().size(); auto source_end = line.find("/;\"\t", source_start);
if(source_end == std::string::npos) {
size_t pos = location.source.find(location.symbol); std::cerr << "Warning (ctags): could not parse line: " << line << std::endl;
if(pos != std::string::npos) return location;
location.index += pos; }
location.source = line.substr(source_start, source_end - source_start - (line[source_end - 1] == '$' ? 1 : 0));
if(markup) {
location.source = Glib::Markup::escape_text(location.source); auto line_start = source_end + 9;
auto symbol = Glib::Markup::escape_text(location.symbol); if(line_start >= line.size()) {
pos = -1; std::cerr << "Warning (ctags): could not parse line: " << line << std::endl;
while((pos = location.source.find(symbol, pos + 1)) != std::string::npos) { return location;
location.source.insert(pos + symbol.size(), "</b>"); }
location.source.insert(pos, "<b>"); auto line_end = line.find('\t', line_start);
pos += 7 + symbol.size(); size_t line_size = line_end == std::string::npos ? std::string::npos : line_end - line_start;
} try {
} location.line = std::stoul(line.substr(line_start, line_size)) - 1;
} }
else { catch(...) {
location.index = 0; location.line = 0;
location.source = location.symbol; }
if(markup)
location.source = "<b>" + Glib::Markup::escape_text(location.source) + "</b>"; if(line_end != std::string::npos && line_end + 1 < line.size()) {
auto scope_start = line.find(':', line_end + 1);
if(scope_start != std::string::npos && scope_start + 1 < line.size())
location.scope = line.substr(scope_start + 1);
}
auto pos = location.source.find(location.symbol);
if(pos != std::string::npos)
location.index += pos;
if(markup) {
location.source = Glib::Markup::escape_text(location.source);
auto symbol = Glib::Markup::escape_text(location.symbol);
pos = -1;
while((pos = location.source.find(symbol, pos + 1)) != std::string::npos) {
location.source.insert(pos + symbol.size(), "</b>");
location.source.insert(pos, "<b>");
pos += 7 + symbol.size();
} }
} }
else
std::cerr << "Warning (ctags): please report to the juCi++ project that the following line was not parsed:\n" << line << std::endl;
return location; return location;
} }

Loading…
Cancel
Save