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

Commit 4cec867

Browse files
committed
Ruby 3.1 syntax
1 parent aca89c3 commit 4cec867

File tree

8 files changed

+226
-108
lines changed

8 files changed

+226
-108
lines changed

Gemfile.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ DEPENDENCIES
4141
syntax_tree!
4242

4343
BUNDLED WITH
44-
2.2.15
44+
2.2.31

lib/syntax_tree.rb

Lines changed: 135 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,7 @@ def on_args_add(arguments, argument)
11731173
# method(&expression)
11741174
#
11751175
class ArgBlock
1176-
# [untyped] the expression being turned into a block
1176+
# [nil | untyped] the expression being turned into a block
11771177
attr_reader :value
11781178

11791179
# [Location] the location of this node
@@ -1194,15 +1194,17 @@ def child_nodes
11941194

11951195
def format(q)
11961196
q.text("&")
1197-
q.format(value)
1197+
q.format(value) if value
11981198
end
11991199

12001200
def pretty_print(q)
12011201
q.group(2, "(", ")") do
12021202
q.text("arg_block")
12031203

1204-
q.breakable
1205-
q.pp(value)
1204+
if value
1205+
q.breakable
1206+
q.pp(value)
1207+
end
12061208

12071209
q.pp(Comment::List.new(comments))
12081210
end
@@ -1221,17 +1223,34 @@ def to_json(*opts)
12211223
# (false | untyped) block
12221224
# ) -> Args
12231225
def on_args_add_block(arguments, block)
1224-
return arguments unless block
1226+
operator = find_token(Op, "&", consume: false)
12251227

1226-
arg_block =
1227-
ArgBlock.new(
1228-
value: block,
1229-
location: find_token(Op, "&").location.to(block.location)
1230-
)
1228+
# If we can't find the & operator, then there's no block to add to the list,
1229+
# so we're just going to return the arguments as-is.
1230+
return arguments unless operator
1231+
1232+
# Now we know we have an & operator, so we're going to delete it from the
1233+
# list of tokens to make sure it doesn't get confused with anything else.
1234+
tokens.delete(operator)
1235+
1236+
# Construct the location that represents the block argument.
1237+
location = operator.location
1238+
location = operator.location.to(block.location) if block
1239+
1240+
# If there are any arguments and the operator we found from the list is not
1241+
# after them, then we're going to return the arguments as-is because we're
1242+
# looking at an & that occurs before the arguments are done.
1243+
if arguments.parts.any? && location.start_char < arguments.location.end_char
1244+
return arguments
1245+
end
1246+
1247+
# Otherwise, we're looking at an actual block argument (with or without a
1248+
# block, which could be missing because it could be a bare & since 3.1.0).
1249+
arg_block = ArgBlock.new(value: block, location: location)
12311250

12321251
Args.new(
12331252
parts: arguments.parts << arg_block,
1234-
location: arguments.location.to(arg_block.location)
1253+
location: arguments.location.to(location)
12351254
)
12361255
end
12371256

@@ -1896,7 +1915,7 @@ def child_nodes
18961915
end
18971916

18981917
def format(q)
1899-
if value.is_a?(HashLiteral)
1918+
if value&.is_a?(HashLiteral)
19001919
format_contents(q)
19011920
else
19021921
q.group { format_contents(q) }
@@ -1910,8 +1929,10 @@ def pretty_print(q)
19101929
q.breakable
19111930
q.pp(key)
19121931

1913-
q.breakable
1914-
q.pp(value)
1932+
if value
1933+
q.breakable
1934+
q.pp(value)
1935+
end
19151936

19161937
q.pp(Comment::List.new(comments))
19171938
end
@@ -1931,6 +1952,7 @@ def to_json(*opts)
19311952

19321953
def format_contents(q)
19331954
q.parent.format_key(q, key)
1955+
return unless value
19341956

19351957
if key.comments.empty? && AssignFormatting.skip_indent?(value)
19361958
q.text(" ")
@@ -1947,7 +1969,10 @@ def format_contents(q)
19471969
# :call-seq:
19481970
# on_assoc_new: (untyped key, untyped value) -> Assoc
19491971
def on_assoc_new(key, value)
1950-
Assoc.new(key: key, value: value, location: key.location.to(value.location))
1972+
location = key.location
1973+
location = location.to(value.location) if value
1974+
1975+
Assoc.new(key: key, value: value, location: location)
19511976
end
19521977

