Browse Source

Merge pull request #53068 from Razoric480/apply-new-signal

Rémi Verschelde 3 years ago
parent
commit
7893dd26df

+ 17 - 0
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 = JSON::print(message);
+	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"));
 }

+ 2 - 0
modules/gdscript/language_server/gdscript_language_protocol.h

@@ -72,6 +72,7 @@ private:
 	Ref<TCP_Server> server;
 	int latest_client_id = 0;
 	int next_client_id = 0;
+	int next_server_id = 0;
 
 	Ref<GDScriptTextDocument> text_document;
 	Ref<GDScriptWorkspace> workspace;
@@ -101,6 +102,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;

+ 52 - 0
modules/gdscript/language_server/gdscript_workspace.cpp

@@ -49,6 +49,55 @@ void GDScriptWorkspace::_bind_methods() {
 	ClassDB::bind_method(D_METHOD("get_file_uri", "path"), &GDScriptWorkspace::get_file_uri);
 	ClassDB::bind_method(D_METHOD("publish_diagnostics", "path"), &GDScriptWorkspace::publish_diagnostics);
 	ClassDB::bind_method(D_METHOD("generate_script_api", "path"), &GDScriptWorkspace::generate_script_api);
+	ClassDB::bind_method(D_METHOD("apply_new_signal", "obj", "function", "args"), &GDScriptWorkspace::apply_new_signal);
+}
+
+void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PoolStringArray 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) {
@@ -360,6 +409,9 @@ Error GDScriptWorkspace::initialize() {
 		}
 	}
 
+	EditorNode *editor_node = EditorNode::get_singleton();
+	editor_node->connect("script_add_function_request", this, "apply_new_signal");
+
 	return OK;
 }
 

+ 2 - 0
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, PoolStringArray args);
+
 public:
 	String root;
 	String root_uri;

+ 22 - 0
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;