Add generate script api to dictionary support

Expose GDScriptLanguageProtocol singleton and classes for editor plugins (Not visiable in class tree)
Fix minor bug in symbol resolve
This commit is contained in:
Geequlim 2019-06-26 20:21:42 +08:00 committed by geequlim
parent 9618b0c63e
commit 666ed89011
8 changed files with 212 additions and 36 deletions

View file

@ -139,7 +139,10 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
symbol.range.end.line = line; symbol.range.end.line = line;
symbol.range.end.character = lines[line].length(); symbol.range.end.character = lines[line].length();
symbol.selectionRange.start.line = symbol.range.start.line; symbol.selectionRange.start.line = symbol.range.start.line;
symbol.detail = "var " + m.identifier; if (m._export.type != Variant::NIL) {
symbol.detail += "export ";
}
symbol.detail += "var " + m.identifier;
if (m.data_type.kind != GDScriptParser::DataType::UNRESOLVED) { if (m.data_type.kind != GDScriptParser::DataType::UNRESOLVED) {
symbol.detail += ": " + m.data_type.to_string(); symbol.detail += ": " + m.data_type.to_string();
} }
@ -210,7 +213,7 @@ void ExtendGDScriptParser::parse_class_symbol(const GDScriptParser::ClassNode *p
if (res.is_valid() && !res->get_path().empty()) { if (res.is_valid() && !res->get_path().empty()) {
value_text = "preload(\"" + res->get_path() + "\")"; value_text = "preload(\"" + res->get_path() + "\")";
if (symbol.documentation.empty()) { if (symbol.documentation.empty()) {
if (Map<String, ExtendGDScriptParser *>::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace().scripts.find(res->get_path())) { if (Map<String, ExtendGDScriptParser *>::Element *S = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(res->get_path())) {
symbol.documentation = S->get()->class_symbol.documentation; symbol.documentation = S->get()->class_symbol.documentation;
} }
} }
@ -335,7 +338,7 @@ String ExtendGDScriptParser::parse_documentation(int p_line, bool p_docs_down) {
String inline_comment = lines[p_line]; String inline_comment = lines[p_line];
int comment_start = inline_comment.find("#"); int comment_start = inline_comment.find("#");
if (comment_start != -1) { if (comment_start != -1) {
inline_comment = inline_comment.substr(comment_start, inline_comment.length()); inline_comment = inline_comment.substr(comment_start, inline_comment.length()).strip_edges();
if (inline_comment.length() > 1) { if (inline_comment.length() > 1) {
doc_lines.push_back(inline_comment.substr(1, inline_comment.length())); doc_lines.push_back(inline_comment.substr(1, inline_comment.length()));
} }
@ -407,7 +410,7 @@ String ExtendGDScriptParser::get_text_for_lookup_symbol(const lsp::Position &p_c
if (i == p_cursor.line) { if (i == p_cursor.line) {
String line = lines[i]; String line = lines[i];
String first_part = line.substr(0, p_cursor.character); String first_part = line.substr(0, p_cursor.character);
String last_part = line.substr(p_cursor.character, lines[i].size()); String last_part = line.substr(p_cursor.character + 1, lines[i].length());
if (!p_symbol.empty()) { if (!p_symbol.empty()) {
String left_cursor_text; String left_cursor_text;
for (int c = p_cursor.character - 1; c >= 0; c--) { for (int c = p_cursor.character - 1; c >= 0; c--) {
@ -473,7 +476,7 @@ String ExtendGDScriptParser::get_identifier_under_position(const lsp::Position &
} }
String ExtendGDScriptParser::get_uri() const { String ExtendGDScriptParser::get_uri() const {
return GDScriptLanguageProtocol::get_singleton()->get_workspace().get_file_uri(path); return GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_uri(path);
} }
const lsp::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(int p_line, const lsp::DocumentSymbol &p_parent) const { const lsp::DocumentSymbol *ExtendGDScriptParser::search_symbol_defined_at_line(int p_line, const lsp::DocumentSymbol &p_parent) const {
@ -555,6 +558,145 @@ const Array &ExtendGDScriptParser::get_member_completions() {
return member_completions; return member_completions;
} }
Dictionary ExtendGDScriptParser::dump_function_api(const GDScriptParser::FunctionNode *p_func) const {
Dictionary func;
ERR_FAIL_NULL_V(p_func, func);
func["name"] = p_func->name;
func["return_type"] = p_func->return_type.to_string();
func["rpc_mode"] = p_func->rpc_mode;
Array arguments;
for (int i = 0; i < p_func->arguments.size(); i++) {
Dictionary arg;
arg["name"] = p_func->arguments[i];
arg["type"] = p_func->argument_types[i].to_string();
int default_value_idx = i - (p_func->arguments.size() - p_func->default_values.size());
if (default_value_idx >= 0) {
const GDScriptParser::ConstantNode *const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(p_func->default_values[default_value_idx]);
if (const_node == NULL) {
const GDScriptParser::OperatorNode *operator_node = dynamic_cast<const GDScriptParser::OperatorNode *>(p_func->default_values[default_value_idx]);
if (operator_node) {
const_node = dynamic_cast<const GDScriptParser::ConstantNode *>(operator_node->next);
}
}
if (const_node) {
arg["default_value"] = const_node->value;
}
}
arguments.push_back(arg);
}
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_func->line))) {
func["signature"] = symbol->detail;
func["description"] = symbol->documentation;
}
func["arguments"] = arguments;
return func;
}
Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode *p_class) const {
Dictionary class_api;
ERR_FAIL_NULL_V(p_class, class_api);
class_api["name"] = String(p_class->name);
class_api["path"] = path;
Array extends_class;
for (int i = 0; i < p_class->extends_class.size(); i++) {
extends_class.append(String(p_class->extends_class[i]));
}
class_api["extends_class"] = extends_class;
class_api["extends_file"] = String(p_class->extends_file);
class_api["icon"] = String(p_class->icon_path);
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(p_class->line))) {
class_api["signature"] = symbol->detail;
class_api["description"] = symbol->documentation;
}
Array subclasses;
for (int i = 0; i < p_class->subclasses.size(); i++) {
subclasses.push_back(dump_class_api(p_class->subclasses[i]));
}
class_api["sub_classes"] = subclasses;
Array constants;
for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_class->constant_expressions.front(); E; E = E->next()) {
const GDScriptParser::ClassNode::Constant &c = E->value();
const GDScriptParser::ConstantNode *node = dynamic_cast<const GDScriptParser::ConstantNode *>(c.expression);
Dictionary api;
api["name"] = E->key();
api["value"] = node->value;
api["data_type"] = node->datatype.to_string();
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(node->line))) {
api["signature"] = symbol->detail;
api["description"] = symbol->documentation;
}
constants.push_back(api);
}
class_api["constants"] = constants;
Array members;
for (int i = 0; i < p_class->variables.size(); ++i) {
const GDScriptParser::ClassNode::Member &m = p_class->variables[i];
Dictionary api;
api["name"] = m.identifier;
api["data_type"] = m.data_type.to_string();
api["default_value"] = m.default_value;
api["setter"] = String(m.setter);
api["getter"] = String(m.getter);
api["export"] = m._export.type != Variant::NIL;
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(m.line))) {
api["signature"] = symbol->detail;
api["description"] = symbol->documentation;
}
members.push_back(api);
}
class_api["members"] = members;
Array signals;
for (int i = 0; i < p_class->_signals.size(); ++i) {
const GDScriptParser::ClassNode::Signal &signal = p_class->_signals[i];
Dictionary api;
api["name"] = signal.name;
Array args;
for (int j = 0; j < signal.arguments.size(); j++) {
args.append(signal.arguments[j]);
}
api["arguments"] = args;
if (const lsp::DocumentSymbol *symbol = get_symbol_defined_at_line(LINE_NUMBER_TO_INDEX(signal.line))) {
api["signature"] = symbol->detail;
api["description"] = symbol->documentation;
}
signals.push_back(api);
}
class_api["signals"] = signals;
Array methods;
for (int i = 0; i < p_class->functions.size(); ++i) {
methods.append(dump_function_api(p_class->functions[i]));
}
class_api["methods"] = methods;
Array static_functions;
for (int i = 0; i < p_class->static_functions.size(); ++i) {
static_functions.append(dump_function_api(p_class->functions[i]));
}
class_api["static_functions"] = static_functions;
return class_api;
}
Dictionary ExtendGDScriptParser::generate_api() const {
Dictionary api;
const GDScriptParser::Node *head = get_parse_tree();
if (const GDScriptParser::ClassNode *gdclass = dynamic_cast<const GDScriptParser::ClassNode *>(head)) {
api = dump_class_api(gdclass);
}
return api;
}
Error ExtendGDScriptParser::parse(const String &p_code, const String &p_path) { Error ExtendGDScriptParser::parse(const String &p_code, const String &p_path) {
path = p_path; path = p_path;
lines = p_code.split("\n"); lines = p_code.split("\n");

View file

@ -65,6 +65,9 @@ class ExtendGDScriptParser : public GDScriptParser {
void parse_class_symbol(const GDScriptParser::ClassNode *p_class, lsp::DocumentSymbol &r_symbol); void parse_class_symbol(const GDScriptParser::ClassNode *p_class, lsp::DocumentSymbol &r_symbol);
void parse_function_symbol(const GDScriptParser::FunctionNode *p_func, lsp::DocumentSymbol &r_symbol); void parse_function_symbol(const GDScriptParser::FunctionNode *p_func, lsp::DocumentSymbol &r_symbol);
Dictionary dump_function_api(const GDScriptParser::FunctionNode *p_func) const;
Dictionary dump_class_api(const GDScriptParser::ClassNode *p_class) const;
String parse_documentation(int p_line, bool p_docs_down = false); String parse_documentation(int p_line, bool p_docs_down = false);
const lsp::DocumentSymbol *search_symbol_defined_at_line(int p_line, const lsp::DocumentSymbol &p_parent) const; const lsp::DocumentSymbol *search_symbol_defined_at_line(int p_line, const lsp::DocumentSymbol &p_parent) const;
@ -87,6 +90,7 @@ public:
const lsp::DocumentSymbol *get_member_symbol(const String &p_name, const String &p_subclass = "") const; const lsp::DocumentSymbol *get_member_symbol(const String &p_name, const String &p_subclass = "") const;
const Array &get_member_completions(); const Array &get_member_completions();
Dictionary generate_api() const;
Error parse(const String &p_code, const String &p_path); Error parse(const String &p_code, const String &p_path);
}; };

View file

@ -86,6 +86,12 @@ void GDScriptLanguageProtocol::_bind_methods() {
ClassDB::bind_method(D_METHOD("on_data_received"), &GDScriptLanguageProtocol::on_data_received); ClassDB::bind_method(D_METHOD("on_data_received"), &GDScriptLanguageProtocol::on_data_received);
ClassDB::bind_method(D_METHOD("on_client_connected"), &GDScriptLanguageProtocol::on_client_connected); ClassDB::bind_method(D_METHOD("on_client_connected"), &GDScriptLanguageProtocol::on_client_connected);
ClassDB::bind_method(D_METHOD("on_client_disconnected"), &GDScriptLanguageProtocol::on_client_disconnected); ClassDB::bind_method(D_METHOD("on_client_disconnected"), &GDScriptLanguageProtocol::on_client_disconnected);
ClassDB::bind_method(D_METHOD("notify_all_clients", "p_method", "p_params"), &GDScriptLanguageProtocol::notify_all_clients, DEFVAL(Variant()));
ClassDB::bind_method(D_METHOD("notify_client", "p_method", "p_params", "p_client"), &GDScriptLanguageProtocol::notify_client, DEFVAL(Variant()), DEFVAL(-1));
ClassDB::bind_method(D_METHOD("is_smart_resolve_enabled"), &GDScriptLanguageProtocol::is_smart_resolve_enabled);
ClassDB::bind_method(D_METHOD("get_text_document"), &GDScriptLanguageProtocol::get_text_document);
ClassDB::bind_method(D_METHOD("get_workspace"), &GDScriptLanguageProtocol::get_workspace);
ClassDB::bind_method(D_METHOD("is_initialized"), &GDScriptLanguageProtocol::is_initialized);
} }
Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) { Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
@ -94,20 +100,20 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
String root_uri = p_params["rootUri"]; String root_uri = p_params["rootUri"];
String root = p_params["rootPath"]; String root = p_params["rootPath"];
bool is_same_workspace = root == workspace.root; bool is_same_workspace = root == workspace->root;
is_same_workspace = root.to_lower() == workspace.root.to_lower(); is_same_workspace = root.to_lower() == workspace->root.to_lower();
#ifdef WINDOWS_ENABLED #ifdef WINDOWS_ENABLED
is_same_workspace = root.replace("\\", "/").to_lower() == workspace.root.to_lower(); is_same_workspace = root.replace("\\", "/").to_lower() == workspace->root.to_lower();
#endif #endif
if (root_uri.length() && is_same_workspace) { if (root_uri.length() && is_same_workspace) {
workspace.root_uri = root_uri; workspace->root_uri = root_uri;
} else { } else {
workspace.root_uri = "file://" + workspace.root; workspace->root_uri = "file://" + workspace->root;
Dictionary params; Dictionary params;
params["path"] = workspace.root; params["path"] = workspace->root;
Dictionary request = make_notification("gdscrip_client/changeWorkspace", params); Dictionary request = make_notification("gdscrip_client/changeWorkspace", params);
if (Ref<WebSocketPeer> *peer = clients.getptr(lastest_client_id)) { if (Ref<WebSocketPeer> *peer = clients.getptr(lastest_client_id)) {
String msg = JSON::print(request); String msg = JSON::print(request);
@ -118,8 +124,8 @@ Dictionary GDScriptLanguageProtocol::initialize(const Dictionary &p_params) {
} }
if (!_initialized) { if (!_initialized) {
workspace.initialize(); workspace->initialize();
text_document.initialize(); text_document->initialize();
_initialized = true; _initialized = true;
} }
@ -187,10 +193,12 @@ GDScriptLanguageProtocol::GDScriptLanguageProtocol() {
server = NULL; server = NULL;
singleton = this; singleton = this;
_initialized = false; _initialized = false;
set_scope("textDocument", &text_document); workspace.instance();
set_scope("completionItem", &text_document); text_document.instance();
set_scope("workspace", &workspace); set_scope("textDocument", text_document.ptr());
workspace.root = ProjectSettings::get_singleton()->get_resource_path(); set_scope("completionItem", text_document.ptr());
set_scope("workspace", workspace.ptr());
workspace->root = ProjectSettings::get_singleton()->get_resource_path();
} }
GDScriptLanguageProtocol::~GDScriptLanguageProtocol() { GDScriptLanguageProtocol::~GDScriptLanguageProtocol() {

View file

@ -52,8 +52,8 @@ class GDScriptLanguageProtocol : public JSONRPC {
WebSocketServer *server; WebSocketServer *server;
int lastest_client_id; int lastest_client_id;
GDScriptTextDocument text_document; Ref<GDScriptTextDocument> text_document;
GDScriptWorkspace workspace; Ref<GDScriptWorkspace> workspace;
void on_data_received(int p_id); void on_data_received(int p_id);
void on_client_connected(int p_id, const String &p_protocal); void on_client_connected(int p_id, const String &p_protocal);
@ -72,7 +72,9 @@ protected:
public: public:
_FORCE_INLINE_ static GDScriptLanguageProtocol *get_singleton() { return singleton; } _FORCE_INLINE_ static GDScriptLanguageProtocol *get_singleton() { return singleton; }
_FORCE_INLINE_ GDScriptWorkspace &get_workspace() { return workspace; } _FORCE_INLINE_ Ref<GDScriptWorkspace> get_workspace() { return workspace; }
_FORCE_INLINE_ Ref<GDScriptTextDocument> get_text_document() { return text_document; }
_FORCE_INLINE_ bool is_initialized() const { return _initialized; }
void poll(); void poll();
Error start(int p_port); Error start(int p_port);

View file

@ -77,7 +77,7 @@ void GDScriptTextDocument::initialize() {
if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
const HashMap<StringName, ClassMembers> &native_members = GDScriptLanguageProtocol::get_singleton()->get_workspace().native_members; const HashMap<StringName, ClassMembers> &native_members = GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members;
const StringName *class_ptr = native_members.next(NULL); const StringName *class_ptr = native_members.next(NULL);
while (class_ptr) { while (class_ptr) {
@ -103,9 +103,9 @@ void GDScriptTextDocument::initialize() {
Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) { Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) {
Dictionary params = p_params["textDocument"]; Dictionary params = p_params["textDocument"];
String uri = params["uri"]; String uri = params["uri"];
String path = GDScriptLanguageProtocol::get_singleton()->get_workspace().get_file_path(uri); String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(uri);
Array arr; Array arr;
if (const Map<String, ExtendGDScriptParser *>::Element *parser = GDScriptLanguageProtocol::get_singleton()->get_workspace().scripts.find(path)) { if (const Map<String, ExtendGDScriptParser *>::Element *parser = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.find(path)) {
Vector<lsp::DocumentedSymbolInformation> list; Vector<lsp::DocumentedSymbolInformation> list;
parser->get()->get_symbols().symbol_tree_as_list(uri, list); parser->get()->get_symbols().symbol_tree_as_list(uri, list);
for (int i = 0; i < list.size(); i++) { for (int i = 0; i < list.size(); i++) {
@ -124,7 +124,7 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) {
Dictionary request_data = params.to_json(); Dictionary request_data = params.to_json();
List<ScriptCodeCompletionOption> options; List<ScriptCodeCompletionOption> options;
GDScriptLanguageProtocol::get_singleton()->get_workspace().completion(params, &options); GDScriptLanguageProtocol::get_singleton()->get_workspace()->completion(params, &options);
if (!options.empty()) { if (!options.empty()) {
@ -178,7 +178,7 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) {
arr = native_member_completions.duplicate(); arr = native_member_completions.duplicate();
for (Map<String, ExtendGDScriptParser *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace().scripts.front(); E; E = E->next()) { for (Map<String, ExtendGDScriptParser *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace()->scripts.front(); E; E = E->next()) {
ExtendGDScriptParser *script = E->get(); ExtendGDScriptParser *script = E->get();
const Array &items = script->get_member_completions(); const Array &items = script->get_member_completions();
@ -206,7 +206,7 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
if (data.get_type() == Variant::DICTIONARY) { if (data.get_type() == Variant::DICTIONARY) {
params.load(p_params["data"]); params.load(p_params["data"]);
symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_symbol(params, item.label, item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function); symbol = 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) { } else if (data.get_type() == Variant::STRING) {
@ -224,14 +224,14 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
inner_class_name = param_symbols[1]; inner_class_name = param_symbols[1];
} }
if (const ClassMembers *members = GDScriptLanguageProtocol::get_singleton()->get_workspace().native_members.getptr(class_name)) { if (const ClassMembers *members = GDScriptLanguageProtocol::get_singleton()->get_workspace()->native_members.getptr(class_name)) {
if (const lsp::DocumentSymbol *const *member = members->getptr(member_name)) { if (const lsp::DocumentSymbol *const *member = members->getptr(member_name)) {
symbol = *member; symbol = *member;
} }
} }
if (!symbol) { if (!symbol) {
if (const Map<String, ExtendGDScriptParser *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace().scripts.find(class_name)) { 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); symbol = E->get()->get_member_symbol(member_name, inner_class_name);
} }
} }
@ -284,7 +284,7 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
lsp::TextDocumentPositionParams params; lsp::TextDocumentPositionParams params;
params.load(p_params); params.load(p_params);
const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_symbol(params); const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params);
if (symbol) { if (symbol) {
lsp::Hover hover; lsp::Hover hover;
@ -296,7 +296,7 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
Dictionary ret; Dictionary ret;
Array contents; Array contents;
List<const lsp::DocumentSymbol *> list; List<const lsp::DocumentSymbol *> list;
GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_related_symbols(params, list); GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(params, list);
for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) { for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
if (const lsp::DocumentSymbol *s = E->get()) { if (const lsp::DocumentSymbol *s = E->get()) {
contents.push_back(s->render().value); contents.push_back(s->render().value);
@ -315,20 +315,20 @@ Array GDScriptTextDocument::definition(const Dictionary &p_params) {
lsp::TextDocumentPositionParams params; lsp::TextDocumentPositionParams params;
params.load(p_params); params.load(p_params);
const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_symbol(params); const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_symbol(params);
if (symbol) { if (symbol) {
lsp::Location location; lsp::Location location;
location.uri = symbol->uri; location.uri = symbol->uri;
location.range = symbol->range; location.range = symbol->range;
const String &path = GDScriptLanguageProtocol::get_singleton()->get_workspace().get_file_path(symbol->uri); const String &path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(symbol->uri);
if (file_checker->file_exists(path)) { if (file_checker->file_exists(path)) {
arr.push_back(location.to_json()); arr.push_back(location.to_json());
} }
} else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) { } else if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
List<const lsp::DocumentSymbol *> list; List<const lsp::DocumentSymbol *> list;
GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_related_symbols(params, list); GDScriptLanguageProtocol::get_singleton()->get_workspace()->resolve_related_symbols(params, list);
for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) { for (List<const lsp::DocumentSymbol *>::Element *E = list.front(); E; E = E->next()) {
if (const lsp::DocumentSymbol *s = E->get()) { if (const lsp::DocumentSymbol *s = E->get()) {
@ -354,6 +354,6 @@ GDScriptTextDocument::~GDScriptTextDocument() {
} }
void GDScriptTextDocument::sync_script_content(const String &p_uri, const String &p_content) { void GDScriptTextDocument::sync_script_content(const String &p_uri, const String &p_content) {
String path = GDScriptLanguageProtocol::get_singleton()->get_workspace().get_file_path(p_uri); String path = GDScriptLanguageProtocol::get_singleton()->get_workspace()->get_file_path(p_uri);
GDScriptLanguageProtocol::get_singleton()->get_workspace().parse_script(path, p_content); GDScriptLanguageProtocol::get_singleton()->get_workspace()->parse_script(path, p_content);
} }

View file

@ -38,6 +38,12 @@
void GDScriptWorkspace::_bind_methods() { void GDScriptWorkspace::_bind_methods() {
ClassDB::bind_method(D_METHOD("symbol"), &GDScriptWorkspace::symbol); ClassDB::bind_method(D_METHOD("symbol"), &GDScriptWorkspace::symbol);
ClassDB::bind_method(D_METHOD("parse_script", "p_path", "p_content"), &GDScriptWorkspace::parse_script);
ClassDB::bind_method(D_METHOD("parse_local_script", "p_path"), &GDScriptWorkspace::parse_local_script);
ClassDB::bind_method(D_METHOD("get_file_path", "p_uri"), &GDScriptWorkspace::get_file_path);
ClassDB::bind_method(D_METHOD("get_file_uri", "p_path"), &GDScriptWorkspace::get_file_uri);
ClassDB::bind_method(D_METHOD("publish_diagnostics", "p_path"), &GDScriptWorkspace::publish_diagnostics);
ClassDB::bind_method(D_METHOD("generate_script_api", "p_path"), &GDScriptWorkspace::generate_script_api);
} }
void GDScriptWorkspace::remove_cache_parser(const String &p_path) { void GDScriptWorkspace::remove_cache_parser(const String &p_path) {
@ -512,6 +518,14 @@ void GDScriptWorkspace::resolve_related_symbols(const lsp::TextDocumentPositionP
} }
} }
Dictionary GDScriptWorkspace::generate_script_api(const String &p_path) {
Dictionary api;
if (const ExtendGDScriptParser *parser = get_parse_successed_script(p_path)) {
api = parser->generate_api();
}
return api;
}
GDScriptWorkspace::GDScriptWorkspace() { GDScriptWorkspace::GDScriptWorkspace() {
ProjectSettings::get_singleton()->get_resource_path(); ProjectSettings::get_singleton()->get_resource_path();
} }

View file

@ -82,6 +82,8 @@ public:
const lsp::DocumentSymbol *resolve_symbol(const lsp::TextDocumentPositionParams &p_doc_pos, const String &p_symbol_name = "", bool p_func_requred = false); 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); void resolve_related_symbols(const lsp::TextDocumentPositionParams &p_doc_pos, List<const lsp::DocumentSymbol *> &r_list);
Dictionary generate_script_api(const String &p_path);
static String marked_documentation(const String &p_bbcode); static String marked_documentation(const String &p_bbcode);
GDScriptWorkspace(); GDScriptWorkspace();

View file

@ -44,6 +44,7 @@ Ref<ResourceFormatSaverGDScript> resource_saver_gd;
#ifdef TOOLS_ENABLED #ifdef TOOLS_ENABLED
#include "core/engine.h"
#include "editor/editor_export.h" #include "editor/editor_export.h"
#include "editor/editor_node.h" #include "editor/editor_node.h"
#include "editor/editor_settings.h" #include "editor/editor_settings.h"
@ -131,8 +132,11 @@ static void _editor_init() {
Ref<EditorExportGDScript> gd_export; Ref<EditorExportGDScript> gd_export;
gd_export.instance(); gd_export.instance();
EditorExport::get_singleton()->add_export_plugin(gd_export); EditorExport::get_singleton()->add_export_plugin(gd_export);
EditorNode::get_singleton()->add_editor_plugin(memnew(GDScriptLanguageServer));
register_lsp_types(); register_lsp_types();
GDScriptLanguageServer *lsp_plugin = memnew(GDScriptLanguageServer);
EditorNode::get_singleton()->add_editor_plugin(lsp_plugin);
Engine::get_singleton()->add_singleton(Engine::Singleton("GDScriptLanguageProtocol", GDScriptLanguageProtocol::get_singleton()));
} }
#endif #endif