diff --git a/modules/gdscript/SCsub b/modules/gdscript/SCsub index a4af0cf66..8108df98b 100644 --- a/modules/gdscript/SCsub +++ b/modules/gdscript/SCsub @@ -9,4 +9,11 @@ env_gdscript.add_source_files(env.modules_sources, "*.cpp") if env["tools"]: env_gdscript.add_source_files(env.modules_sources, "./editor/*.cpp") - \ No newline at end of file + + # Those two modules are required for the language server protocol + if env["module_jsonrpc_enabled"] and env["module_websocket_enabled"]: + env_gdscript.add_source_files(env.modules_sources, "./language_server/*.cpp") + else: + # Using a define in the disabled case, to avoid having an extra define + # in regular builds where all modules are enabled. + env_gdscript.Append(CPPDEFINES=["GDSCRIPT_NO_LSP"]) \ No newline at end of file diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 21f9ce01d..1fea04b80 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -217,7 +217,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p r_symbol.children.push_back(symbol); } - for (Map::Element *E = p_class->constant_expressions.front(); E; E = E->next()) { + for (RBMap::Element *E = p_class->constant_expressions.front(); E; E = E->next()) { lsp::DocumentSymbol symbol; const GDScriptParser::ClassNode::Constant &c = E->value(); const GDScriptParser::ConstantNode *node = dynamic_cast(c.expression); @@ -246,7 +246,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p if (res.is_valid() && !res->get_path().empty()) { value_text = "preload(\"" + res->get_path() + "\")"; if (symbol.documentation.empty()) { - if (Map::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) { + if (RBMap::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) { symbol.documentation = S->get()->class_symbol.documentation; } } @@ -356,7 +356,7 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN } for (const List::Element *B = function_blocks.front(); B; B = B->next()) { - for (const Map::Element *E = B->get()->variables.front(); E; E = E->next()) { + for (const RBMap::Element *E = B->get()->variables.front(); E; E = E->next()) { lsp::DocumentSymbol symbol; const GDScriptParser::LocalVarNode *var = E->value(); symbol.name = E->key(); @@ -651,7 +651,6 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio ERR_FAIL_NULL_V(p_func, func); func["name"] = p_func->name; func["return_type"] = p_func->return_type.to_string(); - func["rpc_mode"] = p_func->rpc_mode; Array arguments; for (int i = 0; i < p_func->arguments.size(); i++) { Dictionary arg; @@ -707,7 +706,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode class_api["sub_classes"] = subclasses; Array constants; - for (Map::Element *E = p_class->constant_expressions.front(); E; E = E->next()) { + for (RBMap::Element *E = p_class->constant_expressions.front(); E; E = E->next()) { const GDScriptParser::ClassNode::Constant &c = E->value(); const GDScriptParser::ConstantNode *node = dynamic_cast(c.expression); ERR_FAIL_COND_V(!node, class_api); diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h index e360fdcf1..28e0b5310 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.h +++ b/modules/gdscript/language_server/gdscript_extend_parser.h @@ -32,7 +32,7 @@ #define GDSCRIPT_EXTEND_PARSER_H #include "../gdscript_parser.h" -#include "core/variant.h" +#include "core/variant/variant.h" #include "lsp.hpp" #ifndef LINE_NUMBER_TO_INDEX diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index f4f7b5b30..86990d560 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -31,9 +31,11 @@ #include "gdscript_language_protocol.h" #include "core/io/json.h" -#include "core/project_settings.h" +#include "core/config/project_settings.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" +#include "editor/editor_help.h" GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = nullptr; @@ -214,7 +216,7 @@ void GDScriptLanguageProtocol::initialized(const Variant &p_params) { lsp::GodotCapabilities capabilities; DocData *doc = EditorHelp::get_doc_data(); - for (Map::Element *E = doc->class_list.front(); E; E = E->next()) { + for (RBMap::Element *E = doc->class_list.front(); E; E = E->next()) { lsp::GodotNativeClassInfo gdclass; gdclass.name = E->get().name; gdclass.class_doc = &(E->get()); diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 9e4245b22..647f5535c 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" int GDScriptLanguageServer::port_override = -1; diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index e48531ea2..ec15f3b59 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -33,7 +33,7 @@ #include "../gdscript.h" #include "core/os/os.h" #include "editor/editor_settings.h" -#include "editor/plugins/script_text_editor.h" +#include "editor_modules/editor_code_editor/editor_script_editor.h" #include "gdscript_extend_parser.h" #include "gdscript_language_protocol.h" @@ -142,7 +142,7 @@ Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) { String uri = params["uri"]; String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(uri); Array arr; - if (const Map::Element *parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) { + if (const RBMap::Element *parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) { Vector list; parser->get()->get_symbols().symbol_tree_as_list(uri, list); for (int i = 0; i < list.size(); i++) { @@ -212,7 +212,7 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { arr = native_member_completions.duplicate(); - for (Map::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.front(); E; E = E->next()) { + for (RBMap::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.front(); E; E = E->next()) { ExtendGDScriptParser *script = E->get(); const Array &items = script->get_member_completions(); @@ -268,7 +268,7 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) { } if (!symbol) { - if (const Map::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(class_name)) { + if (const RBMap::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(class_name)) { symbol = E->get()->get_member_symbol(member_name, inner_class_name); } } @@ -431,7 +431,7 @@ void GDScriptTextDocument::sync_script_content(const String &p_path, const Strin } void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) { - ScriptEditor::get_singleton()->call_deferred("_help_class_goto", p_symbol_id); + EditorScriptEditor::get_singleton()->call_deferred("_help_class_goto", p_symbol_id); OS::get_singleton()->move_window_to_foreground(); } diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h index 4d49b327b..9e77e1108 100644 --- a/modules/gdscript/language_server/gdscript_text_document.h +++ b/modules/gdscript/language_server/gdscript_text_document.h @@ -32,7 +32,7 @@ #define GDSCRIPT_TEXT_DOCUMENT_H #include "core/os/file_access.h" -#include "core/reference.h" +#include "core/object/reference.h" #include "lsp.hpp" class GDScriptTextDocument : public Reference { diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index ed4ba21c3..54c1e1484 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -32,11 +32,12 @@ #include "../gdscript.h" #include "../gdscript_parser.h" -#include "core/project_settings.h" -#include "core/script_language.h" +#include "core/config/project_settings.h" +#include "core/object/script_language.h" #include "editor/editor_file_system.h" #include "editor/editor_help.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" #include "gdscript_language_protocol.h" #include "scene/resources/packed_scene.h" @@ -115,8 +116,8 @@ void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) { } void GDScriptWorkspace::remove_cache_parser(const String &p_path) { - Map::Element *parser = parse_results.find(p_path); - Map::Element *script = scripts.find(p_path); + RBMap::Element *parser = parse_results.find(p_path); + RBMap::Element *script = scripts.find(p_path); if (parser && script) { if (script->get() && script->get() == parser->get()) { memdelete(script->get()); @@ -140,7 +141,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_ StringName empty; while (class_name != empty) { - if (const Map::Element *E = native_symbols.find(class_name)) { + if (const RBMap::Element *E = native_symbols.find(class_name)) { const lsp::DocumentSymbol &class_symbol = E->value(); if (p_member.empty()) { @@ -161,7 +162,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_ } const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_path) const { - const Map::Element *S = scripts.find(p_path); + const RBMap::Element *S = scripts.find(p_path); if (S) { return &(S->get()->get_symbols()); } @@ -209,7 +210,7 @@ void GDScriptWorkspace::reload_all_workspace_scripts() { err = parse_script(path, content); if (err != OK) { - Map::Element *S = parse_results.find(path); + RBMap::Element *S = parse_results.find(path); String err_msg = "Failed parse script " + path; if (S) { err_msg += "\n" + S->get()->get_error(); @@ -238,7 +239,7 @@ void GDScriptWorkspace::list_script_files(const String &p_root_dir, List } ExtendGDScriptParser *GDScriptWorkspace::get_parse_successed_script(const String &p_path) { - const Map::Element *S = scripts.find(p_path); + const RBMap::Element *S = scripts.find(p_path); if (!S) { parse_local_script(p_path); S = scripts.find(p_path); @@ -250,7 +251,7 @@ ExtendGDScriptParser *GDScriptWorkspace::get_parse_successed_script(const String } ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path) { - const Map::Element *S = parse_results.find(p_path); + const RBMap::Element *S = parse_results.find(p_path); if (!S) { parse_local_script(p_path); S = parse_results.find(p_path); @@ -265,7 +266,7 @@ Array GDScriptWorkspace::symbol(const Dictionary &p_params) { String query = p_params["query"]; Array arr; if (!query.empty()) { - for (Map::Element *E = scripts.front(); E; E = E->next()) { + for (RBMap::Element *E = scripts.front(); E; E = E->next()) { Vector script_symbols; E->get()->get_symbols().symbol_tree_as_list(E->key(), script_symbols); for (int i = 0; i < script_symbols.size(); ++i) { @@ -286,7 +287,7 @@ Error GDScriptWorkspace::initialize() { } DocData *doc = EditorHelp::get_doc_data(); - for (Map::Element *E = doc->class_list.front(); E; E = E->next()) { + for (RBMap::Element *E = doc->class_list.front(); E; E = E->next()) { const DocData::ClassDoc &class_data = E->value(); lsp::DocumentSymbol class_symbol; String class_name = E->key(); @@ -397,7 +398,7 @@ Error GDScriptWorkspace::initialize() { reload_all_workspace_scripts(); if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { - for (Map::Element *E = native_symbols.front(); E; E = E->next()) { + for (RBMap::Element *E = native_symbols.front(); E; E = E->next()) { ClassMembers members; const lsp::DocumentSymbol &class_symbol = E->get(); for (int i = 0; i < class_symbol.children.size(); i++) { @@ -408,7 +409,7 @@ Error GDScriptWorkspace::initialize() { } // cache member completions - for (Map::Element *S = scripts.front(); S; S = S->next()) { + for (RBMap::Element *S = scripts.front(); S; S = S->next()) { S->get()->get_member_completions(); } } @@ -422,8 +423,8 @@ Error GDScriptWorkspace::initialize() { Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_content) { ExtendGDScriptParser *parser = memnew(ExtendGDScriptParser); Error err = parser->parse(p_content, p_path); - Map::Element *last_parser = parse_results.find(p_path); - Map::Element *last_script = scripts.find(p_path); + RBMap::Element *last_parser = parse_results.find(p_path); + RBMap::Element *last_script = scripts.find(p_path); if (err == OK) { remove_cache_parser(p_path); @@ -511,7 +512,7 @@ String GDScriptWorkspace::get_file_uri(const String &p_path) const { void GDScriptWorkspace::publish_diagnostics(const String &p_path) { Dictionary params; Array errors; - const Map::Element *ele = parse_results.find(p_path); + const RBMap::Element *ele = parse_results.find(p_path); if (ele) { const Vector &list = ele->get()->get_diagnostics(); errors.resize(list.size()); @@ -687,7 +688,7 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP class_ptr = native_members.next(class_ptr); } - for (Map::Element *E = scripts.front(); E; E = E->next()) { + for (RBMap::Element *E = scripts.front(); E; E = E->next()) { const ExtendGDScriptParser *script = E->get(); const ClassMembers &members = script->get_members(); if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) { @@ -709,7 +710,7 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP } const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params) { - if (Map::Element *E = native_symbols.find(p_params.native_class)) { + if (RBMap::Element *E = native_symbols.find(p_params.native_class)) { const lsp::DocumentSymbol &symbol = E->get(); if (p_params.symbol_name.empty() || p_params.symbol_name == symbol.name) { return &symbol; @@ -787,17 +788,17 @@ GDScriptWorkspace::GDScriptWorkspace() { } GDScriptWorkspace::~GDScriptWorkspace() { - Set cached_parsers; + RBSet cached_parsers; - for (Map::Element *E = parse_results.front(); E; E = E->next()) { + for (RBMap::Element *E = parse_results.front(); E; E = E->next()) { cached_parsers.insert(E->key()); } - for (Map::Element *E = scripts.front(); E; E = E->next()) { + for (RBMap::Element *E = scripts.front(); E; E = E->next()) { cached_parsers.insert(E->key()); } - for (Set::Element *E = cached_parsers.front(); E; E = E->next()) { + for (RBSet::Element *E = cached_parsers.front(); E; E = E->next()) { remove_cache_parser(E->get()); } } diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index c8fbce8cb..c674725be 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -32,7 +32,7 @@ #define GDSCRIPT_WORKSPACE_H #include "../gdscript_parser.h" -#include "core/variant.h" +#include "core/variant/variant.h" #include "editor/editor_file_system.h" #include "gdscript_extend_parser.h" #include "lsp.hpp" @@ -50,7 +50,7 @@ protected: static void _bind_methods(); void remove_cache_parser(const String &p_path); bool initialized = false; - Map native_symbols; + RBMap native_symbols; const lsp::DocumentSymbol *get_native_symbol(const String &p_class, const String &p_member = "") const; const lsp::DocumentSymbol *get_script_symbol(const String &p_path) const; @@ -68,8 +68,8 @@ public: String root; String root_uri; - Map scripts; - Map parse_results; + RBMap scripts; + RBMap parse_results; HashMap native_members; public: diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp index 79685ceee..3177d7f58 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/lsp.hpp @@ -31,8 +31,8 @@ #ifndef GODOT_LSP_H #define GODOT_LSP_H -#include "core/class_db.h" -#include "core/list.h" +#include "core/object/class_db.h" +#include "core/containers/list.h" #include "editor/doc/doc_data.h" namespace lsp { @@ -261,7 +261,7 @@ struct WorkspaceEdit { /** * Holds changes to existing resources. */ - Map> changes; + RBMap> changes; _FORCE_INLINE_ void add_edit(const String &uri, const TextEdit &edit) { if (changes.has(uri)) { @@ -277,7 +277,7 @@ struct WorkspaceEdit { Dictionary dict; Dictionary out_changes; - for (Map>::Element *E = changes.front(); E; E = E->next()) { + for (RBMap>::Element *E = changes.front(); E; E = E->next()) { Array edits; for (int i = 0; i < E->get().size(); ++i) { Dictionary text_edit; @@ -293,7 +293,7 @@ struct WorkspaceEdit { } _FORCE_INLINE_ void add_change(const String &uri, const int &line, const int &start_character, const int &end_character, const String &new_text) { - if (Map>::Element *E = changes.find(uri)) { + if (RBMap>::Element *E = changes.find(uri)) { Vector edit_list = E->value(); for (int i = 0; i < edit_list.size(); ++i) { TextEdit edit = edit_list[i]; @@ -310,7 +310,7 @@ struct WorkspaceEdit { new_edit.range.end.line = line; new_edit.range.end.character = end_character; - if (Map>::Element *E = changes.find(uri)) { + if (RBMap>::Element *E = changes.find(uri)) { E->value().push_back(new_edit); } else { Vector edit_list; diff --git a/modules/gdscript/register_types.cpp b/modules/gdscript/register_types.cpp index c36447785..cabe8a1fa 100644 --- a/modules/gdscript/register_types.cpp +++ b/modules/gdscript/register_types.cpp @@ -54,6 +54,11 @@ Ref resource_saver_gd; #include "editor_code_editor/editor_script_editor.h" #endif +#ifndef GDSCRIPT_NO_LSP +#include "core/config/engine.h" +#include "language_server/gdscript_language_server.h" +#endif // !GDSCRIPT_NO_LSP + class EditorExportGDScript : public EditorExportPlugin { GDCLASS(EditorExportGDScript, EditorExportPlugin); @@ -144,6 +149,13 @@ static void _editor_init() { gdscript_syntax_highlighter.instance(); EditorScriptEditor::get_singleton()->register_syntax_highlighter(gdscript_syntax_highlighter); #endif + +#ifndef GDSCRIPT_NO_LSP + register_lsp_types(); + GDScriptLanguageServer *lsp_plugin = memnew(GDScriptLanguageServer); + EditorNode::get_singleton()->add_editor_plugin(lsp_plugin); + Engine::get_singleton()->add_singleton(Engine::Singleton("GDScriptLanguageProtocol", GDScriptLanguageProtocol::get_singleton())); +#endif // !GDSCRIPT_NO_LSP } #endif // TOOLS_ENABLED diff --git a/scu_builders.py b/scu_builders.py index f2f09fecc..d782afa0d 100644 --- a/scu_builders.py +++ b/scu_builders.py @@ -354,7 +354,7 @@ def generate_scu_files(verbose, is_release_build): ]) process_folder(["modules/gdscript"]) - #process_folder(["modules/gdscript/language_server"]) + process_folder(["modules/gdscript/language_server"]) process_folder(["modules/gridmap"]) process_folder(["modules/gridmap/geometry_parser"])