diff options
Diffstat (limited to 'modules/gdscript/language_server')
-rw-r--r-- | modules/gdscript/language_server/gdscript_extend_parser.cpp | 171 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_extend_parser.h | 62 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_language_protocol.cpp | 96 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_language_protocol.h | 60 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_language_server.cpp | 82 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_language_server.h | 58 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_text_document.cpp | 161 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_text_document.h | 66 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_workspace.cpp | 185 | ||||
-rw-r--r-- | modules/gdscript/language_server/gdscript_workspace.h | 70 | ||||
-rw-r--r-- | modules/gdscript/language_server/godot_lsp.h (renamed from modules/gdscript/language_server/lsp.hpp) | 78 |
11 files changed, 543 insertions, 546 deletions
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp index 49f5303ae6..146ed10ceb 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.cpp +++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gdscript_extend_parser.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_extend_parser.cpp */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ #include "gdscript_extend_parser.h" @@ -38,8 +38,8 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostics.clear(); - const List<ParserError> &errors = get_errors(); - for (const ParserError &error : errors) { + const List<ParserError> &parser_errors = get_errors(); + for (const ParserError &error : parser_errors) { lsp::Diagnostic diagnostic; diagnostic.severity = lsp::DiagnosticSeverity::Error; diagnostic.message = error.message; @@ -47,9 +47,9 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostic.code = -1; lsp::Range range; lsp::Position pos; - const PackedStringArray lines = get_lines(); - int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, lines.size() - 1); - const String &line_text = lines[line]; + const PackedStringArray line_array = get_lines(); + int line = CLAMP(LINE_NUMBER_TO_INDEX(error.line), 0, line_array.size() - 1); + const String &line_text = line_array[line]; pos.line = line; pos.character = line_text.length() - line_text.strip_edges(true, false).length(); range.start = pos; @@ -59,8 +59,8 @@ void ExtendGDScriptParser::update_diagnostics() { diagnostics.push_back(diagnostic); } - const List<GDScriptWarning> &warnings = get_warnings(); - for (const GDScriptWarning &warning : warnings) { + const List<GDScriptWarning> &parser_warnings = get_warnings(); + for (const GDScriptWarning &warning : parser_warnings) { lsp::Diagnostic diagnostic; diagnostic.severity = lsp::DiagnosticSeverity::Warning; diagnostic.message = "(" + warning.get_name() + "): " + warning.get_message(); @@ -83,22 +83,21 @@ void ExtendGDScriptParser::update_diagnostics() { void ExtendGDScriptParser::update_symbols() { members.clear(); - const GDScriptParser::Node *head = get_tree(); - if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { + if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(get_tree())) { parse_class_symbol(gdclass, class_symbol); for (int i = 0; i < class_symbol.children.size(); i++) { const lsp::DocumentSymbol &symbol = class_symbol.children[i]; - members.set(symbol.name, &symbol); + members.insert(symbol.name, &symbol); // cache level one inner classes if (symbol.kind == lsp::SymbolKind::Class) { ClassMembers inner_class; for (int j = 0; j < symbol.children.size(); j++) { const lsp::DocumentSymbol &s = symbol.children[j]; - inner_class.set(s.name, &s); + inner_class.insert(s.name, &s); } - inner_classes.set(symbol.name, inner_class); + inner_classes.insert(symbol.name, inner_class); } } } @@ -107,26 +106,26 @@ void ExtendGDScriptParser::update_symbols() { void ExtendGDScriptParser::update_document_links(const String &p_code) { document_links.clear(); - GDScriptTokenizer tokenizer; - FileAccessRef fs = FileAccess::create(FileAccess::ACCESS_RESOURCES); - tokenizer.set_source_code(p_code); + GDScriptTokenizer scr_tokenizer; + Ref<FileAccess> fs = FileAccess::create(FileAccess::ACCESS_RESOURCES); + scr_tokenizer.set_source_code(p_code); while (true) { - GDScriptTokenizer::Token token = tokenizer.scan(); + GDScriptTokenizer::Token token = scr_tokenizer.scan(); if (token.type == GDScriptTokenizer::Token::TK_EOF) { break; } else if (token.type == GDScriptTokenizer::Token::LITERAL) { const Variant &const_val = token.literal; if (const_val.get_type() == Variant::STRING) { - String path = const_val; - bool exists = fs->file_exists(path); + String scr_path = const_val; + bool exists = fs->file_exists(scr_path); if (!exists) { - path = get_path().get_base_dir() + "/" + path; - exists = fs->file_exists(path); + scr_path = get_path().get_base_dir() + "/" + scr_path; + exists = fs->file_exists(scr_path); } if (exists) { String value = const_val; lsp::DocumentLink link; - link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(path); + link.target = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(scr_path); link.range.start.line = LINE_NUMBER_TO_INDEX(token.start_line); link.range.end.line = LINE_NUMBER_TO_INDEX(token.end_line); link.range.start.character = LINE_NUMBER_TO_INDEX(token.start_column); @@ -212,12 +211,12 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p const Variant &default_value = m.constant->initializer->reduced_value; String value_text; if (default_value.get_type() == Variant::OBJECT) { - RES res = default_value; + Ref<Resource> res = default_value; if (res.is_valid() && !res->get_path().is_empty()) { value_text = "preload(\"" + res->get_path() + "\")"; if (symbol.documentation.is_empty()) { - if (Map<String, ExtendGDScriptParser *>::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) { - symbol.documentation = S->get()->class_symbol.documentation; + if (HashMap<String, ExtendGDScriptParser *>::Iterator S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) { + symbol.documentation = S->value->class_symbol.documentation; } } } else { @@ -307,6 +306,8 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p parse_class_symbol(m.m_class, symbol); r_symbol.children.push_back(symbol); } break; + case ClassNode::Member::GROUP: + break; // No-op, but silences warnings. case ClassNode::Member::UNDEFINED: break; // Unreachable. } @@ -349,8 +350,8 @@ void ExtendGDScriptParser::parse_function_symbol(const GDScriptParser::FunctionN if (parameter->get_datatype().is_hard_type()) { parameters += ": " + parameter->get_datatype().to_string(); } - if (parameter->default_value != nullptr) { - parameters += " = " + parameter->default_value->reduced_value.to_json_string(); + if (parameter->initializer != nullptr) { + parameters += " = " + parameter->initializer->reduced_value.to_json_string(); } } r_symbol.detail += parameters + ")"; @@ -435,11 +436,11 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) { if (!p_docs_down) { // inline comment String inline_comment = lines[p_line]; - int comment_start = inline_comment.find("#"); + int comment_start = inline_comment.find("##"); if (comment_start != -1) { inline_comment = inline_comment.substr(comment_start, inline_comment.length()).strip_edges(); if (inline_comment.length() > 1) { - doc_lines.push_back(inline_comment.substr(1, inline_comment.length())); + doc_lines.push_back(inline_comment.substr(2, inline_comment.length())); } } } @@ -452,8 +453,8 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) { } String line_comment = lines[i].strip_edges(true, false); - if (line_comment.begins_with("#")) { - line_comment = line_comment.substr(1, line_comment.length()); + if (line_comment.begins_with("##")) { + line_comment = line_comment.substr(2, line_comment.length()); if (p_docs_down) { doc_lines.push_back(line_comment); } else { @@ -541,7 +542,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position & for (int c = p_position.character; c >= 0; c--) { start_pos = c; char32_t ch = line[c]; - bool valid_char = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'; + bool valid_char = is_ascii_identifier_char(ch); if (!valid_char) { break; } @@ -550,7 +551,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position & int end_pos = p_position.character; for (int c = p_position.character; c < line.length(); c++) { char32_t ch = line[c]; - bool valid_char = (ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '_'; + bool valid_char = is_ascii_identifier_char(ch); if (!valid_char) { break; } @@ -661,30 +662,22 @@ const List<lsp::DocumentLink> &ExtendGDScriptParser::get_document_links() const const Array &ExtendGDScriptParser::get_member_completions() { if (member_completions.is_empty()) { - const String *name = members.next(nullptr); - while (name) { - const lsp::DocumentSymbol *symbol = members.get(*name); + for (const KeyValue<String, const lsp::DocumentSymbol *> &E : members) { + const lsp::DocumentSymbol *symbol = E.value; lsp::CompletionItem item = symbol->make_completion_item(); - item.data = JOIN_SYMBOLS(path, *name); + item.data = JOIN_SYMBOLS(path, E.key); member_completions.push_back(item.to_json()); - - name = members.next(name); } - const String *_class = inner_classes.next(nullptr); - while (_class) { - const ClassMembers *inner_class = inner_classes.getptr(*_class); - const String *member_name = inner_class->next(nullptr); - while (member_name) { - const lsp::DocumentSymbol *symbol = inner_class->get(*member_name); + for (const KeyValue<String, ClassMembers> &E : inner_classes) { + const ClassMembers *inner_class = &E.value; + + for (const KeyValue<String, const lsp::DocumentSymbol *> &F : *inner_class) { + const lsp::DocumentSymbol *symbol = F.value; lsp::CompletionItem item = symbol->make_completion_item(); - item.data = JOIN_SYMBOLS(path, JOIN_SYMBOLS(*_class, *member_name)); + item.data = JOIN_SYMBOLS(path, JOIN_SYMBOLS(E.key, F.key)); member_completions.push_back(item.to_json()); - - member_name = inner_class->next(member_name); } - - _class = inner_classes.next(_class); } } @@ -696,16 +689,14 @@ Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::Functio ERR_FAIL_NULL_V(p_func, func); func["name"] = p_func->identifier->name; func["return_type"] = p_func->get_datatype().to_string(); - func["rpc_mode"] = p_func->rpc_config.rpc_mode; - func["rpc_transfer_mode"] = p_func->rpc_config.transfer_mode; - func["rpc_transfer_channel"] = p_func->rpc_config.channel; + func["rpc_config"] = p_func->rpc_config; Array parameters; for (int i = 0; i < p_func->parameters.size(); i++) { Dictionary arg; arg["name"] = p_func->parameters[i]->identifier->name; arg["type"] = p_func->parameters[i]->get_datatype().to_string(); - if (p_func->parameters[i]->default_value != nullptr) { - arg["default_value"] = p_func->parameters[i]->default_value->reduced_value; + if (p_func->parameters[i]->initializer != nullptr) { + arg["default_value"] = p_func->parameters[i]->initializer->reduced_value; } parameters.push_back(arg); } @@ -739,7 +730,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode Array nested_classes; Array constants; - Array members; + Array class_members; Array signals; Array methods; Array static_functions; @@ -800,7 +791,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode api["signature"] = symbol->detail; api["description"] = symbol->documentation; } - members.push_back(api); + class_members.push_back(api); } break; case ClassNode::Member::SIGNAL: { Dictionary api; @@ -823,6 +814,8 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode methods.append(dump_function_api(m.function)); } } break; + case ClassNode::Member::GROUP: + break; // No-op, but silences warnings. case ClassNode::Member::UNDEFINED: break; // Unreachable. } @@ -830,7 +823,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode class_api["sub_classes"] = nested_classes; class_api["constants"] = constants; - class_api["members"] = members; + class_api["members"] = class_members; class_api["signals"] = signals; class_api["methods"] = methods; class_api["static_functions"] = static_functions; @@ -840,8 +833,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode Dictionary ExtendGDScriptParser::generate_api() const { Dictionary api; - const GDScriptParser::Node *head = get_tree(); - if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) { + if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(get_tree())) { api = dump_class_api(gdclass); } return api; @@ -852,8 +844,9 @@ Error ExtendGDScriptParser::parse(const String &p_code, const String &p_path) { lines = p_code.split("\n"); Error err = GDScriptParser::parse(p_code, p_path, false); + GDScriptAnalyzer analyzer(this); + if (err == OK) { - GDScriptAnalyzer analyzer(this); err = analyzer.analyze(); } update_diagnostics(); diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h index 99b0bf45d0..4500cb01f3 100644 --- a/modules/gdscript/language_server/gdscript_extend_parser.h +++ b/modules/gdscript/language_server/gdscript_extend_parser.h @@ -1,39 +1,39 @@ -/*************************************************************************/ -/* gdscript_extend_parser.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_extend_parser.h */ +/**************************************************************************/ +/* 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 GDSCRIPT_EXTEND_PARSER_H #define GDSCRIPT_EXTEND_PARSER_H #include "../gdscript_parser.h" #include "core/variant/variant.h" -#include "lsp.hpp" +#include "godot_lsp.h" #ifndef LINE_NUMBER_TO_INDEX #define LINE_NUMBER_TO_INDEX(p_line) ((p_line)-1) @@ -99,4 +99,4 @@ public: Error parse(const String &p_code, const String &p_path); }; -#endif +#endif // GDSCRIPT_EXTEND_PARSER_H diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp index cdddab319d..acd75f039a 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.cpp +++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp @@ -1,39 +1,41 @@ -/*************************************************************************/ -/* gdscript_language_protocol.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_language_protocol.cpp */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ #include "gdscript_language_protocol.h" #include "core/config/project_settings.h" #include "editor/doc_tools.h" +#include "editor/editor_help.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = nullptr; @@ -126,7 +128,7 @@ Error GDScriptLanguageProtocol::on_client_connected() { ERR_FAIL_COND_V_MSG(clients.size() >= LSP_MAX_CLIENTS, FAILED, "Max client limits reached"); Ref<LSPeer> peer = memnew(LSPeer); peer->connection = tcp_peer; - clients.set(next_client_id, peer); + clients.insert(next_client_id, peer); next_client_id++; EditorNode::get_log()->add_message("[LSP] Connection Taken", EditorLog::MSG_TYPE_EDITOR); return OK; @@ -183,7 +185,9 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) { if (root_uri.length() && is_same_workspace) { workspace->root_uri = root_uri; } else { - workspace->root_uri = "file://" + workspace->root; + String r_root = workspace->root; + r_root = r_root.lstrip("/"); + workspace->root_uri = "file:///" + r_root; Dictionary params; params["path"] = workspace->root; @@ -229,28 +233,33 @@ void GDScriptLanguageProtocol::poll() { if (server->is_connection_available()) { on_client_connected(); } - const int *id = nullptr; - while ((id = clients.next(id))) { - Ref<LSPeer> peer = clients.get(*id); + + HashMap<int, Ref<LSPeer>>::Iterator E = clients.begin(); + while (E != clients.end()) { + Ref<LSPeer> peer = E->value; StreamPeerTCP::Status status = peer->connection->get_status(); if (status == StreamPeerTCP::STATUS_NONE || status == StreamPeerTCP::STATUS_ERROR) { - on_client_disconnected(*id); - id = nullptr; + on_client_disconnected(E->key); + E = clients.begin(); + continue; } else { if (peer->connection->get_available_bytes() > 0) { - latest_client_id = *id; + latest_client_id = E->key; Error err = peer->handle_data(); if (err != OK && err != ERR_BUSY) { - on_client_disconnected(*id); - id = nullptr; + on_client_disconnected(E->key); + E = clients.begin(); + continue; } } Error err = peer->send_data(); if (err != OK && err != ERR_BUSY) { - on_client_disconnected(*id); - id = nullptr; + on_client_disconnected(E->key); + E = clients.begin(); + continue; } } + ++E; } } @@ -259,9 +268,8 @@ Error GDScriptLanguageProtocol::start(int p_port, const IPAddress &p_bind_ip) { } void GDScriptLanguageProtocol::stop() { - const int *id = nullptr; - while ((id = clients.next(id))) { - Ref<LSPeer> peer = clients.get(*id); + for (const KeyValue<int, Ref<LSPeer>> &E : clients) { + Ref<LSPeer> peer = clients.get(E.key); peer->connection->disconnect_from_host(); } diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h index 0fed8597f9..d25814f8aa 100644 --- a/modules/gdscript/language_server/gdscript_language_protocol.h +++ b/modules/gdscript/language_server/gdscript_language_protocol.h @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gdscript_language_protocol.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_language_protocol.h */ +/**************************************************************************/ +/* 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 GDSCRIPT_LANGUAGE_PROTOCOL_H #define GDSCRIPT_LANGUAGE_PROTOCOL_H @@ -36,7 +36,7 @@ #include "core/io/tcp_server.h" #include "gdscript_text_document.h" #include "gdscript_workspace.h" -#include "lsp.hpp" +#include "godot_lsp.h" #include "modules/modules_enabled.gen.h" // For jsonrpc. #ifdef MODULE_JSONRPC_ENABLED diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp index 33c1c834f1..062be0fe20 100644 --- a/modules/gdscript/language_server/gdscript_language_server.cpp +++ b/modules/gdscript/language_server/gdscript_language_server.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gdscript_language_server.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_language_server.cpp */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ #include "gdscript_language_server.h" @@ -34,6 +34,7 @@ #include "core/os/os.h" #include "editor/editor_log.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" GDScriptLanguageServer::GDScriptLanguageServer() { _EDITOR_DEF("network/language_server/remote_host", host); @@ -45,24 +46,27 @@ GDScriptLanguageServer::GDScriptLanguageServer() { void GDScriptLanguageServer::_notification(int p_what) { switch (p_what) { - case NOTIFICATION_ENTER_TREE: + case NOTIFICATION_ENTER_TREE: { start(); - break; - case NOTIFICATION_EXIT_TREE: + } break; + + case NOTIFICATION_EXIT_TREE: { stop(); - break; + } break; + case NOTIFICATION_INTERNAL_PROCESS: { if (started && !use_thread) { protocol.poll(); } } break; + case EditorSettings::NOTIFICATION_EDITOR_SETTINGS_CHANGED: { - String host = String(_EDITOR_GET("network/language_server/remote_host")); - int port = (int)_EDITOR_GET("network/language_server/remote_port"); - bool use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); - if (host != this->host || port != this->port || use_thread != this->use_thread) { - this->stop(); - this->start(); + String remote_host = String(_EDITOR_GET("network/language_server/remote_host")); + int remote_port = (int)_EDITOR_GET("network/language_server/remote_port"); + bool remote_use_thread = (bool)_EDITOR_GET("network/language_server/use_thread"); + if (remote_host != host || remote_port != port || remote_use_thread != use_thread) { + stop(); + start(); } } break; } diff --git a/modules/gdscript/language_server/gdscript_language_server.h b/modules/gdscript/language_server/gdscript_language_server.h index 8de72fc9c9..a130dc3ac8 100644 --- a/modules/gdscript/language_server/gdscript_language_server.h +++ b/modules/gdscript/language_server/gdscript_language_server.h @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gdscript_language_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_language_server.h */ +/**************************************************************************/ +/* 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 GDSCRIPT_LANGUAGE_SERVER_H #define GDSCRIPT_LANGUAGE_SERVER_H diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp index 961295b076..35fbdca949 100644 --- a/modules/gdscript/language_server/gdscript_text_document.cpp +++ b/modules/gdscript/language_server/gdscript_text_document.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gdscript_text_document.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_text_document.cpp */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ #include "gdscript_text_document.h" @@ -42,6 +42,7 @@ void GDScriptTextDocument::_bind_methods() { ClassDB::bind_method(D_METHOD("didOpen"), &GDScriptTextDocument::didOpen); ClassDB::bind_method(D_METHOD("didClose"), &GDScriptTextDocument::didClose); ClassDB::bind_method(D_METHOD("didChange"), &GDScriptTextDocument::didChange); + ClassDB::bind_method(D_METHOD("willSaveWaitUntil"), &GDScriptTextDocument::willSaveWaitUntil); ClassDB::bind_method(D_METHOD("didSave"), &GDScriptTextDocument::didSave); ClassDB::bind_method(D_METHOD("nativeSymbol"), &GDScriptTextDocument::nativeSymbol); ClassDB::bind_method(D_METHOD("documentSymbol"), &GDScriptTextDocument::documentSymbol); @@ -81,6 +82,16 @@ void GDScriptTextDocument::didChange(const Variant &p_param) { sync_script_content(doc.uri, doc.text); } +void GDScriptTextDocument::willSaveWaitUntil(const Variant &p_param) { + lsp::TextDocumentItem doc = load_document_item(p_param); + + String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); + Ref<Script> scr = ResourceLoader::load(path); + if (scr.is_valid()) { + ScriptEditor::get_singleton()->clear_docs_from_script(scr); + } +} + void GDScriptTextDocument::didSave(const Variant &p_param) { lsp::TextDocumentItem doc = load_document_item(p_param); Dictionary dict = p_param; @@ -88,11 +99,18 @@ void GDScriptTextDocument::didSave(const Variant &p_param) { sync_script_content(doc.uri, text); - /*String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); - - Ref<GDScript> script = ResourceLoader::load(path); - script->load_source_code(path); - script->reload(true);*/ + String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(doc.uri); + Ref<GDScript> scr = ResourceLoader::load(path); + if (scr.is_valid() && (scr->load_source_code(path) == OK)) { + if (scr->is_tool()) { + scr->get_language()->reload_tool_script(scr, true); + } else { + scr->reload(true); + } + scr->update_exports(); + ScriptEditor::get_singleton()->reload_scripts(true); + ScriptEditor::get_singleton()->update_docs_from_script(scr); + } } lsp::TextDocumentItem GDScriptTextDocument::load_document_item(const Variant &p_param) { @@ -109,23 +127,15 @@ void GDScriptTextDocument::notify_client_show_symbol(const lsp::DocumentSymbol * void GDScriptTextDocument::initialize() { if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { - const HashMap<StringName, ClassMembers> &native_members = GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members; + for (const KeyValue<StringName, ClassMembers> &E : GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members) { + const ClassMembers &members = E.value; - const StringName *class_ptr = native_members.next(nullptr); - while (class_ptr) { - const ClassMembers &members = native_members.get(*class_ptr); - - const String *name = members.next(nullptr); - while (name) { - const lsp::DocumentSymbol *symbol = members.get(*name); + for (const KeyValue<String, const lsp::DocumentSymbol *> &F : members) { + const lsp::DocumentSymbol *symbol = members.get(F.key); lsp::CompletionItem item = symbol->make_completion_item(); - item.data = JOIN_SYMBOLS(String(*class_ptr), *name); + item.data = JOIN_SYMBOLS(String(E.key), F.key); native_member_completions.push_back(item.to_json()); - - name = members.next(name); } - - class_ptr = native_members.next(class_ptr); } } } @@ -149,9 +159,9 @@ Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) { String uri = params["uri"]; String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(uri); Array arr; - if (const Map<String, ExtendGDScriptParser *>::Element *parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) { + if (HashMap<String, ExtendGDScriptParser *>::ConstIterator parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) { Vector<lsp::DocumentedSymbolInformation> list; - parser->get()->get_symbols().symbol_tree_as_list(uri, list); + parser->value->get_symbols().symbol_tree_as_list(uri, list); for (int i = 0; i < list.size(); i++) { arr.push_back(list[i].to_json()); } @@ -166,49 +176,52 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { params.load(p_params); Dictionary request_data = params.to_json(); - List<ScriptCodeCompletionOption> options; + List<ScriptLanguage::CodeCompletionOption> options; GDScriptLanguageProtocol::get_singleton()->get_workspace()->completion(params, &options); if (!options.is_empty()) { int i = 0; arr.resize(options.size()); - for (const ScriptCodeCompletionOption &option : options) { + for (const ScriptLanguage::CodeCompletionOption &option : options) { lsp::CompletionItem item; item.label = option.display; item.data = request_data; + item.insertText = option.insert_text; switch (option.kind) { - case ScriptCodeCompletionOption::KIND_ENUM: + case ScriptLanguage::CODE_COMPLETION_KIND_ENUM: item.kind = lsp::CompletionItemKind::Enum; break; - case ScriptCodeCompletionOption::KIND_CLASS: + case ScriptLanguage::CODE_COMPLETION_KIND_CLASS: item.kind = lsp::CompletionItemKind::Class; break; - case ScriptCodeCompletionOption::KIND_MEMBER: + case ScriptLanguage::CODE_COMPLETION_KIND_MEMBER: item.kind = lsp::CompletionItemKind::Property; break; - case ScriptCodeCompletionOption::KIND_FUNCTION: + case ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION: item.kind = lsp::CompletionItemKind::Method; break; - case ScriptCodeCompletionOption::KIND_SIGNAL: + case ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL: item.kind = lsp::CompletionItemKind::Event; break; - case ScriptCodeCompletionOption::KIND_CONSTANT: + case ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT: item.kind = lsp::CompletionItemKind::Constant; break; - case ScriptCodeCompletionOption::KIND_VARIABLE: + case ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE: item.kind = lsp::CompletionItemKind::Variable; break; - case ScriptCodeCompletionOption::KIND_FILE_PATH: + case ScriptLanguage::CODE_COMPLETION_KIND_FILE_PATH: item.kind = lsp::CompletionItemKind::File; break; - case ScriptCodeCompletionOption::KIND_NODE_PATH: + case ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH: item.kind = lsp::CompletionItemKind::Snippet; break; - case ScriptCodeCompletionOption::KIND_PLAIN_TEXT: + case ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT: item.kind = lsp::CompletionItemKind::Text; break; + default: { + } } arr[i] = item.to_json(); @@ -218,8 +231,8 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) { arr = native_member_completions.duplicate(); for (KeyValue<String, ExtendGDScriptParser *> &E : GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts) { - ExtendGDScriptParser *script = E.value; - const Array &items = script->get_member_completions(); + ExtendGDScriptParser *scr = E.value; + const Array &items = scr->get_member_completions(); const int start_size = arr.size(); arr.resize(start_size + items.size()); @@ -273,8 +286,8 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) { } if (!symbol) { - if (const Map<String, ExtendGDScriptParser *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(class_name)) { - symbol = E->get()->get_member_symbol(member_name, inner_class_name); + if (HashMap<String, ExtendGDScriptParser *>::ConstIterator E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(class_name)) { + symbol = E->value->get_member_symbol(member_name, inner_class_name); } } } @@ -284,12 +297,7 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) { item.documentation = symbol->render(); } - if ((item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function) && !item.label.ends_with("):")) { - item.insertText = item.label + "("; - if (symbol && symbol->children.is_empty()) { - item.insertText += ")"; - } - } else if (item.kind == lsp::CompletionItemKind::Event) { + if (item.kind == lsp::CompletionItemKind::Event) { if (params.context.triggerKind == lsp::CompletionTriggerKind::TriggerCharacter && (params.context.triggerCharacter == "(")) { const String quote_style = EDITOR_GET("text_editor/completion/use_single_quotes") ? "'" : "\""; item.insertText = item.label.quote(quote_style); @@ -422,22 +430,11 @@ GDScriptTextDocument::GDScriptTextDocument() { file_checker = FileAccess::create(FileAccess::ACCESS_RESOURCES); } -GDScriptTextDocument::~GDScriptTextDocument() { - memdelete(file_checker); -} - void GDScriptTextDocument::sync_script_content(const String &p_path, const String &p_content) { String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(p_path); GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content); EditorFileSystem::get_singleton()->update_file(path); - Error error; - Ref<GDScript> script = ResourceLoader::load(path, "", ResourceFormatLoader::CACHE_MODE_REUSE, &error); - if (error == OK) { - if (script->load_source_code(path) == OK) { - script->reload(true); - } - } } void GDScriptTextDocument::show_native_symbol_in_editor(const String &p_symbol_id) { diff --git a/modules/gdscript/language_server/gdscript_text_document.h b/modules/gdscript/language_server/gdscript_text_document.h index eb7b2c0240..aeda10de89 100644 --- a/modules/gdscript/language_server/gdscript_text_document.h +++ b/modules/gdscript/language_server/gdscript_text_document.h @@ -1,50 +1,51 @@ -/*************************************************************************/ -/* gdscript_text_document.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_text_document.h */ +/**************************************************************************/ +/* 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 GDSCRIPT_TEXT_DOCUMENT_H #define GDSCRIPT_TEXT_DOCUMENT_H #include "core/io/file_access.h" #include "core/object/ref_counted.h" -#include "lsp.hpp" +#include "godot_lsp.h" class GDScriptTextDocument : public RefCounted { GDCLASS(GDScriptTextDocument, RefCounted) protected: static void _bind_methods(); - FileAccess *file_checker; + Ref<FileAccess> file_checker; void didOpen(const Variant &p_param); void didClose(const Variant &p_param); void didChange(const Variant &p_param); + void willSaveWaitUntil(const Variant &p_param); void didSave(const Variant &p_param); void sync_script_content(const String &p_path, const String &p_content); @@ -75,7 +76,6 @@ public: void initialize(); GDScriptTextDocument(); - virtual ~GDScriptTextDocument(); }; -#endif +#endif // GDSCRIPT_TEXT_DOCUMENT_H diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp index a944844226..b90c452346 100644 --- a/modules/gdscript/language_server/gdscript_workspace.cpp +++ b/modules/gdscript/language_server/gdscript_workspace.cpp @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gdscript_workspace.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_workspace.cpp */ +/**************************************************************************/ +/* 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. */ +/**************************************************************************/ #include "gdscript_workspace.h" @@ -38,6 +38,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_help.h" #include "editor/editor_node.h" +#include "editor/editor_settings.h" #include "gdscript_language_protocol.h" #include "scene/resources/packed_scene.h" @@ -54,16 +55,16 @@ void GDScriptWorkspace::_bind_methods() { } void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStringArray args) { - Ref<Script> script = obj->get_script(); + Ref<Script> scr = obj->get_script(); - if (script->get_language()->get_name() != "GDScript") { + if (scr->get_language()->get_name() != "GDScript") { return; } String function_signature = "func " + function; - String source = script->get_source_code(); + String source = scr->get_source_code(); - if (source.find(function_signature) != -1) { + if (source.contains(function_signature)) { return; } @@ -97,7 +98,7 @@ void GDScriptWorkspace::apply_new_signal(Object *obj, String function, PackedStr text_edit.newText = function_body; - String uri = get_file_uri(script->get_path()); + String uri = get_file_uri(scr->get_path()); lsp::ApplyWorkspaceEditParams params; params.edit.add_edit(uri, text_edit); @@ -116,22 +117,22 @@ void GDScriptWorkspace::did_delete_files(const Dictionary &p_params) { } void GDScriptWorkspace::remove_cache_parser(const String &p_path) { - Map<String, ExtendGDScriptParser *>::Element *parser = parse_results.find(p_path); - Map<String, ExtendGDScriptParser *>::Element *script = scripts.find(p_path); - if (parser && script) { - if (script->get() && script->get() == parser->get()) { - memdelete(script->get()); + HashMap<String, ExtendGDScriptParser *>::Iterator parser = parse_results.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator scr = scripts.find(p_path); + if (parser && scr) { + if (scr->value && scr->value == parser->value) { + memdelete(scr->value); } else { - memdelete(script->get()); - memdelete(parser->get()); + memdelete(scr->value); + memdelete(parser->value); } parse_results.erase(p_path); scripts.erase(p_path); } else if (parser) { - memdelete(parser->get()); + memdelete(parser->value); parse_results.erase(p_path); - } else if (script) { - memdelete(script->get()); + } else if (scr) { + memdelete(scr->value); scripts.erase(p_path); } } @@ -141,8 +142,8 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_ StringName empty; while (class_name != empty) { - if (const Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(class_name)) { - const lsp::DocumentSymbol &class_symbol = E->value(); + if (HashMap<StringName, lsp::DocumentSymbol>::ConstIterator E = native_symbols.find(class_name)) { + const lsp::DocumentSymbol &class_symbol = E->value; if (p_member.is_empty()) { return &class_symbol; @@ -162,9 +163,9 @@ const lsp::DocumentSymbol *GDScriptWorkspace::get_native_symbol(const String &p_ } const lsp::DocumentSymbol *GDScriptWorkspace::get_script_symbol(const String &p_path) const { - const Map<String, ExtendGDScriptParser *>::Element *S = scripts.find(p_path); + HashMap<String, ExtendGDScriptParser *>::ConstIterator S = scripts.find(p_path); if (S) { - return &(S->get()->get_symbols()); + return &(S->value->get_symbols()); } return nullptr; } @@ -209,10 +210,10 @@ void GDScriptWorkspace::reload_all_workspace_scripts() { err = parse_script(path, content); if (err != OK) { - Map<String, ExtendGDScriptParser *>::Element *S = parse_results.find(path); + HashMap<String, ExtendGDScriptParser *>::Iterator S = parse_results.find(path); String err_msg = "Failed parse script " + path; if (S) { - err_msg += "\n" + S->get()->get_errors()[0].message; + err_msg += "\n" + S->value->get_errors()[0].message; } ERR_CONTINUE_MSG(err != OK, err_msg); } @@ -221,15 +222,15 @@ void GDScriptWorkspace::reload_all_workspace_scripts() { void GDScriptWorkspace::list_script_files(const String &p_root_dir, List<String> &r_files) { Error err; - DirAccessRef dir = DirAccess::open(p_root_dir, &err); + Ref<DirAccess> dir = DirAccess::open(p_root_dir, &err); if (OK == err) { dir->list_dir_begin(); String file_name = dir->get_next(); while (file_name.length()) { if (dir->current_is_dir() && file_name != "." && file_name != ".." && file_name != "./") { - list_script_files(p_root_dir.plus_file(file_name), r_files); + list_script_files(p_root_dir.path_join(file_name), r_files); } else if (file_name.ends_with(".gd")) { - String script_file = p_root_dir.plus_file(file_name); + String script_file = p_root_dir.path_join(file_name); r_files.push_back(script_file); } file_name = dir->get_next(); @@ -238,25 +239,25 @@ void GDScriptWorkspace::list_script_files(const String &p_root_dir, List<String> } ExtendGDScriptParser *GDScriptWorkspace::get_parse_successed_script(const String &p_path) { - const Map<String, ExtendGDScriptParser *>::Element *S = scripts.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator S = scripts.find(p_path); if (!S) { parse_local_script(p_path); S = scripts.find(p_path); } if (S) { - return S->get(); + return S->value; } return nullptr; } ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path) { - const Map<String, ExtendGDScriptParser *>::Element *S = parse_results.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator S = parse_results.find(p_path); if (!S) { parse_local_script(p_path); S = parse_results.find(p_path); } if (S) { - return S->get(); + return S->value; } return nullptr; } @@ -269,7 +270,7 @@ Array GDScriptWorkspace::symbol(const Dictionary &p_params) { Vector<lsp::DocumentedSymbolInformation> script_symbols; E.value->get_symbols().symbol_tree_as_list(E.key, script_symbols); for (int i = 0; i < script_symbols.size(); ++i) { - if (query.is_subsequence_ofi(script_symbols[i].name)) { + if (query.is_subsequence_ofn(script_symbols[i].name)) { lsp::DocumentedSymbolInformation symbol = script_symbols[i]; symbol.location.uri = get_file_uri(symbol.location.uri); arr.push_back(symbol.to_json()); @@ -380,7 +381,7 @@ Error GDScriptWorkspace::initialize() { symbol.children.push_back(symbol_arg); } - if (data.qualifiers.find("vararg") != -1) { + if (data.qualifiers.contains("vararg")) { params += params.is_empty() ? "..." : ", ..."; } @@ -404,9 +405,9 @@ Error GDScriptWorkspace::initialize() { const lsp::DocumentSymbol &class_symbol = E.value; for (int i = 0; i < class_symbol.children.size(); i++) { const lsp::DocumentSymbol &symbol = class_symbol.children[i]; - members.set(symbol.name, &symbol); + members.insert(symbol.name, &symbol); } - native_members.set(E.key, members); + native_members.insert(E.key, members); } // cache member completions @@ -424,8 +425,8 @@ Error GDScriptWorkspace::initialize() { Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_content) { ExtendGDScriptParser *parser = memnew(ExtendGDScriptParser); Error err = parser->parse(p_content, p_path); - Map<String, ExtendGDScriptParser *>::Element *last_parser = parse_results.find(p_path); - Map<String, ExtendGDScriptParser *>::Element *last_script = scripts.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator last_parser = parse_results.find(p_path); + HashMap<String, ExtendGDScriptParser *>::Iterator last_script = scripts.find(p_path); if (err == OK) { remove_cache_parser(p_path); @@ -433,8 +434,8 @@ Error GDScriptWorkspace::parse_script(const String &p_path, const String &p_cont scripts[p_path] = parser; } else { - if (last_parser && last_script && last_parser->get() != last_script->get()) { - memdelete(last_parser->get()); + if (last_parser && last_script && last_parser->value != last_script->value) { + memdelete(last_parser->value); } parse_results[p_path] = parser; } @@ -498,9 +499,9 @@ Error GDScriptWorkspace::parse_local_script(const String &p_path) { } String GDScriptWorkspace::get_file_path(const String &p_uri) const { - String path = p_uri; - path = path.replace(root_uri + "/", "res://"); - path = path.uri_decode(); + String path = p_uri.uri_decode(); + String base_uri = root_uri.uri_decode(); + path = path.replacen(base_uri + "/", "res://"); return path; } @@ -513,9 +514,9 @@ String GDScriptWorkspace::get_file_uri(const String &p_path) const { void GDScriptWorkspace::publish_diagnostics(const String &p_path) { Dictionary params; Array errors; - const Map<String, ExtendGDScriptParser *>::Element *ele = parse_results.find(p_path); + HashMap<String, ExtendGDScriptParser *>::ConstIterator ele = parse_results.find(p_path); if (ele) { - const Vector<lsp::Diagnostic> &list = ele->get()->get_diagnostics(); + const Vector<lsp::Diagnostic> &list = ele->value->get_diagnostics(); errors.resize(list.size()); for (int i = 0; i < list.size(); ++i) { errors[i] = list[i].to_json(); @@ -560,7 +561,7 @@ Node *GDScriptWorkspace::_get_owner_scene_node(String p_path) { for (int i = 0; i < owners.size(); i++) { NodePath owner_path = owners[i]; - RES owner_res = ResourceLoader::load(owner_path); + Ref<Resource> owner_res = ResourceLoader::load(owner_path); if (Object::cast_to<PackedScene>(owner_res.ptr())) { Ref<PackedScene> owner_packed_scene = Ref<PackedScene>(Object::cast_to<PackedScene>(*owner_res)); owner_scene_node = owner_packed_scene->instantiate(); @@ -571,7 +572,7 @@ Node *GDScriptWorkspace::_get_owner_scene_node(String p_path) { return owner_scene_node; } -void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<ScriptCodeCompletionOption> *r_options) { +void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<ScriptLanguage::CodeCompletionOption> *r_options) { String path = get_file_path(p_params.textDocument.uri); String call_hint; bool forced = false; @@ -585,9 +586,9 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S stack.push_back(owner_scene_node); while (!stack.is_empty()) { - current = stack.pop_back(); - Ref<GDScript> script = current->get_script(); - if (script.is_valid() && script->get_path() == path) { + current = Object::cast_to<Node>(stack.pop_back()); + Ref<GDScript> scr = current->get_script(); + if (scr.is_valid() && scr->get_path() == path) { break; } for (int i = 0; i < current->get_child_count(); ++i) { @@ -595,8 +596,8 @@ void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<S } } - Ref<GDScript> script = current->get_script(); - if (!script.is_valid() || script->get_path() != path) { + Ref<GDScript> scr = current->get_script(); + if (!scr.is_valid() || scr->get_path() != path) { current = owner_scene_node; } } @@ -638,7 +639,7 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu symbol_identifier = "_init"; } if (OK == GDScriptLanguage::get_singleton()->lookup_code(parser->get_text_for_lookup_symbol(pos, symbol_identifier, p_func_required), symbol_identifier, path, nullptr, ret)) { - if (ret.type == ScriptLanguage::LookupResult::RESULT_SCRIPT_LOCATION) { + if (ret.type == ScriptLanguage::LOOKUP_RESULT_SCRIPT_LOCATION) { String target_script_path = path; if (!ret.script.is_null()) { target_script_path = ret.script->get_path(); @@ -682,39 +683,33 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP Vector2i offset; symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, offset); - const StringName *class_ptr = native_members.next(nullptr); - while (class_ptr) { - const ClassMembers &members = native_members.get(*class_ptr); + for (const KeyValue<StringName, ClassMembers> &E : native_members) { + const ClassMembers &members = native_members.get(E.key); if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) { r_list.push_back(*symbol); } - class_ptr = native_members.next(class_ptr); } for (const KeyValue<String, ExtendGDScriptParser *> &E : scripts) { - const ExtendGDScriptParser *script = E.value; - const ClassMembers &members = script->get_members(); + const ExtendGDScriptParser *scr = E.value; + const ClassMembers &members = scr->get_members(); if (const lsp::DocumentSymbol *const *symbol = members.getptr(symbol_identifier)) { r_list.push_back(*symbol); } - const HashMap<String, ClassMembers> &inner_classes = script->get_inner_classes(); - const String *_class = inner_classes.next(nullptr); - while (_class) { - const ClassMembers *inner_class = inner_classes.getptr(*_class); + for (const KeyValue<String, ClassMembers> &F : scr->get_inner_classes()) { + const ClassMembers *inner_class = &F.value; if (const lsp::DocumentSymbol *const *symbol = inner_class->getptr(symbol_identifier)) { r_list.push_back(*symbol); } - - _class = inner_classes.next(_class); } } } } const lsp::DocumentSymbol *GDScriptWorkspace::resolve_native_symbol(const lsp::NativeSymbolInspectParams &p_params) { - if (Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.find(p_params.native_class)) { - const lsp::DocumentSymbol &symbol = E->get(); + if (HashMap<StringName, lsp::DocumentSymbol>::Iterator E = native_symbols.find(p_params.native_class)) { + const lsp::DocumentSymbol &symbol = E->value; if (p_params.symbol_name.is_empty() || p_params.symbol_name == symbol.name) { return &symbol; } @@ -790,7 +785,7 @@ GDScriptWorkspace::GDScriptWorkspace() { } GDScriptWorkspace::~GDScriptWorkspace() { - Set<String> cached_parsers; + HashSet<String> cached_parsers; for (const KeyValue<String, ExtendGDScriptParser *> &E : parse_results) { cached_parsers.insert(E.key); @@ -800,7 +795,7 @@ GDScriptWorkspace::~GDScriptWorkspace() { cached_parsers.insert(E.key); } - for (Set<String>::Element *E = cached_parsers.front(); E; E = E->next()) { - remove_cache_parser(E->get()); + for (const String &E : cached_parsers) { + remove_cache_parser(E); } } diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h index ce5bba5f00..a849ef8a8d 100644 --- a/modules/gdscript/language_server/gdscript_workspace.h +++ b/modules/gdscript/language_server/gdscript_workspace.h @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* gdscript_workspace.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* gdscript_workspace.h */ +/**************************************************************************/ +/* 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 GDSCRIPT_WORKSPACE_H #define GDSCRIPT_WORKSPACE_H @@ -35,7 +35,7 @@ #include "core/variant/variant.h" #include "editor/editor_file_system.h" #include "gdscript_extend_parser.h" -#include "lsp.hpp" +#include "godot_lsp.h" class GDScriptWorkspace : public RefCounted { GDCLASS(GDScriptWorkspace, RefCounted); @@ -48,7 +48,7 @@ protected: static void _bind_methods(); void remove_cache_parser(const String &p_path); bool initialized = false; - Map<StringName, lsp::DocumentSymbol> native_symbols; + HashMap<StringName, lsp::DocumentSymbol> native_symbols; const lsp::DocumentSymbol *get_native_symbol(const String &p_class, const String &p_member = "") const; const lsp::DocumentSymbol *get_script_symbol(const String &p_path) const; @@ -68,8 +68,8 @@ public: String root; String root_uri; - Map<String, ExtendGDScriptParser *> scripts; - Map<String, ExtendGDScriptParser *> parse_results; + HashMap<String, ExtendGDScriptParser *> scripts; + HashMap<String, ExtendGDScriptParser *> parse_results; HashMap<StringName, ClassMembers> native_members; public: @@ -85,7 +85,7 @@ public: String get_file_uri(const String &p_path) const; void publish_diagnostics(const String &p_path); - void completion(const lsp::CompletionParams &p_params, List<ScriptCodeCompletionOption> *r_options); + void completion(const lsp::CompletionParams &p_params, List<ScriptLanguage::CodeCompletionOption> *r_options); const lsp::DocumentSymbol *resolve_symbol(const lsp::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name = "", bool p_func_required = false); void resolve_related_symbols(const lsp::TextDocumentPositionParams &p_doc_pos, List<const lsp::DocumentSymbol *> &r_list); @@ -100,4 +100,4 @@ public: ~GDScriptWorkspace(); }; -#endif +#endif // GDSCRIPT_WORKSPACE_H diff --git a/modules/gdscript/language_server/lsp.hpp b/modules/gdscript/language_server/godot_lsp.h index 8e503a9df9..8a033204da 100644 --- a/modules/gdscript/language_server/lsp.hpp +++ b/modules/gdscript/language_server/godot_lsp.h @@ -1,32 +1,32 @@ -/*************************************************************************/ -/* lsp.hpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* 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. */ -/*************************************************************************/ +/**************************************************************************/ +/* godot_lsp.h */ +/**************************************************************************/ +/* 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 GODOT_LSP_H #define GODOT_LSP_H @@ -261,7 +261,7 @@ struct WorkspaceEdit { /** * Holds changes to existing resources. */ - Map<String, Vector<TextEdit>> changes; + HashMap<String, Vector<TextEdit>> changes; _FORCE_INLINE_ void add_edit(const String &uri, const TextEdit &edit) { if (changes.has(uri)) { @@ -293,8 +293,8 @@ struct WorkspaceEdit { } _FORCE_INLINE_ void add_change(const String &uri, const int &line, const int &start_character, const int &end_character, const String &new_text) { - if (Map<String, Vector<TextEdit>>::Element *E = changes.find(uri)) { - Vector<TextEdit> edit_list = E->value(); + if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) { + Vector<TextEdit> edit_list = E->value; for (int i = 0; i < edit_list.size(); ++i) { TextEdit edit = edit_list[i]; if (edit.range.start.character == start_character) { @@ -310,8 +310,8 @@ struct WorkspaceEdit { new_edit.range.end.line = line; new_edit.range.end.character = end_character; - if (Map<String, Vector<TextEdit>>::Element *E = changes.find(uri)) { - E->value().push_back(new_edit); + if (HashMap<String, Vector<TextEdit>>::Iterator E = changes.find(uri)) { + E->value.push_back(new_edit); } else { Vector<TextEdit> edit_list; edit_list.push_back(new_edit); @@ -546,7 +546,7 @@ struct TextDocumentSyncOptions { * If present will save wait until requests are sent to the server. If omitted the request should not be * sent. */ - bool willSaveWaitUntil = false; + bool willSaveWaitUntil = true; /** * If present save notifications are sent to the server. If omitted the notification should not be @@ -702,7 +702,7 @@ struct DiagnosticRelatedInformation { Dictionary to_json() const { Dictionary dict; - dict["location"] = location.to_json(), + dict["location"] = location.to_json(); dict["message"] = message; return dict; } @@ -1004,8 +1004,8 @@ struct CompletionItem { dict["label"] = label; dict["kind"] = kind; dict["data"] = data; + dict["insertText"] = insertText; if (resolved) { - dict["insertText"] = insertText; dict["detail"] = detail; dict["documentation"] = documentation.to_json(); dict["deprecated"] = deprecated; @@ -1940,7 +1940,7 @@ static String marked_documentation(const String &p_bbcode) { line = "\t" + line.substr(code_block_indent, line.length()); } - if (in_code_block && line.find("[/codeblock]") != -1) { + if (in_code_block && line.contains("[/codeblock]")) { line = "\n"; in_code_block = false; } @@ -1975,4 +1975,4 @@ static String marked_documentation(const String &p_bbcode) { } } // namespace lsp -#endif +#endif // GODOT_LSP_H |