jruby-prism-parser 0.23.0.pre.SNAPSHOT-java → 1.4.0-java
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/BSDmakefile +58 -0
- data/CHANGELOG.md +284 -1
- data/CONTRIBUTING.md +0 -4
- data/Makefile +25 -18
- data/README.md +57 -6
- data/config.yml +1724 -140
- data/docs/build_system.md +39 -11
- data/docs/configuration.md +4 -0
- data/docs/cruby_compilation.md +1 -1
- data/docs/fuzzing.md +1 -1
- data/docs/parser_translation.md +14 -9
- data/docs/parsing_rules.md +4 -1
- data/docs/releasing.md +9 -11
- data/docs/relocation.md +34 -0
- data/docs/ripper_translation.md +72 -0
- data/docs/ruby_api.md +2 -1
- data/docs/serialization.md +29 -5
- data/ext/prism/api_node.c +3841 -2000
- data/ext/prism/api_pack.c +9 -0
- data/ext/prism/extconf.rb +55 -34
- data/ext/prism/extension.c +597 -346
- data/ext/prism/extension.h +6 -5
- data/include/prism/ast.h +2612 -455
- data/include/prism/defines.h +160 -2
- data/include/prism/diagnostic.h +188 -76
- data/include/prism/encoding.h +22 -4
- data/include/prism/node.h +89 -17
- data/include/prism/options.h +224 -12
- data/include/prism/pack.h +11 -0
- data/include/prism/parser.h +267 -66
- data/include/prism/prettyprint.h +8 -0
- data/include/prism/regexp.h +18 -8
- data/include/prism/static_literals.h +121 -0
- data/include/prism/util/pm_buffer.h +75 -2
- data/include/prism/util/pm_char.h +1 -2
- data/include/prism/util/pm_constant_pool.h +18 -9
- data/include/prism/util/pm_integer.h +126 -0
- data/include/prism/util/pm_list.h +1 -1
- data/include/prism/util/pm_newline_list.h +23 -3
- data/include/prism/util/pm_string.h +48 -8
- data/include/prism/version.h +3 -3
- data/include/prism.h +99 -5
- data/jruby-prism.jar +0 -0
- data/lib/prism/compiler.rb +11 -1
- data/lib/prism/desugar_compiler.rb +264 -80
- data/lib/prism/dispatcher.rb +45 -1
- data/lib/prism/dot_visitor.rb +201 -77
- data/lib/prism/dsl.rb +672 -457
- data/lib/prism/ffi.rb +308 -94
- data/lib/prism/inspect_visitor.rb +2389 -0
- data/lib/prism/lex_compat.rb +35 -16
- data/lib/prism/mutation_compiler.rb +24 -8
- data/lib/prism/node.rb +9712 -8931
- data/lib/prism/node_ext.rb +328 -32
- data/lib/prism/pack.rb +4 -0
- data/lib/prism/parse_result/comments.rb +34 -24
- data/lib/prism/parse_result/errors.rb +65 -0
- data/lib/prism/parse_result/newlines.rb +102 -12
- data/lib/prism/parse_result.rb +458 -46
- data/lib/prism/pattern.rb +28 -10
- data/lib/prism/polyfill/append_as_bytes.rb +15 -0
- data/lib/prism/polyfill/byteindex.rb +13 -0
- data/lib/prism/polyfill/unpack1.rb +14 -0
- data/lib/prism/reflection.rb +413 -0
- data/lib/prism/relocation.rb +504 -0
- data/lib/prism/serialize.rb +1940 -902
- data/lib/prism/string_query.rb +30 -0
- data/lib/prism/translation/parser/builder.rb +61 -0
- data/lib/prism/translation/parser/compiler.rb +569 -195
- data/lib/prism/translation/parser/lexer.rb +516 -39
- data/lib/prism/translation/parser.rb +188 -11
- data/lib/prism/translation/parser33.rb +12 -0
- data/lib/prism/translation/parser34.rb +12 -0
- data/lib/prism/translation/parser35.rb +12 -0
- data/lib/prism/translation/ripper/sexp.rb +125 -0
- data/lib/prism/translation/ripper/shim.rb +5 -0
- data/lib/prism/translation/ripper.rb +3267 -386
- data/lib/prism/translation/ruby_parser.rb +194 -69
- data/lib/prism/translation.rb +4 -1
- data/lib/prism/version.rb +1 -1
- data/lib/prism/visitor.rb +13 -0
- data/lib/prism.rb +17 -27
- data/prism.gemspec +59 -17
- data/rbi/prism/compiler.rbi +12 -0
- data/rbi/prism/dsl.rbi +524 -0
- data/rbi/prism/inspect_visitor.rbi +12 -0
- data/rbi/prism/node.rbi +8722 -0
- data/rbi/prism/node_ext.rbi +107 -0
- data/rbi/prism/parse_result.rbi +404 -0
- data/rbi/prism/reflection.rbi +58 -0
- data/rbi/prism/string_query.rbi +12 -0
- data/rbi/prism/translation/parser.rbi +11 -0
- data/rbi/prism/translation/parser33.rbi +6 -0
- data/rbi/prism/translation/parser34.rbi +6 -0
- data/rbi/prism/translation/parser35.rbi +6 -0
- data/rbi/prism/translation/ripper.rbi +15 -0
- data/rbi/prism/visitor.rbi +473 -0
- data/rbi/prism.rbi +44 -7745
- data/sig/prism/compiler.rbs +9 -0
- data/sig/prism/dispatcher.rbs +16 -0
- data/sig/prism/dot_visitor.rbs +6 -0
- data/sig/prism/dsl.rbs +351 -0
- data/sig/prism/inspect_visitor.rbs +22 -0
- data/sig/prism/lex_compat.rbs +10 -0
- data/sig/prism/mutation_compiler.rbs +159 -0
- data/sig/prism/node.rbs +3614 -0
- data/sig/prism/node_ext.rbs +82 -0
- data/sig/prism/pack.rbs +43 -0
- data/sig/prism/parse_result.rbs +192 -0
- data/sig/prism/pattern.rbs +13 -0
- data/sig/prism/reflection.rbs +50 -0
- data/sig/prism/relocation.rbs +185 -0
- data/sig/prism/serialize.rbs +8 -0
- data/sig/prism/string_query.rbs +11 -0
- data/sig/prism/visitor.rbs +169 -0
- data/sig/prism.rbs +248 -4767
- data/src/diagnostic.c +672 -230
- data/src/encoding.c +211 -108
- data/src/node.c +7541 -1653
- data/src/options.c +135 -20
- data/src/pack.c +33 -17
- data/src/prettyprint.c +1546 -1488
- data/src/prism.c +7822 -3044
- data/src/regexp.c +225 -73
- data/src/serialize.c +101 -77
- data/src/static_literals.c +617 -0
- data/src/token_type.c +14 -13
- data/src/util/pm_buffer.c +187 -20
- data/src/util/pm_char.c +5 -5
- data/src/util/pm_constant_pool.c +39 -19
- data/src/util/pm_integer.c +670 -0
- data/src/util/pm_list.c +1 -1
- data/src/util/pm_newline_list.c +49 -8
- data/src/util/pm_string.c +213 -33
- data/src/util/pm_strncasecmp.c +13 -1
- data/src/util/pm_strpbrk.c +32 -6
- metadata +59 -21
- data/docs/ripper.md +0 -36
- data/include/prism/util/pm_state_stack.h +0 -42
- data/include/prism/util/pm_string_list.h +0 -44
- data/lib/prism/debug.rb +0 -206
- data/lib/prism/node_inspector.rb +0 -68
- data/lib/prism/translation/parser/rubocop.rb +0 -37
- data/rbi/prism_static.rbi +0 -207
- data/sig/prism_static.rbs +0 -201
- data/src/util/pm_state_stack.c +0 -25
- data/src/util/pm_string_list.c +0 -28
@@ -74,7 +74,29 @@ module Prism
|
|
74
74
|
# []
|
75
75
|
# ^^
|
76
76
|
def visit_array_node(node)
|
77
|
-
|
77
|
+
if node.opening&.start_with?("%w", "%W", "%i", "%I")
|
78
|
+
elements = node.elements.flat_map do |element|
|
79
|
+
if element.is_a?(StringNode)
|
80
|
+
if element.content.include?("\n")
|
81
|
+
string_nodes_from_line_continuations(element.unescaped, element.content, element.content_loc.start_offset, node.opening)
|
82
|
+
else
|
83
|
+
[builder.string_internal([element.unescaped, srange(element.content_loc)])]
|
84
|
+
end
|
85
|
+
elsif element.is_a?(InterpolatedStringNode)
|
86
|
+
builder.string_compose(
|
87
|
+
token(element.opening_loc),
|
88
|
+
string_nodes_from_interpolation(element, node.opening),
|
89
|
+
token(element.closing_loc)
|
90
|
+
)
|
91
|
+
else
|
92
|
+
[visit(element)]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
else
|
96
|
+
elements = visit_all(node.elements)
|
97
|
+
end
|
98
|
+
|
99
|
+
builder.array(token(node.opening_loc), elements, token(node.closing_loc))
|
78
100
|
end
|
79
101
|
|
80
102
|
# foo => [bar]
|
@@ -90,7 +112,11 @@ module Prism
|
|
90
112
|
end
|
91
113
|
|
92
114
|
if node.constant
|
93
|
-
|
115
|
+
if visited.empty?
|
116
|
+
builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc)), token(node.closing_loc))
|
117
|
+
else
|
118
|
+
builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc))
|
119
|
+
end
|
94
120
|
else
|
95
121
|
builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc))
|
96
122
|
end
|
@@ -105,31 +131,49 @@ module Prism
|
|
105
131
|
# { a: 1 }
|
106
132
|
# ^^^^
|
107
133
|
def visit_assoc_node(node)
|
134
|
+
key = node.key
|
135
|
+
|
108
136
|
if in_pattern
|
109
137
|
if node.value.is_a?(ImplicitNode)
|
110
|
-
if
|
111
|
-
|
138
|
+
if key.is_a?(SymbolNode)
|
139
|
+
if key.opening.nil?
|
140
|
+
builder.match_hash_var([key.unescaped, srange(key.location)])
|
141
|
+
else
|
142
|
+
builder.match_hash_var_from_str(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc))
|
143
|
+
end
|
112
144
|
else
|
113
|
-
builder.match_hash_var_from_str(token(
|
145
|
+
builder.match_hash_var_from_str(token(key.opening_loc), visit_all(key.parts), token(key.closing_loc))
|
114
146
|
end
|
147
|
+
elsif key.opening.nil?
|
148
|
+
builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value))
|
115
149
|
else
|
116
|
-
builder.
|
150
|
+
builder.pair_quoted(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc), visit(node.value))
|
117
151
|
end
|
118
152
|
elsif node.value.is_a?(ImplicitNode)
|
119
|
-
|
153
|
+
value = node.value.value
|
154
|
+
|
155
|
+
implicit_value = if value.is_a?(CallNode)
|
156
|
+
builder.call_method(nil, nil, [value.name, srange(value.message_loc)])
|
157
|
+
elsif value.is_a?(ConstantReadNode)
|
158
|
+
builder.const([value.name, srange(key.value_loc)])
|
159
|
+
else
|
160
|
+
builder.ident([value.name, srange(key.value_loc)]).updated(:lvar)
|
161
|
+
end
|
162
|
+
|
163
|
+
builder.pair_keyword([key.unescaped, srange(key)], implicit_value)
|
120
164
|
elsif node.operator_loc
|
121
|
-
builder.pair(visit(
|
122
|
-
elsif
|
123
|
-
builder.pair_keyword([
|
165
|
+
builder.pair(visit(key), token(node.operator_loc), visit(node.value))
|
166
|
+
elsif key.is_a?(SymbolNode) && key.opening_loc.nil?
|
167
|
+
builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value))
|
124
168
|
else
|
125
169
|
parts =
|
126
|
-
if
|
127
|
-
[builder.string_internal([
|
170
|
+
if key.is_a?(SymbolNode)
|
171
|
+
[builder.string_internal([key.unescaped, srange(key.value_loc)])]
|
128
172
|
else
|
129
|
-
visit_all(
|
173
|
+
visit_all(key.parts)
|
130
174
|
end
|
131
175
|
|
132
|
-
builder.pair_quoted(token(
|
176
|
+
builder.pair_quoted(token(key.opening_loc), parts, token(key.closing_loc), visit(node.value))
|
133
177
|
end
|
134
178
|
end
|
135
179
|
|
@@ -139,7 +183,9 @@ module Prism
|
|
139
183
|
# { **foo }
|
140
184
|
# ^^^^^
|
141
185
|
def visit_assoc_splat_node(node)
|
142
|
-
if
|
186
|
+
if in_pattern
|
187
|
+
builder.match_rest(token(node.operator_loc), token(node.value&.location))
|
188
|
+
elsif node.value.nil? && forwarding.include?(:**)
|
143
189
|
builder.forwarded_kwrestarg(token(node.operator_loc))
|
144
190
|
else
|
145
191
|
builder.kwsplat(token(node.operator_loc), visit(node.value))
|
@@ -160,17 +206,24 @@ module Prism
|
|
160
206
|
if (rescue_clause = node.rescue_clause)
|
161
207
|
begin
|
162
208
|
find_start_offset = (rescue_clause.reference&.location || rescue_clause.exceptions.last&.location || rescue_clause.keyword_loc).end_offset
|
163
|
-
find_end_offset = (
|
209
|
+
find_end_offset = (
|
210
|
+
rescue_clause.statements&.location&.start_offset ||
|
211
|
+
rescue_clause.subsequent&.location&.start_offset ||
|
212
|
+
node.else_clause&.location&.start_offset ||
|
213
|
+
node.ensure_clause&.location&.start_offset ||
|
214
|
+
node.end_keyword_loc&.start_offset ||
|
215
|
+
find_start_offset + 1
|
216
|
+
)
|
164
217
|
|
165
218
|
rescue_bodies << builder.rescue_body(
|
166
219
|
token(rescue_clause.keyword_loc),
|
167
220
|
rescue_clause.exceptions.any? ? builder.array(nil, visit_all(rescue_clause.exceptions), nil) : nil,
|
168
221
|
token(rescue_clause.operator_loc),
|
169
222
|
visit(rescue_clause.reference),
|
170
|
-
srange_find(find_start_offset, find_end_offset,
|
223
|
+
srange_find(find_start_offset, find_end_offset, ";"),
|
171
224
|
visit(rescue_clause.statements)
|
172
225
|
)
|
173
|
-
end until (rescue_clause = rescue_clause.
|
226
|
+
end until (rescue_clause = rescue_clause.subsequent).nil?
|
174
227
|
end
|
175
228
|
|
176
229
|
begin_body =
|
@@ -247,21 +300,33 @@ module Prism
|
|
247
300
|
|
248
301
|
if node.call_operator_loc.nil?
|
249
302
|
case name
|
303
|
+
when :-@
|
304
|
+
case (receiver = node.receiver).type
|
305
|
+
when :integer_node, :float_node, :rational_node, :imaginary_node
|
306
|
+
return visit(numeric_negate(node.message_loc, receiver))
|
307
|
+
end
|
250
308
|
when :!
|
251
309
|
return visit_block(builder.not_op(token(node.message_loc), token(node.opening_loc), visit(node.receiver), token(node.closing_loc)), block)
|
310
|
+
when :=~
|
311
|
+
if (receiver = node.receiver).is_a?(RegularExpressionNode)
|
312
|
+
return builder.match_op(visit(receiver), token(node.message_loc), visit(node.arguments.arguments.first))
|
313
|
+
end
|
252
314
|
when :[]
|
253
315
|
return visit_block(builder.index(visit(node.receiver), token(node.opening_loc), visit_all(arguments), token(node.closing_loc)), block)
|
254
316
|
when :[]=
|
255
317
|
if node.message != "[]=" && node.arguments && block.nil? && !node.safe_navigation?
|
318
|
+
arguments = node.arguments.arguments[...-1]
|
319
|
+
arguments << node.block if node.block
|
320
|
+
|
256
321
|
return visit_block(
|
257
322
|
builder.assign(
|
258
323
|
builder.index_asgn(
|
259
324
|
visit(node.receiver),
|
260
325
|
token(node.opening_loc),
|
261
|
-
visit_all(
|
326
|
+
visit_all(arguments),
|
262
327
|
token(node.closing_loc),
|
263
328
|
),
|
264
|
-
srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset,
|
329
|
+
srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset, "="),
|
265
330
|
visit(node.arguments.arguments.last)
|
266
331
|
),
|
267
332
|
block
|
@@ -278,7 +343,7 @@ module Prism
|
|
278
343
|
if name.end_with?("=") && !message_loc.slice.end_with?("=") && node.arguments && block.nil?
|
279
344
|
builder.assign(
|
280
345
|
builder.attr_asgn(visit(node.receiver), call_operator, token(message_loc)),
|
281
|
-
srange_find(message_loc.end_offset, node.arguments.location.start_offset,
|
346
|
+
srange_find(message_loc.end_offset, node.arguments.location.start_offset, "="),
|
282
347
|
visit(node.arguments.arguments.last)
|
283
348
|
)
|
284
349
|
else
|
@@ -309,18 +374,48 @@ module Prism
|
|
309
374
|
[],
|
310
375
|
nil
|
311
376
|
),
|
312
|
-
[node.
|
377
|
+
[node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
|
313
378
|
visit(node.value)
|
314
379
|
)
|
315
380
|
end
|
316
381
|
|
317
382
|
# foo.bar &&= baz
|
318
383
|
# ^^^^^^^^^^^^^^^
|
319
|
-
|
384
|
+
def visit_call_and_write_node(node)
|
385
|
+
call_operator_loc = node.call_operator_loc
|
386
|
+
|
387
|
+
builder.op_assign(
|
388
|
+
builder.call_method(
|
389
|
+
visit(node.receiver),
|
390
|
+
call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)],
|
391
|
+
node.message_loc ? [node.read_name, srange(node.message_loc)] : nil,
|
392
|
+
nil,
|
393
|
+
[],
|
394
|
+
nil
|
395
|
+
),
|
396
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
397
|
+
visit(node.value)
|
398
|
+
)
|
399
|
+
end
|
320
400
|
|
321
401
|
# foo.bar ||= baz
|
322
402
|
# ^^^^^^^^^^^^^^^
|
323
|
-
|
403
|
+
def visit_call_or_write_node(node)
|
404
|
+
call_operator_loc = node.call_operator_loc
|
405
|
+
|
406
|
+
builder.op_assign(
|
407
|
+
builder.call_method(
|
408
|
+
visit(node.receiver),
|
409
|
+
call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)],
|
410
|
+
node.message_loc ? [node.read_name, srange(node.message_loc)] : nil,
|
411
|
+
nil,
|
412
|
+
[],
|
413
|
+
nil
|
414
|
+
),
|
415
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
416
|
+
visit(node.value)
|
417
|
+
)
|
418
|
+
end
|
324
419
|
|
325
420
|
# foo.bar, = 1
|
326
421
|
# ^^^^^^^
|
@@ -347,8 +442,8 @@ module Prism
|
|
347
442
|
token(node.case_keyword_loc),
|
348
443
|
visit(node.predicate),
|
349
444
|
visit_all(node.conditions),
|
350
|
-
token(node.
|
351
|
-
visit(node.
|
445
|
+
token(node.else_clause&.else_keyword_loc),
|
446
|
+
visit(node.else_clause),
|
352
447
|
token(node.end_keyword_loc)
|
353
448
|
)
|
354
449
|
end
|
@@ -360,8 +455,8 @@ module Prism
|
|
360
455
|
token(node.case_keyword_loc),
|
361
456
|
visit(node.predicate),
|
362
457
|
visit_all(node.conditions),
|
363
|
-
token(node.
|
364
|
-
visit(node.
|
458
|
+
token(node.else_clause&.else_keyword_loc),
|
459
|
+
visit(node.else_clause),
|
365
460
|
token(node.end_keyword_loc)
|
366
461
|
)
|
367
462
|
end
|
@@ -387,9 +482,6 @@ module Prism
|
|
387
482
|
|
388
483
|
# @@foo = 1
|
389
484
|
# ^^^^^^^^^
|
390
|
-
#
|
391
|
-
# @@foo, @@bar = 1
|
392
|
-
# ^^^^^ ^^^^^
|
393
485
|
def visit_class_variable_write_node(node)
|
394
486
|
builder.assign(
|
395
487
|
builder.assignable(builder.cvar(token(node.name_loc))),
|
@@ -403,18 +495,30 @@ module Prism
|
|
403
495
|
def visit_class_variable_operator_write_node(node)
|
404
496
|
builder.op_assign(
|
405
497
|
builder.assignable(builder.cvar(token(node.name_loc))),
|
406
|
-
[node.
|
498
|
+
[node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
|
407
499
|
visit(node.value)
|
408
500
|
)
|
409
501
|
end
|
410
502
|
|
411
503
|
# @@foo &&= bar
|
412
504
|
# ^^^^^^^^^^^^^
|
413
|
-
|
505
|
+
def visit_class_variable_and_write_node(node)
|
506
|
+
builder.op_assign(
|
507
|
+
builder.assignable(builder.cvar(token(node.name_loc))),
|
508
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
509
|
+
visit(node.value)
|
510
|
+
)
|
511
|
+
end
|
414
512
|
|
415
513
|
# @@foo ||= bar
|
416
514
|
# ^^^^^^^^^^^^^
|
417
|
-
|
515
|
+
def visit_class_variable_or_write_node(node)
|
516
|
+
builder.op_assign(
|
517
|
+
builder.assignable(builder.cvar(token(node.name_loc))),
|
518
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
519
|
+
visit(node.value)
|
520
|
+
)
|
521
|
+
end
|
418
522
|
|
419
523
|
# @@foo, = bar
|
420
524
|
# ^^^^^
|
@@ -442,18 +546,30 @@ module Prism
|
|
442
546
|
def visit_constant_operator_write_node(node)
|
443
547
|
builder.op_assign(
|
444
548
|
builder.assignable(builder.const([node.name, srange(node.name_loc)])),
|
445
|
-
[node.
|
549
|
+
[node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
|
446
550
|
visit(node.value)
|
447
551
|
)
|
448
552
|
end
|
449
553
|
|
450
554
|
# Foo &&= bar
|
451
555
|
# ^^^^^^^^^^^^
|
452
|
-
|
556
|
+
def visit_constant_and_write_node(node)
|
557
|
+
builder.op_assign(
|
558
|
+
builder.assignable(builder.const([node.name, srange(node.name_loc)])),
|
559
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
560
|
+
visit(node.value)
|
561
|
+
)
|
562
|
+
end
|
453
563
|
|
454
564
|
# Foo ||= bar
|
455
565
|
# ^^^^^^^^^^^^
|
456
|
-
|
566
|
+
def visit_constant_or_write_node(node)
|
567
|
+
builder.op_assign(
|
568
|
+
builder.assignable(builder.const([node.name, srange(node.name_loc)])),
|
569
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
570
|
+
visit(node.value)
|
571
|
+
)
|
572
|
+
end
|
457
573
|
|
458
574
|
# Foo, = bar
|
459
575
|
# ^^^
|
@@ -467,13 +583,13 @@ module Prism
|
|
467
583
|
if node.parent.nil?
|
468
584
|
builder.const_global(
|
469
585
|
token(node.delimiter_loc),
|
470
|
-
[node.
|
586
|
+
[node.name, srange(node.name_loc)]
|
471
587
|
)
|
472
588
|
else
|
473
589
|
builder.const_fetch(
|
474
590
|
visit(node.parent),
|
475
591
|
token(node.delimiter_loc),
|
476
|
-
[node.
|
592
|
+
[node.name, srange(node.name_loc)]
|
477
593
|
)
|
478
594
|
end
|
479
595
|
end
|
@@ -496,18 +612,30 @@ module Prism
|
|
496
612
|
def visit_constant_path_operator_write_node(node)
|
497
613
|
builder.op_assign(
|
498
614
|
builder.assignable(visit(node.target)),
|
499
|
-
[node.
|
615
|
+
[node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
|
500
616
|
visit(node.value)
|
501
617
|
)
|
502
618
|
end
|
503
619
|
|
504
620
|
# Foo::Bar &&= baz
|
505
621
|
# ^^^^^^^^^^^^^^^^
|
506
|
-
|
622
|
+
def visit_constant_path_and_write_node(node)
|
623
|
+
builder.op_assign(
|
624
|
+
builder.assignable(visit(node.target)),
|
625
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
626
|
+
visit(node.value)
|
627
|
+
)
|
628
|
+
end
|
507
629
|
|
508
630
|
# Foo::Bar ||= baz
|
509
631
|
# ^^^^^^^^^^^^^^^^
|
510
|
-
|
632
|
+
def visit_constant_path_or_write_node(node)
|
633
|
+
builder.op_assign(
|
634
|
+
builder.assignable(visit(node.target)),
|
635
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
636
|
+
visit(node.value)
|
637
|
+
)
|
638
|
+
end
|
511
639
|
|
512
640
|
# Foo::Bar, = baz
|
513
641
|
# ^^^^^^^^
|
@@ -637,10 +765,10 @@ module Prism
|
|
637
765
|
visit(node.index),
|
638
766
|
token(node.in_keyword_loc),
|
639
767
|
visit(node.collection),
|
640
|
-
if node.do_keyword_loc
|
641
|
-
token(
|
768
|
+
if (do_keyword_loc = node.do_keyword_loc)
|
769
|
+
token(do_keyword_loc)
|
642
770
|
else
|
643
|
-
srange_find(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset,
|
771
|
+
srange_find(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset, ";")
|
644
772
|
end,
|
645
773
|
visit(node.statements),
|
646
774
|
token(node.end_keyword_loc)
|
@@ -682,9 +810,6 @@ module Prism
|
|
682
810
|
|
683
811
|
# $foo = 1
|
684
812
|
# ^^^^^^^^
|
685
|
-
#
|
686
|
-
# $foo, $bar = 1
|
687
|
-
# ^^^^ ^^^^
|
688
813
|
def visit_global_variable_write_node(node)
|
689
814
|
builder.assign(
|
690
815
|
builder.assignable(builder.gvar(token(node.name_loc))),
|
@@ -698,18 +823,30 @@ module Prism
|
|
698
823
|
def visit_global_variable_operator_write_node(node)
|
699
824
|
builder.op_assign(
|
700
825
|
builder.assignable(builder.gvar(token(node.name_loc))),
|
701
|
-
[node.
|
826
|
+
[node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
|
702
827
|
visit(node.value)
|
703
828
|
)
|
704
829
|
end
|
705
830
|
|
706
831
|
# $foo &&= bar
|
707
832
|
# ^^^^^^^^^^^^
|
708
|
-
|
833
|
+
def visit_global_variable_and_write_node(node)
|
834
|
+
builder.op_assign(
|
835
|
+
builder.assignable(builder.gvar(token(node.name_loc))),
|
836
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
837
|
+
visit(node.value)
|
838
|
+
)
|
839
|
+
end
|
709
840
|
|
710
841
|
# $foo ||= bar
|
711
842
|
# ^^^^^^^^^^^^
|
712
|
-
|
843
|
+
def visit_global_variable_or_write_node(node)
|
844
|
+
builder.op_assign(
|
845
|
+
builder.assignable(builder.gvar(token(node.name_loc))),
|
846
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
847
|
+
visit(node.value)
|
848
|
+
)
|
849
|
+
end
|
713
850
|
|
714
851
|
# $foo, = bar
|
715
852
|
# ^^^^
|
@@ -753,26 +890,26 @@ module Prism
|
|
753
890
|
visit(node.predicate),
|
754
891
|
token(node.then_keyword_loc),
|
755
892
|
visit(node.statements),
|
756
|
-
token(node.
|
757
|
-
visit(node.
|
893
|
+
token(node.subsequent.else_keyword_loc),
|
894
|
+
visit(node.subsequent)
|
758
895
|
)
|
759
896
|
elsif node.if_keyword_loc.start_offset == node.location.start_offset
|
760
897
|
builder.condition(
|
761
898
|
token(node.if_keyword_loc),
|
762
899
|
visit(node.predicate),
|
763
|
-
if node.then_keyword_loc
|
764
|
-
token(
|
900
|
+
if (then_keyword_loc = node.then_keyword_loc)
|
901
|
+
token(then_keyword_loc)
|
765
902
|
else
|
766
|
-
srange_find(node.predicate.location.end_offset, (node.statements&.location || node.
|
903
|
+
srange_find(node.predicate.location.end_offset, (node.statements&.location || node.subsequent&.location || node.end_keyword_loc).start_offset, ";")
|
767
904
|
end,
|
768
905
|
visit(node.statements),
|
769
|
-
case node.
|
906
|
+
case node.subsequent
|
770
907
|
when IfNode
|
771
|
-
token(node.
|
908
|
+
token(node.subsequent.if_keyword_loc)
|
772
909
|
when ElseNode
|
773
|
-
token(node.
|
910
|
+
token(node.subsequent.else_keyword_loc)
|
774
911
|
end,
|
775
|
-
visit(node.
|
912
|
+
visit(node.subsequent),
|
776
913
|
if node.if_keyword != "elsif"
|
777
914
|
token(node.end_keyword_loc)
|
778
915
|
end
|
@@ -780,7 +917,7 @@ module Prism
|
|
780
917
|
else
|
781
918
|
builder.condition_mod(
|
782
919
|
visit(node.statements),
|
783
|
-
visit(node.
|
920
|
+
visit(node.subsequent),
|
784
921
|
token(node.if_keyword_loc),
|
785
922
|
visit(node.predicate)
|
786
923
|
)
|
@@ -788,8 +925,9 @@ module Prism
|
|
788
925
|
end
|
789
926
|
|
790
927
|
# 1i
|
928
|
+
# ^^
|
791
929
|
def visit_imaginary_node(node)
|
792
|
-
visit_numeric(node, builder.complex([node.value, srange(node.location)]))
|
930
|
+
visit_numeric(node, builder.complex([Complex(0, node.numeric.value), srange(node.location)]))
|
793
931
|
end
|
794
932
|
|
795
933
|
# { foo: }
|
@@ -825,7 +963,11 @@ module Prism
|
|
825
963
|
token(node.in_loc),
|
826
964
|
pattern,
|
827
965
|
guard,
|
828
|
-
|
966
|
+
if (then_loc = node.then_loc)
|
967
|
+
token(then_loc)
|
968
|
+
else
|
969
|
+
srange_find(node.pattern.location.end_offset, node.statements&.location&.start_offset, ";")
|
970
|
+
end,
|
829
971
|
visit(node.statements)
|
830
972
|
)
|
831
973
|
end
|
@@ -843,18 +985,46 @@ module Prism
|
|
843
985
|
visit_all(arguments),
|
844
986
|
token(node.closing_loc)
|
845
987
|
),
|
846
|
-
[node.
|
988
|
+
[node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
|
847
989
|
visit(node.value)
|
848
990
|
)
|
849
991
|
end
|
850
992
|
|
851
993
|
# foo[bar] &&= baz
|
852
994
|
# ^^^^^^^^^^^^^^^^
|
853
|
-
|
995
|
+
def visit_index_and_write_node(node)
|
996
|
+
arguments = node.arguments&.arguments || []
|
997
|
+
arguments << node.block if node.block
|
998
|
+
|
999
|
+
builder.op_assign(
|
1000
|
+
builder.index(
|
1001
|
+
visit(node.receiver),
|
1002
|
+
token(node.opening_loc),
|
1003
|
+
visit_all(arguments),
|
1004
|
+
token(node.closing_loc)
|
1005
|
+
),
|
1006
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
1007
|
+
visit(node.value)
|
1008
|
+
)
|
1009
|
+
end
|
854
1010
|
|
855
1011
|
# foo[bar] ||= baz
|
856
1012
|
# ^^^^^^^^^^^^^^^^
|
857
|
-
|
1013
|
+
def visit_index_or_write_node(node)
|
1014
|
+
arguments = node.arguments&.arguments || []
|
1015
|
+
arguments << node.block if node.block
|
1016
|
+
|
1017
|
+
builder.op_assign(
|
1018
|
+
builder.index(
|
1019
|
+
visit(node.receiver),
|
1020
|
+
token(node.opening_loc),
|
1021
|
+
visit_all(arguments),
|
1022
|
+
token(node.closing_loc)
|
1023
|
+
),
|
1024
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
1025
|
+
visit(node.value)
|
1026
|
+
)
|
1027
|
+
end
|
858
1028
|
|
859
1029
|
# foo[bar], = 1
|
860
1030
|
# ^^^^^^^^
|
@@ -875,9 +1045,6 @@ module Prism
|
|
875
1045
|
|
876
1046
|
# @foo = 1
|
877
1047
|
# ^^^^^^^^
|
878
|
-
#
|
879
|
-
# @foo, @bar = 1
|
880
|
-
# ^^^^ ^^^^
|
881
1048
|
def visit_instance_variable_write_node(node)
|
882
1049
|
builder.assign(
|
883
1050
|
builder.assignable(builder.ivar(token(node.name_loc))),
|
@@ -891,18 +1058,30 @@ module Prism
|
|
891
1058
|
def visit_instance_variable_operator_write_node(node)
|
892
1059
|
builder.op_assign(
|
893
1060
|
builder.assignable(builder.ivar(token(node.name_loc))),
|
894
|
-
[node.
|
1061
|
+
[node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
|
895
1062
|
visit(node.value)
|
896
1063
|
)
|
897
1064
|
end
|
898
1065
|
|
899
1066
|
# @foo &&= bar
|
900
1067
|
# ^^^^^^^^^^^^
|
901
|
-
|
1068
|
+
def visit_instance_variable_and_write_node(node)
|
1069
|
+
builder.op_assign(
|
1070
|
+
builder.assignable(builder.ivar(token(node.name_loc))),
|
1071
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
1072
|
+
visit(node.value)
|
1073
|
+
)
|
1074
|
+
end
|
902
1075
|
|
903
1076
|
# @foo ||= bar
|
904
1077
|
# ^^^^^^^^^^^^
|
905
|
-
|
1078
|
+
def visit_instance_variable_or_write_node(node)
|
1079
|
+
builder.op_assign(
|
1080
|
+
builder.assignable(builder.ivar(token(node.name_loc))),
|
1081
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
1082
|
+
visit(node.value)
|
1083
|
+
)
|
1084
|
+
end
|
906
1085
|
|
907
1086
|
# @foo, = bar
|
908
1087
|
# ^^^^
|
@@ -921,7 +1100,7 @@ module Prism
|
|
921
1100
|
def visit_interpolated_regular_expression_node(node)
|
922
1101
|
builder.regexp_compose(
|
923
1102
|
token(node.opening_loc),
|
924
|
-
|
1103
|
+
string_nodes_from_interpolation(node, node.opening),
|
925
1104
|
[node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)],
|
926
1105
|
builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)])
|
927
1106
|
)
|
@@ -934,16 +1113,15 @@ module Prism
|
|
934
1113
|
# "foo #{bar}"
|
935
1114
|
# ^^^^^^^^^^^^
|
936
1115
|
def visit_interpolated_string_node(node)
|
937
|
-
if node.
|
938
|
-
children, closing
|
939
|
-
builder.string_compose(token(node.opening_loc), children, closing)
|
940
|
-
else
|
941
|
-
builder.string_compose(
|
942
|
-
token(node.opening_loc),
|
943
|
-
visit_all(node.parts),
|
944
|
-
token(node.closing_loc)
|
945
|
-
)
|
1116
|
+
if node.heredoc?
|
1117
|
+
return visit_heredoc(node) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) }
|
946
1118
|
end
|
1119
|
+
|
1120
|
+
builder.string_compose(
|
1121
|
+
token(node.opening_loc),
|
1122
|
+
string_nodes_from_interpolation(node, node.opening),
|
1123
|
+
token(node.closing_loc)
|
1124
|
+
)
|
947
1125
|
end
|
948
1126
|
|
949
1127
|
# :"foo #{bar}"
|
@@ -951,7 +1129,7 @@ module Prism
|
|
951
1129
|
def visit_interpolated_symbol_node(node)
|
952
1130
|
builder.symbol_compose(
|
953
1131
|
token(node.opening_loc),
|
954
|
-
|
1132
|
+
string_nodes_from_interpolation(node, node.opening),
|
955
1133
|
token(node.closing_loc)
|
956
1134
|
)
|
957
1135
|
end
|
@@ -959,15 +1137,36 @@ module Prism
|
|
959
1137
|
# `foo #{bar}`
|
960
1138
|
# ^^^^^^^^^^^^
|
961
1139
|
def visit_interpolated_x_string_node(node)
|
962
|
-
if node.
|
963
|
-
children, closing
|
964
|
-
|
1140
|
+
if node.heredoc?
|
1141
|
+
return visit_heredoc(node) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
|
1142
|
+
end
|
1143
|
+
|
1144
|
+
builder.xstring_compose(
|
1145
|
+
token(node.opening_loc),
|
1146
|
+
string_nodes_from_interpolation(node, node.opening),
|
1147
|
+
token(node.closing_loc)
|
1148
|
+
)
|
1149
|
+
end
|
1150
|
+
|
1151
|
+
# -> { it }
|
1152
|
+
# ^^
|
1153
|
+
def visit_it_local_variable_read_node(node)
|
1154
|
+
builder.ident([:it, srange(node.location)]).updated(:lvar)
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
# -> { it }
|
1158
|
+
# ^^^^^^^^^
|
1159
|
+
def visit_it_parameters_node(node)
|
1160
|
+
# FIXME: The builder _should_ always be a subclass of the prism builder.
|
1161
|
+
# Currently RuboCop passes in its own builder that always inherits from the
|
1162
|
+
# parser builder (which is lacking the `itarg` method). Once rubocop-ast
|
1163
|
+
# opts in to use the custom prism builder a warning can be emitted when
|
1164
|
+
# it is not the expected class, and eventually raise.
|
1165
|
+
# https://github.com/rubocop/rubocop-ast/pull/354
|
1166
|
+
if builder.is_a?(Translation::Parser::Builder)
|
1167
|
+
builder.itarg
|
965
1168
|
else
|
966
|
-
builder.
|
967
|
-
token(node.opening_loc),
|
968
|
-
visit_all(node.parts),
|
969
|
-
token(node.closing_loc)
|
970
|
-
)
|
1169
|
+
builder.args(nil, [], nil, false)
|
971
1170
|
end
|
972
1171
|
end
|
973
1172
|
|
@@ -990,15 +1189,17 @@ module Prism
|
|
990
1189
|
end
|
991
1190
|
|
992
1191
|
# -> {}
|
1192
|
+
# ^^^^^
|
993
1193
|
def visit_lambda_node(node)
|
994
1194
|
parameters = node.parameters
|
1195
|
+
implicit_parameters = parameters.is_a?(NumberedParametersNode) || parameters.is_a?(ItParametersNode)
|
995
1196
|
|
996
1197
|
builder.block(
|
997
1198
|
builder.call_lambda(token(node.operator_loc)),
|
998
1199
|
[node.opening, srange(node.opening_loc)],
|
999
1200
|
if parameters.nil?
|
1000
1201
|
builder.args(nil, [], nil, false)
|
1001
|
-
elsif
|
1202
|
+
elsif implicit_parameters
|
1002
1203
|
visit(node.parameters)
|
1003
1204
|
else
|
1004
1205
|
builder.args(
|
@@ -1008,7 +1209,7 @@ module Prism
|
|
1008
1209
|
false
|
1009
1210
|
)
|
1010
1211
|
end,
|
1011
|
-
node.body
|
1212
|
+
visit(node.body),
|
1012
1213
|
[node.closing, srange(node.closing_loc)]
|
1013
1214
|
)
|
1014
1215
|
end
|
@@ -1021,9 +1222,6 @@ module Prism
|
|
1021
1222
|
|
1022
1223
|
# foo = 1
|
1023
1224
|
# ^^^^^^^
|
1024
|
-
#
|
1025
|
-
# foo, bar = 1
|
1026
|
-
# ^^^ ^^^
|
1027
1225
|
def visit_local_variable_write_node(node)
|
1028
1226
|
builder.assign(
|
1029
1227
|
builder.assignable(builder.ident(token(node.name_loc))),
|
@@ -1037,18 +1235,30 @@ module Prism
|
|
1037
1235
|
def visit_local_variable_operator_write_node(node)
|
1038
1236
|
builder.op_assign(
|
1039
1237
|
builder.assignable(builder.ident(token(node.name_loc))),
|
1040
|
-
[node.
|
1238
|
+
[node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)],
|
1041
1239
|
visit(node.value)
|
1042
1240
|
)
|
1043
1241
|
end
|
1044
1242
|
|
1045
1243
|
# foo &&= bar
|
1046
1244
|
# ^^^^^^^^^^^
|
1047
|
-
|
1245
|
+
def visit_local_variable_and_write_node(node)
|
1246
|
+
builder.op_assign(
|
1247
|
+
builder.assignable(builder.ident(token(node.name_loc))),
|
1248
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
1249
|
+
visit(node.value)
|
1250
|
+
)
|
1251
|
+
end
|
1048
1252
|
|
1049
1253
|
# foo ||= bar
|
1050
1254
|
# ^^^^^^^^^^^
|
1051
|
-
|
1255
|
+
def visit_local_variable_or_write_node(node)
|
1256
|
+
builder.op_assign(
|
1257
|
+
builder.assignable(builder.ident(token(node.name_loc))),
|
1258
|
+
[node.operator_loc.slice.chomp("="), srange(node.operator_loc)],
|
1259
|
+
visit(node.value)
|
1260
|
+
)
|
1261
|
+
end
|
1052
1262
|
|
1053
1263
|
# foo, = bar
|
1054
1264
|
# ^^^
|
@@ -1062,22 +1272,12 @@ module Prism
|
|
1062
1272
|
|
1063
1273
|
# foo in bar
|
1064
1274
|
# ^^^^^^^^^^
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
)
|
1072
|
-
end
|
1073
|
-
else
|
1074
|
-
def visit_match_predicate_node(node)
|
1075
|
-
builder.match_pattern(
|
1076
|
-
visit(node.value),
|
1077
|
-
token(node.operator_loc),
|
1078
|
-
within_pattern { |compiler| node.pattern.accept(compiler) }
|
1079
|
-
)
|
1080
|
-
end
|
1275
|
+
def visit_match_predicate_node(node)
|
1276
|
+
builder.match_pattern_p(
|
1277
|
+
visit(node.value),
|
1278
|
+
token(node.operator_loc),
|
1279
|
+
within_pattern { |compiler| node.pattern.accept(compiler) }
|
1280
|
+
)
|
1081
1281
|
end
|
1082
1282
|
|
1083
1283
|
# foo => bar
|
@@ -1121,13 +1321,9 @@ module Prism
|
|
1121
1321
|
# foo, bar = baz
|
1122
1322
|
# ^^^^^^^^
|
1123
1323
|
def visit_multi_target_node(node)
|
1124
|
-
elements = [*node.lefts]
|
1125
|
-
elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
|
1126
|
-
elements.concat(node.rights)
|
1127
|
-
|
1128
1324
|
builder.multi_lhs(
|
1129
1325
|
token(node.lparen_loc),
|
1130
|
-
visit_all(
|
1326
|
+
visit_all(multi_target_elements(node)),
|
1131
1327
|
token(node.rparen_loc)
|
1132
1328
|
)
|
1133
1329
|
end
|
@@ -1135,9 +1331,11 @@ module Prism
|
|
1135
1331
|
# foo, bar = baz
|
1136
1332
|
# ^^^^^^^^^^^^^^
|
1137
1333
|
def visit_multi_write_node(node)
|
1138
|
-
elements =
|
1139
|
-
|
1140
|
-
elements.
|
1334
|
+
elements = multi_target_elements(node)
|
1335
|
+
|
1336
|
+
if elements.length == 1 && elements.first.is_a?(MultiTargetNode) && !node.rest
|
1337
|
+
elements = multi_target_elements(elements.first)
|
1338
|
+
end
|
1141
1339
|
|
1142
1340
|
builder.multi_assign(
|
1143
1341
|
builder.multi_lhs(
|
@@ -1218,12 +1416,12 @@ module Prism
|
|
1218
1416
|
|
1219
1417
|
if node.requireds.any?
|
1220
1418
|
node.requireds.each do |required|
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1226
|
-
|
1419
|
+
params <<
|
1420
|
+
if required.is_a?(RequiredParameterNode)
|
1421
|
+
visit(required)
|
1422
|
+
else
|
1423
|
+
required.accept(copy_compiler(in_destructure: true))
|
1424
|
+
end
|
1227
1425
|
end
|
1228
1426
|
end
|
1229
1427
|
|
@@ -1232,12 +1430,12 @@ module Prism
|
|
1232
1430
|
|
1233
1431
|
if node.posts.any?
|
1234
1432
|
node.posts.each do |post|
|
1235
|
-
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1433
|
+
params <<
|
1434
|
+
if post.is_a?(RequiredParameterNode)
|
1435
|
+
visit(post)
|
1436
|
+
else
|
1437
|
+
post.accept(copy_compiler(in_destructure: true))
|
1438
|
+
end
|
1241
1439
|
end
|
1242
1440
|
end
|
1243
1441
|
|
@@ -1263,7 +1461,8 @@ module Prism
|
|
1263
1461
|
# foo => ^(bar)
|
1264
1462
|
# ^^^^^^
|
1265
1463
|
def visit_pinned_expression_node(node)
|
1266
|
-
builder.
|
1464
|
+
expression = builder.begin(token(node.lparen_loc), visit(node.expression), token(node.rparen_loc))
|
1465
|
+
builder.pin(token(node.operator_loc), expression)
|
1267
1466
|
end
|
1268
1467
|
|
1269
1468
|
# foo = 1 and bar => ^foo
|
@@ -1334,9 +1533,18 @@ module Prism
|
|
1334
1533
|
# /foo/
|
1335
1534
|
# ^^^^^
|
1336
1535
|
def visit_regular_expression_node(node)
|
1536
|
+
parts =
|
1537
|
+
if node.content == ""
|
1538
|
+
[]
|
1539
|
+
elsif node.content.include?("\n")
|
1540
|
+
string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening)
|
1541
|
+
else
|
1542
|
+
[builder.string_internal([node.unescaped, srange(node.content_loc)])]
|
1543
|
+
end
|
1544
|
+
|
1337
1545
|
builder.regexp_compose(
|
1338
1546
|
token(node.opening_loc),
|
1339
|
-
|
1547
|
+
parts,
|
1340
1548
|
[node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)],
|
1341
1549
|
builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)])
|
1342
1550
|
)
|
@@ -1418,6 +1626,11 @@ module Prism
|
|
1418
1626
|
builder.self(token(node.location))
|
1419
1627
|
end
|
1420
1628
|
|
1629
|
+
# A shareable constant.
|
1630
|
+
def visit_shareable_constant_node(node)
|
1631
|
+
visit(node.write)
|
1632
|
+
end
|
1633
|
+
|
1421
1634
|
# class << self; end
|
1422
1635
|
# ^^^^^^^^^^^^^^^^^^
|
1423
1636
|
def visit_singleton_class_node(node)
|
@@ -1476,15 +1689,23 @@ module Prism
|
|
1476
1689
|
# "foo"
|
1477
1690
|
# ^^^^^
|
1478
1691
|
def visit_string_node(node)
|
1479
|
-
if node.
|
1480
|
-
|
1481
|
-
builder.string_compose(token(node.opening_loc), children, closing)
|
1692
|
+
if node.heredoc?
|
1693
|
+
visit_heredoc(node.to_interpolated) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) }
|
1482
1694
|
elsif node.opening == "?"
|
1483
1695
|
builder.character([node.unescaped, srange(node.location)])
|
1696
|
+
elsif node.opening&.start_with?("%") && node.unescaped.empty?
|
1697
|
+
builder.string_compose(token(node.opening_loc), [], token(node.closing_loc))
|
1484
1698
|
else
|
1699
|
+
parts =
|
1700
|
+
if node.content.include?("\n")
|
1701
|
+
string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening)
|
1702
|
+
else
|
1703
|
+
[builder.string_internal([node.unescaped, srange(node.content_loc)])]
|
1704
|
+
end
|
1705
|
+
|
1485
1706
|
builder.string_compose(
|
1486
1707
|
token(node.opening_loc),
|
1487
|
-
|
1708
|
+
parts,
|
1488
1709
|
token(node.closing_loc)
|
1489
1710
|
)
|
1490
1711
|
end
|
@@ -1523,9 +1744,18 @@ module Prism
|
|
1523
1744
|
builder.symbol([node.unescaped, srange(node.location)])
|
1524
1745
|
end
|
1525
1746
|
else
|
1747
|
+
parts =
|
1748
|
+
if node.value == ""
|
1749
|
+
[]
|
1750
|
+
elsif node.value.include?("\n")
|
1751
|
+
string_nodes_from_line_continuations(node.unescaped, node.value, node.value_loc.start_offset, node.opening)
|
1752
|
+
else
|
1753
|
+
[builder.string_internal([node.unescaped, srange(node.value_loc)])]
|
1754
|
+
end
|
1755
|
+
|
1526
1756
|
builder.symbol_compose(
|
1527
1757
|
token(node.opening_loc),
|
1528
|
-
|
1758
|
+
parts,
|
1529
1759
|
token(node.closing_loc)
|
1530
1760
|
)
|
1531
1761
|
end
|
@@ -1553,19 +1783,19 @@ module Prism
|
|
1553
1783
|
builder.condition(
|
1554
1784
|
token(node.keyword_loc),
|
1555
1785
|
visit(node.predicate),
|
1556
|
-
if node.then_keyword_loc
|
1557
|
-
token(
|
1786
|
+
if (then_keyword_loc = node.then_keyword_loc)
|
1787
|
+
token(then_keyword_loc)
|
1558
1788
|
else
|
1559
|
-
srange_find(node.predicate.location.end_offset, (node.statements&.location || node.
|
1789
|
+
srange_find(node.predicate.location.end_offset, (node.statements&.location || node.else_clause&.location || node.end_keyword_loc).start_offset, ";")
|
1560
1790
|
end,
|
1561
|
-
visit(node.
|
1562
|
-
token(node.
|
1791
|
+
visit(node.else_clause),
|
1792
|
+
token(node.else_clause&.else_keyword_loc),
|
1563
1793
|
visit(node.statements),
|
1564
1794
|
token(node.end_keyword_loc)
|
1565
1795
|
)
|
1566
1796
|
else
|
1567
1797
|
builder.condition_mod(
|
1568
|
-
visit(node.
|
1798
|
+
visit(node.else_clause),
|
1569
1799
|
visit(node.statements),
|
1570
1800
|
token(node.keyword_loc),
|
1571
1801
|
visit(node.predicate)
|
@@ -1574,7 +1804,7 @@ module Prism
|
|
1574
1804
|
end
|
1575
1805
|
|
1576
1806
|
# until foo; bar end
|
1577
|
-
#
|
1807
|
+
# ^^^^^^^^^^^^^^^^^^
|
1578
1808
|
#
|
1579
1809
|
# bar until foo
|
1580
1810
|
# ^^^^^^^^^^^^^
|
@@ -1584,7 +1814,11 @@ module Prism
|
|
1584
1814
|
:until,
|
1585
1815
|
token(node.keyword_loc),
|
1586
1816
|
visit(node.predicate),
|
1587
|
-
|
1817
|
+
if (do_keyword_loc = node.do_keyword_loc)
|
1818
|
+
token(do_keyword_loc)
|
1819
|
+
else
|
1820
|
+
srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, ";")
|
1821
|
+
end,
|
1588
1822
|
visit(node.statements),
|
1589
1823
|
token(node.closing_loc)
|
1590
1824
|
)
|
@@ -1604,7 +1838,11 @@ module Prism
|
|
1604
1838
|
builder.when(
|
1605
1839
|
token(node.keyword_loc),
|
1606
1840
|
visit_all(node.conditions),
|
1607
|
-
|
1841
|
+
if (then_keyword_loc = node.then_keyword_loc)
|
1842
|
+
token(then_keyword_loc)
|
1843
|
+
else
|
1844
|
+
srange_find(node.conditions.last.location.end_offset, node.statements&.location&.start_offset, ";")
|
1845
|
+
end,
|
1608
1846
|
visit(node.statements)
|
1609
1847
|
)
|
1610
1848
|
end
|
@@ -1620,7 +1858,11 @@ module Prism
|
|
1620
1858
|
:while,
|
1621
1859
|
token(node.keyword_loc),
|
1622
1860
|
visit(node.predicate),
|
1623
|
-
|
1861
|
+
if (do_keyword_loc = node.do_keyword_loc)
|
1862
|
+
token(do_keyword_loc)
|
1863
|
+
else
|
1864
|
+
srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, ";")
|
1865
|
+
end,
|
1624
1866
|
visit(node.statements),
|
1625
1867
|
token(node.closing_loc)
|
1626
1868
|
)
|
@@ -1637,16 +1879,24 @@ module Prism
|
|
1637
1879
|
# `foo`
|
1638
1880
|
# ^^^^^
|
1639
1881
|
def visit_x_string_node(node)
|
1640
|
-
if node.
|
1641
|
-
|
1642
|
-
builder.xstring_compose(token(node.opening_loc), children, closing)
|
1643
|
-
else
|
1644
|
-
builder.xstring_compose(
|
1645
|
-
token(node.opening_loc),
|
1646
|
-
[builder.string_internal([node.unescaped, srange(node.content_loc)])],
|
1647
|
-
token(node.closing_loc)
|
1648
|
-
)
|
1882
|
+
if node.heredoc?
|
1883
|
+
return visit_heredoc(node.to_interpolated) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) }
|
1649
1884
|
end
|
1885
|
+
|
1886
|
+
parts =
|
1887
|
+
if node.content == ""
|
1888
|
+
[]
|
1889
|
+
elsif node.content.include?("\n")
|
1890
|
+
string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening)
|
1891
|
+
else
|
1892
|
+
[builder.string_internal([node.unescaped, srange(node.content_loc)])]
|
1893
|
+
end
|
1894
|
+
|
1895
|
+
builder.xstring_compose(
|
1896
|
+
token(node.opening_loc),
|
1897
|
+
parts,
|
1898
|
+
token(node.closing_loc)
|
1899
|
+
)
|
1650
1900
|
end
|
1651
1901
|
|
1652
1902
|
# yield
|
@@ -1687,6 +1937,30 @@ module Prism
|
|
1687
1937
|
forwarding
|
1688
1938
|
end
|
1689
1939
|
|
1940
|
+
# Returns the set of targets for a MultiTargetNode or a MultiWriteNode.
|
1941
|
+
def multi_target_elements(node)
|
1942
|
+
elements = [*node.lefts]
|
1943
|
+
elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
|
1944
|
+
elements.concat(node.rights)
|
1945
|
+
elements
|
1946
|
+
end
|
1947
|
+
|
1948
|
+
# Negate the value of a numeric node. This is a special case where you
|
1949
|
+
# have a negative sign on one line and then a number on the next line.
|
1950
|
+
# In normal Ruby, this will always be a method call. The parser gem,
|
1951
|
+
# however, marks this as a numeric literal. We have to massage the tree
|
1952
|
+
# here to get it into the correct form.
|
1953
|
+
def numeric_negate(message_loc, receiver)
|
1954
|
+
case receiver.type
|
1955
|
+
when :integer_node, :float_node
|
1956
|
+
receiver.copy(value: -receiver.value, location: message_loc.join(receiver.location))
|
1957
|
+
when :rational_node
|
1958
|
+
receiver.copy(numerator: -receiver.numerator, location: message_loc.join(receiver.location))
|
1959
|
+
when :imaginary_node
|
1960
|
+
receiver.copy(numeric: numeric_negate(message_loc, receiver.numeric), location: message_loc.join(receiver.location))
|
1961
|
+
end
|
1962
|
+
end
|
1963
|
+
|
1690
1964
|
# Blocks can have a special set of parameters that automatically expand
|
1691
1965
|
# when given arrays if they have a single required parameter and no
|
1692
1966
|
# other parameters.
|
@@ -1716,14 +1990,16 @@ module Prism
|
|
1716
1990
|
Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset])
|
1717
1991
|
end
|
1718
1992
|
|
1719
|
-
# Constructs a new source range by finding the given
|
1720
|
-
# given start offset and end offset. If the needle is not found, it
|
1721
|
-
# returns nil.
|
1722
|
-
|
1723
|
-
|
1724
|
-
|
1725
|
-
|
1726
|
-
|
1993
|
+
# Constructs a new source range by finding the given character between
|
1994
|
+
# the given start offset and end offset. If the needle is not found, it
|
1995
|
+
# returns nil. Importantly it does not search past newlines or comments.
|
1996
|
+
#
|
1997
|
+
# Note that end_offset is allowed to be nil, in which case this will
|
1998
|
+
# search until the end of the string.
|
1999
|
+
def srange_find(start_offset, end_offset, character)
|
2000
|
+
if (match = source_buffer.source.byteslice(start_offset...end_offset)[/\A\s*#{character}/])
|
2001
|
+
final_offset = start_offset + match.bytesize
|
2002
|
+
[character, Range.new(source_buffer, offset_cache[final_offset - character.bytesize], offset_cache[final_offset])]
|
1727
2003
|
end
|
1728
2004
|
end
|
1729
2005
|
|
@@ -1736,20 +2012,22 @@ module Prism
|
|
1736
2012
|
def visit_block(call, block)
|
1737
2013
|
if block
|
1738
2014
|
parameters = block.parameters
|
2015
|
+
implicit_parameters = parameters.is_a?(NumberedParametersNode) || parameters.is_a?(ItParametersNode)
|
1739
2016
|
|
1740
2017
|
builder.block(
|
1741
2018
|
call,
|
1742
2019
|
token(block.opening_loc),
|
1743
2020
|
if parameters.nil?
|
1744
2021
|
builder.args(nil, [], nil, false)
|
1745
|
-
elsif
|
2022
|
+
elsif implicit_parameters
|
1746
2023
|
visit(parameters)
|
1747
2024
|
else
|
1748
2025
|
builder.args(
|
1749
2026
|
token(parameters.opening_loc),
|
1750
2027
|
if procarg0?(parameters.parameters)
|
1751
2028
|
parameter = parameters.parameters.requireds.first
|
1752
|
-
|
2029
|
+
visited = parameter.is_a?(RequiredParameterNode) ? visit(parameter) : parameter.accept(copy_compiler(in_destructure: true))
|
2030
|
+
[builder.procarg0(visited)].concat(visit_all(parameters.locals))
|
1753
2031
|
else
|
1754
2032
|
visit(parameters)
|
1755
2033
|
end,
|
@@ -1757,7 +2035,7 @@ module Prism
|
|
1757
2035
|
false
|
1758
2036
|
)
|
1759
2037
|
end,
|
1760
|
-
block.body
|
2038
|
+
visit(block.body),
|
1761
2039
|
token(block.closing_loc)
|
1762
2040
|
)
|
1763
2041
|
else
|
@@ -1767,29 +2045,22 @@ module Prism
|
|
1767
2045
|
|
1768
2046
|
# Visit a heredoc that can be either a string or an xstring.
|
1769
2047
|
def visit_heredoc(node)
|
1770
|
-
children =
|
2048
|
+
children = Array.new
|
2049
|
+
indented = false
|
2050
|
+
|
2051
|
+
# If this is a dedenting heredoc, then we need to insert the opening
|
2052
|
+
# content into the children as well.
|
2053
|
+
if node.opening.start_with?("<<~") && node.parts.length > 0 && !node.parts.first.is_a?(StringNode)
|
2054
|
+
location = node.parts.first.location
|
2055
|
+
location = location.copy(start_offset: location.start_offset - location.start_line_slice.bytesize)
|
2056
|
+
children << builder.string_internal(token(location))
|
2057
|
+
indented = true
|
2058
|
+
end
|
2059
|
+
|
1771
2060
|
node.parts.each do |part|
|
1772
2061
|
pushing =
|
1773
|
-
if part.is_a?(StringNode) && part.
|
1774
|
-
unescaped
|
1775
|
-
escaped = part.content.lines(chomp: true)
|
1776
|
-
|
1777
|
-
escaped_lengths =
|
1778
|
-
if node.opening.end_with?("'")
|
1779
|
-
escaped.map { |line| line.bytesize + 1 }
|
1780
|
-
else
|
1781
|
-
escaped.chunk_while { |before, after| before.match?(/(?<!\\)\\$/) }.map { |line| line.join.bytesize + line.length }
|
1782
|
-
end
|
1783
|
-
|
1784
|
-
start_offset = part.location.start_offset
|
1785
|
-
end_offset = nil
|
1786
|
-
|
1787
|
-
unescaped.zip(escaped_lengths).map do |unescaped_line, escaped_length|
|
1788
|
-
end_offset = start_offset + (escaped_length || 0)
|
1789
|
-
inner_part = builder.string_internal(["#{unescaped_line}\n", srange_offsets(start_offset, end_offset)])
|
1790
|
-
start_offset = end_offset
|
1791
|
-
inner_part
|
1792
|
-
end
|
2062
|
+
if part.is_a?(StringNode) && part.content.include?("\n")
|
2063
|
+
string_nodes_from_line_continuations(part.unescaped, part.content, part.location.start_offset, node.opening)
|
1793
2064
|
else
|
1794
2065
|
[visit(part)]
|
1795
2066
|
end
|
@@ -1798,7 +2069,12 @@ module Prism
|
|
1798
2069
|
if child.type == :str && child.children.last == ""
|
1799
2070
|
# nothing
|
1800
2071
|
elsif child.type == :str && children.last && children.last.type == :str && !children.last.children.first.end_with?("\n")
|
1801
|
-
|
2072
|
+
appendee = children[-1]
|
2073
|
+
|
2074
|
+
location = appendee.loc
|
2075
|
+
location = location.with_expression(location.expression.join(child.loc.expression))
|
2076
|
+
|
2077
|
+
children[-1] = appendee.updated(:str, ["#{appendee.children.first}#{child.children.first}"], location: location)
|
1802
2078
|
else
|
1803
2079
|
children << child
|
1804
2080
|
end
|
@@ -1807,8 +2083,10 @@ module Prism
|
|
1807
2083
|
|
1808
2084
|
closing = node.closing
|
1809
2085
|
closing_t = [closing.chomp, srange_offsets(node.closing_loc.start_offset, node.closing_loc.end_offset - (closing[/\s+$/]&.length || 0))]
|
2086
|
+
composed = yield children, closing_t
|
1810
2087
|
|
1811
|
-
|
2088
|
+
composed = composed.updated(nil, children[1..-1]) if indented
|
2089
|
+
composed
|
1812
2090
|
end
|
1813
2091
|
|
1814
2092
|
# Visit a numeric node and account for the optional sign.
|
@@ -1832,6 +2110,102 @@ module Prism
|
|
1832
2110
|
parser.pattern_variables.pop
|
1833
2111
|
end
|
1834
2112
|
end
|
2113
|
+
|
2114
|
+
# When the content of a string node is split across multiple lines, the
|
2115
|
+
# parser gem creates individual string nodes for each line the content is part of.
|
2116
|
+
def string_nodes_from_interpolation(node, opening)
|
2117
|
+
node.parts.flat_map do |part|
|
2118
|
+
if part.type == :string_node && part.content.include?("\n") && part.opening_loc.nil?
|
2119
|
+
string_nodes_from_line_continuations(part.unescaped, part.content, part.content_loc.start_offset, opening)
|
2120
|
+
else
|
2121
|
+
visit(part)
|
2122
|
+
end
|
2123
|
+
end
|
2124
|
+
end
|
2125
|
+
|
2126
|
+
# Create parser string nodes from a single prism node. The parser gem
|
2127
|
+
# "glues" strings together when a line continuation is encountered.
|
2128
|
+
def string_nodes_from_line_continuations(unescaped, escaped, start_offset, opening)
|
2129
|
+
unescaped = unescaped.lines
|
2130
|
+
escaped = escaped.lines
|
2131
|
+
percent_array = opening&.start_with?("%w", "%W", "%i", "%I")
|
2132
|
+
regex = opening == "/" || opening&.start_with?("%r")
|
2133
|
+
|
2134
|
+
# Non-interpolating strings
|
2135
|
+
if opening&.end_with?("'") || opening&.start_with?("%q", "%s", "%w", "%i")
|
2136
|
+
current_length = 0
|
2137
|
+
current_line = +""
|
2138
|
+
|
2139
|
+
escaped.filter_map.with_index do |escaped_line, index|
|
2140
|
+
unescaped_line = unescaped.fetch(index, "")
|
2141
|
+
current_length += escaped_line.bytesize
|
2142
|
+
current_line << unescaped_line
|
2143
|
+
|
2144
|
+
# Glue line continuations together. Only %w and %i arrays can contain these.
|
2145
|
+
if percent_array && escaped_line[/(\\)*\n$/, 1]&.length&.odd?
|
2146
|
+
next unless index == escaped.count - 1
|
2147
|
+
end
|
2148
|
+
s = builder.string_internal([current_line, srange_offsets(start_offset, start_offset + current_length)])
|
2149
|
+
start_offset += escaped_line.bytesize
|
2150
|
+
current_line = +""
|
2151
|
+
current_length = 0
|
2152
|
+
s
|
2153
|
+
end
|
2154
|
+
else
|
2155
|
+
escaped_lengths = []
|
2156
|
+
normalized_lengths = []
|
2157
|
+
# Keeps track of where an unescaped line should start a new token. An unescaped
|
2158
|
+
# \n would otherwise be indistinguishable from the actual newline at the end of
|
2159
|
+
# of the line. The parser gem only emits a new string node at "real" newlines,
|
2160
|
+
# line continuations don't start a new node as well.
|
2161
|
+
do_next_tokens = []
|
2162
|
+
|
2163
|
+
escaped
|
2164
|
+
.chunk_while { |before, after| before[/(\\*)\r?\n$/, 1]&.length&.odd? || false }
|
2165
|
+
.each do |lines|
|
2166
|
+
escaped_lengths << lines.sum(&:bytesize)
|
2167
|
+
|
2168
|
+
unescaped_lines_count =
|
2169
|
+
if regex
|
2170
|
+
0 # Will always be preserved as is
|
2171
|
+
else
|
2172
|
+
lines.sum do |line|
|
2173
|
+
count = line.scan(/(\\*)n/).count { |(backslashes)| backslashes&.length&.odd? }
|
2174
|
+
count -= 1 if !line.end_with?("\n") && count > 0
|
2175
|
+
count
|
2176
|
+
end
|
2177
|
+
end
|
2178
|
+
|
2179
|
+
extra = 1
|
2180
|
+
extra = lines.count if percent_array # Account for line continuations in percent arrays
|
2181
|
+
|
2182
|
+
normalized_lengths.concat(Array.new(unescaped_lines_count + extra, 0))
|
2183
|
+
normalized_lengths[-1] = lines.sum { |line| line.bytesize }
|
2184
|
+
do_next_tokens.concat(Array.new(unescaped_lines_count + extra, false))
|
2185
|
+
do_next_tokens[-1] = true
|
2186
|
+
end
|
2187
|
+
|
2188
|
+
current_line = +""
|
2189
|
+
current_normalized_length = 0
|
2190
|
+
|
2191
|
+
emitted_count = 0
|
2192
|
+
unescaped.filter_map.with_index do |unescaped_line, index|
|
2193
|
+
current_line << unescaped_line
|
2194
|
+
current_normalized_length += normalized_lengths.fetch(index, 0)
|
2195
|
+
|
2196
|
+
if do_next_tokens[index]
|
2197
|
+
inner_part = builder.string_internal([current_line, srange_offsets(start_offset, start_offset + current_normalized_length)])
|
2198
|
+
start_offset += escaped_lengths.fetch(emitted_count, 0)
|
2199
|
+
current_line = +""
|
2200
|
+
current_normalized_length = 0
|
2201
|
+
emitted_count += 1
|
2202
|
+
inner_part
|
2203
|
+
else
|
2204
|
+
nil
|
2205
|
+
end
|
2206
|
+
end
|
2207
|
+
end
|
2208
|
+
end
|
1835
2209
|
end
|
1836
2210
|
end
|
1837
2211
|
end
|