summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/language_server/gdscript_text_document.cpp
diff options
context:
space:
mode:
authorGeequlim <geequlim@gmail.com>2019-06-24 18:25:12 +0800
committergeequlim <geequlim@gmail.com>2019-08-11 13:30:15 +0800
commit76c9e4ceb73b02bd95ab0512e27229516208dc60 (patch)
treeb145ae3a4a837a109943f654bf433e704b7eac74 /modules/gdscript/language_server/gdscript_text_document.cpp
parentfa6d6a329c93224b5454b17603284913da0472a3 (diff)
downloadredot-engine-76c9e4ceb73b02bd95ab0512e27229516208dc60.tar.gz
Improved performance for completion and symbol resolvation.
Improved uri and workspace path translatation on windows platform. The smart resolvation is much faster than builtin's in the server side. The smart resolve mode is still disabled as default as the clients might be slow with a planty of completion items.
Diffstat (limited to 'modules/gdscript/language_server/gdscript_text_document.cpp')
-rw-r--r--modules/gdscript/language_server/gdscript_text_document.cpp143
1 files changed, 88 insertions, 55 deletions
diff --git a/modules/gdscript/language_server/gdscript_text_document.cpp b/modules/gdscript/language_server/gdscript_text_document.cpp
index 177f13c04c..a5211fb0f1 100644
--- a/modules/gdscript/language_server/gdscript_text_document.cpp
+++ b/modules/gdscript/language_server/gdscript_text_document.cpp
@@ -30,6 +30,8 @@
#include "gdscript_text_document.h"
#include "../gdscript.h"
+#include "core/os/os.h"
+#include "editor/editor_settings.h"
#include "gdscript_extend_parser.h"
#include "gdscript_language_protocol.h"
@@ -71,6 +73,33 @@ lsp::TextDocumentItem GDScriptTextDocument::load_document_item(const Variant &p_
return doc;
}
+void GDScriptTextDocument::initialize() {
+
+ if (GDScriptLanguageProtocol::get_singleton()->is_smart_resolve_enabled()) {
+
+ const HashMap<StringName, ClassMembers> &native_members = GDScriptLanguageProtocol::get_singleton()->get_workspace().native_members;
+
+ const StringName *class_ptr = native_members.next(NULL);
+ while (class_ptr) {
+
+ const ClassMembers &members = native_members.get(*class_ptr);
+
+ const String *name = members.next(NULL);
+ while (name) {
+
+ const lsp::DocumentSymbol *symbol = members.get(*name);
+ lsp::CompletionItem item = symbol->make_completion_item(false);
+ item.data = JOIN_SYMBOLS(String(*class_ptr), *name);
+ native_member_completions.push_back(item.to_json());
+
+ name = members.next(name);
+ }
+
+ class_ptr = native_members.next(class_ptr);
+ }
+ }
+}
+
Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) {
Dictionary params = p_params["textDocument"];
String uri = params["uri"];
@@ -87,6 +116,7 @@ Array GDScriptTextDocument::documentSymbol(const Dictionary &p_params) {
}
Array GDScriptTextDocument::completion(const Dictionary &p_params) {
+
Array arr;
lsp::CompletionParams params;
@@ -98,18 +128,16 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) {
if (!options.empty()) {
+ int i = 0;
+ arr.resize(options.size());
+
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 (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;
@@ -142,50 +170,24 @@ Array GDScriptTextDocument::completion(const Dictionary &p_params) {
item.kind = lsp::CompletionItemKind::Text;
break;
}
- arr.push_back(item.to_json());
- }
+ arr[i] = item.to_json(true);
+ i++;
+ }
} 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;
+ arr = native_member_completions.duplicate();
- lsp::CompletionItem item;
- item.label = symbol->name;
- item.data = E->key();
+ for (Map<String, ExtendGDScriptParser *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace().scripts.front(); E; E = E->next()) {
- 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;
+ ExtendGDScriptParser *script = E->get();
+ const Array &items = script->get_member_completions();
+
+ const int start_size = arr.size();
+ arr.resize(start_size + items.size());
+ for (int i = start_size; i < arr.size(); i++) {
+ arr[i] = items[i - start_size];
}
- arr.push_back(item.to_json());
}
}
return arr;
@@ -202,19 +204,50 @@ Dictionary GDScriptTextDocument::resolve(const Dictionary &p_params) {
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);
+ 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) {
- if (Map<String, const lsp::DocumentSymbol *>::Element *E = GDScriptLanguageProtocol::get_singleton()->get_workspace().flat_symbols.find(data)) {
- symbol = E->get();
+ String query = data;
+ int seperator_pos = query.find_last(".");
+ if (seperator_pos >= 0 && seperator_pos < query.length() - 1) {
+
+ String class_ = query.substr(0, seperator_pos);
+ StringName class_name = class_;
+ String member_name = query.substr(seperator_pos + 1, query.length());
+
+ if (const ClassMembers *members = GDScriptLanguageProtocol::get_singleton()->get_workspace().native_members.getptr(class_name)) {
+ if (const lsp::DocumentSymbol *const *member = members->getptr(member_name)) {
+ symbol = *member;
+ }
+ }
+
+ 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);
+ }
+ }
}
}
if (symbol) {
item.documentation = symbol->render();
}
+
+ if (item.kind == lsp::CompletionItemKind::Method || item.kind == lsp::CompletionItemKind::Function) {
+ item.insertText = item.label + "(";
+ if (symbol && symbol->detail.find(",") == -1) {
+ item.insertText += ")";
+ }
+ } else if (item.kind == lsp::CompletionItemKind::Event) {
+ if (params.context.triggerKind == lsp::CompletionTriggerKind::TriggerCharacter && (params.context.triggerCharacter == "(")) {
+ const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
+ item.insertText = quote_style + item.label + quote_style;
+ }
+ }
+
return item.to_json();
}
@@ -247,17 +280,20 @@ Variant GDScriptTextDocument::hover(const Dictionary &p_params) {
const lsp::DocumentSymbol *symbol = GDScriptLanguageProtocol::get_singleton()->get_workspace().resolve_symbol(params);
if (symbol) {
+
lsp::Hover hover;
hover.contents = symbol->render();
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);
+ if (const lsp::DocumentSymbol *s = E->get()) {
+ contents.push_back(s->render().value);
}
}
ret["contents"] = contents;
@@ -289,16 +325,13 @@ Array GDScriptTextDocument::definition(const Dictionary &p_params) {
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()) {
+ if (const lsp::DocumentSymbol *s = E->get()) {
lsp::Location location;
- location.uri = symbol->uri;
- location.range = symbol->range;
+ location.uri = s->uri;
+ location.range = s->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());
- }
+ arr.push_back(location.to_json());
}
}
}