@@ -396,6 +396,79 @@ if you prefer a more readable and reliable, but more verbose syntax.
396396``UNSAFE_* `` warnings make unsafe operations more noticeable, than unsafe lines.
397397Currently, ``UNSAFE_* `` warnings do not cover all cases that unsafe lines cover.
398398
399+ Common unsafe operations and their safe counterparts
400+ ----------------------------------------------------
401+
402+ ``UNSAFE_PROPERTY_ACCESS `` and ``UNSAFE_METHOD_ACCESS `` warnings
403+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
404+
405+ In this example, we aim to set a property and call a method on an object
406+ that has a script attached with ``class_name MyScript `` and that ``extends
407+ Node2D ``. If we have a reference to the object as a ``Node2D `` (for instance,
408+ as it was passed to us by the physics system), we can first check if the
409+ property and method exist and then set and call them if they do::
410+
411+ if "some_property" in node_2d:
412+ node_2d.some_property = 20 # Produces UNSAFE_PROPERTY_ACCESS warning.
413+
414+ if node_2d.has_method("some_function"):
415+ node_2d.some_function() # Produces UNSAFE_METHOD_ACCESS warning.
416+
417+ However, this code will produce ``UNSAFE_PROPERTY_ACCESS `` and
418+ ``UNSAFE_METHOD_ACCESS `` warnings as the property and method are not present
419+ in the referenced type - in this case a ``Node2D ``. To make these operations
420+ safe, you can first check if the object is of type ``MyScript `` using the
421+ ``is `` keyword and then declare a variable with the type ``MyScript `` on
422+ which you can set its properties and call its methods::
423+
424+ if node_2d is MyScript:
425+ var my_script: MyScript = node_2d
426+ my_script.some_property = 20
427+ my_script.some_function()
428+
429+ Alternatively, you can declare a variable and use the ``as `` operator to try
430+ to cast the object. You'll then want to check whether the cast was successful
431+ by confirming that the variable was assigned::
432+
433+ var my_script := node_2d as MyScript
434+ if my_script != null:
435+ my_script.some_property = 20
436+ my_script.some_function()
437+
438+ ``UNSAFE_CAST `` warning
439+ ~~~~~~~~~~~~~~~~~~~~~~~
440+
441+ In this example, we would like the label connected to an object entering our
442+ collision area to show the area's name. Once the object enters the collision
443+ area, the physics system sends a signal with a ``Node2D `` object, and the most
444+ straightforward (but not statically typed) solution to do what we want could
445+ be achieved like this::
446+
447+ func _on_body_entered(body: Node2D) -> void:
448+ body.label.text = name # Produces UNSAFE_PROPERTY_ACCESS warning.
449+
450+ This piece of code produces an ``UNSAFE_PROPERTY_ACCESS `` warning because
451+ ``label `` is not defined in ``Node2D ``. To solve this, we could first check if the
452+ ``label `` property exist and cast it to type ``Label `` before settings its text
453+ property like so::
454+
455+ func _on_body_entered(body: Node2D) -> void:
456+ if "label" in body:
457+ (body.label as Label).text = name # Produces UNSAFE_CAST warning.
458+
459+ However, this produces an ``UNSAFE_CAST `` warning because ``body.label `` is of a
460+ ``Variant `` type. To safely get the property in the type you want, you can use the
461+ ``Object.get() `` method which returns the object as a ``Variant `` value or returns
462+ ``null `` if the property doesn't exist. You can then determine whether the
463+ property contains an object of the right type using the ``is `` keyword, and
464+ finally declare a statically typed variable with the object::
465+
466+ func _on_body_entered(body: Node2D) -> void:
467+ var label_variant: Variant = body.get("label")
468+ if label_variant is Label:
469+ var label: Label = label_variant
470+ label.text = name
471+
399472Cases where you can't specify types
400473-----------------------------------
401474
0 commit comments