@@ -1585,12 +1585,12 @@ def format(q)
15851585 q . text ( " " ) unless power
15861586
15871587 if operator == :<<
1588- q . text ( operator )
1588+ q . text ( operator . to_s )
15891589 q . text ( " " )
15901590 q . format ( right )
15911591 else
15921592 q . group do
1593- q . text ( operator )
1593+ q . text ( operator . to_s )
15941594
15951595 q . indent do
15961596 q . breakable ( power ? "" : " " )
@@ -2075,12 +2075,12 @@ def format(q)
20752075 end
20762076 end
20772077
2078- # Formats either a Break or Next node.
2078+ # Formats either a Break, Next, or Return node.
20792079 class FlowControlFormatter
20802080 # [String] the keyword to print
20812081 attr_reader :keyword
20822082
2083- # [Break | Next] the node being formatted
2083+ # [Break | Next | Return ] the node being formatted
20842084 attr_reader :node
20852085
20862086 def initialize ( keyword , node )
@@ -2089,43 +2089,118 @@ def initialize(keyword, node)
20892089 end
20902090
20912091 def format ( q )
2092- arguments = node . arguments
2093-
20942092 q . group do
20952093 q . text ( keyword )
20962094
2097- if arguments . parts . any?
2098- if arguments . parts . length == 1
2099- part = arguments . parts . first
2100-
2101- if part . is_a? ( Paren )
2102- if part . contents . body . length == 1 && skip_parens? ( part . contents . body . first )
2103- q . text ( " " )
2104- contents = part . contents . body . first
2105- contents = contents . contents if contents . is_a? ( ArrayLiteral )
2106- q . format ( contents )
2107- else
2108- q . format ( arguments )
2109- end
2110- elsif part . is_a? ( ArrayLiteral )
2111- q . text ( " " )
2112- if part . contents && part . contents . parts . length > 1
2113- q . format ( part . contents )
2114- else
2115- q . format ( arguments )
2116- end
2117- else
2118- format_arguments ( q , "(" , ")" )
2119- end
2120- else
2121- format_arguments ( q , " [" , "]" )
2122- end
2095+ case node . arguments . parts
2096+ in [ ]
2097+ # Here there are no arguments at all, so we're not going to print
2098+ # anything. This would be like if we had:
2099+ #
2100+ # break
2101+ #
2102+ in [ Paren [ contents : { body : [ ArrayLiteral [ contents : { parts : [ _ , _ , *] } ] => array ] } ] ]
2103+ # Here we have a single argument that is a set of parentheses wrapping
2104+ # an array literal that has at least 2 elements. We're going to print
2105+ # the contents of the array directly. This would be like if we had:
2106+ #
2107+ # break([1, 2, 3])
2108+ #
2109+ # which we will print as:
2110+ #
2111+ # break 1, 2, 3
2112+ #
2113+ q . text ( " " )
2114+ format_array_contents ( q , array )
2115+ in [ Paren [ contents : { body : [ ArrayLiteral => statement ] } ] ]
2116+ # Here we have a single argument that is a set of parentheses wrapping
2117+ # an array literal that has 0 or 1 elements. We're going to skip the
2118+ # parentheses but print the array itself. This would be like if we
2119+ # had:
2120+ #
2121+ # break([1])
2122+ #
2123+ # which we will print as:
2124+ #
2125+ # break [1]
2126+ #
2127+ q . text ( " " )
2128+ q . format ( statement )
2129+ in [ Paren [ contents : { body : [ statement ] } ] ] if skip_parens? ( statement )
2130+ # Here we have a single argument that is a set of parentheses that
2131+ # themselves contain a single statement. That statement is a simple
2132+ # value that we can skip the parentheses for. This would be like if we
2133+ # had:
2134+ #
2135+ # break(1)
2136+ #
2137+ # which we will print as:
2138+ #
2139+ # break 1
2140+ #
2141+ q . text ( " " )
2142+ q . format ( statement )
2143+ in [ Paren => part ]
2144+ # Here we have a single argument that is a set of parentheses. We're
2145+ # going to print the parentheses themselves as if they were the set of
2146+ # arguments. This would be like if we had:
2147+ #
2148+ # break(foo.bar)
2149+ #
2150+ q . format ( part )
2151+ in [ ArrayLiteral [ contents : { parts : [ _ , _ , *] } ] => array ]
2152+ # Here there is a single argument that is an array literal with at
2153+ # least two elements. We skip directly into the array literal's
2154+ # elements in order to print the contents. This would be like if we
2155+ # had:
2156+ #
2157+ # break [1, 2, 3]
2158+ #
2159+ # which we will print as:
2160+ #
2161+ # break 1, 2, 3
2162+ #
2163+ q . text ( " " )
2164+ format_array_contents ( q , array )
2165+ in [ ArrayLiteral => part ]
2166+ # Here there is a single argument that is an array literal with 0 or 1
2167+ # elements. In this case we're going to print the array as it is
2168+ # because skipping the brackets would change the remaining. This would
2169+ # be like if we had:
2170+ #
2171+ # break []
2172+ # break [1]
2173+ #
2174+ q . text ( " " )
2175+ q . format ( part )
2176+ in [ _ ]
2177+ # Here there is a single argument that hasn't matched one of our
2178+ # previous cases. We're going to print the argument as it is. This
2179+ # would be like if we had:
2180+ #
2181+ # break foo
2182+ #
2183+ format_arguments ( q , "(" , ")" )
2184+ else
2185+ # If there are multiple arguments, format them all. If the line is
2186+ # going to break into multiple, then use brackets to start and end the
2187+ # expression.
2188+ format_arguments ( q , " [" , "]" )
21232189 end
21242190 end
21252191 end
21262192
21272193 private
21282194
2195+ def format_array_contents ( q , array )
2196+ q . if_break { q . text ( "[" ) }
2197+ q . indent do
2198+ q . breakable ( "" )
2199+ q . format ( array . contents )
2200+ end
2201+ q . breakable ( "" )
2202+ q . if_break { q . text ( "]" ) }
2203+ end
21292204
21302205 def format_arguments ( q , opening , closing )
21312206 q . if_break { q . text ( opening ) }
@@ -2139,9 +2214,9 @@ def format_arguments(q, opening, closing)
21392214
21402215 def skip_parens? ( node )
21412216 case node
2142- in Int | FloatLiteral | ArrayLiteral
2217+ in FloatLiteral | Imaginary | Int | RationalLiteral
21432218 true
2144- in VarRef [ value : GVar | IVar | CVar | Kw | Const ]
2219+ in VarRef [ value : Const | CVar | GVar | IVar | Kw ]
21452220 true
21462221 else
21472222 false
@@ -2307,7 +2382,13 @@ def format_chain(q, children)
23072382 else
23082383 end
23092384
2310- format_child ( q , child , skip_operator : skip_operator , skip_attached : empty_except_last && children . empty? )
2385+ format_child (
2386+ q ,
2387+ child ,
2388+ skip_comments : children . empty? ,
2389+ skip_operator : skip_operator ,
2390+ skip_attached : empty_except_last && children . empty?
2391+ )
23112392
23122393 # If the parent call node has a comment on the message then we need
23132394 # to print the operator trailing in order to keep it working.
@@ -2355,7 +2436,7 @@ def attach_directly?(node)
23552436 . include? ( node . receiver . class )
23562437 end
23572438
2358- def format_child ( q , child , skip_operator : false , skip_attached : false )
2439+ def format_child ( q , child , skip_comments : false , skip_operator : false , skip_attached : false )
23592440 # First, format the actual contents of the child.
23602441 case child
23612442 in Call
@@ -2370,7 +2451,7 @@ def format_child(q, child, skip_operator: false, skip_attached: false)
23702451
23712452 # If there are any comments on this node then we need to explicitly print
23722453 # them out here since we're bypassing the normal comment printing.
2373- if child . comments . any?
2454+ if child . comments . any? && ! skip_comments
23742455 child . comments . each do |comment |
23752456 comment . inline? ? q . text ( " " ) : q . breakable
23762457 comment . format ( q )
@@ -2444,8 +2525,6 @@ def deconstruct_keys(keys)
24442525 end
24452526
24462527 def format ( q )
2447- call_operator = CallOperatorFormatter . new ( operator )
2448-
24492528 # If we're at the top of a call chain, then we're going to do some
24502529 # specialized printing in case we can print it nicely. We _only_ do this
24512530 # at the top of the chain to avoid weird recursion issues.
@@ -4950,14 +5029,24 @@ def self.call(parent)
49505029 # statements.
49515030 module Ternaryable
49525031 class << self
4953- def call ( node )
4954- case node
4955- in { predicate : Assign | Command | CommandCall | MAssign | OpAssign }
5032+ def call ( q , node )
5033+ case q . parents . take ( 2 ) [ 1 ]
5034+ in Paren [ contents : Statements [ body : [ node ] ] ]
5035+ # If this is a conditional inside of a parentheses as the only
5036+ # content, then we don't want to transform it into a ternary.
5037+ # Presumably the user wanted it to be an explicit conditional because
5038+ # there are parentheses around it. So we'll just leave it in place.
49565039 false
4957- in { statements : { body : [ truthy ] } , consequent : Else [ statements : { body : [ falsy ] } ] }
4958- ternaryable? ( truthy ) && ternaryable? ( falsy )
49595040 else
4960- false
5041+ # Otherwise, we're going to check the conditional for certain cases.
5042+ case node
5043+ in { predicate : Assign | Command | CommandCall | MAssign | OpAssign }
5044+ false
5045+ in { statements : { body : [ truthy ] } , consequent : Else [ statements : { body : [ falsy ] } ] }
5046+ ternaryable? ( truthy ) && ternaryable? ( falsy )
5047+ else
5048+ false
5049+ end
49615050 end
49625051 end
49635052
@@ -5005,7 +5094,7 @@ def initialize(keyword, node)
50055094 def format ( q )
50065095 # If we can transform this node into a ternary, then we're going to print
50075096 # a special version that uses the ternary operator if it fits on one line.
5008- if Ternaryable . call ( node )
5097+ if Ternaryable . call ( q , node )
50095098 format_ternary ( q )
50105099 return
50115100 end
@@ -5220,7 +5309,7 @@ def format(q)
52205309 Yield0 , ZSuper
52215310 ]
52225311
5223- if force_flat . include? ( truthy . class ) || force_flat . include? ( falsy . class )
5312+ if q . parent . is_a? ( Paren ) || force_flat . include? ( truthy . class ) || force_flat . include? ( falsy . class )
52245313 q . group { format_flat ( q ) }
52255314 return
52265315 end
@@ -8659,7 +8748,7 @@ def deconstruct_keys(keys)
86598748
86608749 def format ( q )
86618750 parent = q . parents . take ( 2 ) [ 1 ]
8662- ternary = ( parent . is_a? ( If ) || parent . is_a? ( Unless ) ) && Ternaryable . call ( parent )
8751+ ternary = ( parent . is_a? ( If ) || parent . is_a? ( Unless ) ) && Ternaryable . call ( q , parent )
86638752
86648753 q . text ( "not" )
86658754
0 commit comments