@@ -2206,18 +2206,14 @@ def format(q)
2206
2206
end
2207
2207
2208
2208
class CallChainFormatter
2209
- # [Call] the top of the call chain
2209
+ # [Call | MethodAddBlock ] the top of the call chain
2210
2210
attr_reader :node
2211
2211
2212
2212
def initialize ( node )
2213
2213
@node = node
2214
2214
end
2215
2215
2216
2216
def format ( q )
2217
- q . group { q . if_break { format_chain ( q ) } . if_flat { node . format_contents ( q ) } }
2218
- end
2219
-
2220
- def format_chain ( q )
2221
2217
children = [ node ]
2222
2218
2223
2219
# First, walk down the chain until we get to the point where we're not
@@ -2235,6 +2231,14 @@ def format_chain(q)
2235
2231
end
2236
2232
end
2237
2233
2234
+ if children . length > 2
2235
+ q . group { q . if_break { format_chain ( q , children ) } . if_flat { node . format_contents ( q ) } }
2236
+ else
2237
+ node . format_contents ( q )
2238
+ end
2239
+ end
2240
+
2241
+ def format_chain ( q , children )
2238
2242
# We're going to have some specialized behavior for if it's an entire
2239
2243
# chain of calls without arguments except for the last one. This is common
2240
2244
# enough in Ruby source code that it's worth the extra complexity here.
@@ -2256,6 +2260,11 @@ def format_chain(q)
2256
2260
end
2257
2261
2258
2262
q . indent do
2263
+ # We track another variable that checks if you need to move the
2264
+ # operator to the previous line in case there are trailing comments
2265
+ # and a trailing operator.
2266
+ skip_operator = false
2267
+
2259
2268
while child = children . pop
2260
2269
case child
2261
2270
in Call [ receiver : Call [ message : { value : "where" } ] , message : { value : "not" } ]
@@ -2270,7 +2279,17 @@ def format_chain(q)
2270
2279
else
2271
2280
end
2272
2281
2273
- format_child ( q , child , skip_attached : empty_except_last && children . empty? )
2282
+ format_child ( q , child , skip_operator : skip_operator , skip_attached : empty_except_last && children . empty? )
2283
+
2284
+ # If the parent call node has a comment on the message then we need
2285
+ # to print the operator trailing in order to keep it working.
2286
+ case children . last
2287
+ in Call [ message : { comments : [ _ , *] } , operator :]
2288
+ q . format ( CallOperatorFormatter . new ( operator ) )
2289
+ skip_operator = true
2290
+ else
2291
+ skip_operator = false
2292
+ end
2274
2293
2275
2294
# Pop off the formatter's stack so that it aligns with what would
2276
2295
# have happened if we had been formatting normally.
@@ -2308,11 +2327,11 @@ def attach_directly?(child)
2308
2327
. include? ( child . receiver . class )
2309
2328
end
2310
2329
2311
- def format_child ( q , child , skip_attached : false )
2330
+ def format_child ( q , child , skip_operator : false , skip_attached : false )
2312
2331
# First, format the actual contents of the child.
2313
2332
case child
2314
2333
in Call
2315
- q . format ( CallOperatorFormatter . new ( child . operator ) )
2334
+ q . format ( CallOperatorFormatter . new ( child . operator ) ) unless skip_operator
2316
2335
q . format ( child . message ) if child . message != :call
2317
2336
child . format_arguments ( q ) unless skip_attached
2318
2337
in MethodAddBlock
@@ -5918,6 +5937,17 @@ def deconstruct_keys(keys)
5918
5937
end
5919
5938
5920
5939
def format ( q )
5940
+ # If we're at the top of a call chain, then we're going to do some
5941
+ # specialized printing in case we can print it nicely. We _only_ do this
5942
+ # at the top of the chain to avoid weird recursion issues.
5943
+ if !CallChainFormatter . chained? ( q . parent ) && CallChainFormatter . chained? ( call )
5944
+ q . group { q . if_break { CallChainFormatter . new ( self ) . format ( q ) } . if_flat { format_contents ( q ) } }
5945
+ else
5946
+ format_contents ( q )
5947
+ end
5948
+ end
5949
+
5950
+ def format_contents ( q )
5921
5951
q . format ( call )
5922
5952
q . format ( block )
5923
5953
end
0 commit comments