Merge pull request #79510 from dalexeev/gds-fix-const-non-metatype-subscript
GDScript: Fix subscript resolution for constant non-metatypes
This commit is contained in:
commit
971f678442
5 changed files with 193 additions and 17 deletions
|
@ -4099,7 +4099,7 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
|
||||||
GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
|
GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
|
||||||
bool valid = false;
|
bool valid = false;
|
||||||
// If the base is a metatype, use the analyzer instead.
|
// If the base is a metatype, use the analyzer instead.
|
||||||
if (p_subscript->base->is_constant && !base_type.is_meta_type) {
|
if (p_subscript->base->is_constant && !base_type.is_meta_type && base_type.kind != GDScriptParser::DataType::CLASS) {
|
||||||
// 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(p_subscript->attribute->name, valid);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
|
|
|
@ -4095,25 +4095,29 @@ bool GDScriptParser::export_annotations(const AnnotationNode *p_annotation, Node
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
case GDScriptParser::DataType::ENUM: {
|
case GDScriptParser::DataType::ENUM: {
|
||||||
variable->export_info.type = Variant::INT;
|
if (export_type.is_meta_type) {
|
||||||
variable->export_info.hint = PROPERTY_HINT_ENUM;
|
variable->export_info.type = Variant::DICTIONARY;
|
||||||
|
} else {
|
||||||
|
variable->export_info.type = Variant::INT;
|
||||||
|
variable->export_info.hint = PROPERTY_HINT_ENUM;
|
||||||
|
|
||||||
String enum_hint_string;
|
String enum_hint_string;
|
||||||
bool first = true;
|
bool first = true;
|
||||||
for (const KeyValue<StringName, int64_t> &E : export_type.enum_values) {
|
for (const KeyValue<StringName, int64_t> &E : export_type.enum_values) {
|
||||||
if (!first) {
|
if (!first) {
|
||||||
enum_hint_string += ",";
|
enum_hint_string += ",";
|
||||||
} else {
|
} else {
|
||||||
first = false;
|
first = false;
|
||||||
|
}
|
||||||
|
enum_hint_string += E.key.operator String().capitalize().xml_escape();
|
||||||
|
enum_hint_string += ":";
|
||||||
|
enum_hint_string += String::num_int64(E.value).xml_escape();
|
||||||
}
|
}
|
||||||
enum_hint_string += E.key.operator String().capitalize().xml_escape();
|
|
||||||
enum_hint_string += ":";
|
|
||||||
enum_hint_string += String::num_int64(E.value).xml_escape();
|
|
||||||
}
|
|
||||||
|
|
||||||
variable->export_info.hint_string = enum_hint_string;
|
variable->export_info.hint_string = enum_hint_string;
|
||||||
variable->export_info.usage |= PROPERTY_USAGE_CLASS_IS_ENUM;
|
variable->export_info.usage |= PROPERTY_USAGE_CLASS_IS_ENUM;
|
||||||
variable->export_info.class_name = String(export_type.native_type).replace("::", ".");
|
variable->export_info.class_name = String(export_type.native_type).replace("::", ".");
|
||||||
|
}
|
||||||
} break;
|
} break;
|
||||||
default:
|
default:
|
||||||
push_error(R"(Export type can only be built-in, a resource, a node, or an enum.)", variable);
|
push_error(R"(Export type can only be built-in, a resource, a node, or an enum.)", variable);
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
class_name TestExportEnumAsDictionary
|
||||||
|
|
||||||
|
enum MyEnum {A, B, C}
|
||||||
|
|
||||||
|
const Utils = preload("../../utils.notest.gd")
|
||||||
|
|
||||||
|
@export var x1 = MyEnum
|
||||||
|
@export var x2 = MyEnum.A
|
||||||
|
@export var x3 := MyEnum
|
||||||
|
@export var x4 := MyEnum.A
|
||||||
|
@export var x5: MyEnum
|
||||||
|
|
||||||
|
func test():
|
||||||
|
for property in get_property_list():
|
||||||
|
if property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE:
|
||||||
|
print(Utils.get_property_signature(property))
|
||||||
|
print(" ", Utils.get_property_additional_info(property))
|
|
@ -0,0 +1,11 @@
|
||||||
|
GDTEST_OK
|
||||||
|
@export var x1: Dictionary
|
||||||
|
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
|
||||||
|
@export var x2: TestExportEnumAsDictionary.MyEnum
|
||||||
|
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
|
||||||
|
@export var x3: Dictionary
|
||||||
|
hint=NONE hint_string="" usage=DEFAULT|SCRIPT_VARIABLE
|
||||||
|
@export var x4: TestExportEnumAsDictionary.MyEnum
|
||||||
|
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
|
||||||
|
@export var x5: TestExportEnumAsDictionary.MyEnum
|
||||||
|
hint=ENUM hint_string="A:0,B:1,C:2" usage=DEFAULT|SCRIPT_VARIABLE|CLASS_IS_ENUM
|
|
@ -19,6 +19,7 @@ static func get_type(property: Dictionary, is_return: bool = false) -> String:
|
||||||
return property.class_name
|
return property.class_name
|
||||||
return variant_get_type_name(property.type)
|
return variant_get_type_name(property.type)
|
||||||
|
|
||||||
|
|
||||||
static func get_property_signature(property: Dictionary, is_static: bool = false) -> String:
|
static func get_property_signature(property: Dictionary, is_static: bool = false) -> String:
|
||||||
var result: String = ""
|
var result: String = ""
|
||||||
if not (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE):
|
if not (property.usage & PROPERTY_USAGE_SCRIPT_VARIABLE):
|
||||||
|
@ -30,6 +31,15 @@ static func get_property_signature(property: Dictionary, is_static: bool = false
|
||||||
result += "var " + property.name + ": " + get_type(property)
|
result += "var " + property.name + ": " + get_type(property)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
static func get_property_additional_info(property: Dictionary) -> String:
|
||||||
|
return 'hint=%s hint_string="%s" usage=%s' % [
|
||||||
|
get_property_hint_name(property.hint).trim_prefix("PROPERTY_HINT_"),
|
||||||
|
str(property.hint_string).c_escape(),
|
||||||
|
get_property_usage_string(property.usage).replace("PROPERTY_USAGE_", ""),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
static func get_method_signature(method: Dictionary, is_signal: bool = false) -> String:
|
static func get_method_signature(method: Dictionary, is_signal: bool = false) -> String:
|
||||||
var result: String = ""
|
var result: String = ""
|
||||||
if method.flags & METHOD_FLAG_STATIC:
|
if method.flags & METHOD_FLAG_STATIC:
|
||||||
|
@ -55,6 +65,7 @@ static func get_method_signature(method: Dictionary, is_signal: bool = false) ->
|
||||||
result += " -> " + get_type(method.return, true)
|
result += " -> " + get_type(method.return, true)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
static func variant_get_type_name(type: Variant.Type) -> String:
|
static func variant_get_type_name(type: Variant.Type) -> String:
|
||||||
match type:
|
match type:
|
||||||
TYPE_NIL:
|
TYPE_NIL:
|
||||||
|
@ -135,3 +146,136 @@ static func variant_get_type_name(type: Variant.Type) -> String:
|
||||||
return "PackedColorArray"
|
return "PackedColorArray"
|
||||||
push_error("Argument `type` is invalid. Use `TYPE_*` constants.")
|
push_error("Argument `type` is invalid. Use `TYPE_*` constants.")
|
||||||
return "<invalid type>"
|
return "<invalid type>"
|
||||||
|
|
||||||
|
|
||||||
|
static func get_property_hint_name(hint: PropertyHint) -> String:
|
||||||
|
match hint:
|
||||||
|
PROPERTY_HINT_NONE:
|
||||||
|
return "PROPERTY_HINT_NONE"
|
||||||
|
PROPERTY_HINT_RANGE:
|
||||||
|
return "PROPERTY_HINT_RANGE"
|
||||||
|
PROPERTY_HINT_ENUM:
|
||||||
|
return "PROPERTY_HINT_ENUM"
|
||||||
|
PROPERTY_HINT_ENUM_SUGGESTION:
|
||||||
|
return "PROPERTY_HINT_ENUM_SUGGESTION"
|
||||||
|
PROPERTY_HINT_EXP_EASING:
|
||||||
|
return "PROPERTY_HINT_EXP_EASING"
|
||||||
|
PROPERTY_HINT_LINK:
|
||||||
|
return "PROPERTY_HINT_LINK"
|
||||||
|
PROPERTY_HINT_FLAGS:
|
||||||
|
return "PROPERTY_HINT_FLAGS"
|
||||||
|
PROPERTY_HINT_LAYERS_2D_RENDER:
|
||||||
|
return "PROPERTY_HINT_LAYERS_2D_RENDER"
|
||||||
|
PROPERTY_HINT_LAYERS_2D_PHYSICS:
|
||||||
|
return "PROPERTY_HINT_LAYERS_2D_PHYSICS"
|
||||||
|
PROPERTY_HINT_LAYERS_2D_NAVIGATION:
|
||||||
|
return "PROPERTY_HINT_LAYERS_2D_NAVIGATION"
|
||||||
|
PROPERTY_HINT_LAYERS_3D_RENDER:
|
||||||
|
return "PROPERTY_HINT_LAYERS_3D_RENDER"
|
||||||
|
PROPERTY_HINT_LAYERS_3D_PHYSICS:
|
||||||
|
return "PROPERTY_HINT_LAYERS_3D_PHYSICS"
|
||||||
|
PROPERTY_HINT_LAYERS_3D_NAVIGATION:
|
||||||
|
return "PROPERTY_HINT_LAYERS_3D_NAVIGATION"
|
||||||
|
PROPERTY_HINT_LAYERS_AVOIDANCE:
|
||||||
|
return "PROPERTY_HINT_LAYERS_AVOIDANCE"
|
||||||
|
PROPERTY_HINT_FILE:
|
||||||
|
return "PROPERTY_HINT_FILE"
|
||||||
|
PROPERTY_HINT_DIR:
|
||||||
|
return "PROPERTY_HINT_DIR"
|
||||||
|
PROPERTY_HINT_GLOBAL_FILE:
|
||||||
|
return "PROPERTY_HINT_GLOBAL_FILE"
|
||||||
|
PROPERTY_HINT_GLOBAL_DIR:
|
||||||
|
return "PROPERTY_HINT_GLOBAL_DIR"
|
||||||
|
PROPERTY_HINT_RESOURCE_TYPE:
|
||||||
|
return "PROPERTY_HINT_RESOURCE_TYPE"
|
||||||
|
PROPERTY_HINT_MULTILINE_TEXT:
|
||||||
|
return "PROPERTY_HINT_MULTILINE_TEXT"
|
||||||
|
PROPERTY_HINT_EXPRESSION:
|
||||||
|
return "PROPERTY_HINT_EXPRESSION"
|
||||||
|
PROPERTY_HINT_PLACEHOLDER_TEXT:
|
||||||
|
return "PROPERTY_HINT_PLACEHOLDER_TEXT"
|
||||||
|
PROPERTY_HINT_COLOR_NO_ALPHA:
|
||||||
|
return "PROPERTY_HINT_COLOR_NO_ALPHA"
|
||||||
|
PROPERTY_HINT_OBJECT_ID:
|
||||||
|
return "PROPERTY_HINT_OBJECT_ID"
|
||||||
|
PROPERTY_HINT_TYPE_STRING:
|
||||||
|
return "PROPERTY_HINT_TYPE_STRING"
|
||||||
|
PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE:
|
||||||
|
return "PROPERTY_HINT_NODE_PATH_TO_EDITED_NODE"
|
||||||
|
PROPERTY_HINT_OBJECT_TOO_BIG:
|
||||||
|
return "PROPERTY_HINT_OBJECT_TOO_BIG"
|
||||||
|
PROPERTY_HINT_NODE_PATH_VALID_TYPES:
|
||||||
|
return "PROPERTY_HINT_NODE_PATH_VALID_TYPES"
|
||||||
|
PROPERTY_HINT_SAVE_FILE:
|
||||||
|
return "PROPERTY_HINT_SAVE_FILE"
|
||||||
|
PROPERTY_HINT_GLOBAL_SAVE_FILE:
|
||||||
|
return "PROPERTY_HINT_GLOBAL_SAVE_FILE"
|
||||||
|
PROPERTY_HINT_INT_IS_OBJECTID:
|
||||||
|
return "PROPERTY_HINT_INT_IS_OBJECTID"
|
||||||
|
PROPERTY_HINT_INT_IS_POINTER:
|
||||||
|
return "PROPERTY_HINT_INT_IS_POINTER"
|
||||||
|
PROPERTY_HINT_ARRAY_TYPE:
|
||||||
|
return "PROPERTY_HINT_ARRAY_TYPE"
|
||||||
|
PROPERTY_HINT_LOCALE_ID:
|
||||||
|
return "PROPERTY_HINT_LOCALE_ID"
|
||||||
|
PROPERTY_HINT_LOCALIZABLE_STRING:
|
||||||
|
return "PROPERTY_HINT_LOCALIZABLE_STRING"
|
||||||
|
PROPERTY_HINT_NODE_TYPE:
|
||||||
|
return "PROPERTY_HINT_NODE_TYPE"
|
||||||
|
PROPERTY_HINT_HIDE_QUATERNION_EDIT:
|
||||||
|
return "PROPERTY_HINT_HIDE_QUATERNION_EDIT"
|
||||||
|
PROPERTY_HINT_PASSWORD:
|
||||||
|
return "PROPERTY_HINT_PASSWORD"
|
||||||
|
push_error("Argument `hint` is invalid. Use `PROPERTY_HINT_*` constants.")
|
||||||
|
return "<invalid hint>"
|
||||||
|
|
||||||
|
|
||||||
|
static func get_property_usage_string(usage: int) -> String:
|
||||||
|
if usage == PROPERTY_USAGE_NONE:
|
||||||
|
return "PROPERTY_USAGE_NONE"
|
||||||
|
|
||||||
|
const FLAGS: Array[Array] = [
|
||||||
|
[PROPERTY_USAGE_DEFAULT, "PROPERTY_USAGE_DEFAULT"],
|
||||||
|
[PROPERTY_USAGE_STORAGE, "PROPERTY_USAGE_STORAGE"],
|
||||||
|
[PROPERTY_USAGE_EDITOR, "PROPERTY_USAGE_EDITOR"],
|
||||||
|
[PROPERTY_USAGE_INTERNAL, "PROPERTY_USAGE_INTERNAL"],
|
||||||
|
[PROPERTY_USAGE_CHECKABLE, "PROPERTY_USAGE_CHECKABLE"],
|
||||||
|
[PROPERTY_USAGE_CHECKED, "PROPERTY_USAGE_CHECKED"],
|
||||||
|
[PROPERTY_USAGE_GROUP, "PROPERTY_USAGE_GROUP"],
|
||||||
|
[PROPERTY_USAGE_CATEGORY, "PROPERTY_USAGE_CATEGORY"],
|
||||||
|
[PROPERTY_USAGE_SUBGROUP, "PROPERTY_USAGE_SUBGROUP"],
|
||||||
|
[PROPERTY_USAGE_CLASS_IS_BITFIELD, "PROPERTY_USAGE_CLASS_IS_BITFIELD"],
|
||||||
|
[PROPERTY_USAGE_NO_INSTANCE_STATE, "PROPERTY_USAGE_NO_INSTANCE_STATE"],
|
||||||
|
[PROPERTY_USAGE_RESTART_IF_CHANGED, "PROPERTY_USAGE_RESTART_IF_CHANGED"],
|
||||||
|
[PROPERTY_USAGE_SCRIPT_VARIABLE, "PROPERTY_USAGE_SCRIPT_VARIABLE"],
|
||||||
|
[PROPERTY_USAGE_STORE_IF_NULL, "PROPERTY_USAGE_STORE_IF_NULL"],
|
||||||
|
[PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED, "PROPERTY_USAGE_UPDATE_ALL_IF_MODIFIED"],
|
||||||
|
[PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE, "PROPERTY_USAGE_SCRIPT_DEFAULT_VALUE"],
|
||||||
|
[PROPERTY_USAGE_CLASS_IS_ENUM, "PROPERTY_USAGE_CLASS_IS_ENUM"],
|
||||||
|
[PROPERTY_USAGE_NIL_IS_VARIANT, "PROPERTY_USAGE_NIL_IS_VARIANT"],
|
||||||
|
[PROPERTY_USAGE_ARRAY, "PROPERTY_USAGE_ARRAY"],
|
||||||
|
[PROPERTY_USAGE_ALWAYS_DUPLICATE, "PROPERTY_USAGE_ALWAYS_DUPLICATE"],
|
||||||
|
[PROPERTY_USAGE_NEVER_DUPLICATE, "PROPERTY_USAGE_NEVER_DUPLICATE"],
|
||||||
|
[PROPERTY_USAGE_HIGH_END_GFX, "PROPERTY_USAGE_HIGH_END_GFX"],
|
||||||
|
[PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT, "PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT"],
|
||||||
|
[PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT, "PROPERTY_USAGE_RESOURCE_NOT_PERSISTENT"],
|
||||||
|
[PROPERTY_USAGE_KEYING_INCREMENTS, "PROPERTY_USAGE_KEYING_INCREMENTS"],
|
||||||
|
[PROPERTY_USAGE_DEFERRED_SET_RESOURCE, "PROPERTY_USAGE_DEFERRED_SET_RESOURCE"],
|
||||||
|
[PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT, "PROPERTY_USAGE_EDITOR_INSTANTIATE_OBJECT"],
|
||||||
|
[PROPERTY_USAGE_EDITOR_BASIC_SETTING, "PROPERTY_USAGE_EDITOR_BASIC_SETTING"],
|
||||||
|
[PROPERTY_USAGE_READ_ONLY, "PROPERTY_USAGE_READ_ONLY"],
|
||||||
|
[PROPERTY_USAGE_SECRET, "PROPERTY_USAGE_SECRET"],
|
||||||
|
]
|
||||||
|
|
||||||
|
var result: String = ""
|
||||||
|
|
||||||
|
for flag in FLAGS:
|
||||||
|
if usage & flag[0]:
|
||||||
|
result += flag[1] + "|"
|
||||||
|
usage &= ~flag[0]
|
||||||
|
|
||||||
|
if usage != PROPERTY_USAGE_NONE:
|
||||||
|
push_error("Argument `usage` is invalid. Use `PROPERTY_USAGE_*` constants.")
|
||||||
|
return "<invalid usage flags>"
|
||||||
|
|
||||||
|
return result.left(-1)
|
||||||
|
|
Loading…
Reference in a new issue