19531978
# AssocSplat represents double-splatting a value into a hash (either a hash
@@ -2423,12 +2448,22 @@ def to_json(*opts)
24232448
# :call-seq:
24242449
# on_binary: (untyped left, (Op | Symbol) operator, untyped right) -> Binary
24252450
def on_binary(left, operator, right)
2426-
# On most Ruby implementations, operator is a Symbol that represents that
2427-
# operation being performed. For instance in the example `1 < 2`, the
2428-
# `operator` object would be `:<`. However, on JRuby, it's an `@op` node,
2429-
# so here we're going to explicitly convert it into the same normalized
2430-
# form.
2431-
operator = tokens.delete(operator).value unless operator.is_a?(Symbol)
2451+
if operator.is_a?(Symbol)
2452+
# Here, we're going to search backward for the nearest token that matches
2453+
# the operator so we can delete it from the list.
2454+
token = find_token(Op, operator.to_s, consume: false)
2455+
2456+
if token && token.location.start_char > left.location.end_char
2457+
tokens.delete(token)
2458+
end
2459+
else
2460+
# On most Ruby implementations, operator is a Symbol that represents that
2461+
# operation being performed. For instance in the example `1 < 2`, the
2462+
# `operator` object would be `:<`. However, on JRuby, it's an `@op` node,
2463+
# so here we're going to explicitly convert it into the same normalized
2464+
# form.
2465+
operator = tokens.delete(operator).value
2466+
end
24322467

