From 2630e3001f3c666bababa385b3e44caccd9a32a0 Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 15 May 2020 10:35:56 +0200 Subject: [PATCH] Language client: improved parsing of textDocument/documentSymbol --- src/project.cc | 44 ++++++++++++++++++++--------- src/source_language_protocol.cc | 50 ++++++++++++++++++++------------- src/source_language_protocol.h | 1 + 3 files changed, 61 insertions(+), 34 deletions(-) diff --git a/src/project.cc b/src/project.cc index 4e66c3a..ec87d80 100644 --- a/src/project.cc +++ b/src/project.cc @@ -758,22 +758,38 @@ void Project::LanguageProtocol::show_symbols() { else { std::map<::LanguageProtocol::Location, std::string> locations_rows; std::promise result_processed; - client->write_request(language_protocol_view, "textDocument/documentSymbol", R"("textDocument":{"uri":")" + language_protocol_view->uri + "\"}", [&result_processed, &locations_rows, locations](const boost::property_tree::ptree &result, bool error) { + client->write_request(language_protocol_view, "textDocument/documentSymbol", R"("textDocument":{"uri":")" + language_protocol_view->uri + "\"}", [&result_processed, &locations_rows, locations, language_protocol_view](const boost::property_tree::ptree &result, bool error) { if(!error) { - for(auto it = result.begin(); it != result.end(); ++it) { - try { - ::LanguageProtocol::Location location(it->second.get_child("location")); - - auto container = it->second.get("containerName", ""); - if(container == "null") - container.clear(); - auto row = std::to_string(location.range.start.line + 1) + ": " + (!container.empty() ? container + "::" : "") + "" + it->second.get("name") + ""; - - locations_rows.emplace(std::move(location), std::move(row)); - } - catch(...) { + std::function parse_result = [&locations_rows, &parse_result, language_protocol_view](const boost::property_tree::ptree &pt, const std::string &container) { + for(auto it = pt.begin(); it != pt.end(); ++it) { + try { + std::unique_ptr<::LanguageProtocol::Location> location; + std::string prefix; + auto location_pt = it->second.get_child_optional("location"); + if(location_pt) { + location = std::make_unique<::LanguageProtocol::Location>(*location_pt); + std::string container = it->second.get("containerName", ""); + if(container == "null") + container.clear(); + if(!container.empty()) + prefix = container + "::"; + } + else { + location = std::make_unique<::LanguageProtocol::Location>(language_protocol_view->file_path.string(), ::LanguageProtocol::Range(it->second.get_child("range"))); + if(!container.empty()) + prefix = container + "::"; + } + auto row = std::to_string(location->range.start.line + 1) + ": " + prefix + "" + it->second.get("name") + ""; + locations_rows.emplace(std::move(*location), std::move(row)); + auto children = it->second.get_child_optional("children"); + if(children) + parse_result(*children, (!container.empty() ? container + "::" : "") + it->second.get("name")); + } + catch(...) { + } } - } + }; + parse_result(result, ""); } result_processed.set_value(); }); diff --git a/src/source_language_protocol.cc b/src/source_language_protocol.cc index d523244..aa5dab5 100644 --- a/src/source_language_protocol.cc +++ b/src/source_language_protocol.cc @@ -846,29 +846,39 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { std::promise result_processed; client->write_request(this, "textDocument/documentSymbol", R"("textDocument":{"uri":")" + uri + "\"}", [&result_processed, &methods](const boost::property_tree::ptree &result, bool error) { if(!error) { - for(auto it = result.begin(); it != result.end(); ++it) { - try { - auto kind = it->second.get("kind"); - if(kind == 6 || kind == 9 || kind == 12) { - std::unique_ptr range; - std::string container; - auto location_pt = it->second.get_child_optional("location"); - if(location_pt) { - LanguageProtocol::Location location(*location_pt); - container = it->second.get("containerName", ""); - if(container == "null") - container.clear(); - range = std::make_unique(location.range); + std::function parse_result = [&methods, &parse_result](const boost::property_tree::ptree &pt, const std::string &container) { + for(auto it = pt.begin(); it != pt.end(); ++it) { + try { + auto kind = it->second.get("kind"); + if(kind == 6 || kind == 9 || kind == 12) { + std::unique_ptr range; + std::string prefix; + auto location_pt = it->second.get_child_optional("location"); + if(location_pt) { + LanguageProtocol::Location location(*location_pt); + range = std::make_unique(location.range); + std::string container = it->second.get("containerName", ""); + if(container == "null") + container.clear(); + if(!container.empty()) + prefix = container + "::"; + } + else { + range = std::make_unique(it->second.get_child("range")); + if(!container.empty()) + prefix = container + "::"; + } + methods.emplace_back(Offset(range->start.line, range->start.character), std::to_string(range->start.line + 1) + ": " + prefix + "" + it->second.get("name") + ""); } - else - range = std::make_unique(it->second.get_child("range")); - - methods.emplace_back(Offset(range->start.line, range->start.character), std::to_string(range->start.line + 1) + ": " + (!container.empty() ? container + "::" : "") + "" + it->second.get("name") + ""); + auto children = it->second.get_child_optional("children"); + if(children) + parse_result(*children, (!container.empty() ? container + "::" : "") + it->second.get("name")); + } + catch(...) { } } - catch(...) { - } - } + }; + parse_result(result, ""); } result_processed.set_value(); }); diff --git a/src/source_language_protocol.h b/src/source_language_protocol.h index 5b3f159..24c2933 100644 --- a/src/source_language_protocol.h +++ b/src/source_language_protocol.h @@ -44,6 +44,7 @@ namespace LanguageProtocol { class Location { public: Location(const boost::property_tree::ptree &pt, std::string file_ = {}); + Location(std::string _file, Range _range) : file(std::move(_file)), range(std::move(_range)) {} std::string file; Range range;