Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement applyEdit in LSP for signal connecting [3.x] #53068

Merged
merged 1 commit into from
Sep 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions modules/gdscript/language_server/gdscript_language_protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class GDScriptLanguageProtocol : public JSONRPC {
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;
Expand Down Expand Up @@ -101,6 +102,7 @@ class GDScriptLanguageProtocol : public JSONRPC {
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;
Expand Down
52 changes: 52 additions & 0 deletions modules/gdscript/language_server/gdscript_workspace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 2 additions & 0 deletions modules/gdscript/language_server/gdscript_workspace.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ class GDScriptWorkspace : public Reference {

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;
Expand Down
22 changes: 22 additions & 0 deletions modules/gdscript/language_server/lsp.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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;
Expand Down