فهرست منبع

Merge pull request #67365 from clayjohn/GDScript-static-warning

Add STATIC_CALLED_ON_INSTANCE warning
Rémi Verschelde 2 سال پیش
والد
کامیت
f546d70b8e

+ 3 - 0
doc/classes/ProjectSettings.xml

@@ -413,6 +413,9 @@
 		<member name="debug/gdscript/warnings/standalone_ternary" type="int" setter="" getter="" default="1">
 			When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a ternary expression that has no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement.
 		</member>
+		<member name="debug/gdscript/warnings/static_called_on_instance" type="int" setter="" getter="" default="1">
+			When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a static method from an instance of a class instead of from the class directly.
+		</member>
 		<member name="debug/gdscript/warnings/treat_warnings_as_errors" type="bool" setter="" getter="" default="false">
 			If [code]true[/code], all warnings will be reported as if they are errors.
 		</member>

+ 4 - 0
modules/gdscript/gdscript_analyzer.cpp

@@ -2552,6 +2552,10 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
 		if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL) {
 			parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
 		}
+
+		if (is_static && !base_type.is_meta_type && !(callee_type != GDScriptParser::Node::SUBSCRIPT && parser->current_function != nullptr && parser->current_function->is_static)) {
+			parser->push_warning(p_call, GDScriptWarning::STATIC_CALLED_ON_INSTANCE, p_call->function_name, base_type.to_string());
+		}
 #endif // DEBUG_ENABLED
 
 		call_type = return_type;

+ 5 - 0
modules/gdscript/gdscript_warning.cpp

@@ -155,6 +155,10 @@ String GDScriptWarning::get_message() const {
 		case INT_ASSIGNED_TO_ENUM: {
 			return "Integer used when an enum value is expected. If this is intended cast the integer to the enum type.";
 		}
+		case STATIC_CALLED_ON_INSTANCE: {
+			CHECK_SYMBOLS(2);
+			return vformat(R"(The function '%s()' is a static function but was called from an instance. Instead, it should be directly called from the type: '%s.%s()'.)", symbols[0], symbols[1], symbols[0]);
+		}
 		case WARNING_MAX:
 			break; // Can't happen, but silences warning
 	}
@@ -215,6 +219,7 @@ String GDScriptWarning::get_name_from_code(Code p_code) {
 		"EMPTY_FILE",
 		"SHADOWED_GLOBAL_IDENTIFIER",
 		"INT_ASSIGNED_TO_ENUM",
+		"STATIC_CALLED_ON_INSTANCE",
 	};
 
 	static_assert((sizeof(names) / sizeof(*names)) == WARNING_MAX, "Amount of warning types don't match the amount of warning names.");

+ 1 - 0
modules/gdscript/gdscript_warning.h

@@ -78,6 +78,7 @@ public:
 		EMPTY_FILE, // A script file is empty.
 		SHADOWED_GLOBAL_IDENTIFIER, // A global class or function has the same name as variable.
 		INT_ASSIGNED_TO_ENUM, // An integer value was assigned to an enum-typed variable without casting.
+		STATIC_CALLED_ON_INSTANCE, // A static method was called on an instance of a class instead of on the class itself.
 		WARNING_MAX,
 	};
 

+ 11 - 0
modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.gd

@@ -0,0 +1,11 @@
+class Player:
+	var x = 3
+
+func test():
+	# These should not emit a warning.
+	var _player = Player.new()
+	print(String.num_uint64(8589934592)) # 2 ^ 33
+
+	# This should emit a warning.
+	var some_string = String()
+	print(some_string.num_uint64(8589934592)) # 2 ^ 33

+ 7 - 0
modules/gdscript/tests/scripts/parser/warnings/static_called_on_instance.out

@@ -0,0 +1,7 @@
+GDTEST_OK
+>> WARNING
+>> Line: 11
+>> STATIC_CALLED_ON_INSTANCE
+>> The function 'num_uint64()' is a static function but was called from an instance. Instead, it should be directly called from the type: 'String.num_uint64()'.
+8589934592
+8589934592