From 61fbdfd8a88e3dba2b858de6d2880d125b9b04a9 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sat, 21 Jul 2018 16:31:21 +0200 Subject: [PATCH] Language protocol: rename and showing usages now fallsback to document_highlight if no better capability is supported. This for instance enables rename and showing usages when flow-language-server is used. --- src/source_language_protocol.cc | 181 +++++++++++++++++++------------- 1 file changed, 110 insertions(+), 71 deletions(-) diff --git a/src/source_language_protocol.cc b/src/source_language_protocol.cc index 41a9610..6c2889b 100644 --- a/src/source_language_protocol.cc +++ b/src/source_language_protocol.cc @@ -546,27 +546,40 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { }; } - if(capabilities.references) { + if(capabilities.references || capabilities.document_highlight) { get_usages = [this] { auto iter = get_buffer()->get_insert()->get_iter(); std::vector> usages; std::vector end_offsets; std::promise result_processed; - client->write_request(this, "textDocument/references", R"("textDocument":{"uri":")" + uri + R"("}, "position": {"line": )" + std::to_string(iter.get_line()) + ", \"character\": " + std::to_string(iter.get_line_offset()) + R"(}, "context": {"includeDeclaration": true})", [&usages, &end_offsets, &result_processed](const boost::property_tree::ptree &result, bool error) { + + std::string method; + if(capabilities.document_highlight) + method = "textDocument/documentHighlight"; + else + method = "textDocument/references"; + + client->write_request(this, method, R"("textDocument":{"uri":")" + uri + R"("}, "position": {"line": )" + std::to_string(iter.get_line()) + ", \"character\": " + std::to_string(iter.get_line_offset()) + R"(}, "context": {"includeDeclaration": true})", [this, &usages, &end_offsets, &result_processed](const boost::property_tree::ptree &result, bool error) { if(!error) { try { for(auto it = result.begin(); it != result.end(); ++it) { - auto path = it->second.get("uri", ""); - if(path.size() >= 7) { - path.erase(0, 7); - auto range_it = it->second.find("range"); - if(range_it != it->second.not_found()) { - auto start_it = range_it->second.find("start"); - auto end_it = range_it->second.find("end"); - if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) { - usages.emplace_back(std::make_pair(Offset(start_it->second.get("line"), start_it->second.get("character"), path), "")); - end_offsets.emplace_back(end_it->second.get("line"), end_it->second.get("character")); - } + std::string path; + if(capabilities.document_highlight) + path = file_path.string(); + else { + path = it->second.get("uri", ""); + if(path.size() >= 7) + path.erase(0, 7); + else + continue; + } + auto range_it = it->second.find("range"); + if(range_it != it->second.not_found()) { + auto start_it = range_it->second.find("start"); + auto end_it = range_it->second.find("end"); + if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) { + usages.emplace_back(std::make_pair(Offset(start_it->second.get("line"), start_it->second.get("character"), path), "")); + end_offsets.emplace_back(end_it->second.get("line"), end_it->second.get("character")); } } } @@ -582,7 +595,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { auto embolden_token = [](std::string &line_, unsigned token_start_pos, unsigned token_end_pos) { Glib::ustring line = line_; - if(token_start_pos >= line.size() || token_end_pos >= line.size()) + if(token_start_pos > line.size() || token_end_pos > line.size()) return; //markup token as bold @@ -683,7 +696,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { return get_buffer()->get_text(start, end); }; - if(capabilities.rename) { + if(capabilities.rename || capabilities.document_highlight) { rename_similar_tokens = [this](const std::string &text) { class Usages { public: @@ -699,62 +712,64 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { auto iter = get_buffer()->get_insert()->get_iter(); std::vector usages; std::promise result_processed; - client->write_request(this, "textDocument/rename", R"("textDocument":{"uri":")" + uri + R"("}, "position": {"line": )" + std::to_string(iter.get_line()) + ", \"character\": " + std::to_string(iter.get_line_offset()) + R"(}, "newName": ")" + text + "\"", [this, &usages, &result_processed](const boost::property_tree::ptree &result, bool error) { - if(!error) { - boost::filesystem::path project_path; - auto build = Project::Build::create(file_path); - if(!build->project_path.empty()) - project_path = build->project_path; - else - project_path = file_path.parent_path(); - try { - auto changes_it = result.find("changes"); - if(changes_it != result.not_found()) { - for(auto file_it = changes_it->second.begin(); file_it != changes_it->second.end(); ++file_it) { - auto path = file_it->first; - if(path.size() >= 7) { - path.erase(0, 7); - if(filesystem::file_in_path(path, project_path)) { - usages.emplace_back(Usages{path, nullptr, std::vector>()}); - for(auto edit_it = file_it->second.begin(); edit_it != file_it->second.end(); ++edit_it) { - auto range_it = edit_it->second.find("range"); - if(range_it != edit_it->second.not_found()) { - auto start_it = range_it->second.find("start"); - auto end_it = range_it->second.find("end"); - if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) - usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get("line"), start_it->second.get("character")), - Offset(end_it->second.get("line"), end_it->second.get("character")))); + if(capabilities.rename) { + client->write_request(this, "textDocument/rename", R"("textDocument":{"uri":")" + uri + R"("}, "position": {"line": )" + std::to_string(iter.get_line()) + ", \"character\": " + std::to_string(iter.get_line_offset()) + R"(}, "newName": ")" + text + "\"", [this, &usages, &result_processed](const boost::property_tree::ptree &result, bool error) { + if(!error) { + boost::filesystem::path project_path; + auto build = Project::Build::create(file_path); + if(!build->project_path.empty()) + project_path = build->project_path; + else + project_path = file_path.parent_path(); + try { + auto changes_it = result.find("changes"); + if(changes_it != result.not_found()) { + for(auto file_it = changes_it->second.begin(); file_it != changes_it->second.end(); ++file_it) { + auto path = file_it->first; + if(path.size() >= 7) { + path.erase(0, 7); + if(filesystem::file_in_path(path, project_path)) { + usages.emplace_back(Usages{path, nullptr, std::vector>()}); + for(auto edit_it = file_it->second.begin(); edit_it != file_it->second.end(); ++edit_it) { + auto range_it = edit_it->second.find("range"); + if(range_it != edit_it->second.not_found()) { + auto start_it = range_it->second.find("start"); + auto end_it = range_it->second.find("end"); + if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) + usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get("line"), start_it->second.get("character")), + Offset(end_it->second.get("line"), end_it->second.get("character")))); + } } } } } } - } - else { - auto changes_pt = result.get_child("documentChanges", boost::property_tree::ptree()); - for(auto change_it = changes_pt.begin(); change_it != changes_pt.end(); ++change_it) { - auto document_it = change_it->second.find("textDocument"); - if(document_it != change_it->second.not_found()) { - auto path = document_it->second.get("uri", ""); - if(path.size() >= 7) { - path.erase(0, 7); - if(filesystem::file_in_path(path, project_path)) { - usages.emplace_back(Usages{path, std::make_unique(), std::vector>()}); - auto edits_pt = change_it->second.get_child("edits", boost::property_tree::ptree()); - for(auto edit_it = edits_pt.begin(); edit_it != edits_pt.end(); ++edit_it) { - auto new_text_it = edit_it->second.find("newText"); - if(new_text_it != edit_it->second.not_found()) { - auto range_it = edit_it->second.find("range"); - if(range_it != edit_it->second.not_found()) { - auto start_it = range_it->second.find("start"); - auto end_it = range_it->second.find("end"); - if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) { - auto end_line = end_it->second.get("line"); - if(end_line > std::numeric_limits::max()) - end_line = std::numeric_limits::max(); - *usages.back().new_text = new_text_it->second.get_value(); - usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get("line"), start_it->second.get("character")), - Offset(static_cast(end_line), end_it->second.get("character")))); + else { + auto changes_pt = result.get_child("documentChanges", boost::property_tree::ptree()); + for(auto change_it = changes_pt.begin(); change_it != changes_pt.end(); ++change_it) { + auto document_it = change_it->second.find("textDocument"); + if(document_it != change_it->second.not_found()) { + auto path = document_it->second.get("uri", ""); + if(path.size() >= 7) { + path.erase(0, 7); + if(filesystem::file_in_path(path, project_path)) { + usages.emplace_back(Usages{path, std::make_unique(), std::vector>()}); + auto edits_pt = change_it->second.get_child("edits", boost::property_tree::ptree()); + for(auto edit_it = edits_pt.begin(); edit_it != edits_pt.end(); ++edit_it) { + auto new_text_it = edit_it->second.find("newText"); + if(new_text_it != edit_it->second.not_found()) { + auto range_it = edit_it->second.find("range"); + if(range_it != edit_it->second.not_found()) { + auto start_it = range_it->second.find("start"); + auto end_it = range_it->second.find("end"); + if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) { + auto end_line = end_it->second.get("line"); + if(end_line > std::numeric_limits::max()) + end_line = std::numeric_limits::max(); + *usages.back().new_text = new_text_it->second.get_value(); + usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get("line"), start_it->second.get("character")), + Offset(static_cast(end_line), end_it->second.get("character")))); + } } } } @@ -764,13 +779,37 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { } } } + catch(...) { + usages.clear(); + } } - catch(...) { - usages.clear(); + result_processed.set_value(); + }); + } + else { + client->write_request(this, "textDocument/documentHighlight", R"("textDocument":{"uri":")" + uri + R"("}, "position": {"line": )" + std::to_string(iter.get_line()) + ", \"character\": " + std::to_string(iter.get_line_offset()) + R"(}, "context": {"includeDeclaration": true})", [this, &usages, &result_processed](const boost::property_tree::ptree &result, bool error) { + if(!error) { + try { + usages.emplace_back(Usages{file_path, nullptr, std::vector>()}); + for(auto it = result.begin(); it != result.end(); ++it) { + auto range_it = it->second.find("range"); + if(range_it != it->second.not_found()) { + auto start_it = range_it->second.find("start"); + auto end_it = range_it->second.find("end"); + if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) { + usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get("line"), start_it->second.get("character")), + Offset(end_it->second.get("line"), end_it->second.get("character")))); + } + } + } + } + catch(...) { + usages.clear(); + } } - } - result_processed.set_value(); - }); + result_processed.set_value(); + }); + } result_processed.get_future().get(); std::vector usages_renamed;