1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
// Chain expansion analysis helpers
//
// Pure functions for determining when chains should force expansion:
// - Blank line detection between methods
// - Comment-forced expansion
// - Complex argument detection
use crateis_simple_call_argument;
use ;
use ;
use cratePrinter;
/// Check if there are blank lines BETWEEN methods (not just before the first method)
///
/// Prettier's blank line rules:
/// - Blank line before first method ONLY (no other blank lines) → try to fit inline
/// - Blank lines BETWEEN methods (groups[2+]) → force expand
///
/// Returns true only if there are blank lines after the first method (groups index >= 2),
/// which is when we should force the expanded layout.
pub
/// Check if any chain segment has comments that force expansion.
///
/// Comments between chain segments generally force the chain to expand, EXCEPT
/// for comments before the trailing member/computed member (last member-like node
/// in the chain). Those comments are handled inline via line_suffix in print_node.
///
/// Returns true if comments exist that should force expansion.
pub
/// Whether a node's comment gap holds a comment that forces the chain open — the per-node
/// question of [`has_comments_forcing_expansion`], asked of the CHAIN's share of the gap
/// ([`chain_gap_share_any`]).
///
/// Hole-honoring: the comments a widened range sweeps up belong to the object subtree's own
/// printers or to the chain head, and expanding this chain around one is a layout the
/// un-widened spelling of the same document does not get. And a computed member's share stops
/// at its `[`: the interior is the lookup's own, printed inline around the index — a block
/// against it (`x[/* c */⏎y.p]` prints `x[/* c */ y.p]`), a `//` breaking the brackets — so
/// neither forces the chain. Counting the block forced the chain open on the pass that read it
/// unglued and not on the pass after; counting the `//` broke the chain before a `[` prettier
/// keeps on the object's line (`x[⏎// c⏎y.p⏎]()`). A group the broken index makes break still
/// expands the rest of the chain, as prettier's does (`x[⏎// c⏎y.p⏎]⏎\t.m()⏎\t.n()`).
/// Whether a trailing member's gap carries a line comment the chain must EXPAND around
/// — the exception to the last-member skip in [`has_comments_forcing_expansion`].
///
/// The bar differs by member kind, because what the flat layout does with the comment
/// differs:
///
/// - **computed** (`a.b()⏎// c⏎[0]`): ANY line comment forces — the trailing group
/// prints with no chain-level break of its own, so `print_node_inner` emits a
/// forced break for the gap, since a deferred `//` would swallow the `[i]` printed
/// after it; the chain must expand around that break (left flat, the hardline
/// lands in the one-line variant and renders unindented).
/// - **plain** (`fn()⏎// c⏎.bar`): an OWN-LINE line comment forces (own-line against
/// the gap's start — the object's printed end). A lone same-line `//` stays on the
/// flat path, whose `line_suffix` deferral past the member is the sanctioned
/// collapse (`fn().bar; // c`); an own-line `//` deferred the same way would lose
/// its authored line and weld behind a same-line one.
///
/// The collapse's licence is that the deferral is **lossless**, and it stops exactly
/// where that stops — so a SAME-LINE `//` forces too, in the three places something else
/// can reach the line it is about to take:
///
/// 1. **another comment in the same gap**, behind it. The flat path emits the follower
/// *inline* while the `//` is deferred, so the run comes out REORDERED and the
/// follower loses its authored line (`fn() // c1⏎/* c2 */⏎.bar` →
/// `fn() /* c2 */.bar; // c1`). Asked on the **on-page** axis: a follower glued to
/// the property is *owned* by it — printed by the member's own doc rather than by
/// this gap, which does not spare it from landing ahead of the deferred comment
/// (trailing_member_gap_comment_run).
/// 2. **a comment past the chain** that can reach the same line end
/// ([`Printer::comment_reaches_line_end_after`]): any comment between the chain's end
/// and the end of its enclosing statement, behind whatever tokens (a lookup's
/// brackets and the call on them, `obj[fn()// c⏎.bar](); /* c1 */`; an arrow body,
/// `(() => fn()// c⏎.bar)[i] /* c1 */`; an operator's right side; a following
/// argument), or a trailer past the statement's end through closing punctuation
/// (`fn()// c⏎.bar; // c1`), in-source axis. Both would flush at one line end,
/// welding (`fn().bar; // c // c1`, the second `//` becoming text of the first) or
/// reordering past a block (`fn().bar; /* c1 */ // c`). Conservative by design: a
/// layout break between the two only makes the expansion unneeded, never wrong
/// (trailing_member_gap_comment_statement_trailer).
/// 3. **the host's own output**, whenever this printer does NOT own the line it would defer
/// to (`!EmbedContext::printer_owns_line` — every Svelte template island). The `//` rides
/// to the end of a line the HOST owns: past the island's closing `}` the document is
/// markup, so the comment comes out as rendered page TEXT
/// (`<a href={fn().bar}>t</a> // c`) — a different page, not a weld. Unlike the two above
/// this one is not about another comment at all, so no source read can see it; the
/// printer that owns its lines declares that, and everyone else gets the safe answer by
/// default (svelte/expressions/chain_trailing_member_gap_line_comment).
/// Check if a call node has complex (non-simple) arguments
///
/// Uses Prettier's `isSimpleCallArgument` logic (inverted) to determine
/// if a 3+ call chain should force break.
pub
/// Check if chain ends with member access (not a call)
///
/// Used to enable the intermediate state where callback args expand but chain stays inline.
/// Skips trailing NonNull assertions - `.length!` counts as ending with member.
pub