@@ -2213,18 +2213,14 @@ def format(q)
2213
2213
end
2214
2214
2215
2215
class CallChainFormatter
2216
- # [Call] the top of the call chain
2216
+ # [Call | MethodAddBlock ] the top of the call chain
2217
2217
attr_reader :node
2218
2218
2219
2219
def initialize ( node )
2220
2220
@node = node
2221
2221
end
2222
2222
2223
2223
def format ( q )
2224
- q . group { q . if_break { format_chain ( q ) } . if_flat { node . format_contents ( q ) } }
2225
- end
2226
-
2227
- def format_chain ( q )
2228
2224
children = [ node ]
2229
2225
2230
2226
# First, walk down the chain until we get to the point where we're not
@@ -2242,6 +2238,14 @@ def format_chain(q)
2242
2238
end
2243
2239
end
2244
2240
2241
+ if children . length > 2
2242
+ q . group { q . if_break { format_chain ( q , children ) } . if_flat { node . format_contents ( q ) } }
2243
+ else
2244
+ node . format_contents ( q )
2245
+ end
2246
+ end
2247
+
2248
+ def format_chain ( q , children )
2245
2249
# We're going to have some specialized behavior for if it's an entire
2246
2250
# chain of calls without arguments except for the last one. This is common
2247
2251
# enough in Ruby source code that it's worth the extra complexity here.
@@ -2263,6 +2267,11 @@ def format_chain(q)
2263
2267
end
2264
2268
2265
2269
q . indent do
2270
+ # We track another variable that checks if you need to move the
2271
+ # operator to the previous line in case there are trailing comments
2272
+ # and a trailing operator.
2273
+ skip_operator = false
2274
+
2266
2275
while child = children . pop
2267
2276
case child
2268
2277
in Call [ receiver : Call [ message : { value : "where" } ] , message : { value : "not" } ]
@@ -2277,7 +2286,17 @@ def format_chain(q)
2277
2286
else
2278
2287
end
2279
2288
2280
- format_child ( q , child , skip_attached : empty_except_last && children . empty? )
2289
+ format_child ( q , child , skip_operator : skip_operator , skip_attached : empty_except_last && children . empty? )
2290
+
2291
+ # If the parent call node has a comment on the message then we need
2292
+ # to print the operator trailing in order to keep it working.
2293
+ case children . last
2294
+ in Call [ message : { comments : [ _ , *] } , operator :]
2295
+ q . format ( CallOperatorFormatter . new ( operator ) )
2296
+ skip_operator = true
2297
+ else
2298
+ skip_operator = false
2299
+ end
2281
2300
2282
2301
# Pop off the formatter's stack so that it aligns with what would
2283
2302
# have happened if we had been formatting normally.
@@ -2315,11 +2334,11 @@ def attach_directly?(child)
2315
2334
. include? ( child . receiver . class )
2316
2335
end
2317
2336
2318
- def format_child ( q , child , skip_attached : false )
2337
+ def format_child ( q , child , skip_operator : false , skip_attached : false )
2319
2338
# First, format the actual contents of the child.
2320
2339
case child
2321
2340
in Call
2322
- q . format ( CallOperatorFormatter . new ( child . operator ) )
2341
+ q . format ( CallOperatorFormatter . new ( child . operator ) ) unless skip_operator
2323
2342
q . format ( child . message ) if child . message != :call
2324
2343
child . format_arguments ( q ) unless skip_attached
2325
2344
in MethodAddBlock
@@ -5925,6 +5944,17 @@ def deconstruct_keys(keys)
5925
5944
end
5926
5945
5927
5946
def format ( q )
5947
+ # If we're at the top of a call chain, then we're going to do some
5948
+ # specialized printing in case we can print it nicely. We _only_ do this
5949
+ # at the top of the chain to avoid weird recursion issues.
5950
+ if !CallChainFormatter . chained? ( q . parent ) && CallChainFormatter . chained? ( call )
5951
+ q . group { q . if_break { CallChainFormatter . new ( self ) . format ( q ) } . if_flat { format_contents ( q ) } }
5952
+ else
5953
+ format_contents ( q )
5954
+ end
5955
+ end
5956
+
5957
+ def format_contents ( q )
5928
5958
q . format ( call )
5929
5959
q . format ( block )
5930
5960
end
0 commit comments