From 5d31ce4b161553e85bbd8397f2ce62cbd213095f Mon Sep 17 00:00:00 2001 From: George Marques Date: Wed, 15 Sep 2021 09:56:24 -0300 Subject: [PATCH] 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. --- modules/gdscript/gdscript_compiler.cpp | 2 +- modules/gdscript/gdscript_parser.cpp | 15 ++++++++++++--- .../errors/dictionary_duplicate_key_lua.gd | 6 ++++++ .../errors/dictionary_duplicate_key_lua.out | 2 ++ .../dictionary_duplicate_key_lua_with_string.gd | 6 ++++++ .../dictionary_duplicate_key_lua_with_string.out | 2 ++ .../errors/dictionary_duplicate_key_python.gd | 6 ++++++ .../errors/dictionary_duplicate_key_python.out | 2 ++ .../parser/features/dictionary_lua_style.gd | 9 +++++++++ .../parser/features/dictionary_lua_style.out | 2 ++ 10 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.gd create mode 100644 modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.out create mode 100644 modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.gd create mode 100644 modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.out create mode 100644 modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.gd create mode 100644 modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.out create mode 100644 modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.gd create mode 100644 modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp index b0d0b024439..4f986cf29ec 100644 --- a/modules/gdscript/gdscript_compiler.cpp +++ b/modules/gdscript/gdscript_compiler.cpp @@ -440,7 +440,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code break; case GDScriptParser::DictionaryNode::LUA_TABLE: // Lua-style: key is an identifier interpreted as StringName. - StringName key = static_cast(dn->elements[i].key)->name; + StringName key = dn->elements[i].key->reduced_value.operator StringName(); element = codegen.add_constant(key); break; } diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 19584ce1944..42c06d81615 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -2472,8 +2472,13 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode switch (dictionary->style) { 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(key)->value.get_type() != Variant::STRING) { + push_error("Expected identifier or string as LUA-style dictionary key."); advance(); break; } @@ -2487,7 +2492,11 @@ GDScriptParser::ExpressionNode *GDScriptParser::parse_dictionary(ExpressionNode } if (key != nullptr) { key->is_constant = true; - key->reduced_value = static_cast(key)->name; + if (key->type == Node::IDENTIFIER) { + key->reduced_value = static_cast(key)->name; + } else if (key->type == Node::LITERAL) { + key->reduced_value = StringName(static_cast(key)->value.operator String()); + } } break; case DictionaryNode::PYTHON_DICT: diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.gd b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.gd new file mode 100644 index 00000000000..7a922cd73eb --- /dev/null +++ b/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. + } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.out b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua.out new file mode 100644 index 00000000000..ffdfa56645d --- /dev/null +++ b/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). diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.gd b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.gd new file mode 100644 index 00000000000..933e737ac78 --- /dev/null +++ b/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. + } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.out b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_lua_with_string.out new file mode 100644 index 00000000000..ffdfa56645d --- /dev/null +++ b/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). diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.gd b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.gd new file mode 100644 index 00000000000..3b8c83e9cbc --- /dev/null +++ b/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. + } diff --git a/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.out b/modules/gdscript/tests/scripts/analyzer/errors/dictionary_duplicate_key_python.out new file mode 100644 index 00000000000..ffdfa56645d --- /dev/null +++ b/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). diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.gd b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.gd new file mode 100644 index 00000000000..fdd6de23482 --- /dev/null +++ b/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) diff --git a/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out b/modules/gdscript/tests/scripts/parser/features/dictionary_lua_style.out new file mode 100644 index 00000000000..447d7e223cd --- /dev/null +++ b/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}