diff options
Diffstat (limited to 'modules/gdscript/language_server')
8 files changed, 48 insertions, 32 deletions
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 36806d2f73..ad7af34bf1 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -48,17 +48,17 @@ lsp::Position GodotPosition::to_lsp(const Vector<String> &p_lines) const { lsp::Position res; // Special case: `line = 0` -> root class (range covers everything). - if (this->line <= 0) { + if (line <= 0) { return res; } // Special case: `line = p_lines.size() + 1` -> root class (range covers everything). - if (this->line >= p_lines.size() + 1) { + if (line >= p_lines.size() + 1) { res.line = p_lines.size(); return res; } - res.line = this->line - 1; + res.line = line - 1; // Note: character outside of `pos_line.length()-1` is valid. - res.character = this->column - 1; + res.character = column - 1; String pos_line = p_lines[res.line]; if (pos_line.contains("\t")) { @@ -67,7 +67,7 @@ lsp::Position GodotPosition::to_lsp(const Vector<String> &p_lines) const { int in_col = 1; int res_char = 0; - while (res_char < pos_line.size() && in_col < this->column) { + while (res_char < pos_line.size() && in_col < column) { if (pos_line[res_char] == '\t') { in_col += tab_size; res_char++; @@ -191,7 +191,7 @@ void ExtendGDScriptParser::update_symbols() { void ExtendGDScriptParser::update_document_links(const String &p_code) { document_links.clear(); - GDScriptTokenizer scr_tokenizer; + GDScriptTokenizerText scr_tokenizer; Ref<FileAccess> fs = FileAccess::create(FileAccess::ACCESS_RESOURCES); scr_tokenizer.set_source_code(p_code); while (true) { @@ -211,7 +211,7 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) { String value = const_val; lsp::DocumentLink link; link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(scr_path); - link.range = GodotRange(GodotPosition(token.start_line, token.start_column), GodotPosition(token.end_line, token.end_column)).to_lsp(this->lines); + link.range = GodotRange(GodotPosition(token.start_line, token.start_column), GodotPosition(token.end_line, token.end_column)).to_lsp(lines); document_links.push_back(link); } } @@ -222,7 +222,7 @@ void ExtendGDScriptParser::update_document_links(const String &p_code) { lsp::Range ExtendGDScriptParser::range_of_node(const GDScriptParser::Node *p_node) const { GodotPosition start(p_node->start_line, p_node->start_column); GodotPosition end(p_node->end_line, p_node->end_column); - return GodotRange(start, end).to_lsp(this->lines); + return GodotRange(start, end).to_lsp(lines); } void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p_class, lsp::DocumentSymbol &r_symbol) { @@ -394,8 +394,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p symbol.name = m.enum_value.identifier->name; symbol.kind = lsp::SymbolKind::EnumMember; symbol.deprecated = false; - symbol.range.start = GodotPosition(m.enum_value.line, m.enum_value.leftmost_column).to_lsp(this->lines); - symbol.range.end = GodotPosition(m.enum_value.line, m.enum_value.rightmost_column).to_lsp(this->lines); + symbol.range.start = GodotPosition(m.enum_value.line, m.enum_value.leftmost_column).to_lsp(lines); + symbol.range.end = GodotPosition(m.enum_value.line, m.enum_value.rightmost_column).to_lsp(lines); symbol.selectionRange = range_of_node(m.enum_value.identifier); symbol.documentation = m.enum_value.doc_data.description; symbol.uri = uri; @@ -430,8 +430,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p child.name = value.identifier->name; child.kind = lsp::SymbolKind::EnumMember; child.deprecated = false; - child.range.start = GodotPosition(value.line, value.leftmost_column).to_lsp(this->lines); - child.range.end = GodotPosition(value.line, value.rightmost_column).to_lsp(this->lines); + child.range.start = GodotPosition(value.line, value.leftmost_column).to_lsp(lines); + child.range.end = GodotPosition(value.line, value.rightmost_column).to_lsp(lines); child.selectionRange = range_of_node(value.identifier); child.documentation = value.doc_data.description; child.uri = uri; diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index 8489fc08c1..03d830741b 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -105,7 +105,7 @@ Error GDScriptLanguageProtocol::LSPeer::handle_data() { Error GDScriptLanguageProtocol::LSPeer::send_data() { int sent = 0; - if (!res_queue.is_empty()) { + while (!res_queue.is_empty()) { CharString c_res = res_queue[0]; if (res_sent < c_res.size()) { Error err = connection->put_partial_data((const uint8_t *)c_res.get_data() + res_sent, c_res.size() - res_sent - 1, sent); @@ -229,7 +229,9 @@ void GDScriptLanguageProtocol::initialized(const Variant &p_params) { notify_client("gdscript/capabilities", capabilities.to_json()); } -void GDScriptLanguageProtocol::poll() { +void GDScriptLanguageProtocol::poll(int p_limit_usec) { + uint64_t target_ticks = OS::get_singleton()->get_ticks_usec() + p_limit_usec; + if (server->is_connection_available()) { on_client_connected(); } @@ -244,16 +246,22 @@ void GDScriptLanguageProtocol::poll() { E = clients.begin(); continue; } else { - if (peer->connection->get_available_bytes() > 0) { + Error err = OK; + while (peer->connection->get_available_bytes() > 0) { latest_client_id = E->key; - Error err = peer->handle_data(); - if (err != OK && err != ERR_BUSY) { - on_client_disconnected(E->key); - E = clients.begin(); - continue; + err = peer->handle_data(); + if (err != OK || OS::get_singleton()->get_ticks_usec() >= target_ticks) { + break; } } - Error err = peer->send_data(); + + if (err != OK && err != ERR_BUSY) { + on_client_disconnected(E->key); + E = clients.begin(); + continue; + } + + err = peer->send_data(); if (err != OK && err != ERR_BUSY) { on_client_disconnected(E->key); E = clients.begin(); diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h index a4d9dc6b1d..f29abaa337 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.h +++ b/modules/gdscript/language_server/gdscript_language_protocol.h @@ -105,7 +105,7 @@ public: _FORCE_INLINE_ Ref<GDScriptTextDocument> get_text_document() { return text_document; } _FORCE_INLINE_ bool is_initialized() const { return _initialized; } - void poll(); + void poll(int p_limit_usec); Error start(int p_port, const IPAddress &p_bind_ip); void stop(); diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 053be7eec2..3df26ea576 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -44,6 +44,7 @@ GDScriptLanguageServer::GDScriptLanguageServer() { _EDITOR_DEF("network/language_server/enable_smart_resolve", true); _EDITOR_DEF("network/language_server/show_native_symbols_in_editor", false); _EDITOR_DEF("network/language_server/use_thread", use_thread); + _EDITOR_DEF("network/language_server/poll_limit_usec", poll_limit_usec); } void GDScriptLanguageServer::_notification(int p_what) { @@ -58,15 +59,20 @@ void GDScriptLanguageServer::_notification(int p_what) { case NOTIFICATION_INTERNAL_PROCESS: { if (started && !use_thread) { - protocol.poll(); + protocol.poll(poll_limit_usec); } } break; case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { + if (!EditorSettings::get_singleton()->check_changed_settings_in_group("network/language_server")) { + break; + } + String remote_host = String(_EDITOR_GET("network/language_server/remote_host")); int remote_port = (GDScriptLanguageServer::port_override > -1) ? GDScriptLanguageServer::port_override : (int)_EDITOR_GET("network/language_server/remote_port"); bool remote_use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); - if (remote_host != host || remote_port != port || remote_use_thread != use_thread) { + int remote_poll_limit = (int)_EDITOR_GET("network/language_server/poll_limit_usec"); + if (remote_host != host || remote_port != port || remote_use_thread != use_thread || remote_poll_limit != poll_limit_usec) { stop(); start(); } @@ -79,7 +85,7 @@ void GDScriptLanguageServer::thread_main(void *p_userdata) { GDScriptLanguageServer *self = static_cast<GDScriptLanguageServer *>(p_userdata); while (self->thread_running) { // Poll 20 times per second - self->protocol.poll(); + self->protocol.poll(self->poll_limit_usec); OS::get_singleton()->delay_usec(50000); } } @@ -88,6 +94,7 @@ void GDScriptLanguageServer::start() { host = String(_EDITOR_GET("network/language_server/remote_host")); port = (GDScriptLanguageServer::port_override > -1) ? GDScriptLanguageServer::port_override : (int)_EDITOR_GET("network/language_server/remote_port"); use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); + poll_limit_usec = (int)_EDITOR_GET("network/language_server/poll_limit_usec"); if (protocol.start(port, IPAddress(host)) == OK) { EditorNode::get_log()->add_message("--- GDScript language server started on port " + itos(port) + " ---", EditorLog::MSG_TYPE_EDITOR); if (use_thread) { diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h index e845d139bf..2ace5ca446 100644 --- a/modules/gdscript/language_server/gdscript_language_server.h +++ b/modules/gdscript/language_server/gdscript_language_server.h @@ -47,6 +47,7 @@ class GDScriptLanguageServer : public EditorPlugin { bool use_thread = false; String host = "127.0.0.1"; int port = 6005; + int poll_limit_usec = 100000; static void thread_main(void *p_userdata); private: diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index 0b1371851b..9bf458e031 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -114,7 +114,7 @@ void GDScriptTextDocument::didSave(const Variant &p_param) { scr->update_exports(); ScriptEditor::get_singleton()->reload_scripts(true); ScriptEditor::get_singleton()->update_docs_from_script(scr); - ScriptEditor::get_singleton()->trigger_live_script_reload(); + ScriptEditor::get_singleton()->trigger_live_script_reload(scr->get_path()); } } @@ -421,7 +421,7 @@ Array GDScriptTextDocument::definition(const Dictionary &p_params) { lsp::TextDocumentPositionParams params; params.load(p_params); List<const lsp::DocumentSymbol *> symbols; - Array arr = this->find_symbols(params, symbols); + Array arr = find_symbols(params, symbols); return arr; } @@ -429,7 +429,7 @@ Variant GDScriptTextDocument::declaration(const Dictionary &p_params) { lsp::TextDocumentPositionParams params; params.load(p_params); List<const lsp::DocumentSymbol *> symbols; - Array arr = this->find_symbols(params, symbols); + Array arr = find_symbols(params, symbols); if (arr.is_empty() && !symbols.is_empty() && !symbols.front()->get()->native_class.is_empty()) { // Find a native symbol const lsp::DocumentSymbol *symbol = symbols.front()->get(); if (GDScriptLanguageProtocol::get_singleton()->is_goto_native_symbols_enabled()) { @@ -456,7 +456,7 @@ Variant GDScriptTextDocument::declaration(const Dictionary &p_params) { id = "class_global:" + symbol->native_class + ":" + symbol->name; break; } - call_deferred(SNAME("show_native_symbol_in_editor"), id); + callable_mp(this, &GDScriptTextDocument::show_native_symbol_in_editor).call_deferred(id); } else { notify_client_show_symbol(symbol); } diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 81933c8c87..853a8e0f19 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -641,7 +641,7 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S while (!stack.is_empty()) { current = Object::cast_to<Node>(stack.pop_back()); Ref<GDScript> scr = current->get_script(); - if (scr.is_valid() && scr->get_path() == path) { + if (scr.is_valid() && GDScript::is_canonically_equal_paths(scr->get_path(), path)) { break; } for (int i = 0; i < current->get_child_count(); ++i) { @@ -650,7 +650,7 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S } Ref<GDScript> scr = current->get_script(); - if (!scr.is_valid() || scr->get_path() != path) { + if (!scr.is_valid() || !GDScript::is_canonically_equal_paths(scr->get_path(), path)) { current = owner_scene_node; } } diff --git a/modules/gdscript/language_server/godot_lsp.h b/modules/gdscript/language_server/godot_lsp.h index e09adb74bd..284762018f 100644 --- a/modules/gdscript/language_server/godot_lsp.h +++ b/modules/gdscript/language_server/godot_lsp.h @@ -200,7 +200,7 @@ struct LocationLink { /** * The range that should be selected and revealed when this link is being followed, e.g the name of a function. - * Must be contained by the the `targetRange`. See also `DocumentSymbol#range` + * Must be contained by the `targetRange`. See also `DocumentSymbol#range` */ Range targetSelectionRange; }; |