Przeglądaj źródła

Merge pull request #70613 from vonagam/fix-enum-as-constant

Fixes https://github.com/godotengine/godot/issues/54018
Fixes https://github.com/godotengine/godot/issues/70213
Fixes https://github.com/godotengine/godot/issues/70495
George Marques 2 lat temu
rodzic
commit
33afa82fb0

+ 8 - 5
modules/gdscript/gdscript_analyzer.cpp

@@ -937,6 +937,7 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
 				const GDScriptParser::EnumNode *prev_enum = current_enum;
 				current_enum = member.m_enum;
 
+				Dictionary dictionary;
 				for (int j = 0; j < member.m_enum->values.size(); j++) {
 					GDScriptParser::EnumNode::Value &element = member.m_enum->values.write[j];
 
@@ -960,11 +961,13 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
 					}
 
 					enum_type.enum_values[element.identifier->name] = element.value;
+					dictionary[String(element.identifier->name)] = element.value;
 				}
 
 				current_enum = prev_enum;
 
 				member.m_enum->set_datatype(enum_type);
+				member.m_enum->dictionary = dictionary;
 
 				// Apply annotations.
 				for (GDScriptParser::AnnotationNode *&E : member.m_enum->annotations) {
@@ -3140,10 +3143,9 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
 					p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
 					break;
 				case GDScriptParser::ClassNode::Member::ENUM:
-					if (p_base != nullptr && p_base->is_constant) {
-						p_identifier->is_constant = true;
-						p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
-					}
+					p_identifier->is_constant = true;
+					p_identifier->reduced_value = member.m_enum->dictionary;
+					p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
 					break;
 				case GDScriptParser::ClassNode::Member::VARIABLE:
 					p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
@@ -3197,7 +3199,8 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
 							return;
 						case GDScriptParser::ClassNode::Member::ENUM:
 							p_identifier->set_datatype(member.get_datatype());
-							p_identifier->is_constant = false;
+							p_identifier->is_constant = true;
+							p_identifier->reduced_value = member.m_enum->dictionary;
 							return;
 						case GDScriptParser::ClassNode::Member::CLASS:
 							p_identifier->set_datatype(member.get_datatype());

+ 7 - 13
modules/gdscript/gdscript_compiler.cpp

@@ -2453,26 +2453,20 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
 
 			case GDScriptParser::ClassNode::Member::ENUM: {
 				const GDScriptParser::EnumNode *enum_n = member.m_enum;
+				StringName name = enum_n->identifier->name;
 
-				// TODO: Make enums not be just a dictionary?
-				Dictionary new_enum;
-				for (int j = 0; j < enum_n->values.size(); j++) {
-					// Needs to be string because Variant::get will convert to String.
-					new_enum[String(enum_n->values[j].identifier->name)] = enum_n->values[j].value;
-				}
-
-				p_script->constants.insert(enum_n->identifier->name, new_enum);
+				p_script->constants.insert(name, enum_n->dictionary);
 #ifdef TOOLS_ENABLED
-				p_script->member_lines[enum_n->identifier->name] = enum_n->start_line;
-				p_script->doc_enums[enum_n->identifier->name] = DocData::EnumDoc();
-				p_script->doc_enums[enum_n->identifier->name].name = enum_n->identifier->name;
-				p_script->doc_enums[enum_n->identifier->name].description = enum_n->doc_description;
+				p_script->member_lines[name] = enum_n->start_line;
+				p_script->doc_enums[name] = DocData::EnumDoc();
+				p_script->doc_enums[name].name = name;
+				p_script->doc_enums[name].description = enum_n->doc_description;
 				for (int j = 0; j < enum_n->values.size(); j++) {
 					DocData::ConstantDoc const_doc;
 					const_doc.name = enum_n->values[j].identifier->name;
 					const_doc.value = Variant(enum_n->values[j].value).operator String();
 					const_doc.description = enum_n->values[j].doc_description;
-					p_script->doc_enums[enum_n->identifier->name].values.push_back(const_doc);
+					p_script->doc_enums[name].values.push_back(const_doc);
 				}
 #endif
 			} break;

+ 1 - 0
modules/gdscript/gdscript_parser.h

@@ -483,6 +483,7 @@ public:
 
 		IdentifierNode *identifier = nullptr;
 		Vector<Value> values;
+		Variant dictionary;
 #ifdef TOOLS_ENABLED
 		String doc_description;
 #endif // TOOLS_ENABLED

+ 29 - 0
modules/gdscript/tests/scripts/analyzer/features/enum_as_const.gd

@@ -0,0 +1,29 @@
+class Outer:
+	enum OuterEnum { OuterValue = 3 }
+	const OuterConst := OuterEnum
+
+	class Inner:
+		enum InnerEnum { InnerValue = 7 }
+		const InnerConst := InnerEnum
+
+		static func test() -> void:
+			print(OuterEnum.size());
+			print(OuterEnum.OuterValue);
+			print(OuterConst.size());
+			print(OuterConst.OuterValue);
+			print(Outer.OuterEnum.size());
+			print(Outer.OuterEnum.OuterValue);
+			print(Outer.OuterConst.size());
+			print(Outer.OuterConst.OuterValue);
+
+			print(InnerEnum.size());
+			print(InnerEnum.InnerValue);
+			print(InnerConst.size());
+			print(InnerConst.InnerValue);
+			print(Inner.InnerEnum.size());
+			print(Inner.InnerEnum.InnerValue);
+			print(Inner.InnerConst.size());
+			print(Inner.InnerConst.InnerValue);
+
+func test():
+	Outer.Inner.test()

+ 17 - 0
modules/gdscript/tests/scripts/analyzer/features/enum_as_const.out

@@ -0,0 +1,17 @@
+GDTEST_OK
+1
+3
+1
+3
+1
+3
+1
+3
+1
+7
+1
+7
+1
+7
+1
+7