Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit fd7d7b1

Browse files
committed
Combine the LambdaVar and BlockVar nodes
Both `LambdaVar` and `BlockVar` represent a collection of arguments (positional, optional, keyword, block) as well as block or lambda-local variables. This commit removes the `LambdaVar` node and folds its functionality into the `BlockVar` node, which reduces the number of nodes and simplifies logic.
1 parent 69c6719 commit fd7d7b1

File tree

3 files changed

+85
-93
lines changed

3 files changed

+85
-93
lines changed

lib/syntax_tree/node.rb

Lines changed: 47 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,13 +2086,18 @@ def ===(other)
20862086
end
20872087
end
20882088

2089-
# BlockVar represents the parameters being declared for a block. Effectively
2090-
# this node is everything contained within the pipes. This includes all of the
2091-
# various parameter types, as well as block-local variable declarations.
2089+
# BlockVar represents the parameters being declared for a block or lambda.
2090+
# This includes all of the various parameter types, as well as
2091+
# block-local/lambda-local variable declarations.
20922092
#
20932093
# method do |positional, optional = value, keyword:, █ local|
20942094
# end
20952095
#
2096+
# OR
2097+
#
2098+
# -> (positional, optional = value, keyword:, █ local) do
2099+
# end
2100+
#
20962101
class BlockVar < Node
20972102
# [Params] the parameters being declared with the block
20982103
attr_reader :params
@@ -2103,10 +2108,15 @@ class BlockVar < Node
21032108
# [Array[ Comment | EmbDoc ]] the comments attached to this node
21042109
attr_reader :comments
21052110

2106-
def initialize(params:, locals:, location:)
2111+
# [boolean] whether or not the variables are within pipes
2112+
attr_reader :pipe
2113+
alias pipe? pipe
2114+
2115+
def initialize(params:, locals:, location:, pipe:)
21072116
@params = params
21082117
@locals = locals
21092118
@location = location
2119+
@pipe = pipe
21102120
@comments = []
21112121
end
21122122

@@ -2118,12 +2128,13 @@ def child_nodes
21182128
[params, *locals]
21192129
end
21202130

2121-
def copy(params: nil, locals: nil, location: nil)
2131+
def copy(params: nil, locals: nil, location: nil, pipe: nil)
21222132
node =
21232133
BlockVar.new(
21242134
params: params || self.params,
21252135
locals: locals || self.locals,
2126-
location: location || self.location
2136+
location: location || self.location,
2137+
pipe: pipe || self.pipe
21272138
)
21282139

21292140
node.comments.concat(comments.map(&:copy))
@@ -2133,7 +2144,13 @@ def copy(params: nil, locals: nil, location: nil)
21332144
alias deconstruct child_nodes
21342145

21352146
def deconstruct_keys(_keys)
2136-
{ params: params, locals: locals, location: location, comments: comments }
2147+
{
2148+
params: params,
2149+
locals: locals,
2150+
location: location,
2151+
comments: comments,
2152+
pipe: pipe
2153+
}
21372154
end
21382155

21392156
# Within the pipes of the block declaration, we don't want any spaces. So
@@ -2149,30 +2166,44 @@ def call(q)
21492166
SEPARATOR = Separator.new.freeze
21502167

21512168
def format(q)
2152-
q.text("|")
2153-
q.group do
2154-
q.remove_breaks(q.format(params))
2155-
2156-
if locals.any?
2157-
q.text("; ")
2158-
q.seplist(locals, SEPARATOR) { |local| q.format(local) }
2169+
if pipe?
2170+
q.text("|")
2171+
q.group do
2172+
q.remove_breaks(q.format(params))
2173+
format_locals(q)
21592174
end
2175+
q.text("|")
2176+
else
2177+
q.format(params)
2178+
format_locals(q)
21602179
end
2161-
q.text("|")
21622180
end
21632181

21642182
def ===(other)
21652183
other.is_a?(BlockVar) && params === other.params &&
21662184
ArrayMatch.call(locals, other.locals)
21672185
end
21682186

2187+
def empty?
2188+
params.empty? && locals.empty?
2189+
end
2190+
21692191
# When a single required parameter is declared for a block, it gets
21702192
# automatically expanded if the values being yielded into it are an array.
21712193
def arg0?
21722194
params.requireds.length == 1 && params.optionals.empty? &&
21732195
params.rest.nil? && params.posts.empty? && params.keywords.empty? &&
21742196
params.keyword_rest.nil? && params.block.nil?
21752197
end
2198+
2199+
private
2200+
2201+
def format_locals(q)
2202+
if locals.any?
2203+
q.text("; ")
2204+
q.seplist(locals, SEPARATOR) { |local| q.format(local) }
2205+
end
2206+
end
21762207
end
21772208

21782209
# BlockArg represents declaring a block parameter on a method definition.
@@ -7075,7 +7106,7 @@ def ===(other)
70757106
# ->(value) { value * 2 }
70767107
#
70777108
class Lambda < Node
7078-
# [LambdaVar | Paren] the parameter declaration for this lambda
7109+
# [BlockVar | Paren] the parameter declaration for this lambda
70797110
attr_reader :params
70807111

70817112
# [BodyStmt | Statements] the expressions to be executed in this lambda
@@ -7191,76 +7222,6 @@ def ===(other)
71917222
end
71927223
end
71937224

