Skip to content

Commit 79d8236

Browse files
committed
Add line wrapping in annotation arguments, fix space after ... variadic
parameter Close #330 Close #331
1 parent 8e52c65 commit 79d8236

6 files changed

Lines changed: 88 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ This file documents the changes made to the formatter with each release.
1313
- Removed space between lambda function name and parameter list
1414
- Force @export and @onready annotations to stay on the same line as a variable but keep other annotations separate
1515
- Stop trying to format any code containing parse errors. Until now we tried to still format definitions around the code with errors, but this can lead to cases where the formatter produces invalid code
16+
- Add line wrapping for annotation arguments (#330)
1617

1718
### Fixed
1819

@@ -23,6 +24,7 @@ This file documents the changes made to the formatter with each release.
2324
- Fixed various edge cases with ignored directories: paths are now normalized before comparison
2425
- Fixed special get syntax with parentheses having an extra space (#314)
2526
- Output warnings to stderr when using reorder and safe mode together (#332)
27+
- Removed the space between `...` and variadic parameter names (#331)
2628

2729
## Release 0.24.0 (2026-07-25)
2830

src/formatter.rs

Lines changed: 59 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,15 @@ fn process_node(
360360
}
361361
GDScriptNodeKind::Lambda => process_lambda(input, node, render_elements),
362362
GDScriptNodeKind::Function => process_function(input, node, render_elements),
363+
GDScriptNodeKind::Variable
364+
| GDScriptNodeKind::ExportVariable
365+
| GDScriptNodeKind::OnReadyVariable
366+
if has_inline_annotations_child(node) =>
367+
{
368+
let group_index = begin_group(render_elements);
369+
process_children_with_spacing(input, node, render_elements);
370+
finish_group(render_elements, group_index);
371+
}
363372
GDScriptNodeKind::SetGet => process_setget(input, node, render_elements),
364373
GDScriptNodeKind::ParenthesizedExpression => {
365374
process_parenthesized_expression(input, node, render_elements)
@@ -371,6 +380,46 @@ fn process_node(
371380
}
372381
}
373382

383+
fn has_inline_annotations_child(node: tree_sitter::Node) -> bool {
384+
let mut child_index = 0;
385+
while child_index < node.child_count() {
386+
if let Some(child) = node.child(child_index as u32)
387+
&& GDScriptNodeKind::get_kind_from_ast_node(child) == GDScriptNodeKind::Annotations
388+
{
389+
let Some(next_child) = node.child((child_index + 1) as u32) else {
390+
return false;
391+
};
392+
return child.end_position().row == next_child.start_position().row;
393+
}
394+
child_index += 1;
395+
}
396+
false
397+
}
398+
399+
fn is_inline_variable_annotation_arguments(node: tree_sitter::Node) -> bool {
400+
let Some(annotation) = node.parent() else {
401+
return false;
402+
};
403+
if GDScriptNodeKind::get_kind_from_ast_node(annotation) != GDScriptNodeKind::Annotation {
404+
return false;
405+
}
406+
let Some(annotations) = annotation.parent() else {
407+
return false;
408+
};
409+
if GDScriptNodeKind::get_kind_from_ast_node(annotations) != GDScriptNodeKind::Annotations {
410+
return false;
411+
}
412+
let Some(variable) = annotations.parent() else {
413+
return false;
414+
};
415+
matches!(
416+
GDScriptNodeKind::get_kind_from_ast_node(variable),
417+
GDScriptNodeKind::Variable
418+
| GDScriptNodeKind::ExportVariable
419+
| GDScriptNodeKind::OnReadyVariable
420+
) && has_inline_annotations_child(variable)
421+
}
422+
374423
/// Groups a function header (the declaration line/first line) separately from
375424
/// its body so the complete header, including the return type, is treated as
376425
/// one unit when deciding whether parameters need to be wrapped onto multiple
@@ -1588,9 +1637,7 @@ fn process_container(
15881637
if let Some(open) = node.child(0) {
15891638
process_node(input, open, render_elements);
15901639
}
1591-
if node_kind == GDScriptNodeKind::Dictionary
1592-
|| node_kind == GDScriptNodeKind::EnumeratorList
1593-
{
1640+
if node_kind == GDScriptNodeKind::Dictionary {
15941641
render_elements.push(RenderElement::Space);
15951642
}
15961643
if let Some(close) = node.child(1) {
@@ -1603,7 +1650,10 @@ fn process_container(
16031650
&& node.parent().is_some_and(|parent| {
16041651
GDScriptNodeKind::get_kind_from_ast_node(parent) == GDScriptNodeKind::Function
16051652
});
1606-
let group_index = if is_function_parameters {
1653+
let group_index = if is_function_parameters
1654+
|| (node_kind == GDScriptNodeKind::Arguments
1655+
&& is_inline_variable_annotation_arguments(node))
1656+
{
16071657
None
16081658
} else {
16091659
Some(begin_group(render_elements))
@@ -1620,8 +1670,7 @@ fn process_container(
16201670
render_elements.push(RenderElement::SoftLine);
16211671

16221672
// When we have delimiters like in a function calls, we apply just one
1623-
// indent. Before, we applied double indents by default, treating them as
1624-
// continuation lines.
1673+
// indent. We don't treat them as continuation lines.
16251674
let indent_index = begin_indent(render_elements, 1);
16261675

16271676
let mut has_comment = false;
@@ -3106,6 +3155,10 @@ fn process_separator_between_sibling_nodes(
31063155
return;
31073156
}
31083157

3158+
if previous_child.kind() == "..." {
3159+
return;
3160+
}
3161+
31093162
if parent_kind == GDScriptNodeKind::UnaryOperator
31103163
&& (previous_child.kind() == "~"
31113164
|| previous_child.kind() == "!"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
func only_variadic(...args):
2+
pass
3+
4+
5+
func call_with_many_arguments(
6+
first_argument: String,
7+
second_argument: String,
8+
third_argument: String,
9+
...args: Array,
10+
):
11+
pass

tests/expected/variable_annotations.gd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
@onready var health := max_health
55
@export_range(10.0, 200.0) var jump_height := 50.0
66
@export_range(0.1, 1.5) var jump_time_to_peak := 0.37
7+
@export_custom(
8+
PROPERTY_HINT_TYPE_STRING,
9+
"%d/%d:Zero,One,Two" % [TYPE_INT, PROPERTY_HINT_ENUM],
10+
) var test_export_custom: Array
711

812
@export_group("my group")
913
@export var v = 1
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
func only_variadic(...args):
2+
pass
3+
4+
5+
func call_with_many_arguments(
6+
first_argument: String,
7+
second_argument: String,
8+
third_argument: String,
9+
...args: Array
10+
):
11+
pass

tests/input/variable_annotations.gd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ var health:=max_health
66
@export_range(10.0, 200.0) var jump_height:=50.0
77
@export_range(0.1, 1.5)
88
var jump_time_to_peak:=0.37
9+
@export_custom(PROPERTY_HINT_TYPE_STRING, "%d/%d:Zero,One,Two" % [TYPE_INT, PROPERTY_HINT_ENUM]) var test_export_custom: Array
910

1011
@export_group("my group")
1112
@export var v = 1

0 commit comments

Comments
 (0)