Browse Source

Language client: added support for type declaration and implementation location. Also fixes to utf-8 byte count and regular utf-16 offsets, and cleaned up write_request and write_notification calls

pipelines/353213535
eidheim 5 years ago
parent
commit
70d9818772
  1. 10
      src/autocomplete.cpp
  2. 3
      src/autocomplete.hpp
  3. 4
      src/source_clang.cpp
  4. 2
      src/source_generic.cpp
  5. 1659
      src/source_language_protocol.cpp
  6. 33
      src/source_language_protocol.hpp
  7. 40
      src/utility.cpp
  8. 2
      src/utility.hpp
  9. 19
      tests/utility_test.cpp

10
src/autocomplete.cpp

@ -59,19 +59,19 @@ void Autocomplete::run() {
if(thread.joinable())
thread.join();
auto iter = view->get_buffer()->get_insert()->get_iter();
auto line_nr = iter.get_line() + 1;
auto column_nr = iter.get_line_index() + 1;
auto line = iter.get_line();
auto line_index = iter.get_line_index();
Glib::ustring buffer;
if(pass_buffer_and_strip_word) {
auto pos = iter.get_offset() - 1;
buffer = view->get_buffer()->get_text();
while(pos >= 0 && Source::BaseView::is_token_char(buffer[pos])) {
buffer.replace(pos, 1, " ");
column_nr--;
line_index--;
pos--;
}
}
thread = std::thread([this, line_nr, column_nr, buffer = std::move(buffer)] {
thread = std::thread([this, line, line_index, buffer = std::move(buffer)] {
auto lock = get_parse_lock();
if(!is_processing())
return;
@ -79,7 +79,7 @@ void Autocomplete::run() {
rows.clear();
auto &buffer_raw = const_cast<std::string &>(buffer.raw());
bool success = add_rows(buffer_raw, line_nr, column_nr);
bool success = add_rows(buffer_raw, line, line_index);
if(!is_processing())
return;

3
src/autocomplete.hpp

@ -48,7 +48,8 @@ public:
std::function<void()> on_add_rows_error = [] {};
/// The handler is not run in the main loop. Should return false on error.
std::function<bool(std::string &buffer, int line_number, int column)> add_rows = [](std::string &, int, int) { return true; };
/// Column is line byte index.
std::function<bool(std::string &buffer, int line, int line_index)> add_rows = [](std::string &, int, int) { return true; };
std::function<void()> on_show = [] {};
std::function<void()> on_hide = [] {};

4
src/source_clang.cpp

@ -948,10 +948,10 @@ Source::ClangViewAutocomplete::ClangViewAutocomplete(const boost::filesystem::pa
full_reparse();
};
autocomplete.add_rows = [this](std::string &buffer, int line_number, int column) {
autocomplete.add_rows = [this](std::string &buffer, int line, int line_index) {
if(is_language({"chdr", "cpphdr"}))
clangmm::remove_include_guard(buffer);
code_complete_results = std::make_unique<clangmm::CodeCompleteResults>(clang_tu->get_code_completions(buffer, line_number, column));
code_complete_results = std::make_unique<clangmm::CodeCompleteResults>(clang_tu->get_code_completions(buffer, line + 1, line_index + 1));
if(!code_complete_results->cx_results)
return false;

2
src/source_generic.cpp

@ -243,7 +243,7 @@ void Source::GenericView::setup_autocomplete() {
update_status_state(this);
};
autocomplete.add_rows = [this](std::string &buffer, int line_number, int column) {
autocomplete.add_rows = [this](std::string &buffer, int /*line*/, int /*line_index*/) {
if(autocomplete.state == Autocomplete::State::starting) {
autocomplete_comment.clear();
autocomplete_insert.clear();

1659
src/source_language_protocol.cpp

File diff suppressed because it is too large Load Diff

33
src/source_language_protocol.hpp

@ -101,6 +101,8 @@ namespace LanguageProtocol {
bool completion = false;
bool signature_help = false;
bool definition = false;
bool type_definition = false;
bool implementation = false;
bool references = false;
bool document_highlight = false;
bool workspace_symbol = false;
@ -155,7 +157,7 @@ namespace LanguageProtocol {
void parse_server_message();
void write_request(Source::LanguageProtocolView *view, const std::string &method, const std::string &params, std::function<void(const boost::property_tree::ptree &, bool)> &&function = nullptr);
void write_response(size_t id, const std::string &result);
void write_notification(const std::string &method, const std::string &params);
void write_notification(const std::string &method, const std::string &params = {});
void handle_server_notification(const std::string &method, const boost::property_tree::ptree &params);
void handle_server_request(size_t id, const std::string &method, const boost::property_tree::ptree &params);
@ -174,14 +176,31 @@ namespace Source {
void rename(const boost::filesystem::path &path) override;
bool save() override;
void update_diagnostics_async(std::vector<LanguageProtocol::Diagnostic> &&diagnostics);
private:
std::atomic<size_t> update_diagnostics_async_count = {0};
/// Get line offset depending on if utf-8 byte offsets or utf-16 code units are used
int get_line_pos(const Gtk::TextIter &iter);
/// Get line offset depending on if utf-8 byte offsets or utf-16 code units are used
int get_line_pos(int line, int line_index);
std::pair<std::string, std::string> make_position(int line, int character);
std::pair<std::string, std::string> make_range(const std::pair<int, int> &start, const std::pair<int, int> &end);
std::string to_string(const std::pair<std::string, std::string> &param);
std::string to_string(const std::vector<std::pair<std::string, std::string>> &params);
/// Helper method for calling client->write_request
void write_request(const std::string &method, const std::vector<std::pair<std::string, std::string>> &params, std::function<void(const boost::property_tree::ptree &, bool)> &&function);
/// Helper method for calling client->write_notification
void write_notification(const std::string &method);
/// Helper method for calling client->write_notification
void write_did_open_notification();
/// Helper method for calling client->write_notification
void write_did_change_notification(const std::vector<std::pair<std::string, std::string>> &params);
std::atomic<size_t> update_diagnostics_async_count = {0};
void update_diagnostics(std::vector<LanguageProtocol::Diagnostic> diagnostics);
public:
void update_diagnostics_async(std::vector<LanguageProtocol::Diagnostic> &&diagnostics);
Gtk::TextIter get_iter_at_line_pos(int line, int pos) override;
std::string uri;
@ -208,14 +227,16 @@ namespace Source {
Glib::ThreadPool thread_pool;
void setup_navigation_and_refactoring();
void setup_signals();
void setup_autocomplete();
void tag_similar_symbols();
Offset get_declaration(const Gtk::TextIter &iter);
Offset get_type_declaration(const Gtk::TextIter &iter);
std::vector<Offset> get_implementations(const Gtk::TextIter &iter);
std::unique_ptr<Autocomplete> autocomplete;
void setup_signals();
void setup_autocomplete();
struct AutocompleteRow {
std::string insert;

40
src/utility.cpp

@ -7,31 +7,31 @@ ScopeGuard::~ScopeGuard() {
}
size_t utf8_character_count(const std::string &text, size_t pos, size_t length) noexcept {
size_t count = 0;
size_t characters = 0;
auto size = length == std::string::npos ? text.size() : std::min(pos + length, text.size());
for(; pos < size;) {
if(static_cast<unsigned char>(text[pos]) <= 0b01111111) {
++count;
++characters;
++pos;
}
else if(static_cast<unsigned char>(text[pos]) >= 0b11111000) // Invalid UTF-8 byte
++pos;
else if(static_cast<unsigned char>(text[pos]) >= 0b11110000) {
++count;
++characters;
pos += 4;
}
else if(static_cast<unsigned char>(text[pos]) >= 0b11100000) {
++count;
++characters;
pos += 3;
}
else if(static_cast<unsigned char>(text[pos]) >= 0b11000000) {
++count;
++characters;
pos += 2;
}
else // // Invalid start of UTF-8 character
++pos;
}
return count;
return characters;
}
size_t utf16_code_units_byte_count(const std::string &text, size_t code_units, size_t start_pos) {
@ -73,6 +73,34 @@ size_t utf16_code_units_byte_count(const std::string &text, size_t code_units, s
return pos - start_pos;
}
size_t utf16_code_unit_count(const std::string &text, size_t pos, size_t length) {
size_t code_units = 0;
auto size = length == std::string::npos ? text.size() : std::min(pos + length, text.size());
for(; pos < size;) {
if(static_cast<unsigned char>(text[pos]) <= 0b01111111) {
++code_units;
++pos;
}
else if(static_cast<unsigned char>(text[pos]) >= 0b11111000) // Invalid UTF-8 byte
++pos;
else if(static_cast<unsigned char>(text[pos]) >= 0b11110000) {
code_units += 2;
pos += 4;
}
else if(static_cast<unsigned char>(text[pos]) >= 0b11100000) {
++code_units;
pos += 3;
}
else if(static_cast<unsigned char>(text[pos]) >= 0b11000000) {
++code_units;
pos += 2;
}
else // // Invalid start of UTF-8 character
++pos;
}
return code_units;
}
bool starts_with(const char *str, const std::string &test) noexcept {
for(size_t i = 0; i < test.size(); ++i) {
if(*str == '\0')

2
src/utility.hpp

@ -13,6 +13,8 @@ size_t utf8_character_count(const std::string &text, size_t pos = 0, size_t leng
/// Returns number of bytes in the given utf16 code units in text
size_t utf16_code_units_byte_count(const std::string &text, size_t code_units, size_t start_pos = 0);
/// Returns number of utf16 code units in the text
size_t utf16_code_unit_count(const std::string &text, size_t pos = 0, size_t length = std::string::npos);
bool starts_with(const char *str, const std::string &test) noexcept;
bool starts_with(const char *str, const char *test) noexcept;

19
tests/utility_test.cpp

@ -50,6 +50,25 @@ int main() {
g_assert_cmpuint(utf16_code_units_byte_count("test🔥test", 10), ==, 12); // Fire emoji between test words
g_assert_cmpuint(utf16_code_units_byte_count("test🔥test", 11), ==, 12); // Fire emoji between test words
g_assert_cmpuint(utf16_code_unit_count("", 0, 0), ==, 0);
g_assert_cmpuint(utf16_code_unit_count("", 0, 2), ==, 0);
g_assert_cmpuint(utf16_code_unit_count("", 2, 2), ==, 0);
g_assert_cmpuint(utf16_code_unit_count("test", 0, 1), ==, 1);
g_assert_cmpuint(utf16_code_unit_count("test", 0, 4), ==, 4);
g_assert_cmpuint(utf16_code_unit_count("test", 0, 10), ==, 4);
g_assert_cmpuint(utf16_code_unit_count("test", 2, 2), ==, 2);
g_assert_cmpuint(utf16_code_unit_count("æøå", 0, 0), ==, 0);
g_assert_cmpuint(utf16_code_unit_count("æøå", 0, 2), ==, 1);
g_assert_cmpuint(utf16_code_unit_count("æøå", 0, 4), ==, 2);
g_assert_cmpuint(utf16_code_unit_count("æøå", 0, 6), ==, 3);
g_assert_cmpuint(utf16_code_unit_count("æøå", 2, 6), ==, 2);
g_assert_cmpuint(utf16_code_unit_count("æøå", 4, 6), ==, 1);
g_assert_cmpuint(utf16_code_unit_count("æøå", 6, 6), ==, 0);
g_assert_cmpuint(utf16_code_unit_count("test🔥test", 0, 0), ==, 0); // Fire emoji between test words
g_assert_cmpuint(utf16_code_unit_count("test🔥test", 0, 4), ==, 4); // Fire emoji between test words
g_assert_cmpuint(utf16_code_unit_count("test🔥test", 0, 8), ==, 6); // Fire emoji between test words
g_assert_cmpuint(utf16_code_unit_count("test🔥test", 0, 12), ==, 10); // Fire emoji between test words
std::string empty;
std::string test("test");
std::string testtest("testtest");

Loading…
Cancel
Save