diff options
Diffstat (limited to 'modules/gdscript')
6 files changed, 102 insertions, 6 deletions
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp index bf21c8510a..6186d0edee 100644 --- a/modules/gdscript/gdscript_vm.cpp +++ b/modules/gdscript/gdscript_vm.cpp @@ -88,9 +88,9 @@ static String _get_var_type(const Variant *p_var) { Object *bobj = p_var->get_validated_object_with_check(was_freed); if (!bobj) { if (was_freed) { - basestr = "null instance"; - } else { basestr = "previously freed"; + } else { + basestr = "null instance"; } } else { basestr = bobj->get_class(); @@ -1233,7 +1233,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GD_ERR_BREAK(to_type < 0 || to_type >= Variant::VARIANT_MAX); #ifdef DEBUG_ENABLED - if (src->get_type() == Variant::OBJECT && !src->operator ObjectID().is_ref_counted() && ObjectDB::get_instance(src->operator ObjectID()) == nullptr) { + if (src->operator Object *() && !src->get_validated_object()) { err_text = "Trying to cast a freed object."; OPCODE_BREAK; } @@ -1263,7 +1263,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GD_ERR_BREAK(!nc); #ifdef DEBUG_ENABLED - if (src->get_type() == Variant::OBJECT && !src->operator ObjectID().is_ref_counted() && ObjectDB::get_instance(src->operator ObjectID()) == nullptr) { + if (src->operator Object *() && !src->get_validated_object()) { err_text = "Trying to cast a freed object."; OPCODE_BREAK; } @@ -1295,7 +1295,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a GD_ERR_BREAK(!base_type); #ifdef DEBUG_ENABLED - if (src->get_type() == Variant::OBJECT && !src->operator ObjectID().is_ref_counted() && ObjectDB::get_instance(src->operator ObjectID()) == nullptr) { + if (src->operator Object *() && !src->get_validated_object()) { err_text = "Trying to cast a freed object."; OPCODE_BREAK; } @@ -2138,7 +2138,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a retvalue = gdfs; - Error err = sig.connect(Callable(gdfs.ptr(), "_signal_callback"), varray(gdfs), Object::CONNECT_ONESHOT); + Error err = sig.connect(callable_bind(Callable(gdfs.ptr(), "_signal_callback"), retvalue), Object::CONNECT_ONESHOT); if (err != OK) { err_text = "Error connecting to signal: " + sig.get_name() + " during await."; OPCODE_BREAK; diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index b6c48468f5..bd5a9f01b2 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -284,6 +284,23 @@ void GDScriptLanguageProtocol::notify_client(const String &p_method, const Varia peer->res_queue.push_back(msg.utf8()); } +void GDScriptLanguageProtocol::request_client(const String &p_method, const Variant &p_params, int p_client_id) { + if (p_client_id == -1) { + ERR_FAIL_COND_MSG(latest_client_id == -1, + "GDScript LSP: Can't notify client as none was connected."); + p_client_id = latest_client_id; + } + ERR_FAIL_COND(!clients.has(p_client_id)); + Ref<LSPeer> peer = clients.get(p_client_id); + ERR_FAIL_COND(peer == nullptr); + + Dictionary message = make_request(p_method, p_params, next_server_id); + next_server_id++; + String msg = Variant(message).to_json_string(); + msg = format_output(msg); + peer->res_queue.push_back(msg.utf8()); +} + bool GDScriptLanguageProtocol::is_smart_resolve_enabled() const { return bool(_EDITOR_GET("network/language_server/enable_smart_resolve")); } diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h index 5a2dd55c46..899446fb42 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.h +++ b/modules/gdscript/language_server/gdscript_language_protocol.h @@ -79,6 +79,8 @@ private: int latest_client_id = 0; int next_client_id = 0; + int next_server_id = 0; + Ref<GDScriptTextDocument> text_document; Ref<GDScriptWorkspace> workspace; @@ -107,6 +109,7 @@ public: void stop(); void notify_client(const String &p_method, const Variant &p_params = Variant(), int p_client_id = -1); + void request_client(const String &p_method, const Variant &p_params = Variant(), int p_client_id = -1); bool is_smart_resolve_enabled() const; bool is_goto_native_symbols_enabled() const; diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index 1512b4bb89..86b3a3a326 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -42,6 +42,7 @@ #include "scene/resources/packed_scene.h" 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("symbol"), &GDScriptWorkspace::symbol); ClassDB::bind_method(D_METHOD("parse_script", "path", "content"), &GDScriptWorkspace::parse_script); @@ -52,6 +53,54 @@ void GDScriptWorkspace::_bind_methods() { ClassDB::bind_method(D_METHOD("generate_script_api", "path"), &GDScriptWorkspace::generate_script_api); } +void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStringArray args) { + String function_signature = "func " + function; + Ref<Script> script = obj->get_script(); + + String source = script->get_source_code(); + + if (source.find(function_signature) != -1) { + return; + } + + int first_class = source.find("\nclass "); + int start_line = 0; + if (first_class != -1) { + start_line = source.substr(0, first_class).split("\n").size(); + } else { + start_line = source.split("\n").size(); + } + + String function_body = "\n\n" + function_signature + "("; + for (int i = 0; i < args.size(); ++i) { + function_body += args[i]; + if (i < args.size() - 1) { + function_body += ", "; + } + } + function_body += ")"; + if (EditorSettings::get_singleton()->get_setting("text_editor/completion/add_type_hints")) { + function_body += " -> void"; + } + function_body += ":\n\tpass # Replace with function body.\n"; + + lsp::TextEdit text_edit; + + if (first_class != -1) { + function_body += "\n\n"; + } + text_edit.range.end.line = text_edit.range.start.line = start_line; + + text_edit.newText = function_body; + + String uri = get_file_uri(script->get_path()); + + lsp::ApplyWorkspaceEditParams params; + params.edit.add_edit(uri, text_edit); + + GDScriptLanguageProtocol::get_singleton()->request_client("workspace/applyEdit", params.to_json()); +} + void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) { Array files = p_params["files"]; for (int i = 0; i < files.size(); ++i) { @@ -360,6 +409,9 @@ Error GDScriptWorkspace::initialize() { } } + EditorNode *editor_node = EditorNode::get_singleton(); + editor_node->connect("script_add_function_request", callable_mp(this, &GDScriptWorkspace::apply_new_signal)); + return OK; } diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index 9496677449..e5cd4d9824 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -62,6 +62,8 @@ protected: void list_script_files(const String &p_root_dir, List<String> &r_files); + void apply_new_signal(Object *obj, String function, PackedStringArray args); + public: String root; String root_uri; diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/lsp.hpp index 9ac6c6bd4e..662382d279 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/lsp.hpp @@ -263,6 +263,16 @@ struct WorkspaceEdit { */ Map<String, Vector<TextEdit>> changes; + _FORCE_INLINE_ void add_edit(const String &uri, const TextEdit &edit) { + if (changes.has(uri)) { + changes[uri].push_back(edit); + } else { + Vector<TextEdit> edits; + edits.push_back(edit); + changes[uri] = edits; + } + } + _FORCE_INLINE_ Dictionary to_json() const { Dictionary dict; @@ -1322,6 +1332,18 @@ struct DocumentSymbol { } }; +struct ApplyWorkspaceEditParams { + WorkspaceEdit edit; + + Dictionary to_json() { + Dictionary dict; + + dict["edit"] = edit.to_json(); + + return dict; + } +}; + struct NativeSymbolInspectParams { String native_class; String symbol_name; |