diff options
5 files changed, 126 insertions, 0 deletions
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index 0d1f98778e..fb60da1ff4 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 969c38eab6..ad6c0903c5 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.h +++ b/modules/gdscript/language_server/gdscript_language_protocol.h @@ -73,6 +73,8 @@ private:  	int latest_client_id = 0;  	int next_client_id = 0; +	int next_server_id = 0; +  	Ref<GDScriptTextDocument> text_document;  	Ref<GDScriptWorkspace> workspace; @@ -101,6 +103,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 1915c92cbf..c0a84d63dc 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) { @@ -325,6 +374,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 8b166a873c..e243aa790e 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -60,6 +60,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 a7dcfdb22d..025b1f498c 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/lsp.hpp @@ -1266,6 +1266,58 @@ struct DocumentSymbol {  	}  }; +struct WorkspaceEdit { +	HashMap<String, List<TextEdit>> changes; + +	void add_edit(String uri, TextEdit edit) { +		if (changes.has(uri)) { +			changes[uri].push_back(edit); +		} else { +			List<TextEdit> edits; +			edits.push_back(edit); +			changes[uri] = edits; +		} +	} + +	Dictionary to_json() { +		Dictionary dict; + +		Dictionary changes_dict; + +		List<String> key_list; +		changes.get_key_list(&key_list); +		for (int i = 0; i < key_list.size(); ++i) { +			String uri = key_list[i]; + +			List<TextEdit> edits = changes[key_list[i]]; +			Array changes_arr; +			for (int l = 0; l < edits.size(); ++l) { +				Dictionary change_dict; +				change_dict["newText"] = edits[l].newText; +				change_dict["range"] = edits[l].range.to_json(); +				changes_arr.push_back(change_dict); +			} +			changes_dict[uri] = changes_arr; +		} + +		dict["changes"] = changes_dict; + +		return dict; +	} +}; + +struct ApplyWorkspaceEditParams { +	WorkspaceEdit edit; + +	Dictionary to_json() { +		Dictionary dict; + +		dict["edit"] = edit.to_json(); + +		return dict; +	} +}; +  struct NativeSymbolInspectParams {  	String native_class;  	String symbol_name;  |