1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-07 12:30:27 +00:00

Improve sorting of Code Completion options.

Done by ordering options by their location in the code - e.g. local, parent class, global, etc.
This commit is contained in:
Eric M
2022-03-09 00:03:36 +10:00
parent 74b07dd194
commit 4ab605d14d
7 changed files with 196 additions and 24 deletions

View File

@@ -311,6 +311,13 @@ public:
CODE_COMPLETION_KIND_MAX CODE_COMPLETION_KIND_MAX
}; };
enum CodeCompletionLocation {
LOCATION_LOCAL = 0,
LOCATION_PARENT_MASK = 1 << 8,
LOCATION_OTHER_USER_CODE = 1 << 9,
LOCATION_OTHER = 1 << 10,
};
struct CodeCompletionOption { struct CodeCompletionOption {
CodeCompletionKind kind = CODE_COMPLETION_KIND_PLAIN_TEXT; CodeCompletionKind kind = CODE_COMPLETION_KIND_PLAIN_TEXT;
String display; String display;
@@ -319,13 +326,15 @@ public:
RES icon; RES icon;
Variant default_value; Variant default_value;
Vector<Pair<int, int>> matches; Vector<Pair<int, int>> matches;
int location = LOCATION_OTHER;
CodeCompletionOption() {} CodeCompletionOption() {}
CodeCompletionOption(const String &p_text, CodeCompletionKind p_kind) { CodeCompletionOption(const String &p_text, CodeCompletionKind p_kind, int p_location = LOCATION_OTHER) {
display = p_text; display = p_text;
insert_text = p_text; insert_text = p_text;
kind = p_kind; kind = p_kind;
location = p_location;
} }
}; };

View File

@@ -161,6 +161,11 @@ void ScriptLanguageExtension::_bind_methods() {
BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE); BIND_ENUM_CONSTANT(LOOKUP_RESULT_CLASS_TBD_GLOBALSCOPE);
BIND_ENUM_CONSTANT(LOOKUP_RESULT_MAX); BIND_ENUM_CONSTANT(LOOKUP_RESULT_MAX);
BIND_ENUM_CONSTANT(LOCATION_LOCAL);
BIND_ENUM_CONSTANT(LOCATION_PARENT_MASK);
BIND_ENUM_CONSTANT(LOCATION_OTHER_USER_CODE);
BIND_ENUM_CONSTANT(LOCATION_OTHER);
BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_CLASS); BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_CLASS);
BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_FUNCTION); BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_FUNCTION);
BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_SIGNAL); BIND_ENUM_CONSTANT(CODE_COMPLETION_KIND_SIGNAL);

View File

@@ -387,6 +387,8 @@ public:
option.icon = op["icon"]; option.icon = op["icon"];
ERR_CONTINUE(!op.has("default_value")); ERR_CONTINUE(!op.has("default_value"));
option.default_value = op["default_value"]; option.default_value = op["default_value"];
ERR_CONTINUE(!op.has("location"));
option.location = op["location"];
if (op.has("matches")) { if (op.has("matches")) {
PackedInt32Array matches = op["matches"]; PackedInt32Array matches = op["matches"];
ERR_CONTINUE(matches.size() & 1); ERR_CONTINUE(matches.size() & 1);
@@ -639,6 +641,7 @@ public:
VARIANT_ENUM_CAST(ScriptLanguageExtension::LookupResultType) VARIANT_ENUM_CAST(ScriptLanguageExtension::LookupResultType)
VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionKind) VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionKind)
VARIANT_ENUM_CAST(ScriptLanguageExtension::CodeCompletionLocation)
class ScriptInstanceExtension : public ScriptInstance { class ScriptInstanceExtension : public ScriptInstance {
public: public:

View File

@@ -378,6 +378,18 @@
</constant> </constant>
<constant name="LOOKUP_RESULT_MAX" value="7" enum="LookupResultType"> <constant name="LOOKUP_RESULT_MAX" value="7" enum="LookupResultType">
</constant> </constant>
<constant name="LOCATION_LOCAL" value="0" enum="CodeCompletionLocation">
The option is local to the location of the code completion query - e.g. a local variable.
</constant>
<constant name="LOCATION_PARENT_MASK" value="256" enum="CodeCompletionLocation">
The option is from the containing class or a parent class, relative to the location of the code completion query. Perform a bitwise OR with the class depth (e.g. 0 for the local class, 1 for the parent, 2 for the grandparent, etc) to store the depth of an option in a the class or a parent class.
</constant>
<constant name="LOCATION_OTHER_USER_CODE" value="512" enum="CodeCompletionLocation">
The option is from user code which is not local and not in a derived class (e.g. Autoload Singletons).
</constant>
<constant name="LOCATION_OTHER" value="1024" enum="CodeCompletionLocation">
The option is from other engine code, not covered by the other enum constants - e.g. built-in classes.
</constant>
<constant name="CODE_COMPLETION_KIND_CLASS" value="0" enum="CodeCompletionKind"> <constant name="CODE_COMPLETION_KIND_CLASS" value="0" enum="CodeCompletionKind">
</constant> </constant>
<constant name="CODE_COMPLETION_KIND_FUNCTION" value="1" enum="CodeCompletionKind"> <constant name="CODE_COMPLETION_KIND_FUNCTION" value="1" enum="CodeCompletionKind">

View File

@@ -699,6 +699,9 @@ void ScriptTextEditor::_code_complete_script(const String &p_code, List<ScriptLa
} }
String hint; String hint;
Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint); Error err = script->get_language()->complete_code(p_code, script->get_path(), base, r_options, r_force, hint);
r_options->sort_custom_inplace<CodeCompletionOptionCompare>();
if (err == OK) { if (err == OK) {
code_editor->get_text_editor()->set_code_hint(hint); code_editor->get_text_editor()->set_code_hint(hint);
} }

