diff --git a/doc/classes/JSONRPC.xml b/doc/classes/JSONRPC.xml index e5ee93cb931..b9975d406bf 100644 --- a/doc/classes/JSONRPC.xml +++ b/doc/classes/JSONRPC.xml @@ -69,11 +69,14 @@ - + - - + + + Registers a callback for the given method name. + - [param name] The name that clients can use to access the callback. + - [param callback] The callback which will handle the specific method. diff --git a/misc/extension_api_validation/4.4-stable.expected b/misc/extension_api_validation/4.4-stable.expected index 7ea8fc10789..a7b4de86184 100644 --- a/misc/extension_api_validation/4.4-stable.expected +++ b/misc/extension_api_validation/4.4-stable.expected @@ -24,3 +24,10 @@ Validate extension JSON: Error: Field 'classes/OpenXRAPIExtension/methods/regist Validate extension JSON: Error: Field 'classes/OpenXRAPIExtension/methods/unregister_projection_views_extension/arguments/0': type changed value in new API, from "OpenXRExtensionWrapperExtension" to "OpenXRExtensionWrapper". Switched from `OpenXRExtensionWrapperExtension` to parent `OpenXRExtensionWrapper`. Compatibility methods registered. + + +GH-104890 +--------- +Validate extension JSON: API was removed: classes/JSONRPC/methods/set_scope + +Replaced `set_scope` with `set_method`. Compatibility method registered for binary compatibility. Manual upgrade required by users to retain functionality. diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index c69e99f2591..ef7c0859461 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -334,13 +334,50 @@ bool GDScriptLanguageProtocol::is_goto_native_symbols_enabled() const { return bool(_EDITOR_GET("network/language_server/show_native_symbols_in_editor")); } +// clang-format off +#define SET_DOCUMENT_METHOD(m_method) set_method(_STR(textDocument/m_method), callable_mp(text_document.ptr(), &GDScriptTextDocument::m_method)) +#define SET_COMPLETION_METHOD(m_method) set_method(_STR(completionItem/m_method), callable_mp(text_document.ptr(), &GDScriptTextDocument::m_method)) +#define SET_WORKSPACE_METHOD(m_method) set_method(_STR(workspace/m_method), callable_mp(workspace.ptr(), &GDScriptWorkspace::m_method)) +// clang-format on + GDScriptLanguageProtocol::GDScriptLanguageProtocol() { server.instantiate(); singleton = this; workspace.instantiate(); text_document.instantiate(); - set_scope("textDocument", text_document.ptr()); - set_scope("completionItem", text_document.ptr()); - set_scope("workspace", workspace.ptr()); + + SET_DOCUMENT_METHOD(didOpen); + SET_DOCUMENT_METHOD(didClose); + SET_DOCUMENT_METHOD(didChange); + SET_DOCUMENT_METHOD(willSaveWaitUntil); + SET_DOCUMENT_METHOD(didSave); + + SET_DOCUMENT_METHOD(documentSymbol); + SET_DOCUMENT_METHOD(completion); + SET_DOCUMENT_METHOD(rename); + SET_DOCUMENT_METHOD(prepareRename); + SET_DOCUMENT_METHOD(references); + SET_DOCUMENT_METHOD(foldingRange); + SET_DOCUMENT_METHOD(codeLens); + SET_DOCUMENT_METHOD(documentLink); + SET_DOCUMENT_METHOD(colorPresentation); + SET_DOCUMENT_METHOD(hover); + SET_DOCUMENT_METHOD(definition); + SET_DOCUMENT_METHOD(declaration); + SET_DOCUMENT_METHOD(signatureHelp); + + SET_DOCUMENT_METHOD(nativeSymbol); // Custom method. + + SET_COMPLETION_METHOD(resolve); + + SET_WORKSPACE_METHOD(didDeleteFiles); + + set_method("initialize", callable_mp(this, &GDScriptLanguageProtocol::initialize)); + set_method("initialized", callable_mp(this, &GDScriptLanguageProtocol::initialized)); + workspace->root = ProjectSettings::get_singleton()->get_resource_path(); } + +#undef SET_DOCUMENT_METHOD +#undef SET_COMPLETION_METHOD +#undef SET_WORKSPACE_METHOD diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h index 3160715aced..5e3ef82140f 100644 --- a/modules/gdscript/language_server/gdscript_text_document.h +++ b/modules/gdscript/language_server/gdscript_text_document.h @@ -44,6 +44,14 @@ protected: Ref file_checker; + Array native_member_completions; + +private: + Array find_symbols(const LSP::TextDocumentPositionParams &p_location, List &r_list); + LSP::TextDocumentItem load_document_item(const Variant &p_param); + void notify_client_show_symbol(const LSP::DocumentSymbol *symbol); + +public: void didOpen(const Variant &p_param); void didClose(const Variant &p_param); void didChange(const Variant &p_param); @@ -54,14 +62,6 @@ protected: void sync_script_content(const String &p_path, const String &p_content); void show_native_symbol_in_editor(const String &p_symbol_id); - Array native_member_completions; - -private: - Array find_symbols(const LSP::TextDocumentPositionParams &p_location, List &r_list); - LSP::TextDocumentItem load_document_item(const Variant &p_param); - void notify_client_show_symbol(const LSP::DocumentSymbol *symbol); - -public: Variant nativeSymbol(const Dictionary &p_params); Array documentSymbol(const Dictionary &p_params); Array completion(const Dictionary &p_params); diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index b2e52b74256..6806c801611 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -45,7 +45,7 @@ void GDScriptWorkspace::_bind_methods() { ClassDB::bind_method(D_METHOD("apply_new_signal"), &GDScriptWorkspace::apply_new_signal); - ClassDB::bind_method(D_METHOD("didDeleteFiles"), &GDScriptWorkspace::did_delete_files); + ClassDB::bind_method(D_METHOD("didDeleteFiles"), &GDScriptWorkspace::didDeleteFiles); ClassDB::bind_method(D_METHOD("parse_script", "path", "content"), &GDScriptWorkspace::parse_script); ClassDB::bind_method(D_METHOD("parse_local_script", "path"), &GDScriptWorkspace::parse_local_script); ClassDB::bind_method(D_METHOD("get_file_path", "uri"), &GDScriptWorkspace::get_file_path); @@ -106,7 +106,7 @@ void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStr GDScriptLanguageProtocol::get_singleton()->request_client("workspace/applyEdit", params.to_json()); } -void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) { +void GDScriptWorkspace::didDeleteFiles(const Dictionary &p_params) { Array files = p_params["files"]; for (int i = 0; i < files.size(); ++i) { Dictionary file = files[i]; diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index d19901af06d..cd527f04cea 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -90,7 +90,7 @@ public: void resolve_document_links(const String &p_uri, List &r_list); Dictionary generate_script_api(const String &p_path); Error resolve_signature(const LSP::TextDocumentPositionParams &p_doc_pos, LSP::SignatureHelp &r_signature); - void did_delete_files(const Dictionary &p_params); + void didDeleteFiles(const Dictionary &p_params); Dictionary rename(const LSP::TextDocumentPositionParams &p_doc_pos, const String &new_name); bool can_rename(const LSP::TextDocumentPositionParams &p_doc_pos, LSP::DocumentSymbol &r_symbol, LSP::Range &r_range); Vector find_usages_in_file(const LSP::DocumentSymbol &p_symbol, const String &p_file_path); diff --git a/modules/jsonrpc/jsonrpc.compat.inc b/modules/jsonrpc/jsonrpc.compat.inc new file mode 100644 index 00000000000..ad56dc61c0b --- /dev/null +++ b/modules/jsonrpc/jsonrpc.compat.inc @@ -0,0 +1,41 @@ +/**************************************************************************/ +/* jsonrpc.compat.inc */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef DISABLE_DEPRECATED + +void JSONRPC::_set_scope_bind_compat_104890(const String &p_scope, Object *p_obj) { + ERR_PRINT("JSONRPC::set_scope is not supported anymore. Upgrade to JSONRPC::set_method."); +} + +void JSONRPC::_bind_compatibility_methods() { + ClassDB::bind_compatibility_method(D_METHOD("set_scope", "scope", "target"), &JSONRPC::_set_scope_bind_compat_104890); +} + +#endif diff --git a/modules/jsonrpc/jsonrpc.cpp b/modules/jsonrpc/jsonrpc.cpp index 0f03e49fc8b..6c4259d6fd2 100644 --- a/modules/jsonrpc/jsonrpc.cpp +++ b/modules/jsonrpc/jsonrpc.cpp @@ -29,6 +29,7 @@ /**************************************************************************/ #include "jsonrpc.h" +#include "jsonrpc.compat.inc" #include "core/io/json.h" @@ -39,7 +40,7 @@ JSONRPC::~JSONRPC() { } void JSONRPC::_bind_methods() { - ClassDB::bind_method(D_METHOD("set_scope", "scope", "target"), &JSONRPC::set_scope); + ClassDB::bind_method(D_METHOD("set_method", "name", "callback"), &JSONRPC::set_method); ClassDB::bind_method(D_METHOD("process_action", "action", "recurse"), &JSONRPC::process_action, DEFVAL(false)); ClassDB::bind_method(D_METHOD("process_string", "action"), &JSONRPC::process_string); @@ -113,12 +114,6 @@ Variant JSONRPC::process_action(const Variant &p_action, bool p_process_arr_elem } } - Object *object = this; - if (method_scopes.has(method.get_base_dir())) { - object = method_scopes[method.get_base_dir()]; - method = method.get_file(); - } - Variant id; if (dict.has("id")) { id = dict["id"]; @@ -129,13 +124,13 @@ Variant JSONRPC::process_action(const Variant &p_action, bool p_process_arr_elem } } - if (object == nullptr || !object->has_method(method)) { - ret = make_response_error(JSONRPC::METHOD_NOT_FOUND, "Method not found: " + method, id); - } else { - Variant call_ret = object->callv(method, args); + if (methods.has(method)) { + Variant call_ret = methods[method].callv(args); if (id.get_type() != Variant::NIL) { ret = make_response(call_ret, id); } + } else { + ret = make_response_error(JSONRPC::METHOD_NOT_FOUND, "Method not found: " + method, id); } } else if (p_action.get_type() == Variant::ARRAY && p_process_arr_elements) { Array arr = p_action; @@ -175,6 +170,6 @@ String JSONRPC::process_string(const String &p_input) { return ret.to_json_string(); } -void JSONRPC::set_scope(const String &p_scope, Object *p_obj) { - method_scopes[p_scope] = p_obj; +void JSONRPC::set_method(const String &p_name, const Callable &p_callback) { + methods[p_name] = p_callback; } diff --git a/modules/jsonrpc/jsonrpc.h b/modules/jsonrpc/jsonrpc.h index 774bc9e0bec..254bb3fcac8 100644 --- a/modules/jsonrpc/jsonrpc.h +++ b/modules/jsonrpc/jsonrpc.h @@ -36,11 +36,16 @@ class JSONRPC : public Object { GDCLASS(JSONRPC, Object) - HashMap method_scopes; + HashMap methods; protected: static void _bind_methods(); +#ifndef DISABLE_DEPRECATED + void _set_scope_bind_compat_104890(const String &p_scope, Object *p_obj); + static void _bind_compatibility_methods(); +#endif + public: JSONRPC(); ~JSONRPC(); @@ -61,7 +66,7 @@ public: Variant process_action(const Variant &p_action, bool p_process_arr_elements = false); String process_string(const String &p_input); - void set_scope(const String &p_scope, Object *p_obj); + void set_method(const String &p_name, const Callable &p_callback); }; VARIANT_ENUM_CAST(JSONRPC::ErrorCode); diff --git a/modules/jsonrpc/tests/test_jsonrpc.cpp b/modules/jsonrpc/tests/test_jsonrpc.cpp index 8500ff6da92..c1028892c33 100644 --- a/modules/jsonrpc/tests/test_jsonrpc.cpp +++ b/modules/jsonrpc/tests/test_jsonrpc.cpp @@ -57,10 +57,6 @@ String TestClassJSONRPC::something(const String &p_in) { return p_in + ", please"; } -void TestClassJSONRPC::_bind_methods() { - ClassDB::bind_method(D_METHOD("something", "in"), &TestClassJSONRPC::something); -} - void test_process_action(const Variant &p_in, const Variant &p_expected, bool p_process_array_elements) { TestClassJSONRPC json_rpc = TestClassJSONRPC(); const Variant &observed = json_rpc.process_action(p_in, p_process_array_elements); diff --git a/modules/jsonrpc/tests/test_jsonrpc.h b/modules/jsonrpc/tests/test_jsonrpc.h index ef0404cc43e..08303193125 100644 --- a/modules/jsonrpc/tests/test_jsonrpc.h +++ b/modules/jsonrpc/tests/test_jsonrpc.h @@ -60,20 +60,17 @@ TEST_CASE("[JSONRPC] process_string invalid") { } class TestClassJSONRPC : public JSONRPC { - GDCLASS(TestClassJSONRPC, JSONRPC) - public: - String something(const String &p_in); + TestClassJSONRPC() { + set_method("something", callable_mp(this, &TestClassJSONRPC::something)); + } -protected: - static void _bind_methods(); + String something(const String &p_in); }; void test_process_action(const Variant &p_in, const Variant &p_expected, bool p_process_array_elements = false); TEST_CASE("[JSONRPC] process_action Dictionary") { - ClassDB::register_class(); - Dictionary in_dict = Dictionary(); in_dict["method"] = "something"; in_dict["id"] = "ID";