Merge pull request #84043 from dalexeev/gds-fix-unsafe-cast-warning
GDScript: Fix `UNSAFE_CAST` warning
This commit is contained in:
commit
f8ca571efe
|
@ -574,7 +574,7 @@
|
|||
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when using an expression whose type may not be compatible with the function parameter expected.
|
||||
</member>
|
||||
<member name="debug/gdscript/warnings/unsafe_cast" type="int" setter="" getter="" default="0">
|
||||
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when performing an unsafe cast.
|
||||
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when a [Variant] value is cast to a non-Variant.
|
||||
</member>
|
||||
<member name="debug/gdscript/warnings/unsafe_method_access" type="int" setter="" getter="" default="0">
|
||||
When set to [code]warn[/code] or [code]error[/code], produces a warning or an error respectively when calling a method whose presence is not guaranteed at compile-time in the class.
|
||||
|
|
|
@ -3439,9 +3439,7 @@ void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
|
|||
if (op_type.is_variant() || !op_type.is_hard_type()) {
|
||||
mark_node_unsafe(p_cast);
|
||||
#ifdef DEBUG_ENABLED
|
||||
if (op_type.is_variant() && !op_type.is_hard_type()) {
|
||||
parser->push_warning(p_cast, GDScriptWarning::UNSAFE_CAST, cast_type.to_string());
|
||||
}
|
||||
parser->push_warning(p_cast, GDScriptWarning::UNSAFE_CAST, cast_type.to_string());
|
||||
#endif
|
||||
} else {
|
||||
bool valid = false;
|
||||
|
|
|
@ -96,7 +96,7 @@ String GDScriptWarning::get_message() const {
|
|||
return vformat(R"*(The method "%s()" is not present on the inferred type "%s" (but may be present on a subtype).)*", symbols[0], symbols[1]);
|
||||
case UNSAFE_CAST:
|
||||
CHECK_SYMBOLS(1);
|
||||
return vformat(R"(The value is cast to "%s" but has an unknown type.)", symbols[0]);
|
||||
return vformat(R"(Casting "Variant" to "%s" is unsafe.)", symbols[0]);
|
||||
case UNSAFE_CALL_ARGUMENT:
|
||||
CHECK_SYMBOLS(5);
|
||||
return vformat(R"*(The argument %s of the %s "%s()" requires the subtype "%s" but the supertype "%s" was provided.)*", symbols[0], symbols[1], symbols[2], symbols[3], symbols[4]);
|
||||
|
|
|
@ -65,7 +65,7 @@ public:
|
|||
INFERRED_DECLARATION, // Variable/constant/parameter has an implicitly inferred static type.
|
||||
UNSAFE_PROPERTY_ACCESS, // Property not found in the detected type (but can be in subtypes).
|
||||
UNSAFE_METHOD_ACCESS, // Function not found in the detected type (but can be in subtypes).
|
||||
UNSAFE_CAST, // Cast used in an unknown type.
|
||||
UNSAFE_CAST, // Casting a `Variant` value to non-`Variant`.
|
||||
UNSAFE_CALL_ARGUMENT, // Function call argument is of a supertype of the required type.
|
||||
UNSAFE_VOID_RETURN, // Function returns void but returned a call to a function that can't be type checked.
|
||||
RETURN_VALUE_DISCARDED, // Function call returns something but the value isn't used.
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
func test():
|
||||
var integer := 1
|
||||
print(integer as Array)
|
|
@ -0,0 +1,2 @@
|
|||
GDTEST_ANALYZER_ERROR
|
||||
Invalid cast. Cannot convert from "int" to "Array".
|
|
@ -0,0 +1,3 @@
|
|||
func test():
|
||||
var integer := 1
|
||||
print(integer as Node)
|
|
@ -0,0 +1,2 @@
|
|||
GDTEST_ANALYZER_ERROR
|
||||
Invalid cast. Cannot convert from "int" to "Node".
|
|
@ -0,0 +1,3 @@
|
|||
func test():
|
||||
var object := RefCounted.new()
|
||||
print(object as int)
|
|
@ -0,0 +1,2 @@
|
|||
GDTEST_ANALYZER_ERROR
|
||||
Invalid cast. Cannot convert from "RefCounted" to "int".
|
|
@ -0,0 +1,24 @@
|
|||
# We don't want to execute it because of errors, just analyze.
|
||||
func no_exec_test():
|
||||
var weak_int = 1
|
||||
print(weak_int as Variant) # No warning.
|
||||
print(weak_int as int)
|
||||
print(weak_int as Node)
|
||||
|
||||
var weak_node = Node.new()
|
||||
print(weak_node as Variant) # No warning.
|
||||
print(weak_node as int)
|
||||
print(weak_node as Node)
|
||||
|
||||
var weak_variant = null
|
||||
print(weak_variant as Variant) # No warning.
|
||||
print(weak_variant as int)
|
||||
print(weak_variant as Node)
|
||||
|
||||
var hard_variant: Variant = null
|
||||
print(hard_variant as Variant) # No warning.
|
||||
print(hard_variant as int)
|
||||
print(hard_variant as Node)
|
||||
|
||||
func test():
|
||||
pass
|
|
@ -0,0 +1,33 @@
|
|||
GDTEST_OK
|
||||
>> WARNING
|
||||
>> Line: 5
|
||||
>> UNSAFE_CAST
|
||||
>> Casting "Variant" to "int" is unsafe.
|
||||
>> WARNING
|
||||
>> Line: 6
|
||||
>> UNSAFE_CAST
|
||||
>> Casting "Variant" to "Node" is unsafe.
|
||||
>> WARNING
|
||||
>> Line: 10
|
||||
>> UNSAFE_CAST
|
||||
>> Casting "Variant" to "int" is unsafe.
|
||||
>> WARNING
|
||||
>> Line: 11
|
||||
>> UNSAFE_CAST
|
||||
>> Casting "Variant" to "Node" is unsafe.
|
||||
>> WARNING
|
||||
>> Line: 15
|
||||
>> UNSAFE_CAST
|
||||
>> Casting "Variant" to "int" is unsafe.
|
||||
>> WARNING
|
||||
>> Line: 16
|
||||
>> UNSAFE_CAST
|
||||
>> Casting "Variant" to "Node" is unsafe.
|
||||
>> WARNING
|
||||
>> Line: 20
|
||||
>> UNSAFE_CAST
|
||||
>> Casting "Variant" to "int" is unsafe.
|
||||
>> WARNING
|
||||
>> Line: 21
|
||||
>> UNSAFE_CAST
|
||||
>> Casting "Variant" to "Node" is unsafe.
|
|
@ -0,0 +1,4 @@
|
|||
func test():
|
||||
var node := Node.new()
|
||||
node.free()
|
||||
print(node as Node2D)
|
|
@ -0,0 +1,6 @@
|
|||
GDTEST_RUNTIME_ERROR
|
||||
>> SCRIPT ERROR
|
||||
>> on function: test()
|
||||
>> runtime/errors/cast_freed_object.gd
|
||||
>> 4
|
||||
>> Trying to cast a freed object.
|
|
@ -0,0 +1,4 @@
|
|||
func test():
|
||||
var integer: Variant = 1
|
||||
@warning_ignore("unsafe_cast")
|
||||
print(integer as Array)
|
|
@ -0,0 +1,6 @@
|
|||
GDTEST_RUNTIME_ERROR
|
||||
>> SCRIPT ERROR
|
||||
>> on function: test()
|
||||
>> runtime/errors/cast_int_to_array.gd
|
||||
>> 4
|
||||
>> Invalid cast: could not convert value to 'Array'.
|
|
@ -0,0 +1,4 @@
|
|||
func test():
|
||||
var integer: Variant = 1
|
||||
@warning_ignore("unsafe_cast")
|
||||
print(integer as Node)
|
|
@ -0,0 +1,6 @@
|
|||
GDTEST_RUNTIME_ERROR
|
||||
>> SCRIPT ERROR
|
||||
>> on function: test()
|
||||
>> runtime/errors/cast_int_to_object.gd
|
||||
>> 4
|
||||
>> Invalid cast: can't convert a non-object value to an object type.
|
|
@ -0,0 +1,4 @@
|
|||
func test():
|
||||
var object: Variant = RefCounted.new()
|
||||
@warning_ignore("unsafe_cast")
|
||||
print(object as int)
|
|
@ -0,0 +1,6 @@
|
|||
GDTEST_RUNTIME_ERROR
|
||||
>> SCRIPT ERROR
|
||||
>> on function: test()
|
||||
>> runtime/errors/cast_object_to_int.gd
|
||||
>> 4
|
||||
>> Invalid cast: could not convert value to 'int'.
|
|
@ -0,0 +1,24 @@
|
|||
func print_value(value: Variant) -> void:
|
||||
if value is Object:
|
||||
@warning_ignore("unsafe_method_access")
|
||||
print("<%s>" % value.get_class())
|
||||
else:
|
||||
print(var_to_str(value))
|
||||
|
||||
func test():
|
||||
var int_value := 1
|
||||
print_value(int_value as Variant)
|
||||
print_value(int_value as int)
|
||||
print_value(int_value as float)
|
||||
|
||||
var node_value := Node.new()
|
||||
print_value(node_value as Variant)
|
||||
print_value(node_value as Object)
|
||||
print_value(node_value as Node)
|
||||
print_value(node_value as Node2D)
|
||||
node_value.free()
|
||||
|
||||
var null_value = null
|
||||
print_value(null_value as Variant)
|
||||
@warning_ignore("unsafe_cast")
|
||||
print_value(null_value as Node)
|
|
@ -0,0 +1,10 @@
|
|||
GDTEST_OK
|
||||
1
|
||||
1
|
||||
1.0
|
||||
<Node>
|
||||
<Node>
|
||||
<Node>
|
||||
null
|
||||
null
|
||||
null
|
Loading…
Reference in New Issue