View File

@@ -256,4 +256,51 @@ public:
~ScriptTextEditor(); ~ScriptTextEditor();
}; };
const int KIND_COUNT = 10;
// The order in which to sort code completion options.
const ScriptLanguage::CodeCompletionKind KIND_SORT_ORDER[KIND_COUNT] = {
ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE,
ScriptLanguage::CODE_COMPLETION_KIND_MEMBER,
ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION,
ScriptLanguage::CODE_COMPLETION_KIND_ENUM,
ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL,
ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT,
ScriptLanguage::CODE_COMPLETION_KIND_CLASS,
ScriptLanguage::CODE_COMPLETION_KIND_NODE_PATH,
ScriptLanguage::CODE_COMPLETION_KIND_FILE_PATH,
ScriptLanguage::CODE_COMPLETION_KIND_PLAIN_TEXT,
};
// The custom comparer which will sort completion options.
struct CodeCompletionOptionCompare {
_FORCE_INLINE_ bool operator()(const ScriptLanguage::CodeCompletionOption &l, const ScriptLanguage::CodeCompletionOption &r) const {
if (l.location == r.location) {
// If locations are same, sort on kind
if (l.kind == r.kind) {
// If kinds are same, sort alphanumeric
return l.display < r.display;
}
// Sort kinds based on the const sorting array defined above. Lower index = higher priority.
int l_index = -1;
int r_index = -1;
for (int i = 0; i < KIND_COUNT; i++) {
const ScriptLanguage::CodeCompletionKind kind = KIND_SORT_ORDER[i];
l_index = kind == l.kind ? i : l_index;
r_index = kind == r.kind ? i : r_index;
if (l_index != -1 && r_index != -1) {
return l_index < r_index;
}
}
// This return should never be hit unless something goes wrong.
// l and r should always have a Kind which is in the sort order array.
return l.display < r.display;
}
return l.location < r.location;
}
};
#endif // SCRIPT_TEXT_EDITOR_H #endif // SCRIPT_TEXT_EDITOR_H

View File

