Browse Source

Fixes GDScript define nested dictionary and array as constants #50285

PastMoments 3 years ago
parent
commit
b3704e664d

+ 20 - 0
modules/gdscript/gdscript_analyzer.cpp

@@ -3159,6 +3159,12 @@ void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscri
 		reduce_identifier(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base), true);
 		reduce_identifier(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base), true);
 	} else {
 	} else {
 		reduce_expression(p_subscript->base);
 		reduce_expression(p_subscript->base);
+
+		if (p_subscript->base->type == GDScriptParser::Node::ARRAY) {
+			const_fold_array(static_cast<GDScriptParser::ArrayNode *>(p_subscript->base));
+		} else if (p_subscript->base->type == GDScriptParser::Node::DICTIONARY) {
+			const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_subscript->base));
+		}
 	}
 	}
 
 
 	GDScriptParser::DataType result_type;
 	GDScriptParser::DataType result_type;
@@ -3476,6 +3482,13 @@ void GDScriptAnalyzer::const_fold_array(GDScriptParser::ArrayNode *p_array) {
 
 
 	for (int i = 0; i < p_array->elements.size(); i++) {
 	for (int i = 0; i < p_array->elements.size(); i++) {
 		GDScriptParser::ExpressionNode *element = p_array->elements[i];
 		GDScriptParser::ExpressionNode *element = p_array->elements[i];
+
+		if (element->type == GDScriptParser::Node::ARRAY) {
+			const_fold_array(static_cast<GDScriptParser::ArrayNode *>(element));
+		} else if (element->type == GDScriptParser::Node::DICTIONARY) {
+			const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element));
+		}
+
 		all_is_constant = all_is_constant && element->is_constant;
 		all_is_constant = all_is_constant && element->is_constant;
 		if (!all_is_constant) {
 		if (!all_is_constant) {
 			return;
 			return;
@@ -3496,6 +3509,13 @@ void GDScriptAnalyzer::const_fold_dictionary(GDScriptParser::DictionaryNode *p_d
 
 
 	for (int i = 0; i < p_dictionary->elements.size(); i++) {
 	for (int i = 0; i < p_dictionary->elements.size(); i++) {
 		const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
 		const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
+
+		if (element.value->type == GDScriptParser::Node::ARRAY) {
+			const_fold_array(static_cast<GDScriptParser::ArrayNode *>(element.value));
+		} else if (element.value->type == GDScriptParser::Node::DICTIONARY) {
+			const_fold_dictionary(static_cast<GDScriptParser::DictionaryNode *>(element.value));
+		}
+
 		all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant;
 		all_is_constant = all_is_constant && element.key->is_constant && element.value->is_constant;
 		if (!all_is_constant) {
 		if (!all_is_constant) {
 			return;
 			return;

+ 1 - 1
modules/gdscript/tests/scripts/analyzer/errors/invalid_array_index.out

@@ -1,2 +1,2 @@
 GDTEST_ANALYZER_ERROR
 GDTEST_ANALYZER_ERROR
-Invalid index type "bool" for a base of type "Array".
+Cannot get index "true" from "[0, 1]".

+ 58 - 0
modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.gd

@@ -0,0 +1,58 @@
+# https://github.com/godotengine/godot/issues/50285
+
+@warning_ignore(unused_local_constant)
+func test():
+	const CONST_INNER_DICTIONARY = { "key": true }
+	const CONST_NESTED_DICTIONARY_OLD_WORKAROUND = {
+		"key1": "value1",
+		"key2": CONST_INNER_DICTIONARY
+	}
+	# All of these should be valid
+	const CONST_NESTED_DICTIONARY = {
+		"key1": "value1",
+		"key2": { "key": true }
+	}
+
+
+	const CONST_DICTIONARY_WITH_ARRAY = {
+		"key1": [1,2,3,4]
+	}
+
+	const CONST_NESTED_ARRAY = [[],[2],[1,2,3]]
+	const CONST_ARRAY_WITH_DICT = [{"key1": 3}, {"key2": 5}]
+
+	const THREE_DIMENSIONAL_ARRAY = [[[],[],[]],[[],[],[]],[[],[],[]]]
+	const MANY_NESTED_DICT = {
+		"key1": {
+			"key11": {
+				"key111": {},
+				"key112": {},
+			},
+			"key12": {
+				"key121": {},
+				"key122": {},
+			},
+		},
+		"key2": {
+			"key21": {
+				"key211": {},
+				"key212": {},
+			},
+			"key22": {
+				"key221": {},
+				"key222": {},
+			},
+		}
+	}
+
+
+	const CONST_ARRAY_ACCESS = [1,2,3][0]
+	const CONST_DICT_ACCESS = {"key1": 5}["key1"]
+
+	const CONST_ARRAY_NESTED_ACCESS = [[1,2,3],[4,5,6],[8,9,10]][0][1]
+	const CONST_DICT_NESTED_ACCESS = {"key1": {"key2": 1}}["key1"]["key2"]
+
+	print(CONST_ARRAY_ACCESS)
+	print(CONST_DICT_ACCESS)
+	print(CONST_ARRAY_NESTED_ACCESS)
+	print(CONST_DICT_NESTED_ACCESS)

+ 5 - 0
modules/gdscript/tests/scripts/parser/features/arrays_dictionaries_nested_const.out

@@ -0,0 +1,5 @@
+GDTEST_OK
+1
+5
+2
+1