Merge pull request #87278 from HolonProduction/give-those-autoloads-an-upgrade

Handle GDScript in `_type_from_variant` for autocompletion
This commit is contained in:
Yuri Sizov 2024-01-17 18:53:25 +01:00
commit dc729f1614

View file

@ -1370,7 +1370,7 @@ static void _find_identifiers(const GDScriptParser::CompletionContext &p_context
} }
} }
static GDScriptCompletionIdentifier _type_from_variant(const Variant &p_value) { static GDScriptCompletionIdentifier _type_from_variant(const Variant &p_value, GDScriptParser::CompletionContext &p_context) {
GDScriptCompletionIdentifier ci; GDScriptCompletionIdentifier ci;
ci.value = p_value; ci.value = p_value;
ci.type.is_constant = true; ci.type.is_constant = true;
@ -1392,8 +1392,22 @@ static GDScriptCompletionIdentifier _type_from_variant(const Variant &p_value) {
scr = obj->get_script(); scr = obj->get_script();
} }
if (scr.is_valid()) { if (scr.is_valid()) {
ci.type.script_type = scr; ci.type.script_path = scr->get_path();
if (scr->get_path().ends_with(".gd")) {
Error err;
Ref<GDScriptParserRef> parser = GDScriptCache::get_parser(scr->get_path(), GDScriptParserRef::INTERFACE_SOLVED, err);
if (err == OK) {
ci.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
ci.type.class_type = parser->get_parser()->get_tree();
ci.type.kind = GDScriptParser::DataType::CLASS;
p_context.dependent_parsers.push_back(parser);
return ci;
}
}
ci.type.kind = GDScriptParser::DataType::SCRIPT; ci.type.kind = GDScriptParser::DataType::SCRIPT;
ci.type.script_type = scr;
ci.type.native_type = scr->get_instance_base_type(); ci.type.native_type = scr->get_instance_base_type();
} else { } else {
ci.type.kind = GDScriptParser::DataType::NATIVE; ci.type.kind = GDScriptParser::DataType::NATIVE;
@ -1481,7 +1495,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
if (p_expression->is_constant) { if (p_expression->is_constant) {
// Already has a value, so just use that. // Already has a value, so just use that.
r_type = _type_from_variant(p_expression->reduced_value); r_type = _type_from_variant(p_expression->reduced_value, p_context);
switch (p_expression->get_datatype().kind) { switch (p_expression->get_datatype().kind) {
case GDScriptParser::DataType::ENUM: case GDScriptParser::DataType::ENUM:
case GDScriptParser::DataType::CLASS: case GDScriptParser::DataType::CLASS:
@ -1495,7 +1509,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
switch (p_expression->type) { switch (p_expression->type) {
case GDScriptParser::Node::LITERAL: { case GDScriptParser::Node::LITERAL: {
const GDScriptParser::LiteralNode *literal = static_cast<const GDScriptParser::LiteralNode *>(p_expression); const GDScriptParser::LiteralNode *literal = static_cast<const GDScriptParser::LiteralNode *>(p_expression);
r_type = _type_from_variant(literal->value); r_type = _type_from_variant(literal->value, p_context);
found = true; found = true;
} break; } break;
case GDScriptParser::Node::SELF: { case GDScriptParser::Node::SELF: {
@ -1676,7 +1690,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
if (!which.is_empty()) { if (!which.is_empty()) {
// Try singletons first // Try singletons first
if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(which)) { if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(which)) {
r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[which]); r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[which], p_context);
found = true; found = true;
} else { } else {
for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) { for (const KeyValue<StringName, ProjectSettings::AutoloadInfo> &E : ProjectSettings::get_singleton()->get_autoload_list()) {
@ -1727,7 +1741,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
if (ce.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) { if (ce.error == Callable::CallError::CALL_OK && ret.get_type() != Variant::NIL) {
if (ret.get_type() != Variant::OBJECT || ret.operator Object *() != nullptr) { if (ret.get_type() != Variant::OBJECT || ret.operator Object *() != nullptr) {
r_type = _type_from_variant(ret); r_type = _type_from_variant(ret, p_context);
found = true; found = true;
} }
} }
@ -1755,7 +1769,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
if (base.value.get_type() == Variant::DICTIONARY && base.value.operator Dictionary().has(String(subscript->attribute->name))) { if (base.value.get_type() == Variant::DICTIONARY && base.value.operator Dictionary().has(String(subscript->attribute->name))) {
Variant value = base.value.operator Dictionary()[String(subscript->attribute->name)]; Variant value = base.value.operator Dictionary()[String(subscript->attribute->name)];
r_type = _type_from_variant(value); r_type = _type_from_variant(value, p_context);
found = true; found = true;
break; break;
} }
@ -1807,7 +1821,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
if (base.value.in(index.value)) { if (base.value.in(index.value)) {
Variant value = base.value.get(index.value); Variant value = base.value.get(index.value);
r_type = _type_from_variant(value); r_type = _type_from_variant(value, p_context);
found = true; found = true;
break; break;
} }
@ -1862,7 +1876,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
bool valid = false; bool valid = false;
Variant res = base_val.get(index.value, &valid); Variant res = base_val.get(index.value, &valid);
if (valid) { if (valid) {
r_type = _type_from_variant(res); r_type = _type_from_variant(res, p_context);
r_type.value = Variant(); r_type.value = Variant();
r_type.type.is_constant = false; r_type.type.is_constant = false;
found = true; found = true;
@ -1920,7 +1934,7 @@ static bool _guess_expression_type(GDScriptParser::CompletionContext &p_context,
found = false; found = false;
break; break;
} }
r_type = _type_from_variant(res); r_type = _type_from_variant(res, p_context);
if (!v1_use_value || !v2_use_value) { if (!v1_use_value || !v2_use_value) {
r_type.value = Variant(); r_type.value = Variant();
r_type.type.is_constant = false; r_type.type.is_constant = false;
@ -2155,7 +2169,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
} else { } else {
Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(p_identifier->name)); Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(p_identifier->name));
if (scr.is_valid()) { if (scr.is_valid()) {
r_type = _type_from_variant(scr); r_type = _type_from_variant(scr, p_context);
r_type.type.is_meta_type = true; r_type.type.is_meta_type = true;
return true; return true;
} }
@ -2165,7 +2179,7 @@ static bool _guess_identifier_type(GDScriptParser::CompletionContext &p_context,
// Check global variables (including autoloads). // Check global variables (including autoloads).
if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(p_identifier->name)) { if (GDScriptLanguage::get_singleton()->get_named_globals_map().has(p_identifier->name)) {
r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[p_identifier->name]); r_type = _type_from_variant(GDScriptLanguage::get_singleton()->get_named_globals_map()[p_identifier->name], p_context);
return true; return true;
} }
@ -2218,7 +2232,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
const GDScriptParser::ExpressionNode *init = member.variable->initializer; const GDScriptParser::ExpressionNode *init = member.variable->initializer;
if (init->is_constant) { if (init->is_constant) {
r_type.value = init->reduced_value; r_type.value = init->reduced_value;
r_type = _type_from_variant(init->reduced_value); r_type = _type_from_variant(init->reduced_value, p_context);
return true; return true;
} else if (init->start_line == p_context.current_line) { } else if (init->start_line == p_context.current_line) {
return false; return false;
@ -2245,7 +2259,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
r_type.enumeration = member.m_enum->identifier->name; r_type.enumeration = member.m_enum->identifier->name;
return true; return true;
case GDScriptParser::ClassNode::Member::ENUM_VALUE: case GDScriptParser::ClassNode::Member::ENUM_VALUE:
r_type = _type_from_variant(member.enum_value.value); r_type = _type_from_variant(member.enum_value.value, p_context);
return true; return true;
case GDScriptParser::ClassNode::Member::SIGNAL: case GDScriptParser::ClassNode::Member::SIGNAL:
r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; r_type.type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
@ -2281,7 +2295,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
HashMap<StringName, Variant> constants; HashMap<StringName, Variant> constants;
scr->get_constants(&constants); scr->get_constants(&constants);
if (constants.has(p_identifier)) { if (constants.has(p_identifier)) {
r_type = _type_from_variant(constants[p_identifier]); r_type = _type_from_variant(constants[p_identifier], p_context);
return true; return true;
} }
@ -2345,7 +2359,7 @@ static bool _guess_identifier_type_from_base(GDScriptParser::CompletionContext &
bool valid = false; bool valid = false;
Variant res = tmp.get(p_identifier, &valid); Variant res = tmp.get(p_identifier, &valid);
if (valid) { if (valid) {
r_type = _type_from_variant(res); r_type = _type_from_variant(res, p_context);
r_type.value = Variant(); r_type.value = Variant();
r_type.type.is_constant = false; r_type.type.is_constant = false;
return true; return true;