Browse Source

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.

merge-requests/389/head
eidheim 7 years ago
parent
commit
61fbdfd8a8
  1. 181
      src/source_language_protocol.cc

181
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] { get_usages = [this] {
auto iter = get_buffer()->get_insert()->get_iter(); auto iter = get_buffer()->get_insert()->get_iter();
std::vector<std::pair<Offset, std::string>> usages; std::vector<std::pair<Offset, std::string>> usages;
std::vector<Offset> end_offsets; std::vector<Offset> end_offsets;
std::promise<void> result_processed; std::promise<void> 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) { if(!error) {
try { try {
for(auto it = result.begin(); it != result.end(); ++it) { for(auto it = result.begin(); it != result.end(); ++it) {
auto path = it->second.get<std::string>("uri", ""); std::string path;
if(path.size() >= 7) { if(capabilities.document_highlight)
path.erase(0, 7); path = file_path.string();
auto range_it = it->second.find("range"); else {
if(range_it != it->second.not_found()) { path = it->second.get<std::string>("uri", "");
auto start_it = range_it->second.find("start"); if(path.size() >= 7)
auto end_it = range_it->second.find("end"); path.erase(0, 7);
if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) { else
usages.emplace_back(std::make_pair(Offset(start_it->second.get<unsigned>("line"), start_it->second.get<unsigned>("character"), path), "")); continue;
end_offsets.emplace_back(end_it->second.get<unsigned>("line"), end_it->second.get<unsigned>("character")); }
} 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<unsigned>("line"), start_it->second.get<unsigned>("character"), path), ""));
end_offsets.emplace_back(end_it->second.get<unsigned>("line"), end_it->second.get<unsigned>("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) { auto embolden_token = [](std::string &line_, unsigned token_start_pos, unsigned token_end_pos) {
Glib::ustring line = line_; 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; return;
//markup token as bold //markup token as bold
@ -683,7 +696,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
return get_buffer()->get_text(start, end); return get_buffer()->get_text(start, end);
}; };
if(capabilities.rename) { if(capabilities.rename || capabilities.document_highlight) {
rename_similar_tokens = [this](const std::string &text) { rename_similar_tokens = [this](const std::string &text) {
class Usages { class Usages {
public: public:
@ -699,62 +712,64 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
auto iter = get_buffer()->get_insert()->get_iter(); auto iter = get_buffer()->get_insert()->get_iter();
std::vector<Usages> usages; std::vector<Usages> usages;
std::promise<void> result_processed; std::promise<void> 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(capabilities.rename) {
if(!error) { 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) {
boost::filesystem::path project_path; if(!error) {
auto build = Project::Build::create(file_path); boost::filesystem::path project_path;
if(!build->project_path.empty()) auto build = Project::Build::create(file_path);
project_path = build->project_path; if(!build->project_path.empty())
else project_path = build->project_path;
project_path = file_path.parent_path(); else
try { project_path = file_path.parent_path();
auto changes_it = result.find("changes"); try {
if(changes_it != result.not_found()) { auto changes_it = result.find("changes");
for(auto file_it = changes_it->second.begin(); file_it != changes_it->second.end(); ++file_it) { if(changes_it != result.not_found()) {
auto path = file_it->first; for(auto file_it = changes_it->second.begin(); file_it != changes_it->second.end(); ++file_it) {
if(path.size() >= 7) { auto path = file_it->first;
path.erase(0, 7); if(path.size() >= 7) {
if(filesystem::file_in_path(path, project_path)) { path.erase(0, 7);
usages.emplace_back(Usages{path, nullptr, std::vector<std::pair<Offset, Offset>>()}); if(filesystem::file_in_path(path, project_path)) {
for(auto edit_it = file_it->second.begin(); edit_it != file_it->second.end(); ++edit_it) { usages.emplace_back(Usages{path, nullptr, std::vector<std::pair<Offset, Offset>>()});
auto range_it = edit_it->second.find("range"); for(auto edit_it = file_it->second.begin(); edit_it != file_it->second.end(); ++edit_it) {
if(range_it != edit_it->second.not_found()) { auto range_it = edit_it->second.find("range");
auto start_it = range_it->second.find("start"); if(range_it != edit_it->second.not_found()) {
auto end_it = range_it->second.find("end"); auto start_it = range_it->second.find("start");
if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) auto end_it = range_it->second.find("end");
usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get<unsigned>("line"), start_it->second.get<unsigned>("character")), if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found())
Offset(end_it->second.get<unsigned>("line"), end_it->second.get<unsigned>("character")))); usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get<unsigned>("line"), start_it->second.get<unsigned>("character")),
Offset(end_it->second.get<unsigned>("line"), end_it->second.get<unsigned>("character"))));
}
} }
} }
} }
} }
} }
} else {
else { auto changes_pt = result.get_child("documentChanges", boost::property_tree::ptree());
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) {
for(auto change_it = changes_pt.begin(); change_it != changes_pt.end(); ++change_it) { auto document_it = change_it->second.find("textDocument");
auto document_it = change_it->second.find("textDocument"); if(document_it != change_it->second.not_found()) {
if(document_it != change_it->second.not_found()) { auto path = document_it->second.get<std::string>("uri", "");
auto path = document_it->second.get<std::string>("uri", ""); if(path.size() >= 7) {
if(path.size() >= 7) { path.erase(0, 7);
path.erase(0, 7); if(filesystem::file_in_path(path, project_path)) {
if(filesystem::file_in_path(path, project_path)) { usages.emplace_back(Usages{path, std::make_unique<std::string>(), std::vector<std::pair<Offset, Offset>>()});
usages.emplace_back(Usages{path, std::make_unique<std::string>(), std::vector<std::pair<Offset, Offset>>()}); auto edits_pt = change_it->second.get_child("edits", boost::property_tree::ptree());
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) {
for(auto edit_it = edits_pt.begin(); edit_it != edits_pt.end(); ++edit_it) { auto new_text_it = edit_it->second.find("newText");
auto new_text_it = edit_it->second.find("newText"); if(new_text_it != edit_it->second.not_found()) {
if(new_text_it != edit_it->second.not_found()) { auto range_it = edit_it->second.find("range");
auto range_it = edit_it->second.find("range"); if(range_it != edit_it->second.not_found()) {
if(range_it != edit_it->second.not_found()) { auto start_it = range_it->second.find("start");
auto start_it = range_it->second.find("start"); auto end_it = range_it->second.find("end");
auto end_it = range_it->second.find("end"); if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) {
if(start_it != range_it->second.not_found() && end_it != range_it->second.not_found()) { auto end_line = end_it->second.get<size_t>("line");
auto end_line = end_it->second.get<size_t>("line"); if(end_line > std::numeric_limits<int>::max())
if(end_line > std::numeric_limits<int>::max()) end_line = std::numeric_limits<int>::max();
end_line = std::numeric_limits<int>::max(); *usages.back().new_text = new_text_it->second.get_value<std::string>();
*usages.back().new_text = new_text_it->second.get_value<std::string>(); usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get<unsigned>("line"), start_it->second.get<unsigned>("character")),
usages.back().offsets.emplace_back(std::make_pair(Offset(start_it->second.get<unsigned>("line"), start_it->second.get<unsigned>("character")), Offset(static_cast<unsigned>(end_line), end_it->second.get<unsigned>("character"))));
Offset(static_cast<unsigned>(end_line), end_it->second.get<unsigned>("character")))); }
} }
} }
} }
@ -764,13 +779,37 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
} }
} }
} }
catch(...) {
usages.clear();
}
} }
catch(...) { result_processed.set_value();
usages.clear(); });
}
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<std::pair<Offset, Offset>>()});
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<unsigned>("line"), start_it->second.get<unsigned>("character")),
Offset(end_it->second.get<unsigned>("line"), end_it->second.get<unsigned>("character"))));
}
}
}
}
catch(...) {
usages.clear();
}
} }
} result_processed.set_value();
result_processed.set_value(); });
}); }
result_processed.get_future().get(); result_processed.get_future().get();
std::vector<Usages *> usages_renamed; std::vector<Usages *> usages_renamed;

Loading…
Cancel
Save