Browse Source

GDScript: Fix `STANDALONE_EXPRESSION` warning for `preload()`

Danil Alexeev 1 year ago
parent
commit
7dd801c580

+ 2 - 2
doc/classes/ProjectSettings.xml

@@ -554,10 +554,10 @@
 			When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or subclass member variable that would shadow a variable that is inherited from a parent class.
 			When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when defining a local or subclass member variable that would shadow a variable that is inherited from a parent class.
 		</member>
 		</member>
 		<member name="debug/gdscript/warnings/standalone_expression" type="int" setter="" getter="" default="1">
 		<member name="debug/gdscript/warnings/standalone_expression" 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 an expression that has no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
+			When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling an expression that may have no effect on the surrounding code, such as writing [code]2 + 2[/code] as a statement.
 		</member>
 		</member>
 		<member name="debug/gdscript/warnings/standalone_ternary" type="int" setter="" getter="" default="1">
 		<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.
+			When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a ternary expression that may have no effect on the surrounding code, such as writing [code]42 if active else 0[/code] as a statement.
 		</member>
 		</member>
 		<member name="debug/gdscript/warnings/static_called_on_instance" type="int" setter="" getter="" default="1">
 		<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.
 			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.

+ 1 - 0
modules/gdscript/gdscript_analyzer.cpp

@@ -3394,6 +3394,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
 		}
 		}
 
 
 #ifdef DEBUG_ENABLED
 #ifdef DEBUG_ENABLED
+		// FIXME: No warning for built-in constructors and utilities due to early return.
 		if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL &&
 		if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL &&
 				!(p_call->is_super && p_call->function_name == GDScriptLanguage::get_singleton()->strings._init)) {
 				!(p_call->is_super && p_call->function_name == GDScriptLanguage::get_singleton()->strings._init)) {
 			parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
 			parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);

+ 4 - 0
modules/gdscript/gdscript_parser.cpp

@@ -1877,6 +1877,10 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
 					case Node::CALL:
 					case Node::CALL:
 						// Fine.
 						// Fine.
 						break;
 						break;
+					case Node::PRELOAD:
+						// `preload` is a function-like keyword.
+						push_warning(expression, GDScriptWarning::RETURN_VALUE_DISCARDED, "preload");
+						break;
 					case Node::LAMBDA:
 					case Node::LAMBDA:
 						// Standalone lambdas can't be used, so make this an error.
 						// Standalone lambdas can't be used, so make this an error.
 						push_error("Standalone lambdas cannot be accessed. Consider assigning it to a variable.", expression);
 						push_error("Standalone lambdas cannot be accessed. Consider assigning it to a variable.", expression);

+ 1 - 1
modules/gdscript/gdscript_warning.cpp

@@ -74,7 +74,7 @@ String GDScriptWarning::get_message() const {
 		case UNREACHABLE_PATTERN:
 		case UNREACHABLE_PATTERN:
 			return "Unreachable pattern (pattern after wildcard or bind).";
 			return "Unreachable pattern (pattern after wildcard or bind).";
 		case STANDALONE_EXPRESSION:
 		case STANDALONE_EXPRESSION:
-			return "Standalone expression (the line has no effect).";
+			return "Standalone expression (the line may have no effect).";
 		case STANDALONE_TERNARY:
 		case STANDALONE_TERNARY:
 			return "Standalone ternary operator: the return value is being discarded.";
 			return "Standalone ternary operator: the return value is being discarded.";
 		case INCOMPATIBLE_TERNARY:
 		case INCOMPATIBLE_TERNARY:

+ 1 - 0
modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.gd

@@ -4,3 +4,4 @@ func i_return_int() -> int:
 
 
 func test():
 func test():
 	i_return_int()
 	i_return_int()
+	preload("../../utils.notest.gd") # `preload` is a function-like keyword.

+ 4 - 0
modules/gdscript/tests/scripts/parser/warnings/return_value_discarded.out

@@ -3,3 +3,7 @@ GDTEST_OK
 >> Line: 6
 >> Line: 6
 >> RETURN_VALUE_DISCARDED
 >> RETURN_VALUE_DISCARDED
 >> The function "i_return_int()" returns a value that will be discarded if not used.
 >> The function "i_return_int()" returns a value that will be discarded if not used.
+>> WARNING
+>> Line: 7
+>> RETURN_VALUE_DISCARDED
+>> The function "preload()" returns a value that will be discarded if not used.

+ 13 - 0
modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd

@@ -6,3 +6,16 @@ func test():
 	Vector3.ZERO
 	Vector3.ZERO
 	[true, false]
 	[true, false]
 	float(125)
 	float(125)
+	# The following statements should not produce `STANDALONE_EXPRESSION`:
+	var _a = 1
+	_a = 2 # Assignment is a local (or global) side effect.
+	@warning_ignore("redundant_await")
+	await 3 # The `await` operand is usually a coroutine or a signal.
+	absi(4) # A call (in general) can have side effects.
+	@warning_ignore("return_value_discarded")
+	preload("../../utils.notest.gd") # A static initializer may have side effects.
+	"""
+	Python-like "comment".
+	"""
+	@warning_ignore("standalone_ternary")
+	1 if 2 else 3 # Produces `STANDALONE_TERNARY` instead.

+ 4 - 4
modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out

@@ -2,16 +2,16 @@ GDTEST_OK
 >> WARNING
 >> WARNING
 >> Line: 3
 >> Line: 3
 >> STANDALONE_EXPRESSION
 >> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
 >> WARNING
 >> WARNING
 >> Line: 4
 >> Line: 4
 >> STANDALONE_EXPRESSION
 >> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
 >> WARNING
 >> WARNING
 >> Line: 6
 >> Line: 6
 >> STANDALONE_EXPRESSION
 >> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).
 >> WARNING
 >> WARNING
 >> Line: 7
 >> Line: 7
 >> STANDALONE_EXPRESSION
 >> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).
+>> Standalone expression (the line may have no effect).