Jelajahi Sumber

GDScript: Allow string keys on Lua-style dictionaries

Which is useful when the key isn't a valid identifier, such as keys with
spaces or numeric keys.
George Marques 4 tahun lalu
induk
melakukan
5d31ce4b16

+ 1 - 1
modules/gdscript/gdscript_compiler.cpp

@@ -440,7 +440,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 						break;
 						break;
 					case GDScriptParser::DictionaryNode::LUA_TABLE:
 					case GDScriptParser::DictionaryNode::LUA_TABLE:
 						// Lua-style: key is an identifier interpreted as StringName.
 						// Lua-style: key is an identifier interpreted as StringName.
-						StringName key = static_cast<const GDScriptParser::IdentifierNode *>(dn->elements[i].key)->name;
+						StringName key = dn->elements[i].key->reduced_value.operator StringName();
 						element = codegen.add_constant(key);
 						element = codegen.add_constant(key);
 						break;
 						break;
 				}
 				}

+ 12 - 3
modules/gdscript/gdscript_parser.cpp

@@ -2472,8 +2472,13 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode
 
 
 			switch (dictionary->style) {
 			switch (dictionary->style) {
 				case DictionaryNode::LUA_TABLE:
 				case DictionaryNode::LUA_TABLE:
-					if (key != nullptr && key->type != Node::IDENTIFIER) {
-						push_error("Expected identifier as LUA-style dictionary key.");
+					if (key != nullptr && key->type != Node::IDENTIFIER && key->type != Node::LITERAL) {
+						push_error("Expected identifier or string as LUA-style dictionary key.");
+						advance();
+						break;
+					}
+					if (key != nullptr && key->type == Node::LITERAL && static_cast<LiteralNode *>(key)->value.get_type() != Variant::STRING) {
+						push_error("Expected identifier or string as LUA-style dictionary key.");
 						advance();
 						advance();
 						break;
 						break;
 					}
 					}
@@ -2487,7 +2492,11 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode
 					}
 					}
 					if (key != nullptr) {
 					if (key != nullptr) {
 						key->is_constant = true;
 						key->is_constant = true;
-						key->reduced_value = static_cast<IdentifierNode *>(key)->name;
+						if (key->type == Node::IDENTIFIER) {
+							key->reduced_value = static_cast<IdentifierNode *>(key)->name;
+						} else if (key->type == Node::LITERAL) {
+							key->reduced_value = StringName(static_cast<LiteralNode *>(key)->value.operator String());
+						}
 					}
 					}
 					break;
 					break;
 				case DictionaryNode::PYTHON_DICT:
 				case DictionaryNode::PYTHON_DICT:

+ 6 - 0
modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.gd

@@ -0,0 +1,6 @@
+func test():
+	var lua_dict = {
+		a = 1,
+		b = 2,
+		a = 3, # Duplicate isn't allowed.
+	}

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.out

@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Key "a" was already used in this dictionary (at line 3).

+ 6 - 0
modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.gd

@@ -0,0 +1,6 @@
+func test():
+	var lua_dict_with_string = {
+		a = 1,
+		b = 2,
+		"a" = 3, # Duplicate isn't allowed.
+	}

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.out

@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Key "a" was already used in this dictionary (at line 3).

+ 6 - 0
modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.gd

@@ -0,0 +1,6 @@
+func test():
+	var python_dict = {
+		"a": 1,
+		"b": 2,
+		"a": 3, # Duplicate isn't allowed.
+	}

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.out

@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Key "a" was already used in this dictionary (at line 3).

+ 9 - 0
modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.gd

@@ -0,0 +1,9 @@
+func test():
+	var lua_dict = {
+		a = 1,
+		"b" = 2, # Using strings are allowed too.
+		"with spaces" = 3, # Especially useful when key has spaces...
+		"2" = 4, # ... or invalid identifiers.
+	}
+
+	print(lua_dict)

+ 2 - 0
modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out

@@ -0,0 +1,2 @@
+GDTEST_OK
+{2:4, a:1, b:2, with spaces:3}