Skip to content

Commit 4d9227e

Browse files
committed
Combine Elsif node into IfNode
Many other Ruby ASTs do not have a separate node representing `elsif` conditionals; instead, they use the same node as `if` but make it a consequent of other `if` nodes. This commit removes the `Elsif` node and combines its functionality with `IfNode`, ensuring that both the parsing and formatting logic are still functional.
1 parent 4864692 commit 4d9227e

File tree

3 files changed

+49
-99
lines changed

3 files changed

+49
-99
lines changed

lib/syntax_tree/node.rb

Lines changed: 43 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -4835,95 +4835,6 @@ def ===(other)
48354835
end
48364836
end
48374837

4838-
# Elsif represents another clause in an +if+ or +unless+ chain.
4839-
#
4840-
# if variable
4841-
# elsif other_variable
4842-
# end
4843-
#
4844-
class Elsif < Node
4845-
# [Node] the expression to be checked
4846-
attr_reader :predicate
4847-
4848-
# [Statements] the expressions to be executed
4849-
attr_reader :statements
4850-
4851-
# [nil | Elsif | Else] the next clause in the chain
4852-
attr_reader :consequent
4853-
4854-
# [Array[ Comment | EmbDoc ]] the comments attached to this node
4855-
attr_reader :comments
4856-
4857-
def initialize(predicate:, statements:, consequent:, location:)
4858-
@predicate = predicate
4859-
@statements = statements
4860-
@consequent = consequent
4861-
@location = location
4862-
@comments = []
4863-
end
4864-
4865-
def accept(visitor)
4866-
visitor.visit_elsif(self)
4867-
end
4868-
4869-
def child_nodes
4870-
[predicate, statements, consequent]
4871-
end
4872-
4873-
def copy(predicate: nil, statements: nil, consequent: nil, location: nil)
4874-
node =
4875-
Elsif.new(
4876-
predicate: predicate || self.predicate,
4877-
statements: statements || self.statements,
4878-
consequent: consequent || self.consequent,
4879-
location: location || self.location
4880-
)
4881-
4882-
node.comments.concat(comments.map(&:copy))
4883-
node
4884-
end
4885-
4886-
alias deconstruct child_nodes
4887-
4888-
def deconstruct_keys(_keys)
4889-
{
4890-
predicate: predicate,
4891-
statements: statements,
4892-
consequent: consequent,
4893-
location: location,
4894-
comments: comments
4895-
}
4896-
end
4897-
4898-
def format(q)
4899-
q.group do
4900-
q.group do
4901-
q.text("elsif ")
4902-
q.nest("elsif".length - 1) { q.format(predicate) }
4903-
end
4904-
4905-
unless statements.empty?
4906-
q.indent do
4907-
q.breakable_force
4908-
q.format(statements)
4909-
end
4910-
end
4911-
4912-
if consequent
4913-
q.group do
4914-
q.breakable_force
4915-
q.format(consequent)
4916-
end
4917-
end
4918-
end
4919-
end
4920-
4921-
def ===(other)
4922-
other.is_a?(Elsif) && predicate === other.predicate &&
4923-
statements === other.statements && consequent === other.consequent
4924-
end
4925-
end
4926-
49274838
# EmbDoc represents a multi-line comment.
49284839
#
49294840
# =begin
@@ -6439,25 +6350,29 @@ def contains_conditional?
64396350
end
64406351
end
64416352

6442-
# If represents the first clause in an +if+ chain.
6353+
# If an +if+ or +elsif+ clause in an +if+ chain.
64436354
#
64446355
# if predicate
64456356
# end
64466357
#
64476358
class IfNode < Node
6359+
# [Kw] the opening keyword of the conditional statement
6360+
attr_reader :keyword
6361+
64486362
# [Node] the expression to be checked
64496363
attr_reader :predicate
64506364

64516365
# [Statements] the expressions to be executed
64526366
attr_reader :statements
64536367

6454-
# [nil | Elsif | Else] the next clause in the chain
6368+
# [nil | IfNode | Else] the next clause in the chain
64556369
attr_reader :consequent
64566370

64576371
# [Array[ Comment | EmbDoc ]] the comments attached to this node
64586372
attr_reader :comments
64596373

