Parse more informations for code completion

This commit is contained in:
Geequlim 2019-06-13 17:17:20 +08:00
parent 2293c612e6
commit ed7ed52151
9 changed files with 194 additions and 93 deletions

View file

@ -200,6 +200,34 @@ public:
virtual ~ScriptInstance();
};
struct ScriptCodeCompletionOption {
enum Kind {
KIND_CLASS,
KIND_FUNCTION,
KIND_SIGNAL,
KIND_VARIABLE,
KIND_MEMBER,
KIND_ENUM,
KIND_CONSTANT,
KIND_NODE_PATH,
KIND_FILE_PATH,
KIND_PLAIN_TEXT,
};
Kind kind;
String display;
String insert_text;
ScriptCodeCompletionOption() {
kind = KIND_PLAIN_TEXT;
}
ScriptCodeCompletionOption(const String &p_text, Kind p_kind) {
display = p_text;
insert_text = p_text;
kind = p_kind;
}
};
class ScriptCodeCompletionCache {
static ScriptCodeCompletionCache *singleton;
@ -250,7 +278,7 @@ public:
virtual Error open_in_external_editor(const Ref<Script> &p_script, int p_line, int p_col) { return ERR_UNAVAILABLE; }
virtual bool overrides_external_editor() { return false; }
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) { return ERR_UNAVAILABLE; }
struct LookupResult {
enum Type {

View file

@ -724,7 +724,7 @@ void CodeTextEditor::_code_complete_timer_timeout() {
void CodeTextEditor::_complete_request() {
List<String> entries;
List<ScriptCodeCompletionOption> entries;
String ctext = text_editor->get_text_for_completion();
_code_complete_script(ctext, &entries);
bool forced = false;
@ -733,15 +733,16 @@ void CodeTextEditor::_complete_request() {
}
if (entries.size() == 0)
return;
Vector<String> strs;
strs.resize(entries.size());
int i = 0;
for (List<String>::Element *E = entries.front(); E; E = E->next()) {
strs.write[i++] = E->get();
Vector<String> options;
options.resize(entries.size());
size_t i = 0;
for (List<ScriptCodeCompletionOption>::Element *E = entries.front(); E; E = E->next()) {
options.write[i] = E->get().insert_text;
i++;
}
text_editor->code_complete(strs, forced);
text_editor->code_complete(options, forced);
}
void CodeTextEditor::_font_resize_timeout() {

View file

@ -131,7 +131,7 @@ public:
FindReplaceBar();
};
typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, List<String> *r_options, bool &r_forced);
typedef void (*CodeTextEditorCodeCompleteFunc)(void *p_ud, const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_forced);
class CodeTextEditor : public VBoxContainer {
@ -183,7 +183,7 @@ class CodeTextEditor : public VBoxContainer {
protected:
virtual void _load_theme_settings() {}
virtual void _validate_script() {}
virtual void _code_complete_script(const String &p_code, List<String> *r_options) {}
virtual void _code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options) {}
void _text_changed_idle_timeout();
void _code_complete_timer_timeout();

View file

@ -773,13 +773,13 @@ void ScriptEditor::_update_modified_scripts_for_external_editor(Ref<Script> p_fo
}
}
void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options, bool &r_force) {
void ScriptTextEditor::_code_complete_scripts(void *p_ud, const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force) {
ScriptTextEditor *ste = (ScriptTextEditor *)p_ud;
ste->_code_complete_script(p_code, r_options, r_force);
}
void ScriptTextEditor::_code_complete_script(const String &p_code, List<String> *r_options, bool &r_force) {
void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force) {
if (color_panel->is_visible_in_tree()) return;
Node *base = get_tree()->get_edited_scene_root();

View file

@ -143,7 +143,6 @@ class ScriptTextEditor : public ScriptEditorBase {
};
protected:
static void _code_complete_scripts(void *p_ud, const String &p_code, List<String> *r_options, bool &r_force);
void _update_breakpoint_list();
void _breakpoint_item_pressed(int p_idx);
void _breakpoint_toggled(int p_row);
@ -151,7 +150,10 @@ protected:
void _validate_script(); // No longer virtual.
void _update_bookmark_list();
void _bookmark_item_pressed(int p_idx);
void _code_complete_script(const String &p_code, List<String> *r_options, bool &r_force);
static void _code_complete_scripts(void *p_ud, const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force);
void _code_complete_script(const String &p_code, List<ScriptCodeCompletionOption> *r_options, bool &r_force);
void _load_theme_settings();
void _set_theme_for_script();
void _show_warnings_panel(bool p_show);

View file

@ -159,7 +159,7 @@ String PluginScriptLanguage::make_function(const String &p_class, const String &
return String();
}
Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint) {
Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_force, String &r_call_hint) {
if (_desc.complete_code) {
Array options;
godot_error tmp = _desc.complete_code(
@ -171,7 +171,8 @@ Error PluginScriptLanguage::complete_code(const String &p_code, const String &p_
&r_force,
(godot_string *)&r_call_hint);
for (int i = 0; i < options.size(); i++) {
r_options->push_back(String(options[i]));
ScriptCodeCompletionOption option(options[i], ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
r_options->push_back(option);
}
return (Error)tmp;
}

View file

@ -81,7 +81,7 @@ public:
virtual bool can_inherit_from_file() { return true; }
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_force, String &r_call_hint);
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_force, String &r_call_hint);
virtual void auto_indent_code(String &p_code, int p_from_line, int p_to_line) const;
virtual void add_global_constant(const StringName &p_variable, const Variant &p_value);

View file

@ -458,7 +458,7 @@ public:
virtual bool can_inherit_from_file() { return true; }
virtual int find_function(const String &p_function, const String &p_code) const;
virtual String make_function(const String &p_class, const String &p_name, const PoolStringArray &p_args) const;
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint);
virtual Error complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint);
#ifdef TOOLS_ENABLED
virtual Error lookup_code(const String &p_code, const String &p_symbol, const String &p_path, Object *p_owner, LookupResult &r_result);
#endif

View file

@ -509,12 +509,14 @@ struct GDScriptCompletionIdentifier {
assigned_expression(NULL) {}
};
static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Set<String> &r_list) {
static void _get_directory_contents(EditorFileSystemDirectory *p_dir, Map<String, ScriptCodeCompletionOption> &r_list) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
for (int i = 0; i < p_dir->get_file_count(); i++) {
r_list.insert(quote_style + p_dir->get_file_path(i) + quote_style);
ScriptCodeCompletionOption option(p_dir->get_file_path(i), ScriptCodeCompletionOption::KIND_FILE_PATH);
option.insert_text = quote_style + option.display + quote_style;
r_list.insert(option.display, option);
}
for (int i = 0; i < p_dir->get_subdir_count(); i++) {
@ -1807,14 +1809,15 @@ static String _make_arguments_hint(const GDScriptParser::FunctionNode *p_functio
return arghint;
}
static void _find_enumeration_candidates(const String p_enum_hint, Set<String> &r_result) {
static void _find_enumeration_candidates(const String p_enum_hint, Map<String, ScriptCodeCompletionOption> &r_result) {
if (p_enum_hint.find(".") == -1) {
// Global constant
StringName current_enum = p_enum_hint;
for (int i = 0; i < GlobalConstants::get_global_constant_count(); i++) {
if (GlobalConstants::get_global_constant_enum(i) == current_enum) {
r_result.insert(GlobalConstants::get_global_constant_name(i));
ScriptCodeCompletionOption option(GlobalConstants::get_global_constant_name(i), ScriptCodeCompletionOption::KIND_ENUM);
r_result.insert(option.display, option);
}
}
} else {
@ -1829,15 +1832,17 @@ static void _find_enumeration_candidates(const String p_enum_hint, Set<String> &
ClassDB::get_enum_constants(class_name, enum_name, &enum_constants);
for (List<StringName>::Element *E = enum_constants.front(); E; E = E->next()) {
String candidate = class_name + "." + E->get();
r_result.insert(candidate);
ScriptCodeCompletionOption option(candidate, ScriptCodeCompletionOption::KIND_ENUM);
r_result.insert(option.display, option);
}
}
}
static void _find_identifiers_in_block(const GDScriptCompletionContext &p_context, Set<String> &r_result) {
static void _find_identifiers_in_block(const GDScriptCompletionContext &p_context, Map<String, ScriptCodeCompletionOption> &r_result) {
for (Map<StringName, GDScriptParser::LocalVarNode *>::Element *E = p_context.block->variables.front(); E; E = E->next()) {
if (E->get()->line < p_context.line) {
r_result.insert(E->key().operator String());
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_VARIABLE);
r_result.insert(option.display, option);
}
}
if (p_context.block->parent_block) {
@ -1847,40 +1852,47 @@ static void _find_identifiers_in_block(const GDScriptCompletionContext &p_contex
}
}
static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Set<String> &r_result);
static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result);
static void _find_identifiers_in_class(const GDScriptCompletionContext &p_context, bool p_static, bool p_only_functions, bool p_parent_only, Set<String> &r_result) {
static void _find_identifiers_in_class(const GDScriptCompletionContext &p_context, bool p_static, bool p_only_functions, bool p_parent_only, Map<String, ScriptCodeCompletionOption> &r_result) {
if (!p_parent_only) {
if (!p_static && !p_only_functions) {
for (int i = 0; i < p_context._class->variables.size(); i++) {
r_result.insert(p_context._class->variables[i].identifier);
ScriptCodeCompletionOption option(p_context._class->variables[i].identifier, ScriptCodeCompletionOption::KIND_MEMBER);
r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (Map<StringName, GDScriptParser::ClassNode::Constant>::Element *E = p_context._class->constant_expressions.front(); E; E = E->next()) {
r_result.insert(E->key());
ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_CONSTANT);
r_result.insert(option.display, option);
}
for (int i = 0; i < p_context._class->subclasses.size(); i++) {
r_result.insert(p_context._class->subclasses[i]->name);
ScriptCodeCompletionOption option(p_context._class->subclasses[i]->name, ScriptCodeCompletionOption::KIND_CLASS);
r_result.insert(option.display, option);
}
}
for (int i = 0; i < p_context._class->static_functions.size(); i++) {
ScriptCodeCompletionOption option(p_context._class->static_functions[i]->name.operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (p_context._class->static_functions[i]->arguments.size()) {
r_result.insert(p_context._class->static_functions[i]->name.operator String() + "(");
option.insert_text += "(";
} else {
r_result.insert(p_context._class->static_functions[i]->name.operator String() + "()");
option.insert_text += "()";
}
r_result.insert(option.display, option);
}
if (!p_static) {
for (int i = 0; i < p_context._class->functions.size(); i++) {
ScriptCodeCompletionOption option(p_context._class->functions[i]->name.operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (p_context._class->functions[i]->arguments.size()) {
r_result.insert(p_context._class->functions[i]->name.operator String() + "(");
option.insert_text += "(";
} else {
r_result.insert(p_context._class->functions[i]->name.operator String() + "()");
option.insert_text += "()";
}
r_result.insert(option.display, option);
}
}
}
@ -1898,12 +1910,14 @@ static void _find_identifiers_in_class(const GDScriptCompletionContext &p_contex
_find_identifiers_in_base(c, base_type, p_only_functions, r_result);
}
static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Set<String> &r_result) {
static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result) {
GDScriptParser::DataType base_type = p_base.type;
bool _static = base_type.is_meta_type;
if (_static && base_type.kind != GDScriptParser::DataType::BUILTIN) {
r_result.insert("new(");
ScriptCodeCompletionOption option("new", ScriptCodeCompletionOption::KIND_FUNCTION);
option.insert_text += "(";
r_result.insert(option.display, option);
}
while (base_type.has_type) {
@ -1921,26 +1935,31 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (script.is_valid()) {
if (!_static && !p_only_functions) {
for (const Set<StringName>::Element *E = script->get_members().front(); E; E = E->next()) {
r_result.insert(E->get().operator String());
ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_MEMBER);
r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (const Map<StringName, Variant>::Element *E = script->get_constants().front(); E; E = E->next()) {
r_result.insert(E->key().operator String());
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
r_result.insert(option.display, option);
}
}
for (const Map<StringName, GDScriptFunction *>::Element *E = script->get_member_functions().front(); E; E = E->next()) {
if (!_static || E->get()->is_static()) {
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get()->get_argument_count()) {
r_result.insert(E->key().operator String() + "(");
option.insert_text += "(";
} else {
r_result.insert(E->key().operator String() + "()");
option.insert_text += "()";
}
r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
for (const Map<StringName, Ref<GDScript> >::Element *E = script->get_subclasses().front(); E; E = E->next()) {
r_result.insert(E->key().operator String());
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
r_result.insert(option.display, option);
}
}
base_type = GDScriptParser::DataType();
@ -1964,25 +1983,29 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<PropertyInfo> members;
scr->get_script_property_list(&members);
for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
r_result.insert(E->get().name);
ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
r_result.insert(option.display, option);
}
}
if (!p_only_functions) {
Map<StringName, Variant> constants;
scr->get_constants(&constants);
for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
r_result.insert(E->key().operator String());
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
r_result.insert(option.display, option);
}
}
List<MethodInfo> methods;
scr->get_script_method_list(&methods);
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
r_result.insert(E->get().name + "(");
option.insert_text += "(";
} else {
r_result.insert(E->get().name + "()");
option.insert_text += "()";
}
r_result.insert(option.display, option);
}
Ref<Script> base_script = scr->get_base_script();
@ -2009,7 +2032,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<String> constants;
ClassDB::get_integer_constant_list(type, &constants);
for (List<String>::Element *E = constants.front(); E; E = E->next()) {
r_result.insert(E->get());
ScriptCodeCompletionOption option(E->get(), ScriptCodeCompletionOption::KIND_CONSTANT);
r_result.insert(option.display, option);
}
if (!_static) {
@ -2022,7 +2046,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (E->get().name.find("/") != -1) {
continue;
}
r_result.insert(E->get().name);
ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
r_result.insert(option.display, option);
}
}
}
@ -2035,11 +2060,13 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
if (E->get().name.begins_with("_")) {
continue;
}
ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
r_result.insert(E->get().name + "(");
option.insert_text += "(";
} else {
r_result.insert(E->get().name + "()");
option.insert_text += "()";
}
r_result.insert(option.display, option);
}
}
@ -2058,7 +2085,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
for (List<PropertyInfo>::Element *E = members.front(); E; E = E->next()) {
if (String(E->get().name).find("/") == -1) {
r_result.insert(E->get().name);
ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_MEMBER);
r_result.insert(option.display, option);
}
}
}
@ -2066,11 +2094,13 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
List<MethodInfo> methods;
tmp.get_method_list(&methods);
for (List<MethodInfo>::Element *E = methods.front(); E; E = E->next()) {
ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_FUNCTION);
if (E->get().arguments.size()) {
r_result.insert(E->get().name + "(");
option.insert_text += "(";
} else {
r_result.insert(E->get().name + "()");
option.insert_text += "()";
}
r_result.insert(option.display, option);
}
return;
@ -2082,7 +2112,7 @@ static void _find_identifiers_in_base(const GDScriptCompletionContext &p_context
}
}
static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p_only_functions, Set<String> &r_result) {
static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p_only_functions, Map<String, ScriptCodeCompletionOption> &r_result) {
const GDScriptParser::BlockNode *block = p_context.block;
@ -2091,7 +2121,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
const GDScriptParser::FunctionNode *f = p_context.function;
for (int i = 0; i < f->arguments.size(); i++) {
r_result.insert(f->arguments[i].operator String());
ScriptCodeCompletionOption option(f->arguments[i].operator String(), ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
r_result.insert(option.display, option);
}
}
@ -2116,11 +2147,13 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
for (int i = 0; i < GDScriptFunctions::FUNC_MAX; i++) {
MethodInfo mi = GDScriptFunctions::get_info(GDScriptFunctions::Function(i));
ScriptCodeCompletionOption option(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))), ScriptCodeCompletionOption::KIND_FUNCTION);
if (mi.arguments.size() || (mi.flags & METHOD_FLAG_VARARG)) {
r_result.insert(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) + "(");
option.insert_text += "(";
} else {
r_result.insert(String(GDScriptFunctions::get_func_name(GDScriptFunctions::Function(i))) + "()");
option.insert_text += "()";
}
r_result.insert(option.display, option);
}
static const char *_type_names[Variant::VARIANT_MAX] = {
@ -2130,7 +2163,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
};
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
r_result.insert(_type_names[i]);
ScriptCodeCompletionOption option(_type_names[i], ScriptCodeCompletionOption::KIND_CLASS);
r_result.insert(option.display, option);
}
static const char *_keywords[] = {
@ -2144,7 +2178,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
const char **kw = _keywords;
while (*kw) {
r_result.insert(*kw);
ScriptCodeCompletionOption option(*kw, ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
r_result.insert(option.display, option);
kw++;
}
@ -2158,7 +2193,8 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
}
String path = ProjectSettings::get_singleton()->get(s);
if (path.begins_with("*")) {
r_result.insert(s.get_slice("/", 1));
ScriptCodeCompletionOption option(s.get_slice("/", 1), ScriptCodeCompletionOption::KIND_CONSTANT);
r_result.insert(option.display, option);
}
}
@ -2166,16 +2202,18 @@ static void _find_identifiers(const GDScriptCompletionContext &p_context, bool p
List<StringName> named_scripts;
ScriptServer::get_global_class_list(&named_scripts);
for (List<StringName>::Element *E = named_scripts.front(); E; E = E->next()) {
r_result.insert(E->get().operator String());
ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
r_result.insert(option.display, option);
}
// Native classes
for (const Map<StringName, int>::Element *E = GDScriptLanguage::get_singleton()->get_global_map().front(); E; E = E->next()) {
r_result.insert(E->key().operator String());
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
r_result.insert(option.display, option);
}
}
static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Set<String> &r_result, String &r_arghint) {
static void _find_call_arguments(const GDScriptCompletionContext &p_context, const GDScriptCompletionIdentifier &p_base, const StringName &p_method, int p_argidx, bool p_static, Map<String, ScriptCodeCompletionOption> &r_result, String &r_arghint) {
Variant base = p_base.value;
GDScriptParser::DataType base_type = p_base.type;
@ -2199,7 +2237,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
if ((p_method == "connect" || p_method == "emit_signal") && p_argidx == 0) {
for (int i = 0; i < base_type.class_type->_signals.size(); i++) {
r_result.insert(quote_style + base_type.class_type->_signals[i].name.operator String() + quote_style);
ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL);
option.insert_text = quote_style + option.display + quote_style;
r_result.insert(option.display, option);
}
}
@ -2212,7 +2252,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<MethodInfo> signals;
gds->get_script_signal_list(&signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
r_result.insert(quote_style + E->get().name + quote_style);
ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_SIGNAL);
option.insert_text = quote_style + option.display + quote_style;
r_result.insert(option.display, option);
}
}
Ref<GDScript> base_script = gds->get_base_script();
@ -2250,7 +2292,8 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<String> options;
obj->get_argument_options(p_method, p_argidx, &options);
for (List<String>::Element *F = options.front(); F; F = F->next()) {
r_result.insert(F->get());
ScriptCodeCompletionOption option(F->get(), ScriptCodeCompletionOption::KIND_FUNCTION);
r_result.insert(option.display, option);
}
}
}
@ -2271,7 +2314,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
List<MethodInfo> signals;
ClassDB::get_signal_list(class_name, &signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
r_result.insert(quote_style + E->get().name + quote_style);
ScriptCodeCompletionOption option(E->get().name, ScriptCodeCompletionOption::KIND_SIGNAL);
option.insert_text = quote_style + option.display + quote_style;
r_result.insert(option.display, option);
}
}
@ -2286,7 +2331,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
continue;
}
String name = s.get_slice("/", 1);
r_result.insert(quote_style + "/root/" + name + quote_style);
ScriptCodeCompletionOption option("/root/" + name, ScriptCodeCompletionOption::KIND_NODE_PATH);
option.insert_text = quote_style + option.display + quote_style;
r_result.insert(option.display, option);
}
}
@ -2300,7 +2347,9 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
continue;
}
String name = s.get_slice("/", 1);
r_result.insert(quote_style + name + quote_style);
ScriptCodeCompletionOption option(name, ScriptCodeCompletionOption::KIND_CONSTANT);
option.insert_text = quote_style + option.display + quote_style;
r_result.insert(option.display, option);
}
}
@ -2333,7 +2382,7 @@ static void _find_call_arguments(const GDScriptCompletionContext &p_context, con
}
}
static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Set<String> &r_result, bool &r_forced, String &r_arghint) {
static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDScriptParser::Node *p_node, int p_argidx, Map<String, ScriptCodeCompletionOption> &r_result, bool &r_forced, String &r_arghint) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
@ -2451,17 +2500,19 @@ static void _find_call_arguments(GDScriptCompletionContext &p_context, const GDS
_find_call_arguments(p_context, ci, function, p_argidx, _static, r_result, r_arghint);
if (function == "connect" && p_argidx == 2) {
Set<String> methods;
Map<String, ScriptCodeCompletionOption> methods;
_find_identifiers_in_base(p_context, connect_base, true, methods);
for (Set<String>::Element *E = methods.front(); E; E = E->next()) {
r_result.insert(quote_style + E->get().replace("(", "").replace(")", "") + quote_style);
for (Map<String, ScriptCodeCompletionOption>::Element *E = methods.front(); E; E = E->next()) {
ScriptCodeCompletionOption &option = E->value();
option.insert_text = quote_style + option.display + quote_style;
r_result.insert(option.display, option);
}
}
r_forced = r_result.size() > 0;
}
Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) {
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
@ -2469,7 +2520,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
parser.parse(p_code, p_path.get_base_dir(), false, p_path, true);
r_forced = false;
Set<String> options;
Map<String, ScriptCodeCompletionOption> options;
GDScriptCompletionContext context;
context._class = parser.get_completion_class();
context.block = parser.get_completion_block();
@ -2490,7 +2541,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<StringName> constants;
Variant::get_constants_for_type(parser.get_completion_built_in_constant(), &constants);
for (List<StringName>::Element *E = constants.front(); E; E = E->next()) {
options.insert(E->get().operator String());
ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CONSTANT);
options.insert(option.display, option);
}
} break;
case GDScriptParser::COMPLETION_PARENT_FUNCTION: {
@ -2515,9 +2567,11 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
r_forced = true;
String idopt = opt.unquote();
if (idopt.replace("/", "_").is_valid_identifier()) {
options.insert(idopt);
ScriptCodeCompletionOption option(idopt, ScriptCodeCompletionOption::KIND_NODE_PATH);
options.insert(option.display, option);
} else {
options.insert(opt);
ScriptCodeCompletionOption option(opt, ScriptCodeCompletionOption::KIND_NODE_PATH);
options.insert(option.display, option);
}
}
}
@ -2532,7 +2586,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
continue;
}
String name = s.get_slice("/", 1);
options.insert(quote_style + "/root/" + name + quote_style);
ScriptCodeCompletionOption option(quote_style + "/root/" + name + quote_style, ScriptCodeCompletionOption::KIND_NODE_PATH);
options.insert(option.display, option);
}
}
} break;
@ -2655,7 +2710,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
}
method_hint += ":";
options.insert(method_hint);
ScriptCodeCompletionOption option(method_hint, ScriptCodeCompletionOption::KIND_FUNCTION);
options.insert(option.display, option);
}
} break;
case GDScriptParser::COMPLETION_YIELD: {
@ -2673,7 +2729,9 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
switch (base_type.kind) {
case GDScriptParser::DataType::CLASS: {
for (int i = 0; i < base_type.class_type->_signals.size(); i++) {
options.insert(quote_style + base_type.class_type->_signals[i].name.operator String() + quote_style);
ScriptCodeCompletionOption option(base_type.class_type->_signals[i].name.operator String(), ScriptCodeCompletionOption::KIND_SIGNAL);
option.insert_text = quote_style + option.display + quote_style;
options.insert(option.display, option);
}
base_type = base_type.class_type->base_type;
} break;
@ -2684,7 +2742,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<MethodInfo> signals;
scr->get_script_signal_list(&signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
options.insert(quote_style + E->get().name + quote_style);
ScriptCodeCompletionOption option(quote_style + E->get().name + quote_style, ScriptCodeCompletionOption::KIND_SIGNAL);
options.insert(option.display, option);
}
Ref<Script> base_script = scr->get_base_script();
if (base_script.is_valid()) {
@ -2711,7 +2770,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
List<MethodInfo> signals;
ClassDB::get_signal_list(class_name, &signals);
for (List<MethodInfo>::Element *E = signals.front(); E; E = E->next()) {
options.insert(quote_style + E->get().name + quote_style);
ScriptCodeCompletionOption option(quote_style + E->get().name + quote_style, ScriptCodeCompletionOption::KIND_SIGNAL);
options.insert(option.display, option);
}
} break;
default: {
@ -2748,18 +2808,21 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
c.line = E->value().expression->line;
if (_guess_expression_type(c, E->value().expression, constant)) {
if (constant.type.has_type && constant.type.is_meta_type) {
options.insert(E->key().operator String());
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
options.insert(option.display, option);
}
}
}
for (int i = 0; i < clss->subclasses.size(); i++) {
if (clss->subclasses[i]->name != StringName()) {
options.insert(clss->subclasses[i]->name.operator String());
ScriptCodeCompletionOption option(clss->subclasses[i]->name.operator String(), ScriptCodeCompletionOption::KIND_CLASS);
options.insert(option.display, option);
}
}
clss = clss->owner;
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
options.insert(Variant::get_type_name((Variant::Type)i));
ScriptCodeCompletionOption option(Variant::get_type_name((Variant::Type)i), ScriptCodeCompletionOption::KIND_CLASS);
options.insert(option.display, option);
}
}
@ -2773,18 +2836,21 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
if (Engine::get_singleton()->has_singleton(class_name)) {
continue;
}
options.insert(class_name);
ScriptCodeCompletionOption option(class_name, ScriptCodeCompletionOption::KIND_CLASS);
options.insert(option.display, option);
}
// Named scripts
List<StringName> named_scripts;
ScriptServer::get_global_class_list(&named_scripts);
for (List<StringName>::Element *E = named_scripts.front(); E; E = E->next()) {
options.insert(E->get().operator String());
ScriptCodeCompletionOption option(E->get().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
options.insert(option.display, option);
}
if (parser.get_completion_identifier_is_function()) {
options.insert("void");
ScriptCodeCompletionOption option("void", ScriptCodeCompletionOption::KIND_PLAIN_TEXT);
options.insert(option.display, option);
}
r_forced = true;
} break;
@ -2831,13 +2897,15 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
c2.line = E->value().expression->line;
if (_guess_expression_type(c2, E->value().expression, constant)) {
if (constant.type.has_type && constant.type.is_meta_type) {
options.insert(E->key().operator String());
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
options.insert(option.display, option);
}
}
}
for (int i = 0; i < base_type.class_type->subclasses.size(); i++) {
if (base_type.class_type->subclasses[i]->name != StringName()) {
options.insert(base_type.class_type->subclasses[i]->name.operator String());
ScriptCodeCompletionOption option(base_type.class_type->subclasses[i]->name.operator String(), ScriptCodeCompletionOption::KIND_CLASS);
options.insert(option.display, option);
}
}
@ -2855,7 +2923,8 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
for (Map<StringName, Variant>::Element *E = constants.front(); E; E = E->next()) {
Ref<Script> const_scr = E->value();
if (const_scr.is_valid()) {
options.insert(E->key().operator String());
ScriptCodeCompletionOption option(E->key().operator String(), ScriptCodeCompletionOption::KIND_CLASS);
options.insert(option.display, option);
}
}
Ref<Script> base_script = scr->get_base_script();
@ -2877,7 +2946,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
} break;
}
for (Set<String>::Element *E = options.front(); E; E = E->next()) {
for (Map<String, ScriptCodeCompletionOption>::Element *E = options.front(); E; E = E->next()) {
r_options->push_back(E->get());
}
@ -2886,7 +2955,7 @@ Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path
#else
Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<String> *r_options, bool &r_forced, String &r_call_hint) {
Error GDScriptLanguage::complete_code(const String &p_code, const String &p_path, Object *p_owner, List<ScriptCodeCompletionOption> *r_options, bool &r_forced, String &r_call_hint) {
return OK;
}