Skip to content

Commit 8db6a90

Browse files
committed
Improve subscr_expr/getattr/getattr_call chains formatting
1 parent 05c3616 commit 8db6a90

File tree

7 files changed

+280
-28
lines changed

7 files changed

+280
-28
lines changed

gdtoolkit/formatter/expression.py

Lines changed: 71 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ def _format_foldable_to_multiple_lines(
136136
"actual_type_cast": _format_operator_chain_based_expression_to_multiple_lines,
137137
"await_expr": _format_await_expression_to_multiple_lines,
138138
"standalone_call": _format_call_expression_to_multiple_lines,
139-
"getattr_call": _collapse_to_getattr_chain_and_format_to_multiple_lines,
140-
"getattr": _collapse_to_getattr_chain_and_format_to_multiple_lines,
141-
"subscr_expr": _format_subscription_to_multiple_lines,
139+
"getattr_call": _collapse_getattr_tree_to_dot_chain_and_format_to_multiple_lines,
140+
"getattr": _collapse_getattr_tree_to_dot_chain_and_format_to_multiple_lines,
141+
"subscr_expr": _collapse_subscr_expr_tree_to_dot_chain_and_format_to_multiple_lines,
142142
"par_expr": _format_parentheses_to_multiple_lines,
143143
"array": _format_array_to_multiple_lines,
144144
"string": _format_string_to_multiple_lines,
@@ -188,8 +188,9 @@ def _format_foldable_to_multiple_lines(
188188
"func_var_inf": lambda e, ec, c: _append_to_expression_context_and_pass_standalone(
189189
f"var {expression_to_str(e.children[0])} := ", e.children[1], ec, c
190190
),
191-
"getattr_chain": _format_operator_chain_based_expression_to_multiple_lines,
191+
"dot_chain": _format_operator_chain_based_expression_to_multiple_lines,
192192
"actual_getattr_call": _format_call_expression_to_multiple_lines,
193+
"actual_subscr_expr": _format_subscription_to_multiple_lines,
193194
} # type: Dict[str, Callable]
194195
return handlers[expression.data](expression, expression_context, context)
195196

@@ -380,14 +381,23 @@ def _format_call_expression_to_multiple_lines(
380381
)
381382

382383

383-
def _collapse_to_getattr_chain_and_format_to_multiple_lines(
384+
def _collapse_getattr_tree_to_dot_chain_and_format_to_multiple_lines(
384385
expression: Tree, expression_context: ExpressionContext, context: Context
385386
) -> FormattedLines:
386387
return _format_foldable_to_multiple_lines(
387-
_collapse_getattr_tree_to_getattr_chain(expression), expression_context, context
388+
_collapse_getattr_tree_to_dot_chain(expression), expression_context, context
388389
)
389390

390391

392+
def _collapse_subscr_expr_tree_to_dot_chain_and_format_to_multiple_lines(
393+
expression: Tree, expression_context: ExpressionContext, context: Context
394+
) -> FormattedLines:
395+
dot_chain = _collapse_subscr_expr_tree_to_dot_chain(expression)
396+
if len(dot_chain.children) == 1:
397+
dot_chain = dot_chain.children[0]
398+
return _format_foldable_to_multiple_lines(dot_chain, expression_context, context)
399+
400+
391401
def _format_subscription_to_multiple_lines(
392402
expression: Tree, expression_context: ExpressionContext, context: Context
393403
) -> FormattedLines:
@@ -699,20 +709,20 @@ def _format_inline_lambda_statements_to_multiple_lines(
699709
)
700710

701711

702-
def _collapse_getattr_tree_to_getattr_chain(expression: Tree) -> Tree:
703-
reversed_getattr_chain_children = [] # type: List[Node]
712+
def _collapse_getattr_tree_to_dot_chain(expression: Tree) -> Tree:
713+
reversed_dot_chain_children = [] # type: List[Node]
704714
pending_getattr_call_to_match = None
705715
next_expression_to_process = expression # type: Optional[Node]
706716
while next_expression_to_process is not None:
707717
if isinstance(next_expression_to_process, Token):
708-
reversed_getattr_chain_children.append(next_expression_to_process)
718+
reversed_dot_chain_children.append(next_expression_to_process)
709719
next_expression_to_process = None
710720
elif next_expression_to_process.data == "getattr_call":
711721
pending_getattr_call_to_match = next_expression_to_process
712722
next_expression_to_process = next_expression_to_process.children[0]
713723
elif next_expression_to_process.data == "getattr":
714724
if pending_getattr_call_to_match is None:
715-
reversed_getattr_chain_children += reversed(
725+
reversed_dot_chain_children += reversed(
716726
next_expression_to_process.children[1:]
717727
)
718728
else:
@@ -726,21 +736,64 @@ def _collapse_getattr_tree_to_getattr_chain(expression: Tree) -> Tree:
726736
fake_meta,
727737
)
728738
pending_getattr_call_to_match = None
729-
reversed_getattr_chain_children.append(fake_expression)
730-
reversed_getattr_chain_children += reversed(
739+
reversed_dot_chain_children.append(fake_expression)
740+
reversed_dot_chain_children += reversed(
731741
next_expression_to_process.children[1:-1]
732742
)
733743
next_expression_to_process = next_expression_to_process.children[0]
744+
elif next_expression_to_process.data == "subscr_expr":
745+
sub_dot_chain = _collapse_subscr_expr_tree_to_dot_chain(
746+
next_expression_to_process
747+
)
748+
reversed_dot_chain_children = reversed_dot_chain_children + list(
749+
reversed(sub_dot_chain.children)
750+
)
751+
next_expression_to_process = None
734752
else:
735-
reversed_getattr_chain_children.append(next_expression_to_process)
753+
reversed_dot_chain_children.append(next_expression_to_process)
736754
next_expression_to_process = None
737-
getattr_chain_children = list(reversed(reversed_getattr_chain_children))
755+
dot_chain_children = list(reversed(reversed_dot_chain_children))
756+
fake_meta = Meta()
757+
fake_meta.line = dot_chain_children[0].line
758+
fake_meta.end_line = dot_chain_children[-1].end_line
759+
fake_expression = Tree(
760+
"dot_chain",
761+
dot_chain_children,
762+
fake_meta,
763+
)
764+
return fake_expression
765+
766+
767+
def _collapse_subscr_expr_tree_to_dot_chain(expression: Tree) -> Tree:
768+
subscriptee = expression.children[0]
769+
subscript_to_match = expression.children[1]
770+
collapsers = {
771+
"subscr_expr": _collapse_subscr_expr_tree_to_dot_chain,
772+
"getattr": _collapse_getattr_tree_to_dot_chain,
773+
"getattr_call": _collapse_getattr_tree_to_dot_chain,
774+
}
775+
sub_dot_chain = (
776+
collapsers[subscriptee.data](subscriptee).children
777+
if isinstance(subscriptee, Tree) and subscriptee.data in collapsers
778+
else [subscriptee]
779+
)
780+
matching_expr = sub_dot_chain[-1]
781+
fake_meta = Meta()
782+
fake_meta.line = matching_expr.line
783+
fake_meta.end_line = expression.end_line
784+
fake_expression = Tree(
785+
"actual_subscr_expr",
786+
[matching_expr, subscript_to_match],
787+
fake_meta,
788+
)
789+
790+
dot_chain_children = sub_dot_chain[:-1] + [fake_expression]
738791
fake_meta = Meta()
739-
fake_meta.line = getattr_chain_children[0].line
740-
fake_meta.end_line = getattr_chain_children[-1].end_line
792+
fake_meta.line = dot_chain_children[0].line
793+
fake_meta.end_line = dot_chain_children[-1].end_line
741794
fake_expression = Tree(
742-
"getattr_chain",
743-
getattr_chain_children,
795+
"dot_chain",
796+
dot_chain_children,
744797
fake_meta,
745798
)
746799
return fake_expression

gdtoolkit/formatter/expression_to_str.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,9 @@ def expression_to_str(expression: Node) -> str:
138138
e.children[1].value,
139139
standalone_expression_to_str(e.children[2]),
140140
),
141-
"getattr_chain": _operator_chain_based_expression_to_str,
141+
"dot_chain": _operator_chain_based_expression_to_str,
142142
"actual_getattr_call": _getattr_call_to_str,
143+
"actual_subscr_expr": _subscription_to_str,
143144
# patterns (fake expressions):
144145
"list_pattern": lambda e: ", ".join(map(expression_to_str, e.children)),
145146
"test_pattern": _operator_chain_based_expression_to_str,

tests/formatter/input-output-pairs/attribute-expressions.out.gd

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,12 @@ class X:
1111
. rrrrrrrrrrrrr
1212
)
1313
var z = (
14-
(
15-
xxxxxxxxxxx[[
16-
1,
17-
]]
18-
. y
19-
. z
20-
. x
21-
)[[
14+
xxxxxxxxxxx[[
15+
1,
16+
]]
17+
. y
18+
. z
19+
. x[[
2220
1,
2321
]]
2422
. c
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
func cccc(a,b,c):
2+
pass
3+
func foo(aaaaa):
4+
var x = aaaaa.bbbbb.cccc[1].ddd().ffff.ggg.hhh().iii.jjj.kkkkkkk.llllllll.mmmmmmm.nnnnnnnn.ooooo.ppppppppppp
5+
var y = aaaaa.bbbbb.cccc[[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]].ddd().ffff.ggg.hhh().iii.jjj.kkkkkkk.llllllll.mmmmmmm.nnnnnnnn.ooooo.ppppppppppp
6+
var z = aaaaa.bbbbb.cccc[0][1].ddd().ffff.ggg.hhh().iii.jjj.kkkkkkk.llllllll.mmmmmmm.nnnnnnnn.ooooo.ppppppppppp
7+
var q = aaaaa.bbbbb.cccc(1,2,3)[1].ddd().ffff.ggg.hhh().iii.jjj.kkkkkkk.llllllll.mmmmmmm.nnnnnnnn.ooooo.ppppppppppp
8+
var w = cccc(1,2,3)[1].ddd().ffff.ggg.hhh().iii.jjj.kkkkkkk.llllllll.mmmmmmm.nnnnnnnn.ooooo.ppppppppppp.aaaaa.bbbbb
9+
var e = cccc(1,2,3)[1].ddd().ffff.ggg.hhh().iii.jjj.kkkkkkk.llllllll.mmmmmmm.nnnnnnnn.ooooo.ppppppppppp.aaaaa.bbbbb[1]
10+
var f = {1:1}[1].ddd().ffff.ggg.hhh().iii.jjj.kkkkkkk.llllllll.mmmmmmm.nnnnnnnn.ooooo.ppppppppppp.aaaaa.bbbbb[1]
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
func cccc(a, b, c):
2+
pass
3+
4+
5+
func foo(aaaaa):
6+
var x = (
7+
aaaaa
8+
. bbbbb
9+
. cccc[1]
10+
. ddd()
11+
. ffff
12+
. ggg
13+
. hhh()
14+
. iii
15+
. jjj
16+
. kkkkkkk
17+
. llllllll
18+
. mmmmmmm
19+
. nnnnnnnn
20+
. ooooo
21+
. ppppppppppp
22+
)
23+
var y = (
24+
aaaaa
25+
. bbbbb
26+
. cccc[[
27+
1,
28+
1,
29+
1,
30+
1,
31+
1,
32+
1,
33+
1,
34+
1,
35+
1,
36+
1,
37+
1,
38+
1,
39+
1,
40+
1,
41+
1,
42+
1,
43+
1,
44+
1,
45+
1,
46+
1,
47+
1,
48+
1,
49+
1,
50+
1,
51+
1,
52+
1,
53+
1,
54+
1,
55+
1,
56+
1,
57+
1,
58+
1,
59+
1,
60+
1,
61+
1,
62+
1,
63+
1,
64+
1,
65+
1,
66+
1,
67+
1,
68+
1,
69+
1,
70+
1,
71+
1,
72+
1,
73+
1,
74+
1,
75+
1,
76+
1,
77+
1,
78+
1,
79+
1,
80+
1,
81+
1,
82+
1
83+
]]
84+
. ddd()
85+
. ffff
86+
. ggg
87+
. hhh()
88+
. iii
89+
. jjj
90+
. kkkkkkk
91+
. llllllll
92+
. mmmmmmm
93+
. nnnnnnnn
94+
. ooooo
95+
. ppppppppppp
96+
)
97+
var z = (
98+
aaaaa
99+
. bbbbb
100+
. cccc[0][1]
101+
. ddd()
102+
. ffff
103+
. ggg
104+
. hhh()
105+
. iii
106+
. jjj
107+
. kkkkkkk
108+
. llllllll
109+
. mmmmmmm
110+
. nnnnnnnn
111+
. ooooo
112+
. ppppppppppp
113+
)
114+
var q = (
115+
aaaaa
116+
. bbbbb
117+
. cccc(1, 2, 3)[1]
118+
. ddd()
119+
. ffff
120+
. ggg
121+
. hhh()
122+
. iii
123+
. jjj
124+
. kkkkkkk
125+
. llllllll
126+
. mmmmmmm
127+
. nnnnnnnn
128+
. ooooo
129+
. ppppppppppp
130+
)
131+
var w = (
132+
cccc(1, 2, 3)[1]
133+
. ddd()
134+
. ffff
135+
. ggg
136+
. hhh()
137+
. iii
138+
. jjj
139+
. kkkkkkk
140+
. llllllll
141+
. mmmmmmm
142+
. nnnnnnnn
143+
. ooooo
144+
. ppppppppppp
145+
. aaaaa
146+
. bbbbb
147+
)
148+
var e = (
149+
cccc(1, 2, 3)[1]
150+
. ddd()
151+
. ffff
152+
. ggg
153+
. hhh()
154+
. iii
155+
. jjj
156+
. kkkkkkk
157+
. llllllll
158+
. mmmmmmm
159+
. nnnnnnnn
160+
. ooooo
161+
. ppppppppppp
162+
. aaaaa
163+
. bbbbb[1]
164+
)
165+
var f = (
166+
{1: 1}[1]
167+
. ddd()
168+
. ffff
169+
. ggg
170+
. hhh()
171+
. iii
172+
. jjj
173+
. kkkkkkk
174+
. llllllll
175+
. mmmmmmm
176+
. nnnnnnnn
177+
. ooooo
178+
. ppppppppppp
179+
. aaaaa
180+
. bbbbb[1]
181+
)
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
func foo(Global):
22
if true:
33
if !(
4-
Global.current_project.layers[Global.current_project.current_layer]
4+
Global
5+
. current_project
6+
. layers[Global.current_project.current_layer]
57
. can_layer_get_drawn()
68
):
79
return

tests/formatter/test_scripts_validity.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
GODOT_SERVER = "godot4"
1010
EXCEPTIONS = set(
1111
[
12+
# TODO: check (problems with latest Godot 4)
13+
"long-inline-lambdas.in.gd",
14+
"long-inline-lambdas.out.gd",
15+
"simple-inline-lambdas.in.gd",
16+
"simple-inline-lambdas.out.gd",
17+
"inline-lambdas-w-comments.in.gd",
18+
"inline-lambdas-w-comments.out.gd",
1219
# complex expressions where Godot does more than just parsing
1320
"type-cast-corner-case-expressions.in.gd",
1421
"type-cast-corner-case-expressions.out.gd",

0 commit comments

Comments
 (0)