From 232e9b4876193b75114674985fbe8b693e0d98da Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 17 Jun 2019 21:13:39 +0200 Subject: [PATCH] Language protocol: now sorts locations received from server, and added some support for newer lsp specification --- src/project.cc | 30 ++++++++++++++++++------------ src/source_language_protocol.cc | 13 ++++++++++--- src/source_language_protocol.h | 25 ++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 18 deletions(-) diff --git a/src/project.cc b/src/project.cc index 067c245..e314b90 100644 --- a/src/project.cc +++ b/src/project.cc @@ -715,9 +715,9 @@ void Project::LanguageProtocol::show_symbols() { if(text.empty()) return; } - std::vector rows; + std::map<::LanguageProtocol::Location, std::string> locations_rows; std::promise result_processed; - client->write_request(nullptr, "workspace/symbol", R"("query":")" + text + '"', [&result_processed, &rows, locations, project_path](const boost::property_tree::ptree &result, bool error) { + client->write_request(nullptr, "workspace/symbol", R"("query":")" + text + '"', [&result_processed, &locations_rows, locations, project_path](const boost::property_tree::ptree &result, bool error) { if(!error) { for(auto it = result.begin(); it != result.end(); ++it) { try { @@ -731,8 +731,7 @@ void Project::LanguageProtocol::show_symbols() { row += container_name + ':'; row += std::to_string(location.range.start.line + 1) + ": " + it->second.get("name") + ""; - locations->emplace_back(std::move(location)); - rows.emplace_back(std::move(row)); + locations_rows.emplace(std::move(location), std::move(row)); } } catch(...) { @@ -742,14 +741,18 @@ void Project::LanguageProtocol::show_symbols() { result_processed.set_value(); }); result_processed.get_future().get(); - for(auto &row : rows) - SelectionDialog::get()->add_row(row); + + locations->reserve(locations_rows.size()); + for(auto &location_row : locations_rows) { + locations->emplace_back(std::move(location_row.first)); + SelectionDialog::get()->add_row(location_row.second); + } }; } else { - std::vector rows; + 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, &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](const boost::property_tree::ptree &result, bool error) { if(!error) { for(auto it = result.begin(); it != result.end(); ++it) { try { @@ -761,8 +764,7 @@ void Project::LanguageProtocol::show_symbols() { row += container_name + ':'; row += std::to_string(location.range.start.line + 1) + ": " + it->second.get("name") + ""; - locations->emplace_back(std::move(location)); - rows.emplace_back(std::move(row)); + locations_rows.emplace(std::move(location), std::move(row)); } catch(...) { } @@ -771,8 +773,12 @@ void Project::LanguageProtocol::show_symbols() { result_processed.set_value(); }); result_processed.get_future().get(); - for(auto &row : rows) - SelectionDialog::get()->add_row(row); + + locations->reserve(locations_rows.size()); + for(auto &location_row : locations_rows) { + locations->emplace_back(std::move(location_row.first)); + SelectionDialog::get()->add_row(location_row.second); + } } SelectionDialog::get()->on_select = [locations](unsigned int index, const std::string &text, bool hide_window) { diff --git a/src/source_language_protocol.cc b/src/source_language_protocol.cc index 327de13..db0422a 100644 --- a/src/source_language_protocol.cc +++ b/src/source_language_protocol.cc @@ -116,7 +116,12 @@ LanguageProtocol::Capabilities LanguageProtocol::Client::initialize(Source::Lang if(!error) { auto capabilities_pt = result.find("capabilities"); if(capabilities_pt != result.not_found()) { - capabilities.text_document_sync = static_cast(capabilities_pt->second.get("textDocumentSync", 0)); + try { + capabilities.text_document_sync = static_cast(capabilities_pt->second.get("textDocumentSync")); + } + catch(...) { + capabilities.text_document_sync = static_cast(capabilities_pt->second.get("textDocumentSync.change", 0)); + } capabilities.hover = capabilities_pt->second.get("hoverProvider", false); capabilities.completion = capabilities_pt->second.find("completionProvider") != capabilities_pt->second.not_found() ? true : false; capabilities.signature_help = capabilities_pt->second.find("signatureHelpProvider") != capabilities_pt->second.not_found() ? true : false; @@ -579,7 +584,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { if(capabilities.references || capabilities.document_highlight) { get_usages = [this] { auto iter = get_buffer()->get_insert()->get_iter(); - std::vector locations; + std::set locations; std::promise result_processed; std::string method; @@ -592,7 +597,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { if(!error) { try { for(auto it = result.begin(); it != result.end(); ++it) - locations.emplace_back(it->second, !capabilities.references ? file_path.string() : std::string()); + locations.emplace(it->second, !capabilities.references ? file_path.string() : std::string()); } catch(...) { locations.clear(); @@ -1379,6 +1384,8 @@ void Source::LanguageProtocolView::setup_autocomplete() { auto detail = it->second.get("detail", ""); auto documentation = it->second.get("documentation", ""); auto insert = it->second.get("insertText", ""); + if(insert.empty()) + insert = it->second.get("textEdit.newText", ""); if(!insert.empty()) { // In case ( is missing in insert but is present in label if(label.size() > insert.size() && label.back() == ')' && insert.find('(') == std::string::npos) { diff --git a/src/source_language_protocol.h b/src/source_language_protocol.h index 4e3a8b1..d1932ff 100644 --- a/src/source_language_protocol.h +++ b/src/source_language_protocol.h @@ -18,15 +18,27 @@ namespace LanguageProtocol { class Offset { public: Offset(const boost::property_tree::ptree &pt); - int line; - int character; + int line, character; + + bool operator<(const Offset &rhs) const { + return line < rhs.line || (line == rhs.line && character < rhs.character); + } + bool operator==(const Offset &rhs) const { + return line == rhs.line && character == rhs.character; + } }; class Range { public: Range(const boost::property_tree::ptree &pt); - Range() = default; Offset start, end; + + bool operator<(const Range &rhs) const { + return start < rhs.start || (start == rhs.start && end < rhs.end); + } + bool operator==(const Range &rhs) const { + return start == rhs.start && end == rhs.end; + } }; class Location { @@ -34,6 +46,13 @@ namespace LanguageProtocol { Location(const boost::property_tree::ptree &pt, std::string file_ = {}); std::string file; Range range; + + bool operator<(const Location &rhs) const { + return file < rhs.file || (file == rhs.file && range < rhs.range); + } + bool operator==(const Location &rhs) const { + return file == rhs.file && range == rhs.range; + } }; class Diagnostic {