Summary
When a script has no class_name and no extends header (an implicit RefCounted script that begins directly with members), --reorder-code treats a per-function @warning_ignore("...") decorator as a standalone/script-level annotation and detaches it from its function. The function silently loses its warning suppression, and with multiple functions the annotations pile up at the top of the file.
Adding any class header (extends RefCounted, extends Node, or class_name Foo) makes the problem disappear. The output also passes --safe (exit 0), so safe mode does not catch it.
Version
gdscript-formatter 0.20.1
Minimal reproduction
A. Single function — annotation separated from its function
Input:
@warning_ignore("unused_parameter")
func do_thing(value: int) -> void:
pass
gdscript-formatter --reorder-code output:
@warning_ignore("unused_parameter")
func do_thing(value: int) -> void:
pass
The annotation is pushed two blank lines away from do_thing, i.e. parsed as a top-level annotation instead of a decorator on the function.
B. Two functions — a function silently loses its suppression
Input:
@warning_ignore("unused_parameter")
func _helper(value: int) -> void:
pass
@warning_ignore("unused_parameter")
func do_thing(value: int) -> void:
pass
gdscript-formatter --reorder-code output:
@warning_ignore("unused_parameter")
@warning_ignore("unused_parameter")
func do_thing(value: int) -> void:
pass
func _helper(value: int) -> void:
pass
Both annotations are hoisted and stacked at the top of the file, detached from their functions. _helper now has no @warning_ignore (lost its suppression); do_thing effectively receives both. The more annotated functions a script has, the more annotations accumulate at the top.
Expected
The @warning_ignore("...") decorator should move with its function during reordering and stay directly attached to it — exactly as it does when the script has a header. Adding extends RefCounted produces the correct result:
Input:
extends RefCounted
@warning_ignore("unused_parameter")
func _helper(value: int) -> void:
pass
@warning_ignore("unused_parameter")
func do_thing(value: int) -> void:
pass
Output (correct — each annotation stays on its function):
extends RefCounted
@warning_ignore("unused_parameter")
func do_thing(value: int) -> void:
pass
@warning_ignore("unused_parameter")
func _helper(value: int) -> void:
pass
Trigger condition (isolated)
| Header |
Result |
no class_name, no extends |
bug reproduces |
extends RefCounted / extends Node / … |
OK |
class_name Foo only |
OK |
class_name Foo + extends … |
OK |
The trigger is specifically a header-less script. It does not depend on the warning name or the parameter name, and it reproduces even with a single function (no actual reordering required, as in example A).
Notes / related
--safe does not reject this; the buggy output passes --reorder-code --safe.
Summary
When a script has no
class_nameand noextendsheader (an implicitRefCountedscript that begins directly with members),--reorder-codetreats a per-function@warning_ignore("...")decorator as a standalone/script-level annotation and detaches it from its function. The function silently loses its warning suppression, and with multiple functions the annotations pile up at the top of the file.Adding any class header (
extends RefCounted,extends Node, orclass_name Foo) makes the problem disappear. The output also passes--safe(exit 0), so safe mode does not catch it.Version
gdscript-formatter 0.20.1Minimal reproduction
A. Single function — annotation separated from its function
Input:
gdscript-formatter --reorder-codeoutput:The annotation is pushed two blank lines away from
do_thing, i.e. parsed as a top-level annotation instead of a decorator on the function.B. Two functions — a function silently loses its suppression
Input:
gdscript-formatter --reorder-codeoutput:Both annotations are hoisted and stacked at the top of the file, detached from their functions.
_helpernow has no@warning_ignore(lost its suppression);do_thingeffectively receives both. The more annotated functions a script has, the more annotations accumulate at the top.Expected
The
@warning_ignore("...")decorator should move with its function during reordering and stay directly attached to it — exactly as it does when the script has a header. Addingextends RefCountedproduces the correct result:Input:
Output (correct — each annotation stays on its function):
Trigger condition (isolated)
class_name, noextendsextends RefCounted/extends Node/ …class_name Fooonlyclass_name Foo+extends …The trigger is specifically a header-less script. It does not depend on the warning name or the parameter name, and it reproduces even with a single function (no actual reordering required, as in example A).
Notes / related
--safedoes not reject this; the buggy output passes--reorder-code --safe.