6460-
def initialize(predicate:, statements:, consequent:, location:)
6374+
def initialize(keyword:, predicate:, statements:, consequent:, location:)
6375+
@keyword = keyword
64616376
@predicate = predicate
64626377
@statements = statements
64636378
@consequent = consequent
@@ -6473,9 +6388,16 @@ def child_nodes
64736388
[predicate, statements, consequent]
64746389
end
64756390

6476-
def copy(predicate: nil, statements: nil, consequent: nil, location: nil)
6391+
def copy(
6392+
keyword: nil,
6393+
predicate: nil,
6394+
statements: nil,
6395+
consequent: nil,
6396+
location: nil
6397+
)
64776398
node =
64786399
IfNode.new(
6400+
keyword: keyword || self.keyword,
64796401
predicate: predicate || self.predicate,
64806402
statements: statements || self.statements,
64816403
consequent: consequent || self.consequent,
@@ -6494,17 +6416,42 @@ def deconstruct_keys(_keys)
64946416
statements: statements,
64956417
consequent: consequent,
64966418
location: location,
6419+
keyword: keyword,
64976420
comments: comments
64986421
}
64996422
end
65006423

65016424
def format(q)
6502-
ConditionalFormatter.new("if", self).format(q)
6425+
if keyword.value == "elsif"
6426+
q.group do
6427+
q.group do
6428+
q.text("elsif ")
6429+
q.nest("elsif".length - 1) { q.format(predicate) }
6430+
end
6431+
6432+
unless statements.empty?
6433+
q.indent do
6434+
q.breakable_force
6435+
q.format(statements)
6436+
end
6437+
end
6438+
6439+
if consequent
6440+
q.group do
6441+
q.breakable_force
6442+
q.format(consequent)
6443+
end
6444+
end
6445+
end
6446+
else
6447+
ConditionalFormatter.new(keyword.value, self).format(q)
6448+
end
65036449
end
65046450

65056451
def ===(other)
65066452
other.is_a?(IfNode) && predicate === other.predicate &&
6507-
statements === other.statements && consequent === other.consequent
6453+
statements === other.statements && consequent === other.consequent &&
6454+
keyword === other.keyword
65086455
end
65096456

65106457
# Checks if the node was originally found in the modifier form.
@@ -11295,7 +11242,7 @@ class UnlessNode < Node
1129511242
# [Statements] the expressions to be executed
1129611243
attr_reader :statements
1129711244

11298-
# [nil | Elsif | Else] the next clause in the chain
11245+
# [nil | IfNode | Else] the next clause in the chain
1129911246
attr_reader :consequent
1130011247

1130111248
# [Array[ Comment | EmbDoc ]] the comments attached to this node

lib/syntax_tree/parser.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,7 +1575,8 @@ def on_elsif(predicate, statements, consequent)
15751575
ending.location.start_column
15761576
)
15771577

1578-
Elsif.new(
1578+
IfNode.new(
1579+
keyword: beginning,
15791580
predicate: predicate,
15801581
statements: statements,
15811582
consequent: consequent,
@@ -2062,6 +2063,7 @@ def on_if(predicate, statements, consequent)
20622063
)
20632064

20642065
IfNode.new(
2066+
keyword: beginning,
20652067
predicate: predicate,
20662068
statements: statements,
20672069
consequent: consequent,
@@ -2083,9 +2085,10 @@ def on_ifop(predicate, truthy, falsy)
20832085
# :call-seq:
20842086
# on_if_mod: (untyped predicate, untyped statement) -> IfNode
20852087
def on_if_mod(predicate, statement)
2086-
consume_keyword(:if)
2088+
beginning = consume_keyword(:if)
20872089

20882090
IfNode.new(
2091+
keyword: beginning,
20892092
predicate: predicate,
20902093
statements:
20912094
Statements.new(body: [statement], location: statement.location),

test/node_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ def test_elsif
452452
SOURCE
453453

454454
at = location(lines: 2..4, chars: 9..30)
455-
assert_node(Elsif, source, at: at, &:consequent)
455+
assert_node(IfNode, source, at: at, &:consequent)
456456
end
457457

458458
def test_embdoc

0 commit comments

Comments
 (0)