Browse Source

Unescape Ctags source, and slight optimization of Ctag functions

pipelines/143601543
eidheim 6 years ago
parent
commit
9ac4e65ddd
  1. 50
      src/ctags.cc
  2. 4
      src/ctags.h
  3. 4
      src/source_generic.cc
  4. 34
      tests/ctags_grep_test.cc

50
src/ctags.cc

@ -8,9 +8,13 @@
#include <regex>
#include <vector>
std::pair<boost::filesystem::path, std::unique_ptr<std::stringstream>> Ctags::get_result(const boost::filesystem::path &path, bool enable_kinds) {
std::pair<boost::filesystem::path, std::unique_ptr<std::stringstream>> Ctags::get_result(const boost::filesystem::path &path, bool enable_scope, bool enable_kind) {
boost::filesystem::path run_path;
auto fields = std::string(" --fields=ns") + (enable_kinds ? "K" : "");
std::string fields(" --fields=n");
if(enable_scope)
fields += 's';
if(enable_kind)
fields += 'K';
std::string command;
boost::system::error_code ec;
if(boost::filesystem::is_directory(path, ec)) {
@ -37,7 +41,7 @@ std::pair<boost::filesystem::path, std::unique_ptr<std::stringstream>> Ctags::ge
return {run_path, std::move(stdout_stream)};
}
Ctags::Location Ctags::get_location(const std::string &line_, bool add_markup, bool kinds_enabled) {
Ctags::Location Ctags::get_location(const std::string &line_, bool add_markup, bool scope_enabled, bool kind_enabled) {
Location location;
#ifdef _WIN32
@ -86,10 +90,22 @@ Ctags::Location Ctags::get_location(const std::string &line_, bool add_markup, b
std::cerr << "Warning (ctags): could not parse line: " << line << std::endl;
return location;
}
location.source = line.substr(source_start, source_end - source_start - (line[source_end - 1] == '$' ? 1 : 0));
// Unescape source
auto end = source_end - (line[source_end - 1] == '$' ? 1 : 0);
location.source.reserve(end - source_start);
bool escaped = false;
for(auto i = source_start; i < end; ++i) {
if(!escaped && line[i] == '\\') {
escaped = true;
continue;
}
escaped = false;
location.source += line[i];
}
size_t line_start;
if(kinds_enabled) {
if(kind_enabled) {
auto kind_start = source_end + 4;
if(kind_start >= line.size()) {
std::cerr << "Warning (ctags): could not parse line: " << line << std::endl;
@ -119,26 +135,32 @@ Ctags::Location Ctags::get_location(const std::string &line_, bool add_markup, b
location.line = 0;
}
if(line_end != std::string::npos && line_end + 1 < line.size()) {
if(scope_enabled && 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(add_markup) {
location.source = Glib::Markup::escape_text(location.source);
std::string symbol = Glib::Markup::escape_text(location.symbol);
pos = -1;
while((pos = location.source.find(symbol, pos + 1)) != std::string::npos) {
size_t pos = 0;
bool first = true;
while((pos = location.source.find(symbol, pos)) != std::string::npos) {
if(first) {
location.index += pos;
first = false;
}
location.source.insert(pos + symbol.size(), "</b>");
location.source.insert(pos, "<b>");
pos += 7 + symbol.size();
}
}
else {
auto pos = location.source.find(location.symbol);
if(pos != std::string::npos)
location.index += pos;
}
return location;
}
@ -166,7 +188,7 @@ std::vector<std::string> Ctags::get_type_parts(const std::string &type) {
}
std::vector<Ctags::Location> Ctags::get_locations(const boost::filesystem::path &path, const std::string &name, const std::string &type) {
auto result = get_result(path);
auto result = get_result(path, true);
result.second->seekg(0, std::ios::end);
if(result.second->tellg() == 0)
return std::vector<Location>();
@ -194,7 +216,7 @@ std::vector<Ctags::Location> Ctags::get_locations(const boost::filesystem::path
while(std::getline(*result.second, line)) {
if(line.size() > 2048)
continue;
auto location = Ctags::get_location(line, false);
auto location = Ctags::get_location(line, false, true);
if(!location.scope.empty()) {
if(location.scope + "::" + location.symbol != name)
continue;

4
src/ctags.h

@ -18,9 +18,9 @@ public:
operator bool() const { return !file_path.empty(); }
};
static std::pair<boost::filesystem::path, std::unique_ptr<std::stringstream>> get_result(const boost::filesystem::path &path, bool enable_kinds = false);
static std::pair<boost::filesystem::path, std::unique_ptr<std::stringstream>> get_result(const boost::filesystem::path &path, bool enable_scope = false, bool enable_kind = false);
static Location get_location(const std::string &line, bool add_markup, bool kinds_enabled = false);
static Location get_location(const std::string &line, bool add_markup, bool scope_enabled = false, bool kind_enabled = false);
static std::vector<Location> get_locations(const boost::filesystem::path &path, const std::string &name, const std::string &type);

4
src/source_generic.cc

@ -82,7 +82,7 @@ Source::GenericView::GenericView(const boost::filesystem::path &file_path, const
else
file_path = this->file_path;
auto pair = Ctags::get_result(file_path, true);
auto pair = Ctags::get_result(file_path, false, true);
if(use_tmp_file)
boost::filesystem::remove_all(file_path.parent_path(), ec);
auto path = std::move(pair.first);
@ -97,7 +97,7 @@ Source::GenericView::GenericView(const boost::filesystem::path &file_path, const
std::string line;
while(std::getline(*stream, line)) {
auto location = Ctags::get_location(line, true, true);
auto location = Ctags::get_location(line, true, false, true);
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",

34
tests/ctags_grep_test.cc

@ -7,6 +7,11 @@
void ctags_grep_test_function() {
}
class Test {
void ctags_grep_test_function2() {
}
};
int main() {
auto app = Gtk::Application::create();
Config::get().project.ctags_command = "ctags";
@ -50,14 +55,14 @@ int main() {
g_assert(found == true);
}
{
auto result = Ctags::get_result(tests_path, true);
auto result = Ctags::get_result(tests_path, false, true);
g_assert(result.first == tests_path.parent_path());
bool found = false;
std::string line;
while(std::getline(*result.second, line)) {
if(line.find("ctags_grep_test_function") != std::string::npos) {
{
auto location = Ctags::get_location(line, false, true);
auto location = Ctags::get_location(line, false, false, true);
g_assert(location.source == "void ctags_grep_test_function() {");
g_assert(result.first / location.file_path == tests_path / "ctags_grep_test.cc");
g_assert_cmpint(location.line, ==, 6);
@ -67,7 +72,7 @@ int main() {
g_assert(location.kind == "function");
}
{
auto location = Ctags::get_location(line, true, true);
auto location = Ctags::get_location(line, true, false, true);
g_assert(location.source == "void <b>ctags_grep_test_function</b>() {");
g_assert(result.first / location.file_path == tests_path / "ctags_grep_test.cc");
g_assert_cmpint(location.line, ==, 6);
@ -82,6 +87,29 @@ int main() {
}
g_assert(found == true);
}
{
auto result = Ctags::get_result(tests_path, true);
g_assert(result.first == tests_path.parent_path());
bool found = false;
std::string line;
while(std::getline(*result.second, line)) {
if(line.find("ctags_grep_test_function2") != std::string::npos) {
{
auto location = Ctags::get_location(line, false, true);
g_assert(location.source == "void ctags_grep_test_function2() {");
g_assert(result.first / location.file_path == tests_path / "ctags_grep_test.cc");
g_assert_cmpint(location.line, ==, 10);
g_assert_cmpint(location.index, ==, 7);
g_assert(location.symbol == "ctags_grep_test_function2");
g_assert(location.scope == "Test");
g_assert(location.kind.empty());
}
found = true;
break;
}
}
g_assert(found == true);
}
// Grep tests
{

Loading…
Cancel
Save