Skip to content

Commit 929726b

Browse files
committed
Remove remaining pattern matching
1 parent 7b6dbeb commit 929726b

File tree

4 files changed

+129
-117
lines changed

4 files changed

+129
-117
lines changed

bin/ybench

-17
This file was deleted.

lib/syntax_tree/formatter.rb

+4
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ def format_each(nodes)
120120
nodes.each { |node| format(node) }
121121
end
122122

123+
def grandparent
124+
stack[-3]
125+
end
126+
123127
def parent
124128
stack[-2]
125129
end

lib/syntax_tree/node.rb

+114-90
Original file line numberDiff line numberDiff line change
@@ -2298,10 +2298,15 @@ def format_arguments(q, opening, closing)
22982298

22992299
def skip_parens?(node)
23002300
case node
2301-
in FloatLiteral | Imaginary | Int | RationalLiteral
2302-
true
2303-
in VarRef[value: Const | CVar | GVar | IVar | Kw]
2301+
when FloatLiteral, Imaginary, Int, RationalLiteral
23042302
true
2303+
when VarRef
2304+
case node.value
2305+
when Const, CVar, GVar, IVar, Kw
2306+
true
2307+
else
2308+
false
2309+
end
23052310
else
23062311
false
23072312
end
@@ -2364,8 +2369,14 @@ def comments
23642369

23652370
def format(q)
23662371
case operator
2367-
in :"::" | Op[value: "::"]
2372+
when :"::"
23682373
q.text(".")
2374+
when Op
2375+
if operator.value == "::"
2376+
q.text(".")
2377+
else
2378+
operator.format(q)
2379+
end
23692380
else
23702381
operator.format(q)
23712382
end
@@ -2401,13 +2412,18 @@ def format(q)
24012412
# First, walk down the chain until we get to the point where we're not
24022413
# longer at a chainable node.
24032414
loop do
2404-
case children.last
2405-
in Call[receiver: Call]
2406-
children << children.last.receiver
2407-
in Call[receiver: MethodAddBlock[call: Call]]
2408-
children << children.last.receiver
2409-
in MethodAddBlock[call: Call]
2410-
children << children.last.call
2415+
case (child = children.last)
2416+
when Call
2417+
case (receiver = child.receiver)
2418+
when Call
2419+
children << receiver
2420+
when MethodAddBlock
2421+
receiver.call.is_a?(Call) ? children << receiver : break
2422+
else
2423+
break
2424+
end
2425+
when MethodAddBlock
2426+
child.call.is_a?(Call) ? children << child.call : break
24112427
else
24122428
break
24132429
end
@@ -2426,10 +2442,8 @@ def format(q)
24262442
# nodes.
24272443
parent = parents[3] if parent.is_a?(DoBlock)
24282444

2429-
case parent
2430-
in MethodAddBlock[call: FCall[value: { value: "sig" }]]
2445+
if parent.is_a?(MethodAddBlock) && parent.call.is_a?(FCall) && parent.call.value.value == "sig"
24312446
threshold = 2
2432-
else
24332447
end
24342448
end
24352449

@@ -2472,20 +2486,17 @@ def format_chain(q, children)
24722486
skip_operator = false
24732487

24742488
while (child = children.pop)
2475-
case child
2476-
in Call[
2477-
receiver: Call[message: { value: "where" }],
2478-
message: { value: "not" }
2479-
]
2480-
# This is very specialized behavior wherein we group
2481-
# .where.not calls together because it looks better. For more
2482-
# information, see
2483-
# https://github.com/prettier/plugin-ruby/issues/862.
2484-
in Call
2485-
# If we're at a Call node and not a MethodAddBlock node in the
2486-
# chain then we're going to add a newline so it indents properly.
2487-
q.breakable_empty
2488-
else
2489+
if child.is_a?(Call)
2490+
if child.receiver.is_a?(Call) && child.receiver.message.value == "where" && child.message.value == "not"
2491+
# This is very specialized behavior wherein we group
2492+
# .where.not calls together because it looks better. For more
2493+
# information, see
2494+
# https://github.com/prettier/plugin-ruby/issues/862.
2495+
else
2496+
# If we're at a Call node and not a MethodAddBlock node in the
2497+
# chain then we're going to add a newline so it indents properly.
2498+
q.breakable_empty
2499+
end
24892500
end
24902501

