summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.cpp43
-rw-r--r--modules/gdscript/language_server/gdscript_extend_parser.h7
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.cpp5
-rw-r--r--modules/gdscript/language_server/gdscript_language_protocol.h2
-rw-r--r--modules/gdscript/language_server/gdscript_language_server.cpp1
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp184
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.cpp71
-rw-r--r--modules/gdscript/language_server/gdscript_workspace.h12
8 files changed, 260 insertions, 65 deletions
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.cpp b/modules/gdscript/language_server/gdscript_extend_parser.cpp
index 9ec93a813e..16af7cb92f 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.cpp
+++ b/modules/gdscript/language_server/gdscript_extend_parser.cpp
@@ -123,7 +123,9 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
if (m.data_type.kind != GDScriptParser::DataType::UNRESOLVED) {
symbol.detail += ": " + m.data_type.to_string();
}
- symbol.detail += " = " + String(m.default_value);
+ if (m.default_value.get_type() != Variant::NIL) {
+ symbol.detail += " = " + JSON::print(m.default_value);
+ }
symbol.documentation = parse_documentation(line);
symbol.uri = uri;
@@ -493,12 +495,39 @@ const lsp::DocumentSymbol *ExtendGDScriptParser::get_member_symbol(const String
return NULL;
}
-void ExtendGDScriptParser::dump_symbols(HashMap<String, lsp::DocumentedSymbolInformation> &r_symbols) {
- Vector<lsp::DocumentedSymbolInformation> list;
- class_symbol.symbol_tree_as_list(path, list, path, true);
- for (int i = 0; i < list.size(); i++) {
- const lsp::DocumentedSymbolInformation &symbol = list[i];
- r_symbols.set(symbol.name, symbol);
+void ExtendGDScriptParser::dump_member_symbols(Map<String, const lsp::DocumentSymbol *> &r_symbols) {
+
+ const GDScriptParser::Node *head = get_parse_tree();
+ if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) {
+
+ for (const Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = gdclass->constant_expressions.front(); E; E = E->next()) {
+ get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(E->get().expression->line));
+ }
+
+ for (int i = 0; i < gdclass->subclasses.size(); i++) {
+ const ClassNode *m = gdclass->subclasses[i];
+ r_symbols.insert(JOIN_SYMBOLS(path, m->name), get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m->line)));
+ }
+
+ for (int i = 0; i < gdclass->variables.size(); i++) {
+ const GDScriptParser::ClassNode::Member &m = gdclass->variables[i];
+ r_symbols.insert(JOIN_SYMBOLS(path, m.identifier), get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.line)));
+ }
+
+ for (int i = 0; i < gdclass->functions.size(); i++) {
+ const GDScriptParser::FunctionNode *m = gdclass->functions[i];
+ r_symbols.insert(JOIN_SYMBOLS(path, m->name), get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m->line)));
+ }
+
+ for (int i = 0; i < gdclass->static_functions.size(); i++) {
+ const GDScriptParser::FunctionNode *m = gdclass->static_functions[i];
+ r_symbols.insert(JOIN_SYMBOLS(path, m->name), get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m->line)));
+ }
+
+ for (int i = 0; i < gdclass->_signals.size(); i++) {
+ const GDScriptParser::ClassNode::Signal &m = gdclass->_signals[i];
+ r_symbols.insert(JOIN_SYMBOLS(path, m.name), get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.line)));
+ }
}
}
diff --git a/modules/gdscript/language_server/gdscript_extend_parser.h b/modules/gdscript/language_server/gdscript_extend_parser.h
index a1a2e2c31f..a7e5130e2c 100644
--- a/modules/gdscript/language_server/gdscript_extend_parser.h
+++ b/modules/gdscript/language_server/gdscript_extend_parser.h
@@ -39,6 +39,10 @@
#define LINE_NUMBER_TO_INDEX(p_line) ((p_line)-1)
#endif
+#ifndef JOIN_SYMBOLS
+#define JOIN_SYMBOLS(p_path, name) ((p_path) + "." + (name))
+#endif
+
class ExtendGDScriptParser : public GDScriptParser {
String path;
String code;
@@ -70,8 +74,7 @@ public:
const lsp::DocumentSymbol *get_symbol_defined_at_line(int p_line) const;
const lsp::DocumentSymbol *get_member_symbol(const String &p_name) const;
-
- void dump_symbols(HashMap<String, lsp::DocumentedSymbolInformation> &r_symbols);
+ void dump_member_symbols(Map<String, const lsp::DocumentSymbol *> &r_symbols);
Error parse(const String &p_code, const String &p_path);
};
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.cpp b/modules/gdscript/language_server/gdscript_language_protocol.cpp
index 7f74e68a94..7c24efe450 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.cpp
+++ b/modules/gdscript/language_server/gdscript_language_protocol.cpp
@@ -32,6 +32,7 @@
#include "core/io/json.h"
#include "core/os/copymem.h"
#include "core/project_settings.h"
+#include "editor/editor_node.h"
GDScriptLanguageProtocol *GDScriptLanguageProtocol::singleton = NULL;
@@ -159,6 +160,10 @@ void GDScriptLanguageProtocol::notify_client(const String &p_method, const Varia
(*peer)->put_packet((const uint8_t *)charstr.ptr(), charstr.length());
}
+bool GDScriptLanguageProtocol::is_smart_resolve_enabled() const {
+ return bool(_EDITOR_GET("network/language_server/enable_smart_resolve"));
+}
+
GDScriptLanguageProtocol::GDScriptLanguageProtocol() {
server = NULL;
singleton = this;
diff --git a/modules/gdscript/language_server/gdscript_language_protocol.h b/modules/gdscript/language_server/gdscript_language_protocol.h
index c6495250c1..dbe073dd07 100644
--- a/modules/gdscript/language_server/gdscript_language_protocol.h
+++ b/modules/gdscript/language_server/gdscript_language_protocol.h
@@ -79,6 +79,8 @@ public:
void notify_all_clients(const String &p_method, const Variant &p_params = Variant());
void notify_client(const String &p_method, const Variant &p_params = Variant(), int p_client = -1);
+ bool is_smart_resolve_enabled() const;
+
GDScriptLanguageProtocol();
~GDScriptLanguageProtocol();
};
diff --git a/modules/gdscript/language_server/gdscript_language_server.cpp b/modules/gdscript/language_server/gdscript_language_server.cpp
index 63ced28ddd..893bfd5f98 100644
--- a/modules/gdscript/language_server/gdscript_language_server.cpp
+++ b/modules/gdscript/language_server/gdscript_language_server.cpp
@@ -37,6 +37,7 @@ GDScriptLanguageServer::GDScriptLanguageServer() {
thread = NULL;
thread_exit = false;
_EDITOR_DEF("network/language_server/remote_port", 6008);
+ _EDITOR_DEF("network/language_server/enable_smart_resolve", false);
}
void GDScriptLanguageServer::_notification(int p_what) {
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index 7e5d2a512a..177f13c04c 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -68,7 +68,6 @@ lsp::TextDocumentItem GDScriptTextDocument::load_document_item(const Variant &p_
lsp::TextDocumentItem doc;
Dictionary params = p_param;
doc.load(params["textDocument"]);
- print_line(doc.text);
return doc;
}
@@ -97,62 +96,122 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) {
List<ScriptCodeCompletionOption> options;
GDScriptLanguageProtocol::get_singleton()->get_workspace().completion(params, &options);
- for (const List<ScriptCodeCompletionOption>::Element *E = options.front(); E; E = E->next()) {
- const ScriptCodeCompletionOption &option = E->get();
- lsp::CompletionItem item;
- item.label = option.display;
- item.insertText = option.insert_text;
- item.data = request_data;
+ if (!options.empty()) {
- if (params.context.triggerKind == lsp::CompletionTriggerKind::TriggerCharacter && (params.context.triggerCharacter == "'" || params.context.triggerCharacter == "\"") && (option.insert_text.begins_with("'") || option.insert_text.begins_with("\""))) {
- item.insertText = option.insert_text.substr(1, option.insert_text.length() - 2);
- }
+ for (const List<ScriptCodeCompletionOption>::Element *E = options.front(); E; E = E->next()) {
+
+ const ScriptCodeCompletionOption &option = E->get();
+ lsp::CompletionItem item;
+ item.label = option.display;
+ item.insertText = option.insert_text;
+ item.data = request_data;
- switch (option.kind) {
- case ScriptCodeCompletionOption::KIND_ENUM:
- item.kind = lsp::CompletionItemKind::Enum;
- break;
- case ScriptCodeCompletionOption::KIND_CLASS:
- item.kind = lsp::CompletionItemKind::Class;
- break;
- case ScriptCodeCompletionOption::KIND_MEMBER:
- item.kind = lsp::CompletionItemKind::Property;
- break;
- case ScriptCodeCompletionOption::KIND_FUNCTION:
- item.kind = lsp::CompletionItemKind::Method;
- break;
- case ScriptCodeCompletionOption::KIND_SIGNAL:
- item.kind = lsp::CompletionItemKind::Event;
- break;
- case ScriptCodeCompletionOption::KIND_CONSTANT:
- item.kind = lsp::CompletionItemKind::Constant;
- break;
- case ScriptCodeCompletionOption::KIND_VARIABLE:
- item.kind = lsp::CompletionItemKind::Variable;
- break;
- case ScriptCodeCompletionOption::KIND_FILE_PATH:
- item.kind = lsp::CompletionItemKind::File;
- break;
- case ScriptCodeCompletionOption::KIND_NODE_PATH:
- item.kind = lsp::CompletionItemKind::Snippet;
- break;
- case ScriptCodeCompletionOption::KIND_PLAIN_TEXT:
- item.kind = lsp::CompletionItemKind::Text;
- break;
+ if (params.context.triggerKind == lsp::CompletionTriggerKind::TriggerCharacter && (params.context.triggerCharacter == "'" || params.context.triggerCharacter == "\"") && (option.insert_text.begins_with("'") || option.insert_text.begins_with("\""))) {
+ item.insertText = option.insert_text.substr(1, option.insert_text.length() - 2);
+ }
+
+ switch (option.kind) {
+ case ScriptCodeCompletionOption::KIND_ENUM:
+ item.kind = lsp::CompletionItemKind::Enum;
+ break;
+ case ScriptCodeCompletionOption::KIND_CLASS:
+ item.kind = lsp::CompletionItemKind::Class;
+ break;
+ case ScriptCodeCompletionOption::KIND_MEMBER:
+ item.kind = lsp::CompletionItemKind::Property;
+ break;
+ case ScriptCodeCompletionOption::KIND_FUNCTION:
+ item.kind = lsp::CompletionItemKind::Method;
+ break;
+ case ScriptCodeCompletionOption::KIND_SIGNAL:
+ item.kind = lsp::CompletionItemKind::Event;
+ break;
+ case ScriptCodeCompletionOption::KIND_CONSTANT:
+ item.kind = lsp::CompletionItemKind::Constant;
+ break;
+ case ScriptCodeCompletionOption::KIND_VARIABLE:
+ item.kind = lsp::CompletionItemKind::Variable;
+ break;
+ case ScriptCodeCompletionOption::KIND_FILE_PATH:
+ item.kind = lsp::CompletionItemKind::File;
+ break;
+ case ScriptCodeCompletionOption::KIND_NODE_PATH:
+ item.kind = lsp::CompletionItemKind::Snippet;
+ break;
+ case ScriptCodeCompletionOption::KIND_PLAIN_TEXT:
+ item.kind = lsp::CompletionItemKind::Text;
+ break;
+ }
+ arr.push_back(item.to_json());
}
- arr.push_back(item.to_json());
- }
+ } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ for (Map<String, const lsp::DocumentSymbol *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace().flat_symbols.front(); E; E = E->next()) {
+ const lsp::DocumentSymbol *symbol = E->get();
+ if (!symbol) continue;
+
+ lsp::CompletionItem item;
+ item.label = symbol->name;
+ item.data = E->key();
+
+ switch (symbol->kind) {
+ case lsp::SymbolKind::Enum:
+ item.kind = lsp::CompletionItemKind::Enum;
+ break;
+ case lsp::SymbolKind::Class:
+ item.kind = lsp::CompletionItemKind::Class;
+ break;
+ case lsp::SymbolKind::Property:
+ item.kind = lsp::CompletionItemKind::Property;
+ break;
+ case lsp::SymbolKind::Method:
+ case lsp::SymbolKind::Function:
+ item.kind = lsp::CompletionItemKind::Method;
+ break;
+ case lsp::SymbolKind::Event:
+ item.kind = lsp::CompletionItemKind::Event;
+ break;
+ case lsp::SymbolKind::Constant:
+ item.kind = lsp::CompletionItemKind::Constant;
+ break;
+ case lsp::SymbolKind::Variable:
+ item.kind = lsp::CompletionItemKind::Variable;
+ break;
+ case lsp::SymbolKind::File:
+ item.kind = lsp::CompletionItemKind::File;
+ break;
+ default:
+ item.kind = lsp::CompletionItemKind::Text;
+ break;
+ }
+ arr.push_back(item.to_json());
+ }
+ }
return arr;
}
Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
+
lsp::CompletionItem item;
item.load(p_params);
+
lsp::CompletionParams params;
- params.load(p_params["data"]);
- const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_symbol(params, item.label, item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function);
+ Variant data = p_params["data"];
+
+ const lsp::DocumentSymbol *symbol = NULL;
+
+ if (data.get_type() == Variant::DICTIONARY) {
+ params.load(p_params["data"]);
+ GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_symbol(params, item.label, item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function);
+
+ } else if (data.get_type() == Variant::STRING) {
+
+ if (Map<String, const lsp::DocumentSymbol *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace().flat_symbols.find(data)) {
+ symbol = E->get();
+ }
+ }
+
if (symbol) {
item.documentation = symbol->render();
}
@@ -182,7 +241,6 @@ Array GDScriptTextDocument::colorPresentation(const Dictionary &p_params) {
}
Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
- Variant ret;
lsp::TextDocumentPositionParams params;
params.load(p_params);
@@ -191,10 +249,22 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
if (symbol) {
lsp::Hover hover;
hover.contents = symbol->render();
- ret = hover.to_json();
+ return hover.to_json();
+ } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ Dictionary ret;
+ Array contents;
+ List<const lsp::DocumentSymbol *> list;
+ GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_related_symbols(params, list);
+ for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
+ if (const lsp::DocumentSymbol *symbol = E->get()) {
+ contents.push_back(symbol->render().value);
+ }
+ }
+ ret["contents"] = contents;
+ return ret;
}
- return ret;
+ return Variant();
}
Array GDScriptTextDocument::definition(const Dictionary &p_params) {
@@ -213,6 +283,24 @@ Array GDScriptTextDocument::definition(const Dictionary &p_params) {
if (file_checker->file_exists(path)) {
arr.push_back(location.to_json());
}
+ } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+
+ List<const lsp::DocumentSymbol *> list;
+ GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_related_symbols(params, list);
+ for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
+
+ if (const lsp::DocumentSymbol *symbol = E->get()) {
+
+ lsp::Location location;
+ location.uri = symbol->uri;
+ location.range = symbol->range;
+
+ const String &path = GDScriptLanguageProtocol::get_singleton()->get_workspace().get_file_path(symbol->uri);
+ if (file_checker->file_exists(path)) {
+ arr.push_back(location.to_json());
+ }
+ }
+ }
}
return arr;
diff --git a/modules/gdscript/language_server/gdscript_workspace.cpp b/modules/gdscript/language_server/gdscript_workspace.cpp
index 068930002b..d21f53652f 100644
--- a/modules/gdscript/language_server/gdscript_workspace.cpp
+++ b/modules/gdscript/language_server/gdscript_workspace.cpp
@@ -148,13 +148,10 @@ ExtendGDScriptParser *GDScriptWorkspace::get_parse_successed_script(const String
}
ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path) {
- const Map<String, ExtendGDScriptParser *>::Element *S = scripts.find(p_path);
+ const Map<String, ExtendGDScriptParser *>::Element *S = parse_results.find(p_path);
if (!S) {
+ parse_local_script(p_path);
S = parse_results.find(p_path);
- if (!S) {
- parse_local_script(p_path);
- S = scripts.find(p_path);
- }
}
if (S) {
return S->get();
@@ -162,6 +159,22 @@ ExtendGDScriptParser *GDScriptWorkspace::get_parse_result(const String &p_path)
return NULL;
}
+void GDScriptWorkspace::strip_flat_symbols(const String &p_branch) {
+
+ typedef Map<String, const lsp::DocumentSymbol *>::Element *Item;
+
+ List<Item> removal_items;
+ for (Item E = flat_symbols.front(); E; E = E->next()) {
+ if (E->key().begins_with(p_branch)) {
+ removal_items.push_back(E);
+ }
+ }
+
+ for (List<Item>::Element *E = removal_items.front(); E; E = E->next()) {
+ flat_symbols.erase(E->get());
+ }
+}
+
String GDScriptWorkspace::marked_documentation(const String &p_bbcode) {
String markdown = p_bbcode.strip_edges();
@@ -313,21 +326,41 @@ Error GDScriptWorkspace::initialize() {
native_symbols.insert(class_name, class_symbol);
}
+ if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ // expand symbol trees to the flat symbol pool
+ for (Map<StringName, lsp::DocumentSymbol>::Element *E = native_symbols.front(); E; E = E->next()) {
+ const lsp::DocumentSymbol &class_symbol = E->get();
+ for (int i = 0; i < class_symbol.children.size(); i++) {
+ const lsp::DocumentSymbol &symbol = class_symbol.children[i];
+ flat_symbols.insert(JOIN_SYMBOLS(class_symbol.name, symbol.name), &symbol);
+ }
+ }
+ }
+
reload_all_workspace_scripts();
return OK;
}
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);
if (err == OK) {
+
remove_cache_parser(p_path);
parse_results[p_path] = parser;
scripts[p_path] = parser;
+
+ if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+ // update flat symbol pool
+ strip_flat_symbols(p_path);
+ parser->dump_member_symbols(flat_symbols);
+ }
+
} else {
if (last_parser && last_script && last_parser->get() != last_script->get()) {
memdelete(last_parser->get());
@@ -377,11 +410,13 @@ void GDScriptWorkspace::publish_diagnostics(const String &p_path) {
}
void GDScriptWorkspace::completion(const lsp::CompletionParams &p_params, List<ScriptCodeCompletionOption> *r_options) {
+
String path = get_file_path(p_params.textDocument.uri);
String call_hint;
bool forced = false;
- if (Map<String, ExtendGDScriptParser *>::Element *E = parse_results.find(path)) {
- String code = E->get()->get_text_for_completion(p_params.position);
+
+ if (const ExtendGDScriptParser *parser = get_parse_result(path)) {
+ String code = parser->get_text_for_completion(p_params.position);
GDScriptLanguage::get_singleton()->complete_code(code, path, NULL, r_options, forced, call_hint);
}
}
@@ -442,6 +477,28 @@ const lsp::DocumentSymbol *GDScriptWorkspace::resolve_symbol(const lsp::TextDocu
return symbol;
}
+void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionParams &p_doc_pos, List<const lsp::DocumentSymbol *> &r_list) {
+
+ String path = get_file_path(p_doc_pos.textDocument.uri);
+ if (const ExtendGDScriptParser *parser = get_parse_result(path)) {
+
+ String symbol_identifier;
+ Vector2i offset;
+ symbol_identifier = parser->get_identifier_under_position(p_doc_pos.position, offset);
+
+ for (Map<String, const lsp::DocumentSymbol *>::Element *E = flat_symbols.front(); E; E = E->next()) {
+ String id = E->key();
+ int idx = id.find_last(".");
+ if (idx >= 0 && idx < id.length() - 1) {
+ String name = id.substr(idx + 1, id.length());
+ if (name == symbol_identifier) {
+ r_list.push_back(E->get());
+ }
+ }
+ }
+ }
+}
+
GDScriptWorkspace::GDScriptWorkspace() {
ProjectSettings::get_singleton()->get_resource_path();
}
diff --git a/modules/gdscript/language_server/gdscript_workspace.h b/modules/gdscript/language_server/gdscript_workspace.h
index ebefd12587..2ae488b451 100644
--- a/modules/gdscript/language_server/gdscript_workspace.h
+++ b/modules/gdscript/language_server/gdscript_workspace.h
@@ -50,27 +50,37 @@ protected:
void reload_all_workspace_scripts();
- void list_script_files(const String &p_root_dir, List<String> &r_files);
ExtendGDScriptParser *get_parse_successed_script(const String &p_path);
ExtendGDScriptParser *get_parse_result(const String &p_path);
+ void strip_flat_symbols(const String &p_branch);
+ void list_script_files(const String &p_root_dir, List<String> &r_files);
+
public:
String root;
+
Map<String, ExtendGDScriptParser *> scripts;
Map<String, ExtendGDScriptParser *> parse_results;
+ Map<String, const lsp::DocumentSymbol *> flat_symbols;
public:
Array symbol(const Dictionary &p_params);
public:
Error initialize();
+
Error parse_script(const String &p_path, const String &p_content);
Error parse_local_script(const String &p_path);
+
String get_file_path(const String &p_uri) const;
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);
+
const lsp::DocumentSymbol *resolve_symbol(const lsp::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name = "", bool p_func_requred = false);
+ void resolve_related_symbols(const lsp::TextDocumentPositionParams &p_doc_pos, List<const lsp::DocumentSymbol *> &r_list);
+
static String marked_documentation(const String &p_bbcode);
GDScriptWorkspace();