Browse Source

Now underlines clickable symbols. Also cleanup of similar_symbol tagging/untagging.

merge-requests/389/head
eidheim 7 years ago
parent
commit
0c7dbecb0d
  1. 102
      src/source.cc
  2. 10
      src/source.h
  3. 16
      src/source_base.cc
  4. 6
      src/source_base.h
  5. 74
      src/source_clang.cc
  6. 7
      src/source_clang.h
  7. 67
      src/source_language_protocol.cc
  8. 14
      src/source_language_protocol.h

102
src/source.cc

@ -119,6 +119,9 @@ Source::View::View(const boost::filesystem::path &file_path, const Glib::RefPtr<
similar_symbol_tag = get_buffer()->create_tag();
similar_symbol_tag->property_weight() = Pango::WEIGHT_ULTRAHEAVY;
clickable_tag = get_buffer()->create_tag();
clickable_tag->property_underline() = Pango::Underline::UNDERLINE_SINGLE;
clickable_tag->property_underline_set() = true;
get_buffer()->create_tag("def:warning");
get_buffer()->create_tag("def:warning_underline");
@ -148,23 +151,6 @@ Source::View::View(const boost::filesystem::path &file_path, const Glib::RefPtr<
link_tag = get_buffer()->create_tag("link");
get_buffer()->signal_changed().connect([this]() {
if(update_status_location)
update_status_location(this);
});
signal_realize().connect([this] {
auto gutter = get_gutter(Gtk::TextWindowType::TEXT_WINDOW_LEFT);
auto renderer = gutter->get_renderer_at_pos(15, 0);
if(renderer) {
renderer_activate_connection.disconnect();
renderer_activate_connection = renderer->signal_activate().connect([this](const Gtk::TextIter &iter, const Gdk::Rectangle &, GdkEvent *) {
if(toggle_breakpoint)
toggle_breakpoint(iter.get_line());
});
}
});
if(language) {
auto language_id = language->get_id();
if(language_id == "chdr" || language_id == "cpphdr" || language_id == "c" || language_id == "cpp") {
@ -201,7 +187,7 @@ Source::View::View(const boost::filesystem::path &file_path, const Glib::RefPtr<
}
}
setup_tooltip_and_dialog_events();
setup_signals();
setup_format_style(is_generic_view);
std::string comment_characters;
@ -455,7 +441,35 @@ void Source::View::configure() {
}
}
void Source::View::setup_tooltip_and_dialog_events() {
void Source::View::setup_signals() {
get_buffer()->signal_changed().connect([this]() {
if(update_status_location)
update_status_location(this);
hide_tooltips();
if(similar_symbol_tag_applied) {
get_buffer()->remove_tag(similar_symbol_tag, get_buffer()->begin(), get_buffer()->end());
similar_symbol_tag_applied = false;
}
if(clickable_tag_applied) {
get_buffer()->remove_tag(clickable_tag, get_buffer()->begin(), get_buffer()->end());
clickable_tag_applied = false;
}
});
signal_realize().connect([this] {
auto gutter = get_gutter(Gtk::TextWindowType::TEXT_WINDOW_LEFT);
auto renderer = gutter->get_renderer_at_pos(15, 0);
if(renderer) {
renderer_activate_connection.disconnect();
renderer_activate_connection = renderer->signal_activate().connect([this](const Gtk::TextIter &iter, const Gdk::Rectangle &, GdkEvent *) {
if(toggle_breakpoint)
toggle_breakpoint(iter.get_line());
});
}
});
type_tooltips.on_motion = [this] {
delayed_tooltips_connection.disconnect();
};
@ -463,10 +477,6 @@ void Source::View::setup_tooltip_and_dialog_events() {
delayed_tooltips_connection.disconnect();
};
get_buffer()->signal_changed().connect([this] {
hide_tooltips();
});
signal_motion_notify_event().connect([this](GdkEventMotion *event) {
if(on_motion_last_x != event->x || on_motion_last_y != event->y) {
delayed_tooltips_connection.disconnect();
@ -485,6 +495,24 @@ void Source::View::setup_tooltip_and_dialog_events() {
return false;
}, 100);
}
if(clickable_tag_applied) {
get_buffer()->remove_tag(clickable_tag, get_buffer()->begin(), get_buffer()->end());
clickable_tag_applied = false;
}
if((event->state & primary_modifier_mask) && !(event->state & GDK_SHIFT_MASK) && !(event->state & GDK_BUTTON1_MASK)) {
delayed_tag_clickable_connection.disconnect();
delayed_tag_clickable_connection = Glib::signal_timeout().connect([this, x = event->x, y = event->y]() {
int buffer_x, buffer_y;
window_to_buffer_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, x, y, buffer_x, buffer_y);
Gtk::TextIter iter;
get_iter_at_location(iter, buffer_x, buffer_y);
apply_clickable_tag(iter);
clickable_tag_applied = true;
return false;
}, 100);
}
auto last_mouse_pos = std::make_pair(on_motion_last_x, on_motion_last_y);
auto mouse_pos = std::make_pair(event->x, event->y);
type_tooltips.hide(last_mouse_pos, mouse_pos);
@ -501,6 +529,7 @@ void Source::View::setup_tooltip_and_dialog_events() {
if(mark->get_name() == "insert") {
hide_tooltips();
delayed_tooltips_connection.disconnect();
delayed_tooltips_connection = Glib::signal_timeout().connect([this]() {
Tooltips::init();
@ -518,6 +547,13 @@ void Source::View::setup_tooltip_and_dialog_events() {
return false;
}, 500);
delayed_tag_similar_symbols_connection.disconnect();
delayed_tag_similar_symbols_connection = Glib::signal_timeout().connect([this] {
apply_similar_symbol_tag();
similar_symbol_tag_applied = true;
return false;
}, 100);
if(SelectionDialog::get())
SelectionDialog::get()->hide();
if(CompletionDialog::get())
@ -528,6 +564,14 @@ void Source::View::setup_tooltip_and_dialog_events() {
}
});
signal_key_release_event().connect([this](GdkEventKey *event) {
if((event->state & primary_modifier_mask) && clickable_tag_applied) {
get_buffer()->remove_tag(clickable_tag, get_buffer()->begin(), get_buffer()->end());
clickable_tag_applied = false;
}
return false;
});
signal_scroll_event().connect([this](GdkEventScroll *event) {
hide_tooltips();
hide_dialogs();
@ -536,6 +580,10 @@ void Source::View::setup_tooltip_and_dialog_events() {
signal_focus_out_event().connect([this](GdkEventFocus *event) {
hide_tooltips();
if(clickable_tag_applied) {
get_buffer()->remove_tag(clickable_tag, get_buffer()->begin(), get_buffer()->end());
clickable_tag_applied = false;
}
return false;
});
@ -883,6 +931,7 @@ void Source::View::setup_format_style(bool is_generic_view) {
Source::View::~View() {
delayed_tooltips_connection.disconnect();
delayed_tag_similar_symbols_connection.disconnect();
delayed_tag_clickable_connection.disconnect();
renderer_activate_connection.disconnect();
non_deleted_views.erase(this);
@ -2637,12 +2686,7 @@ bool Source::View::on_button_press_event(GdkEventButton *event) {
// Go to implementation or declaration
if((event->type == GDK_BUTTON_PRESS) && (event->button == 1)) {
#ifdef __APPLE__
GdkModifierType mask = GDK_MOD2_MASK;
#else
GdkModifierType mask = GDK_CONTROL_MASK;
#endif
if(event->state & mask) {
if(event->state & primary_modifier_mask) {
int x, y;
window_to_buffer_coords(Gtk::TextWindowType::TEXT_WINDOW_TEXT, event->x, event->y, x, y);
Gtk::TextIter iter;

10
src/source.h

@ -91,8 +91,16 @@ namespace Source {
Tooltips diagnostic_tooltips;
Tooltips type_tooltips;
sigc::connection delayed_tooltips_connection;
Glib::RefPtr<Gtk::TextTag> similar_symbol_tag;
sigc::connection delayed_tag_similar_symbols_connection;
virtual void apply_similar_symbol_tag() {}
bool similar_symbol_tag_applied = false;
Glib::RefPtr<Gtk::TextTag> clickable_tag;
sigc::connection delayed_tag_clickable_connection;
virtual void apply_clickable_tag(const Gtk::TextIter &iter) {}
bool clickable_tag_applied = false;
virtual void show_diagnostic_tooltips(const Gdk::Rectangle &rectangle) { diagnostic_tooltips.show(rectangle); }
void add_diagnostic_tooltip(const Gtk::TextIter &start, const Gtk::TextIter &end, bool error, std::function<void(const Glib::RefPtr<Gtk::TextBuffer> &)> &&set_buffer);
void clear_diagnostic_tooltips();
@ -125,7 +133,7 @@ namespace Source {
bool interactive_completion = true;
private:
void setup_tooltip_and_dialog_events();
void setup_signals();
void setup_format_style(bool is_generic_view);
Gsv::DrawSpacesFlags parse_show_whitespace_characters(const std::string &text);

16
src/source_base.cc

@ -45,6 +45,13 @@ Source::BaseView::BaseView(const boost::filesystem::path &file_path, const Glib:
}
set_tab_char_and_size(tab_char, tab_size);
#ifdef __APPLE__
primary_modifier_mask = GDK_MOD2_MASK;
#else
primary_modifier_mask = GDK_CONTROL_MASK;
#endif
search_settings = gtk_source_search_settings_new();
gtk_source_search_settings_set_wrap_around(search_settings, true);
search_context = gtk_source_search_context_new(get_source_buffer()->gobj(), search_settings);
@ -594,7 +601,7 @@ Gtk::TextIter Source::BaseView::get_tabs_end_iter() {
return get_tabs_end_iter(get_buffer()->get_insert());
}
std::string Source::BaseView::get_token(Gtk::TextIter iter) {
std::pair<Gtk::TextIter, Gtk::TextIter> Source::BaseView::get_token_iters(Gtk::TextIter iter) {
auto start = iter;
auto end = iter;
@ -608,7 +615,12 @@ std::string Source::BaseView::get_token(Gtk::TextIter iter) {
break;
}
return get_buffer()->get_text(start, end);
return {start, end};
}
std::string Source::BaseView::get_token(const Gtk::TextIter &iter) {
auto range = get_token_iters(iter);
return get_buffer()->get_text(range.first, range.second);
}
void Source::BaseView::cleanup_whitespace_characters() {

6
src/source_base.h

@ -90,6 +90,9 @@ namespace Source {
std::string tab;
std::pair<char, unsigned> find_tab_char_and_size();
/// Apple key for MacOS, and control key otherwise
GdkModifierType primary_modifier_mask;
/// Move iter to line start. Depending on iter position, before or after indentation.
/// Works with wrapped lines.
Gtk::TextIter get_smart_home_iter(const Gtk::TextIter &iter);
@ -110,7 +113,8 @@ namespace Source {
Gtk::TextIter get_tabs_end_iter(int line_nr);
Gtk::TextIter get_tabs_end_iter();
std::string get_token(Gtk::TextIter iter);
std::pair<Gtk::TextIter, Gtk::TextIter> get_token_iters(Gtk::TextIter iter);
std::string get_token(const Gtk::TextIter &iter);
void cleanup_whitespace_characters();
void cleanup_whitespace_characters(const Gtk::TextIter &iter);

74
src/source_clang.cc

@ -17,6 +17,8 @@
clangmm::Index Source::ClangViewParse::clang_index(0, 0);
const std::regex include_regex(R"(^[ \t]*#[ \t]*include[ \t]*[<"]([^<>"]+)[>"].*$)");
Source::ClangViewParse::ClangViewParse(const boost::filesystem::path &file_path, const Glib::RefPtr<Gsv::Language> &language)
: BaseView(file_path, language), Source::View(file_path, language) {
Usages::Clang::erase_cache(file_path);
@ -828,13 +830,6 @@ const std::unordered_map<std::string, std::string> &Source::ClangViewAutocomplet
Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file_path, const Glib::RefPtr<Gsv::Language> &language)
: BaseView(file_path, language), Source::ClangViewParse(file_path, language) {
get_buffer()->signal_changed().connect([this]() {
if(last_tagged_identifier) {
get_buffer()->remove_tag(similar_symbol_tag, get_buffer()->begin(), get_buffer()->end());
last_tagged_identifier = Identifier();
}
});
get_token_spelling = [this]() {
if(!parsed) {
Info::get().print("Buffer is parsing");
@ -969,17 +964,6 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
}
};
get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator &iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) {
if(mark->get_name() == "insert") {
delayed_tag_similar_symbols_connection.disconnect();
delayed_tag_similar_symbols_connection = Glib::signal_timeout().connect([this]() {
auto identifier = get_identifier();
tag_similar_identifiers(identifier);
return false;
}, 100);
}
});
auto declaration_location = [this]() {
auto identifier = get_identifier();
if(identifier) {
@ -989,7 +973,6 @@ Source::ClangViewRefactor::ClangViewRefactor(const boost::filesystem::path &file
}
else {
// If cursor is at an include line, return offset to included file
const static std::regex include_regex(R"(^[ \t]*#[ \t]*include[ \t]*[<"]([^<>"]+)[>"].*$)");
std::smatch sm;
auto line = get_line();
if(std::regex_match(line, sm, include_regex)) {
@ -1721,26 +1704,51 @@ void Source::ClangViewRefactor::wait_parsing() {
}
}
void Source::ClangViewRefactor::tag_similar_identifiers(const Identifier &identifier) {
if(parsed) {
if(identifier && last_tagged_identifier != identifier) {
get_buffer()->remove_tag(similar_symbol_tag, get_buffer()->begin(), get_buffer()->end());
auto offsets = clang_tokens->get_similar_token_offsets(identifier.kind, identifier.spelling, identifier.cursor.get_all_usr_extended());
for(auto &offset : offsets) {
auto start_iter = get_buffer()->get_iter_at_line_index(offset.first.line - 1, offset.first.index - 1);
auto end_iter = get_buffer()->get_iter_at_line_index(offset.second.line - 1, offset.second.index - 1);
get_buffer()->apply_tag(similar_symbol_tag, start_iter, end_iter);
void Source::ClangViewRefactor::apply_similar_symbol_tag() {
get_buffer()->remove_tag(similar_symbol_tag, get_buffer()->begin(), get_buffer()->end());
auto identifier = get_identifier();
if(identifier) {
auto offsets = clang_tokens->get_similar_token_offsets(identifier.kind, identifier.spelling, identifier.cursor.get_all_usr_extended());
for(auto &offset : offsets) {
auto start_iter = get_buffer()->get_iter_at_line_index(offset.first.line - 1, offset.first.index - 1);
auto end_iter = get_buffer()->get_iter_at_line_index(offset.second.line - 1, offset.second.index - 1);
get_buffer()->apply_tag(similar_symbol_tag, start_iter, end_iter);
}
}
}
void Source::ClangViewRefactor::apply_clickable_tag(const Gtk::TextIter &iter) {
if(!parsed)
return;
auto line = static_cast<unsigned>(iter.get_line());
auto index = static_cast<unsigned>(iter.get_line_index());
for(size_t c = clang_tokens->size() - 1; c != static_cast<size_t>(-1); --c) {
auto &token = (*clang_tokens)[c];
if(token.is_identifier()) {
auto &token_offsets = clang_tokens_offsets[c];
if(line == token_offsets.first.line - 1 && index >= token_offsets.first.index - 1 && index <= token_offsets.second.index - 1) {
auto referenced = token.get_cursor().get_referenced();
if(referenced) {
auto start = get_buffer()->get_iter_at_line_index(token_offsets.first.line - 1, token_offsets.first.index - 1);
auto end = get_buffer()->get_iter_at_line_index(token_offsets.second.line - 1, token_offsets.second.index - 1);
get_buffer()->apply_tag(clickable_tag, start, end);
return;
}
break;
}
last_tagged_identifier = identifier;
}
}
if(!identifier && last_tagged_identifier) {
get_buffer()->remove_tag(similar_symbol_tag, get_buffer()->begin(), get_buffer()->end());
last_tagged_identifier = Identifier();
std::smatch sm;
auto line_at_iter = this->get_line(iter);
if(std::regex_match(line_at_iter, sm, include_regex)) {
auto start = get_buffer()->get_iter_at_line(line);
auto end = start;
end.forward_to_line_end();
get_buffer()->apply_tag(clickable_tag, start, end);
}
}
Source::ClangView::ClangView(const boost::filesystem::path &file_path, const Glib::RefPtr<Gsv::Language> &language)
: BaseView(file_path, language), ClangViewParse(file_path, language), ClangViewAutocomplete(file_path, language), ClangViewRefactor(file_path, language) {
if(language) {

7
src/source_clang.h

@ -93,12 +93,13 @@ namespace Source {
public:
ClangViewRefactor(const boost::filesystem::path &file_path, const Glib::RefPtr<Gsv::Language> &language);
protected:
void apply_similar_symbol_tag() override;
void apply_clickable_tag(const Gtk::TextIter &iter) override;
private:
Identifier get_identifier();
void wait_parsing();
void tag_similar_identifiers(const Identifier &identifier);
Identifier last_tagged_identifier;
};
class ClangView : public ClangViewAutocomplete, public ClangViewRefactor {

67
src/source_language_protocol.cc

@ -93,7 +93,7 @@ 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<LanguageProtocol::Capabilities::TextDocumentSync>(capabilities_pt->second.get<unsigned>("textDocumentSync", 0));
capabilities.text_document_sync = static_cast<LanguageProtocol::Capabilities::TextDocumentSync>(capabilities_pt->second.get<int>("textDocumentSync", 0));
capabilities.hover = capabilities_pt->second.get<bool>("hoverProvider", false);
capabilities.completion = capabilities_pt->second.find("completionProvider") != capabilities_pt->second.not_found() ? true : false;
capabilities.definition = capabilities_pt->second.get<bool>("definitionProvider", false);
@ -340,20 +340,6 @@ Source::LanguageProtocolView::LanguageProtocolView(const boost::filesystem::path
initialize(true);
get_buffer()->signal_changed().connect([this] {
get_buffer()->remove_tag(similar_symbol_tag, get_buffer()->begin(), get_buffer()->end());
});
get_buffer()->signal_mark_set().connect([this](const Gtk::TextBuffer::iterator &iterator, const Glib::RefPtr<Gtk::TextBuffer::Mark> &mark) {
if(mark->get_name() == "insert") {
delayed_tag_similar_symbols_connection.disconnect();
delayed_tag_similar_symbols_connection = Glib::signal_timeout().connect([this]() {
tag_similar_symbols();
return false;
}, 200);
}
});
get_buffer()->signal_insert().connect([this](const Gtk::TextBuffer::iterator &start, const Glib::ustring &text_, int bytes) {
std::string content_changes;
if(capabilities.text_document_sync == LanguageProtocol::Capabilities::TextDocumentSync::NONE)
@ -514,8 +500,8 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
// If entire buffer is replaced:
if(text_edits.size() == 1 &&
text_edits[0].range.start.line == 0 && text_edits[0].range.start.character == 0 &&
(text_edits[0].range.end.line > static_cast<unsigned>(end_iter.get_line()) ||
(text_edits[0].range.end.line == static_cast<unsigned>(end_iter.get_line()) && text_edits[0].range.end.character >= static_cast<unsigned>(end_iter.get_line_offset())))) {
(text_edits[0].range.end.line > end_iter.get_line() ||
(text_edits[0].range.end.line == end_iter.get_line() && text_edits[0].range.end.character >= end_iter.get_line_offset()))) {
replace_text(text_edits[0].new_text);
}
else {
@ -574,20 +560,20 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
});
result_processed.get_future().get();
auto embolden_token = [](std::string &line_, unsigned token_start_pos, unsigned token_end_pos) {
auto embolden_token = [](std::string &line_, int token_start_pos, int token_end_pos) {
Glib::ustring line = line_;
if(token_start_pos > line.size() || token_end_pos > line.size())
if(static_cast<size_t>(token_start_pos) > line.size() || static_cast<size_t>(token_end_pos) > line.size())
return;
//markup token as bold
size_t pos = 0;
while((pos = line.find('&', pos)) != Glib::ustring::npos) {
size_t pos2 = line.find(';', pos + 2);
if(token_start_pos > pos) {
if(static_cast<size_t>(token_start_pos) > pos) {
token_start_pos += pos2 - pos;
token_end_pos += pos2 - pos;
}
else if(token_end_pos > pos)
else if(static_cast<size_t>(token_end_pos) > pos)
token_end_pos += pos2 - pos;
else
break;
@ -620,7 +606,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
}
}
if(view_it != views.end()) {
if(location.range.start.line < static_cast<unsigned>((*view_it)->get_buffer()->get_line_count())) {
if(location.range.start.line < (*view_it)->get_buffer()->get_line_count()) {
auto start = (*view_it)->get_buffer()->get_iter_at_line(location.range.start.line);
auto end = start;
end.forward_to_line_end();
@ -649,7 +635,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
}
}
if(location.range.start.line < it->second.size()) {
if(static_cast<size_t>(location.range.start.line) < it->second.size()) {
usage.second = Glib::Markup::escape_text(it->second[location.range.start.line]);
embolden_token(usage.second, location.range.start.character, location.range.end.character);
}
@ -778,8 +764,8 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
// If entire buffer is replaced
if(change.text_edits.size() == 1 &&
change.text_edits[0].range.start.line == 0 && change.text_edits[0].range.start.character == 0 &&
(change.text_edits[0].range.end.line > static_cast<unsigned>(end_iter.get_line()) ||
(change.text_edits[0].range.end.line == static_cast<unsigned>(end_iter.get_line()) && change.text_edits[0].range.end.character >= static_cast<unsigned>(end_iter.get_line_offset()))))
(change.text_edits[0].range.end.line > end_iter.get_line() ||
(change.text_edits[0].range.end.line == end_iter.get_line() && change.text_edits[0].range.end.character >= end_iter.get_line_offset())))
replace_text(change.text_edits[0].new_text);
else {
for(auto edit_it = change.text_edits.rbegin(); edit_it != change.text_edits.rend(); ++edit_it) {
@ -812,10 +798,10 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() {
for(auto edit_it = change.text_edits.rbegin(); edit_it != change.text_edits.rend(); ++edit_it) {
auto start_line = edit_it->range.start.line;
auto end_line = edit_it->range.end.line;
if(start_line < lines_start_pos.size()) {
if(static_cast<size_t>(start_line) < lines_start_pos.size()) {
auto start = lines_start_pos[start_line] + edit_it->range.start.character;
unsigned end;
if(end_line >= lines_start_pos.size())
size_t end;
if(static_cast<size_t>(end_line) >= lines_start_pos.size())
end = buffer.size();
else
end = lines_start_pos[end_line] + edit_it->range.end.character;
@ -1037,7 +1023,7 @@ void Source::LanguageProtocolView::show_type_tooltips(const Gdk::Rectangle &rect
});
}
void Source::LanguageProtocolView::tag_similar_symbols() {
void Source::LanguageProtocolView::apply_similar_symbol_tag() {
if(!capabilities.document_highlight && !capabilities.references)
return;
@ -1063,7 +1049,7 @@ void Source::LanguageProtocolView::tag_similar_symbols() {
}
}
dispatcher.post([this, ranges = std::move(ranges), current_request] {
if(current_request != request_count)
if(current_request != request_count || !similar_symbol_tag_applied)
return;
get_buffer()->remove_tag(similar_symbol_tag, get_buffer()->begin(), get_buffer()->end());
for(auto &range : ranges) {
@ -1076,6 +1062,25 @@ void Source::LanguageProtocolView::tag_similar_symbols() {
});
}
void Source::LanguageProtocolView::apply_clickable_tag(const Gtk::TextIter &iter) {
static int request_count = 0;
request_count++;
auto current_request = request_count;
auto line = iter.get_line();
auto offset = iter.get_line_offset();
client->write_request(this, "textDocument/definition", R"("textDocument":{"uri":"file://)" + file_path.string() + R"("}, "position": {"line": )" + std::to_string(line) + ", \"character\": " + std::to_string(offset) + "}", [this, current_request, line, offset](const boost::property_tree::ptree &result, bool error) {
if(!error && !result.empty()) {
dispatcher.post([this, current_request, line, offset] {
if(current_request != request_count || !clickable_tag_applied)
return;
get_buffer()->remove_tag(clickable_tag, get_buffer()->begin(), get_buffer()->end());
auto range = get_token_iters(get_iter_at_line_offset(line, offset));
get_buffer()->apply_tag(clickable_tag, range.first, range.second);
});
}
});
}
Source::Offset Source::LanguageProtocolView::get_declaration(const Gtk::TextIter &iter) {
auto offset = std::make_shared<Offset>();
std::promise<void> result_processed;
@ -1229,7 +1234,7 @@ void Source::LanguageProtocolView::setup_autocomplete() {
}
else {
insert = label;
auto kind = it->second.get<unsigned>("kind", 0);
auto kind = it->second.get<int>("kind", 0);
if(kind >= 2 && kind <= 3) {
bool found_bracket = false;
for(auto &chr : insert) {

14
src/source_language_protocol.h

@ -16,10 +16,10 @@ namespace Source {
namespace LanguageProtocol {
class Offset {
public:
Offset(const boost::property_tree::ptree &pt) : line(pt.get<unsigned>("line")),
character(pt.get<unsigned>("character")) {}
unsigned line;
unsigned character;
Offset(const boost::property_tree::ptree &pt) : line(pt.get<int>("line")),
character(pt.get<int>("character")) {}
int line;
int character;
};
class Range {
@ -56,14 +56,14 @@ namespace LanguageProtocol {
Diagnostic(const boost::property_tree::ptree &pt) : message(pt.get<std::string>("message")),
range(pt.get_child("range")),
severity(pt.get<unsigned>("severity", 0)) {
severity(pt.get<int>("severity", 0)) {
auto related_information_it = pt.get_child("relatedInformation", boost::property_tree::ptree());
for(auto it = related_information_it.begin(); it != related_information_it.end(); ++it)
related_informations.emplace_back(it->second);
}
std::string message;
Range range;
unsigned severity;
int severity;
std::vector<RelatedInformation> related_informations;
};
@ -152,6 +152,8 @@ namespace Source {
protected:
void show_type_tooltips(const Gdk::Rectangle &rectangle) override;
void apply_similar_symbol_tag() override;
void apply_clickable_tag(const Gtk::TextIter &iter) override;
private:
std::string language_id;

Loading…
Cancel
Save