24912502
format_child(
@@ -2498,9 +2509,9 @@ def format_chain(q, children)
24982509

24992510
# If the parent call node has a comment on the message then we need
25002511
# to print the operator trailing in order to keep it working.
2501-
case children.last
2502-
in Call[message: { comments: [_, *] }, operator:]
2503-
q.format(CallOperatorFormatter.new(operator))
2512+
last_child = children.last
2513+
if last_child.is_a?(Call) && last_child.message.comments.any?
2514+
q.format(CallOperatorFormatter.new(last_child.operator))
25042515
skip_operator = true
25052516
else
25062517
skip_operator = false
@@ -2515,18 +2526,22 @@ def format_chain(q, children)
25152526

25162527
if empty_except_last
25172528
case node
2518-
in Call
2529+
when Call
25192530
node.format_arguments(q)
2520-
in MethodAddBlock[block:]
2521-
q.format(block)
2531+
when MethodAddBlock
2532+
q.format(node.block)
25222533
end
25232534
end
25242535
end
25252536

25262537
def self.chained?(node)
2538+
return false if ENV["STREE_FAST_FORMAT"]
2539+
25272540
case node
2528-
in Call | MethodAddBlock[call: Call]
2541+
when Call
25292542
true
2543+
when MethodAddBlock
2544+
node.call.is_a?(Call)
25302545
else
25312546
false
25322547
end
@@ -2538,9 +2553,12 @@ def self.chained?(node)
25382553
# want to indent the first call. So we'll pop off the first children and
25392554
# format it separately here.
25402555
def attach_directly?(node)
2541-
[ArrayLiteral, HashLiteral, Heredoc, If, Unless, XStringLiteral].include?(
2542-
node.receiver.class
2543-
)
2556+
case node.receiver
2557+
when ArrayLiteral, HashLiteral, Heredoc, If, Unless, XStringLiteral
2558+
true
2559+
else
2560+
false
2561+
end
25442562
end
25452563

25462564
def format_child(
@@ -2552,15 +2570,15 @@ def format_child(
25522570
)
25532571
# First, format the actual contents of the child.
25542572
case child
2555-
in Call
2573+
when Call
25562574
q.group do
25572575
unless skip_operator
25582576
q.format(CallOperatorFormatter.new(child.operator))
25592577
end
25602578
q.format(child.message) if child.message != :call
25612579
child.format_arguments(q) unless skip_attached
25622580
end
2563-
in MethodAddBlock
2581+
when MethodAddBlock
25642582
q.format(child.block) unless skip_attached
25652583
end
25662584

@@ -2643,9 +2661,7 @@ def format(q)
26432661
# If we're at the top of a call chain, then we're going to do some
26442662
# specialized printing in case we can print it nicely. We _only_ do this
26452663
# at the top of the chain to avoid weird recursion issues.
2646-
if !ENV["STREE_SKIP_CALL_CHAIN"] &&
2647-
!CallChainFormatter.chained?(q.parent) &&
2648-
CallChainFormatter.chained?(receiver)
2664+
if CallChainFormatter.chained?(receiver) && !CallChainFormatter.chained?(q.parent)
26492665
q.group do
26502666
q
26512667
.if_break { CallChainFormatter.new(self).format(q) }
@@ -2658,9 +2674,9 @@ def format(q)
26582674

26592675
def format_arguments(q)
26602676
case arguments
2661-
in ArgParen
2677+
when ArgParen
26622678
q.format(arguments)
2663-
in Args
2679+
when Args
26642680
q.text(" ")
26652681
q.format(arguments)
26662682
else
@@ -2821,7 +2837,7 @@ def format(q)
28212837
q.format(operator)
28222838

28232839
case pattern
2824-
in AryPtn | FndPtn | HshPtn
2840+
when AryPtn, FndPtn, HshPtn
28252841
q.text(" ")
28262842
q.format(pattern)
28272843
else
@@ -5286,28 +5302,35 @@ def self.call(parent)
52865302
module Ternaryable
52875303
class << self
52885304
def call(q, node)
5289-
case q.parents.take(2)[1]
5290-
in Paren[contents: Statements[body: [node]]]
5291-
# If this is a conditional inside of a parentheses as the only
5292-
# content, then we don't want to transform it into a ternary.
5293-
# Presumably the user wanted it to be an explicit conditional because
5294-
# there are parentheses around it. So we'll just leave it in place.
5295-
false
5296-
else
5297-
# Otherwise, we're going to check the conditional for certain cases.
5298-
case node
5299-
in predicate: Assign | Command | CommandCall | MAssign | OpAssign
5300-
false
5301-
in predicate: Not[parentheses: false]
5302-
false
5303-
in {
5304-
statements: { body: [truthy] },
5305-
consequent: Else[statements: { body: [falsy] }] }
5306-
ternaryable?(truthy) && ternaryable?(falsy)
5307-
else
5308-
false
5309-
end
5305+
return false if ENV["STREE_FAST_FORMAT"]
5306+
5307+
# If this is a conditional inside of a parentheses as the only content,
5308+
# then we don't want to transform it into a ternary. Presumably the user
5309+
# wanted it to be an explicit conditional because there are parentheses
5310+
# around it. So we'll just leave it in place.
5311+
grandparent = q.grandparent
5312+
if grandparent.is_a?(Paren) && (body = grandparent.contents.body) && body.length == 1 && body.first == node
5313+
return false
5314+
end
5315+
5316+
# Otherwise, we'll check the type of predicate. For certain nodes we
5317+
# want to force it to not be a ternary, like if the predicate is an
5318+
# assignment because it's hard to read.
5319+
case node.predicate
5320+
when Assign, Command, CommandCall, MAssign, OpAssign
5321+
return false
5322+
when Not
5323+
return false unless node.predicate.parentheses?
53105324
end
5325+
5326+
# If there's no Else, then this can't be represented as a ternary.
5327+
return false unless node.consequent.is_a?(Else)
5328+
5329+
truthy_body = node.statements.body
5330+
falsy_body = node.consequent.statements.body
5331+
5332+
(truthy_body.length == 1) && ternaryable?(truthy_body.first) &&
5333+
(falsy_body.length == 1) && ternaryable?(falsy_body.first)
53115334
end
53125335

53135336
private
@@ -5316,24 +5339,23 @@ def call(q, node)
53165339
# parentheses around them. In this case we say they cannot be ternaried
53175340
# and default instead to breaking them into multiple lines.
53185341
def ternaryable?(statement)
5319-
# This is a list of nodes that should not be allowed to be a part of a
5320-
# ternary clause.
5321-
no_ternary = [
5322-
Alias, Assign, Break, Command, CommandCall, Heredoc, If, IfMod, IfOp,
5342+
case statement
5343+
when Alias, Assign, Break, Command, CommandCall, Heredoc, If, IfMod, IfOp,
53235344
Lambda, MAssign, Next, OpAssign, RescueMod, Return, Return0, Super,
53245345
Undef, Unless, UnlessMod, Until, UntilMod, VarAlias, VoidStmt, While,
53255346
WhileMod, Yield, Yield0, ZSuper
5326-
]
5327-
5328-
# Here we're going to check that the only statement inside the
5329-
# statements node is no a part of our denied list of nodes that can be
5330-
# ternaries.
5331-
#
5332-
# If the user is using one of the lower precedence "and" or "or"
5333-
# operators, then we can't use a ternary expression as it would break
5334-
# the flow control.
5335-
!no_ternary.include?(statement.class) &&
5336-
!(statement.is_a?(Binary) && %i[and or].include?(statement.operator))
5347+
# This is a list of nodes that should not be allowed to be a part of a
5348+
# ternary clause.
5349+
false
5350+
when Binary
5351+
# If the user is using one of the lower precedence "and" or "or"
5352+
# operators, then we can't use a ternary expression as it would break
5353+
# the flow control.
5354+
operator = statement.operator
5355+
operator != "and" && operator != "or"
5356+
else
5357+
true
5358+
end
53375359
end
53385360
end
53395361
end
@@ -5453,8 +5475,11 @@ def format_ternary(q)
54535475
end
54545476

54555477
def contains_conditional?
5456-
case node
5457-
in statements: { body: [If | IfMod | IfOp | Unless | UnlessMod] }
5478+
statements = node.statements.body
5479+
return false if statements.length != 1
5480+
5481+
case statements.first
5482+
when If, IfMod, IfOp, Unless, UnlessMod
54585483
true
54595484
else
54605485
false
@@ -6410,9 +6435,7 @@ def format(q)
64106435
# If we're at the top of a call chain, then we're going to do some
64116436
# specialized printing in case we can print it nicely. We _only_ do this
64126437
# at the top of the chain to avoid weird recursion issues.
6413-
if !ENV["STREE_SKIP_CALL_CHAIN"] &&
6414-
!CallChainFormatter.chained?(q.parent) &&
6415-
CallChainFormatter.chained?(call)
6438+
if CallChainFormatter.chained?(call) && !CallChainFormatter.chained?(q.parent)
64166439
q.group do
64176440
q
64186441
.if_break { CallChainFormatter.new(self).format(q) }
@@ -9122,6 +9145,7 @@ class Not < Node
91229145

91239146
# [boolean] whether or not parentheses were used
91249147
attr_reader :parentheses
9148+
alias parentheses? parentheses
91259149

91269150
# [Array[ Comment | EmbDoc ]] the comments attached to this node
91279151
attr_reader :comments
@@ -9160,10 +9184,10 @@ def format(q)
91609184
q.format(statement) if statement
91619185
q.text(")")
91629186
else
9163-
parent = q.parents.take(2)[1]
9187+
grandparent = q.grandparent
91649188
ternary =
9165-
(parent.is_a?(If) || parent.is_a?(Unless)) &&
9166-
Ternaryable.call(q, parent)
9189+
(grandparent.is_a?(If) || grandparent.is_a?(Unless)) &&
9190+
Ternaryable.call(q, grandparent)
91679191

91689192
if ternary
91699193
q.if_break { q.text(" ") }.if_flat { q.text("(") }

0 commit comments

Comments
 (0)