7194-
# LambdaVar represents the parameters being declared for a lambda. Effectively
7195-
# this node is everything contained within the parentheses. This includes all
7196-
# of the various parameter types, as well as block-local variable
7197-
# declarations.
7198-
#
7199-
# -> (positional, optional = value, keyword:, &block; local) do
7200-
# end
7201-
#
7202-
class LambdaVar < Node
7203-
# [Params] the parameters being declared with the block
7204-
attr_reader :params
7205-
7206-
# [Array[ Ident ]] the list of block-local variable declarations
7207-
attr_reader :locals
7208-
7209-
# [Array[ Comment | EmbDoc ]] the comments attached to this node
7210-
attr_reader :comments
7211-
7212-
def initialize(params:, locals:, location:)
7213-
@params = params
7214-
@locals = locals
7215-
@location = location
7216-
@comments = []
7217-
end
7218-
7219-
def accept(visitor)
7220-
visitor.visit_lambda_var(self)
7221-
end
7222-
7223-
def child_nodes
7224-
[params, *locals]
7225-
end
7226-
7227-
def copy(params: nil, locals: nil, location: nil)
7228-
node =
7229-
LambdaVar.new(
7230-
params: params || self.params,
7231-
locals: locals || self.locals,
7232-
location: location || self.location
7233-
)
7234-
7235-
node.comments.concat(comments.map(&:copy))
7236-
node
7237-
end
7238-
7239-
alias deconstruct child_nodes
7240-
7241-
def deconstruct_keys(_keys)
7242-
{ params: params, locals: locals, location: location, comments: comments }
7243-
end
7244-
7245-
def empty?
7246-
params.empty? && locals.empty?
7247-
end
7248-
7249-
def format(q)
7250-
q.format(params)
7251-
7252-
if locals.any?
7253-
q.text("; ")
7254-
q.seplist(locals, BlockVar::SEPARATOR) { |local| q.format(local) }
7255-
end
7256-
end
7257-
7258-
def ===(other)
7259-
other.is_a?(LambdaVar) && params === other.params &&
7260-
ArrayMatch.call(locals, other.locals)
7261-
end
7262-
end
7263-
72647225
# LBrace represents the use of a left brace, i.e., {.
72657226
class LBrace < Node
72667227
# [String] the left brace

lib/syntax_tree/parser.rb

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,8 @@ def on_block_var(params, locals)
885885
BlockVar.new(
886886
params: params,
887887
locals: locals || [],
888-
location: beginning.location.to(ending.location)
888+
location: beginning.location.to(ending.location),
889+
pipe: true
889890
)
890891
end
891892

@@ -2157,10 +2158,11 @@ def on_lambda(params, statements)
21572158
Paren.new(
21582159
lparen: params.lparen,
21592160
contents:
2160-
LambdaVar.new(
2161+
BlockVar.new(
21612162
params: params.contents,
21622163
locals: locals,
2163-
location: location
2164+
location: location,
2165+
pipe: false
21642166
),
21652167
location: params.location
21662168
)
@@ -2171,8 +2173,13 @@ def on_lambda(params, statements)
21712173
# In this case we've gotten to the <3.2 plain set of parameters. In
21722174
# this case there cannot be lambda locals, so we will wrap the
21732175
# parameters into a lambda var that has no locals.
2174-
LambdaVar.new(params: params, locals: [], location: params.location)
2175-
when LambdaVar
2176+
BlockVar.new(
2177+
params: params,
2178+
locals: [],
2179+
location: params.location,
2180+
pipe: false
2181+
)
2182+
when BlockVar
21762183
# In this case we've gotten to 3.2+ lambda var. In this case we don't
21772184
# need to do anything and can just the value as given.
21782185
params
@@ -2202,12 +2209,17 @@ def on_lambda(params, statements)
22022209
end
22032210

22042211
# :call-seq:
2205-
# on_lambda_var: (Params params, Array[ Ident ] locals) -> LambdaVar
2212+
# on_lambda_var: (Params params, Array[ Ident ] locals) -> BlockVar
22062213
def on_lambda_var(params, locals)
22072214
location = params.location
22082215
location = location.to(locals.last.location) if locals.any?
22092216

2210-
LambdaVar.new(params: params, locals: locals || [], location: location)
2217+
BlockVar.new(
2218+
params: params,
2219+
locals: locals || [],
2220+
location: location,
2221+
pipe: false
2222+
)
22112223
end
22122224

22132225
# Ripper doesn't support capturing lambda local variables until 3.2. To

test/node_test.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,25 @@ def test_lambda
635635
source = "->(value) { value * 2 }"
636636

637637
assert_node(Lambda, source)
638+
639+
at = location(chars: 3..8)
640+
assert_node(BlockVar, source, at: at) { |node| node.params.contents }
641+
end
642+
643+
def test_lambda_no_parens
644+
source = "-> value { value * 2 }"
645+
646+
assert_node(Lambda, source)
647+
648+
at = location(chars: 3..8)
649+
assert_node(BlockVar, source, at: at, &:params)
650+
end
651+
652+
def test_lambda_braces
653+
source = "lambda { |value| value * 2 }"
654+
655+
at = location(chars: 9..16)
656+
assert_node(BlockVar, source, at: at) { |node| node.block.block_var }
638657
end
639658

640659
def test_lambda_do

0 commit comments

Comments
 (0)