mirror of https://github.com/godotengine/godot
GDScript: Fix error when using a string literal suffix in subscript of class
This commit is contained in:
parent
b0655dc86f
commit
4a0bad8da6
|
|
@ -4728,7 +4728,28 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
|
||||||
if (p_subscript->attribute == nullptr) {
|
if (p_subscript->attribute == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (p_subscript->index != nullptr) {
|
||||||
|
reduce_expression(p_subscript->index);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_attribute_like = false;
|
||||||
|
GDScriptParser::IdentifierNode *attribute = nullptr;
|
||||||
|
if (p_subscript->is_attribute) {
|
||||||
|
is_attribute_like = true;
|
||||||
|
attribute = p_subscript->attribute;
|
||||||
|
} else if (p_subscript->index && p_subscript->index->is_constant && (p_subscript->index->reduced_value.get_type() == Variant::STRING || p_subscript->index->reduced_value.get_type() == Variant::STRING_NAME)) {
|
||||||
|
is_attribute_like = true;
|
||||||
|
attribute = parser->alloc_node<GDScriptParser::IdentifierNode>();
|
||||||
|
parser->reset_extents(attribute, p_subscript->index);
|
||||||
|
parser->complete_extents(attribute);
|
||||||
|
attribute->name = p_subscript->index->reduced_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_attribute_like) {
|
||||||
GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
|
GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
||||||
|
|
@ -4743,23 +4764,23 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
|
||||||
// Makes a metatype from a constant GDScript, since `base_type` is not a metatype.
|
// Makes a metatype from a constant GDScript, since `base_type` is not a metatype.
|
||||||
GDScriptParser::DataType base_type_meta = type_from_variant(gdscript, p_subscript);
|
GDScriptParser::DataType base_type_meta = type_from_variant(gdscript, p_subscript);
|
||||||
// First try to reduce the attribute from the metatype.
|
// First try to reduce the attribute from the metatype.
|
||||||
reduce_identifier_from_base(p_subscript->attribute, &base_type_meta);
|
reduce_identifier_from_base(attribute, &base_type_meta);
|
||||||
GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
|
GDScriptParser::DataType attr_type = attribute->get_datatype();
|
||||||
if (attr_type.is_set()) {
|
if (attr_type.is_set()) {
|
||||||
valid = !attr_type.is_pseudo_type || p_can_be_pseudo_type;
|
valid = !attr_type.is_pseudo_type || p_can_be_pseudo_type;
|
||||||
result_type = attr_type;
|
result_type = attr_type;
|
||||||
p_subscript->is_constant = p_subscript->attribute->is_constant;
|
p_subscript->is_constant = attribute->is_constant;
|
||||||
p_subscript->reduced_value = p_subscript->attribute->reduced_value;
|
p_subscript->reduced_value = attribute->reduced_value;
|
||||||
}
|
}
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
// If unsuccessful, reset and return to the normal route.
|
// If unsuccessful, reset and return to the normal route.
|
||||||
p_subscript->attribute->set_datatype(GDScriptParser::DataType());
|
attribute->set_datatype(GDScriptParser::DataType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!base_is_gdscript) {
|
if (!base_is_gdscript) {
|
||||||
// Just try to get it.
|
// Just try to get it.
|
||||||
Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid);
|
Variant value = p_subscript->base->reduced_value.get_named(attribute->name, valid);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
p_subscript->is_constant = true;
|
p_subscript->is_constant = true;
|
||||||
p_subscript->reduced_value = value;
|
p_subscript->reduced_value = value;
|
||||||
|
|
@ -4777,7 +4798,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
|
||||||
// Special case: it may be a global enum with pseudo base (e.g. Variant.Type).
|
// Special case: it may be a global enum with pseudo base (e.g. Variant.Type).
|
||||||
String enum_name;
|
String enum_name;
|
||||||
if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
|
if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
|
||||||
enum_name = String(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base)->name) + ENUM_SEPARATOR + String(p_subscript->attribute->name);
|
enum_name = String(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base)->name) + ENUM_SEPARATOR + String(attribute->name);
|
||||||
}
|
}
|
||||||
if (CoreConstants::is_global_enum(enum_name)) {
|
if (CoreConstants::is_global_enum(enum_name)) {
|
||||||
result_type = make_global_enum_type(enum_name, StringName());
|
result_type = make_global_enum_type(enum_name, StringName());
|
||||||
|
|
@ -4789,8 +4810,8 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
|
||||||
mark_node_unsafe(p_subscript);
|
mark_node_unsafe(p_subscript);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reduce_identifier_from_base(p_subscript->attribute, &base_type);
|
reduce_identifier_from_base(attribute, &base_type);
|
||||||
GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
|
GDScriptParser::DataType attr_type = attribute->get_datatype();
|
||||||
if (attr_type.is_set()) {
|
if (attr_type.is_set()) {
|
||||||
if (base_type.builtin_type == Variant::DICTIONARY && base_type.has_container_element_types()) {
|
if (base_type.builtin_type == Variant::DICTIONARY && base_type.has_container_element_types()) {
|
||||||
Variant::Type key_type = base_type.get_container_element_type_or_variant(0).builtin_type;
|
Variant::Type key_type = base_type.get_container_element_type_or_variant(0).builtin_type;
|
||||||
|
|
@ -4806,14 +4827,14 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
|
||||||
} else {
|
} else {
|
||||||
valid = !attr_type.is_pseudo_type || p_can_be_pseudo_type;
|
valid = !attr_type.is_pseudo_type || p_can_be_pseudo_type;
|
||||||
result_type = attr_type;
|
result_type = attr_type;
|
||||||
p_subscript->is_constant = p_subscript->attribute->is_constant;
|
p_subscript->is_constant = attribute->is_constant;
|
||||||
p_subscript->reduced_value = p_subscript->attribute->reduced_value;
|
p_subscript->reduced_value = attribute->reduced_value;
|
||||||
}
|
}
|
||||||
} else if (!base_type.is_meta_type || !base_type.is_constant) {
|
} else if (!base_type.is_meta_type || !base_type.is_constant) {
|
||||||
valid = base_type.kind != GDScriptParser::DataType::BUILTIN;
|
valid = base_type.kind != GDScriptParser::DataType::BUILTIN;
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
if (valid) {
|
if (valid) {
|
||||||
parser->push_warning(p_subscript, GDScriptWarning::UNSAFE_PROPERTY_ACCESS, p_subscript->attribute->name, base_type.to_string());
|
parser->push_warning(p_subscript, GDScriptWarning::UNSAFE_PROPERTY_ACCESS, attribute->name, base_type.to_string());
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
result_type.kind = GDScriptParser::DataType::VARIANT;
|
result_type.kind = GDScriptParser::DataType::VARIANT;
|
||||||
|
|
@ -4822,20 +4843,15 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
|
GDScriptParser::DataType attr_type = attribute->get_datatype();
|
||||||
if (!p_can_be_pseudo_type && (attr_type.is_pseudo_type || result_type.is_pseudo_type)) {
|
if (!p_can_be_pseudo_type && (attr_type.is_pseudo_type || result_type.is_pseudo_type)) {
|
||||||
push_error(vformat(R"(Type "%s" in base "%s" cannot be used on its own.)", p_subscript->attribute->name, type_from_metatype(base_type).to_string()), p_subscript->attribute);
|
push_error(vformat(R"(Type "%s" in base "%s" cannot be used on its own.)", attribute->name, type_from_metatype(base_type).to_string()), attribute);
|
||||||
} else {
|
} else {
|
||||||
push_error(vformat(R"(Cannot find member "%s" in base "%s".)", p_subscript->attribute->name, type_from_metatype(base_type).to_string()), p_subscript->attribute);
|
push_error(vformat(R"(Cannot find member "%s" in base "%s".)", attribute->name, type_from_metatype(base_type).to_string()), attribute);
|
||||||
}
|
}
|
||||||
result_type.kind = GDScriptParser::DataType::VARIANT;
|
result_type.kind = GDScriptParser::DataType::VARIANT;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (p_subscript->index == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
reduce_expression(p_subscript->index);
|
|
||||||
|
|
||||||
if (p_subscript->base->is_constant && p_subscript->index->is_constant) {
|
if (p_subscript->base->is_constant && p_subscript->index->is_constant) {
|
||||||
// Just try to get it.
|
// Just try to get it.
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
class MyClass:
|
||||||
|
static func my_static() -> void:
|
||||||
|
print("success")
|
||||||
|
|
||||||
|
func test():
|
||||||
|
print(MyClass["my_static"])
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
GDTEST_OK
|
||||||
|
GDScript::my_static
|
||||||
Loading…
Reference in New Issue