瀏覽代碼

GDScript: Fix false positive `CONFUSABLE_CAPTURE_REASSIGNMENT` warnings

Danil Alexeev 1 年之前
父節點
當前提交
d15ed0bcbb

+ 24 - 1
modules/gdscript/gdscript_analyzer.cpp

@@ -2665,14 +2665,37 @@ void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assig
 
 #ifdef DEBUG_ENABLED
 	{
+		bool is_subscript = false;
 		GDScriptParser::ExpressionNode *base = p_assignment->assignee;
 		while (base && base->type == GDScriptParser::Node::SUBSCRIPT) {
+			is_subscript = true;
 			base = static_cast<GDScriptParser::SubscriptNode *>(base)->base;
 		}
 		if (base && base->type == GDScriptParser::Node::IDENTIFIER) {
 			GDScriptParser::IdentifierNode *id = static_cast<GDScriptParser::IdentifierNode *>(base);
 			if (current_lambda && current_lambda->captures_indices.has(id->name)) {
-				parser->push_warning(p_assignment, GDScriptWarning::CONFUSABLE_CAPTURE_REASSIGNMENT, id->name);
+				bool need_warn = false;
+				if (is_subscript) {
+					const GDScriptParser::DataType &id_type = id->datatype;
+					if (id_type.is_hard_type()) {
+						switch (id_type.kind) {
+							case GDScriptParser::DataType::BUILTIN:
+								// TODO: Change `Variant::is_type_shared()` to include packed arrays?
+								need_warn = !Variant::is_type_shared(id_type.builtin_type) && id_type.builtin_type < Variant::PACKED_BYTE_ARRAY;
+								break;
+							case GDScriptParser::DataType::ENUM:
+								need_warn = true;
+								break;
+							default:
+								break;
+						}
+					}
+				} else {
+					need_warn = true;
+				}
+				if (need_warn) {
+					parser->push_warning(p_assignment, GDScriptWarning::CONFUSABLE_CAPTURE_REASSIGNMENT, id->name);
+				}
 			}
 		}
 	}

+ 16 - 20
modules/gdscript/tests/scripts/analyzer/warnings/confusable_capture_reassignment.gd

@@ -5,23 +5,19 @@ func test():
 	var string := "1"
 	var vector := Vector2i(1, 0)
 	var array_assign := [1]
-	var array_append := [1]
-	var f := func ():
-		member = 2
-		number = 2
-		string += "2"
-		vector.x = 2
-		array_assign = [2]
-		array_append.append(2)
-		var g := func ():
-			member = 3
-			number = 3
-			string += "3"
-			vector.x = 3
-			array_assign = [3]
-			array_append.append(3)
-			prints("g", member, number, string, vector, array_assign, array_append)
-		g.call()
-		prints("f", member, number, string, vector, array_assign, array_append)
-	f.call()
-	prints("test", member, number, string, vector, array_assign, array_append)
+	var array_index := [1]
+	var dictionary := { x = 0 }
+
+	var lambda := func ():
+		member = 2 # Member variable, not captured.
+		number = 2 # Local variable, captured.
+		string += "2" # Test compound assignment operator.
+		vector.x = 2 # Test subscript assignment.
+		array_assign = [2] # Pass-by-reference type, reassignment.
+		array_index[0] = 2 # Pass-by-reference type, index access.
+		dictionary.x = 2 # Pass-by-reference type, attribute access.
+
+		prints("lambda", member, number, string, vector, array_assign, array_index, dictionary)
+
+	lambda.call()
+	prints("outer", member, number, string, vector, array_assign, array_index, dictionary)

+ 5 - 22
modules/gdscript/tests/scripts/analyzer/warnings/confusable_capture_reassignment.out

@@ -1,36 +1,19 @@
 GDTEST_OK
 >> WARNING
->> Line: 11
->> CONFUSABLE_CAPTURE_REASSIGNMENT
->> Reassigning lambda capture does not modify the outer local variable "number".
->> WARNING
->> Line: 12
->> CONFUSABLE_CAPTURE_REASSIGNMENT
->> Reassigning lambda capture does not modify the outer local variable "string".
->> WARNING
 >> Line: 13
 >> CONFUSABLE_CAPTURE_REASSIGNMENT
->> Reassigning lambda capture does not modify the outer local variable "vector".
->> WARNING
->> Line: 14
->> CONFUSABLE_CAPTURE_REASSIGNMENT
->> Reassigning lambda capture does not modify the outer local variable "array_assign".
->> WARNING
->> Line: 18
->> CONFUSABLE_CAPTURE_REASSIGNMENT
 >> Reassigning lambda capture does not modify the outer local variable "number".
 >> WARNING
->> Line: 19
+>> Line: 14
 >> CONFUSABLE_CAPTURE_REASSIGNMENT
 >> Reassigning lambda capture does not modify the outer local variable "string".
 >> WARNING
->> Line: 20
+>> Line: 15
 >> CONFUSABLE_CAPTURE_REASSIGNMENT
 >> Reassigning lambda capture does not modify the outer local variable "vector".
 >> WARNING
->> Line: 21
+>> Line: 16
 >> CONFUSABLE_CAPTURE_REASSIGNMENT
 >> Reassigning lambda capture does not modify the outer local variable "array_assign".
-g 3 3 123 (3, 0) [3] [1, 2, 3]
-f 3 2 12 (2, 0) [2] [1, 2, 3]
-test 3 1 1 (1, 0) [1] [1, 2, 3]
+lambda 2 2 12 (2, 0) [2] [2] { "x": 2 }
+outer 2 1 1 (1, 0) [1] [2] { "x": 2 }