24332468
Binary.new(
24342469
left: left,
@@ -2578,7 +2613,7 @@ def on_block_var(params, locals)
25782613
# def method(&block); end
25792614
#
25802615
class BlockArg
2581-
# [Ident] the name of the block argument
2616+
# [nil | Ident] the name of the block argument
25822617
attr_reader :name
25832618

25842619
# [Location] the location of this node
@@ -2599,15 +2634,17 @@ def child_nodes
25992634

26002635
def format(q)
26012636
q.text("&")
2602-
q.format(name)
2637+
q.format(name) if name
26032638
end
26042639

26052640
def pretty_print(q)
26062641
q.group(2, "(", ")") do
26072642
q.text("blockarg")
26082643

2609-
q.breakable
2610-
q.pp(name)
2644+
if name
2645+
q.breakable
2646+
q.pp(name)
2647+
end
26112648

26122649
q.pp(Comment::List.new(comments))
26132650
end
@@ -2625,7 +2662,10 @@ def to_json(*opts)
26252662
def on_blockarg(name)
26262663
operator = find_token(Op, "&")
26272664

2628-
BlockArg.new(name: name, location: operator.location.to(name.location))
2665+
location = operator.location
2666+
location = location.to(name.location) if name
2667+
2668+
BlockArg.new(name: name, location: location)
26292669
end
26302670

26312671
# bodystmt can't actually determine its bounds appropriately because it
@@ -4423,7 +4463,7 @@ class DefEndless
44234463
# [Backtick | Const | Ident | Kw | Op] the name of the method
44244464
attr_reader :name
44254465

4426-
# [nil | Paren] the parameter declaration for the method
4466+
# [nil | Params | Paren] the parameter declaration for the method
44274467
attr_reader :paren
44284468

44294469
# [untyped] the expression to be executed by the method
@@ -4467,7 +4507,12 @@ def format(q)
44674507
end
44684508

44694509
q.format(name)
4470-
q.format(paren) if paren && !paren.contents.empty?
4510+
4511+
if paren
4512+
params = paren
4513+
params = params.contents if params.is_a?(Paren)
4514+
q.format(paren) unless params.empty?
4515+
end
44714516

44724517
q.text(" =")
44734518
q.group do
@@ -4533,21 +4578,6 @@ def on_def(name, params, bodystmt)
45334578
# and normal method definitions.
45344579
beginning = find_token(Kw, "def")
45354580

4536-
# If we don't have a bodystmt node, then we have a single-line method
4537-
unless bodystmt.is_a?(BodyStmt)
4538-
node =
4539-
DefEndless.new(
4540-
target: nil,
4541-
operator: nil,
4542-
name: name,
4543-
paren: params,
4544-
statement: bodystmt,
4545-
location: beginning.location.to(bodystmt.location)
4546-
)
4547-
4548-
return node
4549-
end
4550-
45514581
# If there aren't any params then we need to correct the params node
45524582
# location information
45534583
if params.is_a?(Params) && params.empty?
@@ -4563,18 +4593,35 @@ def on_def(name, params, bodystmt)
45634593
params = Params.new(location: location)
45644594
end
45654595

4566-
ending = find_token(Kw, "end")
4567-
bodystmt.bind(
4568-
find_next_statement_start(params.location.end_char),
4569-
ending.location.start_char
4570-
)
4596+
ending = find_token(Kw, "end", consume: false)
45714597

4572-
Def.new(
4573-
name: name,
4574-
params: params,
4575-
bodystmt: bodystmt,
4576-
location: beginning.location.to(ending.location)
4577-
)
4598+
if ending
4599+
tokens.delete(ending)
4600+
bodystmt.bind(
4601+
find_next_statement_start(params.location.end_char),
4602+
ending.location.start_char
4603+
)
4604+
4605+
Def.new(
4606+
name: name,
4607+
params: params,
4608+
bodystmt: bodystmt,
4609+
location: beginning.location.to(ending.location)
4610+
)
4611+
else
4612+
# In Ruby >= 3.1.0, this is a BodyStmt that wraps a single statement in
4613+
# the statements list. Before, it was just the individual statement.
4614+
statement = bodystmt.is_a?(BodyStmt) ? bodystmt.statements : bodystmt
4615+
4616+
DefEndless.new(
4617+
target: nil,
4618+
operator: nil,
4619+
name: name,
4620+
paren: params,
4621+
statement: statement,
4622+
location: beginning.location.to(bodystmt.location)
4623+
)
4624+
end
45784625
end
45794626

45804627
# Defined represents the use of the +defined?+ operator. It can be used with
@@ -4782,37 +4829,37 @@ def on_defs(target, operator, name, params, bodystmt)
47824829
end
47834830

47844831
beginning = find_token(Kw, "def")
4832+
ending = find_token(Kw, "end", consume: false)
47854833

4786-
# If we don't have a bodystmt node, then we have a single-line method
4787-
unless bodystmt.is_a?(BodyStmt)
4788-
node =
4789-
DefEndless.new(
4790-
target: target,
4791-
operator: operator,
4792-
name: name,
4793-
paren: params,
4794-
statement: bodystmt,
4795-
location: beginning.location.to(bodystmt.location)
4796-
)
4797-
4798-
return node
4799-
end
4800-
4801-
ending = find_token(Kw, "end")
4834+
if ending
4835+
tokens.delete(ending)
4836+
bodystmt.bind(
4837+
find_next_statement_start(params.location.end_char),
4838+
ending.location.start_char
4839+
)
48024840

4803-
bodystmt.bind(
4804-
find_next_statement_start(params.location.end_char),
4805-
ending.location.start_char
4806-
)
4841+
Defs.new(
4842+
target: target,
4843+
operator: operator,
4844+
name: name,
4845+
params: params,
4846+
bodystmt: bodystmt,
4847+
location: beginning.location.to(ending.location)
4848+
)
4849+
else
4850+
# In Ruby >= 3.1.0, this is a BodyStmt that wraps a single statement in
4851+
# the statements list. Before, it was just the individual statement.
4852+
statement = bodystmt.is_a?(BodyStmt) ? bodystmt.statements : bodystmt
48074853

4808-
Defs.new(
4809-
target: target,
4810-
operator: operator,
4811-
name: name,
4812-
params: params,
4813-
bodystmt: bodystmt,
4814-
location: beginning.location.to(ending.location)
4815-
)
4854+
DefEndless.new(
4855+
target: target,
4856+
operator: operator,
4857+
name: name,
4858+
paren: params,
4859+
statement: statement,
4860+
location: beginning.location.to(bodystmt.location)
4861+
)
4862+
end
48164863
end
48174864

48184865
# DoBlock represents passing a block to a method call using the +do+ and +end+
@@ -8931,7 +8978,7 @@ def format(q)
89318978
end
89328979

89338980
class KeywordRestFormatter
8934-
# [:nil | KwRestParam] the value of the parameter
8981+
# [:nil | ArgsForward | KwRestParam] the value of the parameter
89358982
attr_reader :value
89368983

89378984
def initialize(value)
@@ -9046,7 +9093,7 @@ def format(q)
90469093
q.format(rest) if rest && rest.is_a?(ExcessedComma)
90479094
end
90489095

9049-
if [Def, Defs].include?(q.parent.class)
9096+
if [Def, Defs, DefEndless].include?(q.parent.class)
90509097
q.group(0, "(", ")") do
90519098
q.indent do
90529099
q.breakable("")
@@ -9146,8 +9193,8 @@ def to_json(*opts)
91469193
# (nil | ArgsForward | ExcessedComma | RestParam) rest,
91479194
# (nil | Array[Ident]) posts,
91489195
# (nil | Array[[Ident, nil | untyped]]) keywords,
9149-
# (nil | :nil | KwRestParam) keyword_rest,
9150-
# (nil | BlockArg) block
9196+
# (nil | :nil | ArgsForward | KwRestParam) keyword_rest,
9197+
# (nil | :& | BlockArg) block
91519198
# ) -> Params
91529199
def on_params(
91539200
requireds,
@@ -9165,7 +9212,7 @@ def on_params(
91659212
*posts,
91669213
*keywords&.flat_map { |(key, value)| [key, value || nil] },
91679214
(keyword_rest if keyword_rest != :nil),
9168-
block
9215+
(block if block != :&)
91699216
].compact
91709217

91719218
location =
@@ -9182,7 +9229,7 @@ def on_params(
91829229
posts: posts || [],
91839230
keywords: keywords || [],
91849231
keyword_rest: keyword_rest,
9185-
block: block,
9232+
block: (block if block != :&),
91869233
location: location
91879234
)
91889235
end

0 commit comments

Comments
 (0)