@@ -490,6 +490,89 @@ struct GDScriptCompletionIdentifier {
const GDScriptParser::ExpressionNode *assigned_expression = nullptr; const GDScriptParser::ExpressionNode *assigned_expression = nullptr;
}; };
// LOCATION METHODS
// These methods are used to populate the `CodeCompletionOption::location` integer.
// For these methods, the location is based on the depth in the inheritance chain that the property
// appears. For example, if you are completing code in a class that inherits Node2D, a property found on Node2D
// will have a "better" (lower) location "score" than a property that is found on CanvasItem.
static int _get_property_location(StringName p_class, StringName p_property) {
if (!ClassDB::has_property(p_class, p_property)) {
return ScriptLanguage::LOCATION_OTHER;
}
int depth = 0;
StringName class_test = p_class;
while (class_test && !ClassDB::has_property(class_test, p_property, true)) {
class_test = ClassDB::get_parent_class(class_test);
depth++;
}
return depth | ScriptLanguage::LOCATION_PARENT_MASK;
}
static int _get_constant_location(StringName p_class, StringName p_constant) {
if (!ClassDB::has_integer_constant(p_class, p_constant)) {
return ScriptLanguage::LOCATION_OTHER;
}
int depth = 0;
StringName class_test = p_class;
while (class_test && !ClassDB::has_integer_constant(class_test, p_constant, true)) {
class_test = ClassDB::get_parent_class(class_test);
depth++;
}
return depth | ScriptLanguage::LOCATION_PARENT_MASK;
}
static int _get_signal_location(StringName p_class, StringName p_signal) {
if (!ClassDB::has_signal(p_class, p_signal)) {
return ScriptLanguage::LOCATION_OTHER;
}
int depth = 0;
StringName class_test = p_class;
while (class_test && !ClassDB::has_signal(class_test, p_signal, true)) {
class_test = ClassDB::get_parent_class(class_test);
depth++;
}
return depth | ScriptLanguage::LOCATION_PARENT_MASK;
}
static int _get_method_location(StringName p_class, StringName p_method) {
if (!ClassDB::has_method(p_class, p_method)) {
return ScriptLanguage::LOCATION_OTHER;
}
int depth = 0;
StringName class_test = p_class;
while (class_test && !ClassDB::has_method(class_test, p_method, true)) {
class_test = ClassDB::get_parent_class(class_test);
depth++;
}
return depth | ScriptLanguage::LOCATION_PARENT_MASK;
}
static int _get_enum_constant_location(StringName p_class, StringName p_enum_constant) {
if (!ClassDB::get_integer_constant_enum(p_class, p_enum_constant)) {
return ScriptLanguage::LOCATION_OTHER;
}
int depth = 0;
StringName class_test = p_class;
while (class_test && !ClassDB::get_integer_constant_enum(class_test, p_enum_constant, true)) {
class_test = ClassDB::get_parent_class(class_test);
depth++;
}
return depth | ScriptLanguage::LOCATION_PARENT_MASK;
}
// END LOCATION METHODS
static String _get_visual_datatype(const PropertyInfo &p_info, bool p_is_arg = true) { static String _get_visual_datatype(const PropertyInfo &p_info, bool p_is_arg = true) {
if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) { if (p_info.usage & PROPERTY_USAGE_CLASS_IS_ENUM) {
String enum_name = p_info.class_name; String enum_name = p_info.class_name;
@@ -726,18 +809,18 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
const GDScriptParser::ClassNode::Member &member = current->members[i]; const GDScriptParser::ClassNode::Member &member = current->members[i];
switch (member.type) { switch (member.type) {
case GDScriptParser::ClassNode::Member::CLASS: { case GDScriptParser::ClassNode::Member::CLASS: {
ScriptLanguage::CodeCompletionOption option(member.m_class->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS); ScriptLanguage::CodeCompletionOption option(member.m_class->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_LOCAL);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} break; } break;
case GDScriptParser::ClassNode::Member::ENUM: { case GDScriptParser::ClassNode::Member::ENUM: {
if (!p_inherit_only) { if (!p_inherit_only) {
ScriptLanguage::CodeCompletionOption option(member.m_enum->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_ENUM); ScriptLanguage::CodeCompletionOption option(member.m_enum->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_ENUM, ScriptLanguage::LOCATION_LOCAL);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} break; } break;
case GDScriptParser::ClassNode::Member::CONSTANT: { case GDScriptParser::ClassNode::Member::CONSTANT: {
if (member.constant->get_datatype().is_meta_type && p_context.current_class->outer != nullptr) { if (member.constant->get_datatype().is_meta_type && p_context.current_class->outer != nullptr) {
ScriptLanguage::CodeCompletionOption option(member.constant->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS); ScriptLanguage::CodeCompletionOption option(member.constant->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_LOCAL);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} break; } break;
@@ -753,7 +836,7 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
List<StringName> global_classes; List<StringName> global_classes;
ScriptServer::get_global_class_list(&global_classes); ScriptServer::get_global_class_list(&global_classes);
for (const StringName &E : global_classes) { for (const StringName &E : global_classes) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS); ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
@@ -764,7 +847,7 @@ static void _list_available_types(bool p_inherit_only, GDScriptParser::Completio
if (!info.is_singleton || info.path.get_extension().to_lower() != "gd") { if (!info.is_singleton || info.path.get_extension().to_lower() != "gd") {
continue; continue;
} }
ScriptLanguage::CodeCompletionOption option(info.name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS); ScriptLanguage::CodeCompletionOption option(info.name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, ScriptLanguage::LOCATION_OTHER_USER_CODE);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} }
@@ -773,10 +856,10 @@ static void _find_identifiers_in_suite(const GDScriptParser::SuiteNode *p_suite,
for (int i = 0; i < p_suite->locals.size(); i++) { for (int i = 0; i < p_suite->locals.size(); i++) {
ScriptLanguage::CodeCompletionOption option; ScriptLanguage::CodeCompletionOption option;
if (p_suite->locals[i].type == GDScriptParser::SuiteNode::Local::CONSTANT) { if (p_suite->locals[i].type == GDScriptParser::SuiteNode::Local::CONSTANT) {
option = ScriptLanguage::CodeCompletionOption(p_suite->locals[i].name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); option = ScriptLanguage::CodeCompletionOption(p_suite->locals[i].name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, ScriptLanguage::LOCATION_LOCAL);
option.default_value = p_suite->locals[i].constant->initializer->reduced_value; option.default_value = p_suite->locals[i].constant->initializer->reduced_value;
} else { } else {
option = ScriptLanguage::CodeCompletionOption(p_suite->locals[i].name, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE); option = ScriptLanguage::CodeCompletionOption(p_suite->locals[i].name, ScriptLanguage::CODE_COMPLETION_KIND_VARIABLE, ScriptLanguage::LOCATION_LOCAL);
} }
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
@@ -793,8 +876,10 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (!p_parent_only) { if (!p_parent_only) {
bool outer = false; bool outer = false;
const GDScriptParser::ClassNode *clss = p_class; const GDScriptParser::ClassNode *clss = p_class;
int classes_processed = 0;
while (clss) { while (clss) {
for (int i = 0; i < clss->members.size(); i++) { for (int i = 0; i < clss->members.size(); i++) {
const int location = (classes_processed + p_recursion_depth) | ScriptLanguage::LOCATION_PARENT_MASK;
const GDScriptParser::ClassNode::Member &member = clss->members[i]; const GDScriptParser::ClassNode::Member &member = clss->members[i];
ScriptLanguage::CodeCompletionOption option; ScriptLanguage::CodeCompletionOption option;
switch (member.type) { switch (member.type) {
@@ -802,7 +887,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (p_only_functions || outer || (p_static)) { if (p_only_functions || outer || (p_static)) {
continue; continue;
} }
option = ScriptLanguage::CodeCompletionOption(member.variable->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER); option = ScriptLanguage::CodeCompletionOption(member.variable->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location);
break; break;
case GDScriptParser::ClassNode::Member::CONSTANT: case GDScriptParser::ClassNode::Member::CONSTANT:
if (p_only_functions) { if (p_only_functions) {
@@ -811,7 +896,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (r_result.has(member.constant->identifier->name)) { if (r_result.has(member.constant->identifier->name)) {
continue; continue;
} }
option = ScriptLanguage::CodeCompletionOption(member.constant->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); option = ScriptLanguage::CodeCompletionOption(member.constant->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, location);
if (member.constant->initializer) { if (member.constant->initializer) {
option.default_value = member.constant->initializer->reduced_value; option.default_value = member.constant->initializer->reduced_value;
} }
@@ -820,25 +905,25 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (p_only_functions) { if (p_only_functions) {
continue; continue;
} }
option = ScriptLanguage::CodeCompletionOption(member.m_class->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS); option = ScriptLanguage::CodeCompletionOption(member.m_class->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CLASS, location);
break; break;
case GDScriptParser::ClassNode::Member::ENUM_VALUE: case GDScriptParser::ClassNode::Member::ENUM_VALUE:
if (p_only_functions) { if (p_only_functions) {
continue; continue;
} }
option = ScriptLanguage::CodeCompletionOption(member.enum_value.identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); option = ScriptLanguage::CodeCompletionOption(member.enum_value.identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, location);
break; break;
case GDScriptParser::ClassNode::Member::ENUM: case GDScriptParser::ClassNode::Member::ENUM:
if (p_only_functions) { if (p_only_functions) {
continue; continue;
} }
option = ScriptLanguage::CodeCompletionOption(member.m_enum->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_ENUM); option = ScriptLanguage::CodeCompletionOption(member.m_enum->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_ENUM, location);
break; break;
case GDScriptParser::ClassNode::Member::FUNCTION: case GDScriptParser::ClassNode::Member::FUNCTION:
if (outer || (p_static && !member.function->is_static) || member.function->identifier->name.operator String().begins_with("@")) { if (outer || (p_static && !member.function->is_static) || member.function->identifier->name.operator String().begins_with("@")) {
continue; continue;
} }
option = ScriptLanguage::CodeCompletionOption(member.function->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); option = ScriptLanguage::CodeCompletionOption(member.function->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (member.function->parameters.size() > 0) { if (member.function->parameters.size() > 0) {
option.insert_text += "("; option.insert_text += "(";
} else { } else {
@@ -849,7 +934,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
if (p_only_functions || outer) { if (p_only_functions || outer) {
continue; continue;
} }
option = ScriptLanguage::CodeCompletionOption(member.signal->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL); option = ScriptLanguage::CodeCompletionOption(member.signal->identifier->name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL, location);
break; break;
case GDScriptParser::ClassNode::Member::UNDEFINED: case GDScriptParser::ClassNode::Member::UNDEFINED:
break; break;
@@ -858,6 +943,7 @@ static void _find_identifiers_in_class(const GDScriptParser::ClassNode *p_class,
} }
outer = true; outer = true;
clss = clss->outer; clss = clss->outer;
classes_processed++;
} }
} }
@@ -896,21 +982,24 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
List<PropertyInfo> members; List<PropertyInfo> members;
scr->get_script_property_list(&members); scr->get_script_property_list(&members);
for (const PropertyInfo &E : members) { for (const PropertyInfo &E : members) {
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER); int location = p_recursion_depth + _get_property_location(scr->get_class_name(), E.class_name);
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} }
Map<StringName, Variant> constants; Map<StringName, Variant> constants;
scr->get_constants(&constants); scr->get_constants(&constants);
for (const KeyValue<StringName, Variant> &E : constants) { for (const KeyValue<StringName, Variant> &E : constants) {
ScriptLanguage::CodeCompletionOption option(E.key.operator String(), ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); int location = p_recursion_depth + _get_constant_location(scr->get_class_name(), E.key);
ScriptLanguage::CodeCompletionOption option(E.key.operator String(), ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, location);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
List<MethodInfo> signals; List<MethodInfo> signals;
scr->get_script_signal_list(&signals); scr->get_script_signal_list(&signals);
for (const MethodInfo &E : signals) { for (const MethodInfo &E : signals) {
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL); int location = p_recursion_depth + _get_signal_location(scr->get_class_name(), E.name);
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_SIGNAL, location);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} }
@@ -921,7 +1010,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
if (E.name.begins_with("@")) { if (E.name.begins_with("@")) {
continue; continue;
} }
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); int location = p_recursion_depth + _get_method_location(scr->get_class_name(), E.name);
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (E.arguments.size()) { if (E.arguments.size()) {
option.insert_text += "("; option.insert_text += "(";
} else { } else {
@@ -951,7 +1041,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
List<String> constants; List<String> constants;
ClassDB::get_integer_constant_list(type, &constants); ClassDB::get_integer_constant_list(type, &constants);
for (const String &E : constants) { for (const String &E : constants) {
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT); int location = p_recursion_depth + _get_constant_location(type, StringName(E));
ScriptLanguage::CodeCompletionOption option(E, ScriptLanguage::CODE_COMPLETION_KIND_CONSTANT, location);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
@@ -965,7 +1056,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
if (E.name.contains("/")) { if (E.name.contains("/")) {
continue; continue;
} }
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER); int location = p_recursion_depth + _get_property_location(type, E.class_name);
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_MEMBER, location);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} }
@@ -978,7 +1070,8 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
if (E.name.begins_with("_")) { if (E.name.begins_with("_")) {
continue; continue;
} }
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION); int location = p_recursion_depth + _get_method_location(type, E.name);
ScriptLanguage::CodeCompletionOption option(E.name, ScriptLanguage::CODE_COMPLETION_KIND_FUNCTION, location);
if (E.arguments.size()) { if (E.arguments.size()) {
option.insert_text += "("; option.insert_text += "(";
} else { } else {
@@ -987,7 +1080,6 @@ static void _find_identifiers_in_base(const GDScriptCompletionIdentifier &p_base
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} }
return; return;
} break; } break;
case GDScriptParser::DataType::BUILTIN: { case GDScriptParser::DataType::BUILTIN: {
@@ -2247,7 +2339,8 @@ static void _find_enumeration_candidates(GDScriptParser::CompletionContext &p_co
ClassDB::get_enum_constants(class_name, enum_name, &enum_constants); ClassDB::get_enum_constants(class_name, enum_name, &enum_constants);
for (const StringName &E : enum_constants) { for (const StringName &E : enum_constants) {
String candidate = class_name + "." + E; String candidate = class_name + "." + E;
ScriptLanguage::CodeCompletionOption option(candidate, ScriptLanguage::CODE_COMPLETION_KIND_ENUM); int location = _get_enum_constant_location(class_name, E);
ScriptLanguage::CodeCompletionOption option(candidate, ScriptLanguage::CODE_COMPLETION_KIND_ENUM, location);
r_result.insert(option.display, option); r_result.insert(option.display, option);
} }
} }