prism 1.4.0 → 1.7.0

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.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +73 -1
  3. data/Makefile +7 -5
  4. data/README.md +3 -1
  5. data/config.yml +294 -41
  6. data/docs/build_system.md +2 -2
  7. data/docs/cruby_compilation.md +1 -1
  8. data/docs/design.md +2 -2
  9. data/docs/parser_translation.md +8 -23
  10. data/docs/releasing.md +6 -25
  11. data/docs/ripper_translation.md +1 -1
  12. data/ext/prism/api_node.c +9 -3
  13. data/ext/prism/extconf.rb +1 -1
  14. data/ext/prism/extension.c +24 -3
  15. data/ext/prism/extension.h +1 -1
  16. data/include/prism/ast.h +360 -70
  17. data/include/prism/diagnostic.h +7 -0
  18. data/include/prism/options.h +49 -3
  19. data/include/prism/parser.h +3 -0
  20. data/include/prism/regexp.h +2 -2
  21. data/include/prism/util/pm_buffer.h +8 -0
  22. data/include/prism/util/pm_integer.h +4 -0
  23. data/include/prism/util/pm_list.h +6 -0
  24. data/include/prism/util/pm_string.h +12 -2
  25. data/include/prism/version.h +2 -2
  26. data/include/prism.h +40 -15
  27. data/lib/prism/compiler.rb +456 -151
  28. data/lib/prism/desugar_compiler.rb +1 -0
  29. data/lib/prism/dispatcher.rb +16 -0
  30. data/lib/prism/dot_visitor.rb +10 -1
  31. data/lib/prism/dsl.rb +5 -2
  32. data/lib/prism/ffi.rb +28 -10
  33. data/lib/prism/inspect_visitor.rb +4 -0
  34. data/lib/prism/lex_compat.rb +1 -0
  35. data/lib/prism/mutation_compiler.rb +3 -0
  36. data/lib/prism/node.rb +559 -349
  37. data/lib/prism/node_ext.rb +4 -1
  38. data/lib/prism/pack.rb +2 -0
  39. data/lib/prism/parse_result/comments.rb +1 -0
  40. data/lib/prism/parse_result/errors.rb +1 -0
  41. data/lib/prism/parse_result/newlines.rb +1 -0
  42. data/lib/prism/parse_result.rb +3 -15
  43. data/lib/prism/pattern.rb +1 -0
  44. data/lib/prism/polyfill/scan_byte.rb +14 -0
  45. data/lib/prism/polyfill/warn.rb +36 -0
  46. data/lib/prism/reflection.rb +4 -1
  47. data/lib/prism/relocation.rb +1 -0
  48. data/lib/prism/serialize.rb +30 -22
  49. data/lib/prism/string_query.rb +1 -0
  50. data/lib/prism/translation/parser/builder.rb +1 -0
  51. data/lib/prism/translation/parser/compiler.rb +63 -41
  52. data/lib/prism/translation/parser/lexer.rb +29 -21
  53. data/lib/prism/translation/parser.rb +25 -4
  54. data/lib/prism/translation/parser33.rb +1 -0
  55. data/lib/prism/translation/parser34.rb +1 -0
  56. data/lib/prism/translation/parser35.rb +2 -6
  57. data/lib/prism/translation/parser40.rb +13 -0
  58. data/lib/prism/translation/parser41.rb +13 -0
  59. data/lib/prism/translation/parser_current.rb +26 -0
  60. data/lib/prism/translation/ripper/sexp.rb +1 -0
  61. data/lib/prism/translation/ripper.rb +19 -3
  62. data/lib/prism/translation/ruby_parser.rb +340 -22
  63. data/lib/prism/translation.rb +4 -0
  64. data/lib/prism/visitor.rb +457 -152
  65. data/lib/prism.rb +22 -0
  66. data/prism.gemspec +9 -1
  67. data/rbi/prism/dsl.rbi +6 -6
  68. data/rbi/prism/node.rbi +42 -17
  69. data/rbi/prism/translation/parser35.rbi +0 -2
  70. data/rbi/prism/translation/parser40.rbi +6 -0
  71. data/rbi/prism/translation/parser41.rbi +6 -0
  72. data/sig/prism/dispatcher.rbs +3 -0
  73. data/sig/prism/dsl.rbs +5 -5
  74. data/sig/prism/node.rbs +462 -38
  75. data/sig/prism/node_ext.rbs +84 -17
  76. data/sig/prism/parse_result/comments.rbs +38 -0
  77. data/sig/prism/parse_result.rbs +4 -0
  78. data/sig/prism/reflection.rbs +1 -1
  79. data/sig/prism.rbs +4 -0
  80. data/src/diagnostic.c +13 -1
  81. data/src/encoding.c +172 -67
  82. data/src/node.c +11 -0
  83. data/src/options.c +17 -7
  84. data/src/prettyprint.c +18 -0
  85. data/src/prism.c +1495 -2021
  86. data/src/serialize.c +9 -1
  87. data/src/token_type.c +38 -36
  88. data/src/util/pm_constant_pool.c +1 -1
  89. data/src/util/pm_string.c +6 -8
  90. metadata +11 -3
@@ -1,12 +1,18 @@
1
1
  # frozen_string_literal: true
2
+ # :markup: markdown
2
3
 
3
4
  begin
4
- require "ruby_parser"
5
+ require "sexp"
5
6
  rescue LoadError
6
- warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.})
7
+ warn(%q{Error: Unable to load sexp. Add `gem "sexp_processor"` to your Gemfile.})
7
8
  exit(1)
8
9
  end
9
10
 
11
+ class RubyParser # :nodoc:
12
+ class SyntaxError < RuntimeError # :nodoc:
13
+ end
14
+ end
15
+
10
16
  module Prism
11
17
  module Translation
12
18
  # This module is the entry-point for converting a prism syntax tree into the
@@ -15,7 +21,7 @@ module Prism
15
21
  # A prism visitor that builds Sexp objects.
16
22
  class Compiler < ::Prism::Compiler
17
23
  # This is the name of the file that we are compiling. We set it on every
18
- # Sexp object that is generated, and also use it to compile __FILE__
24
+ # Sexp object that is generated, and also use it to compile `__FILE__`
19
25
  # nodes.
20
26
  attr_reader :file
21
27
 
@@ -34,26 +40,34 @@ module Prism
34
40
  @in_pattern = in_pattern
35
41
  end
36
42
 
43
+ # ```
37
44
  # alias foo bar
38
45
  # ^^^^^^^^^^^^^
46
+ # ```
39
47
  def visit_alias_method_node(node)
40
48
  s(node, :alias, visit(node.new_name), visit(node.old_name))
41
49
  end
42
50
 
51
+ # ```
43
52
  # alias $foo $bar
44
53
  # ^^^^^^^^^^^^^^^
54
+ # ```
45
55
  def visit_alias_global_variable_node(node)
46
56
  s(node, :valias, node.new_name.name, node.old_name.name)
47
57
  end
48
58
 
59
+ # ```
49
60
  # foo => bar | baz
50
61
  # ^^^^^^^^^
62
+ # ```
51
63
  def visit_alternation_pattern_node(node)
52
64
  s(node, :or, visit(node.left), visit(node.right))
53
65
  end
54
66
 
67
+ # ```
55
68
  # a and b
56
69
  # ^^^^^^^
70
+ # ```
57
71
  def visit_and_node(node)
58
72
  left = visit(node.left)
59
73
 
@@ -70,8 +84,10 @@ module Prism
70
84
  end
71
85
  end
72
86
 
87
+ # ```
73
88
  # []
74
89
  # ^^
90
+ # ```
75
91
  def visit_array_node(node)
76
92
  if in_pattern
77
93
  s(node, :array_pat, nil).concat(visit_all(node.elements))
@@ -80,8 +96,10 @@ module Prism
80
96
  end
81
97
  end
82
98
 
99
+ # ```
83
100
  # foo => [bar]
84
101
  # ^^^^^
102
+ # ```
85
103
  def visit_array_pattern_node(node)
86
104
  if node.constant.nil? && node.requireds.empty? && node.rest.nil? && node.posts.empty?
87
105
  s(node, :array_pat)
@@ -103,23 +121,29 @@ module Prism
103
121
  end
104
122
  end
105
123
 
124
+ # ```
106
125
  # foo(bar)
107
126
  # ^^^
127
+ # ```
108
128
  def visit_arguments_node(node)
109
129
  raise "Cannot visit arguments directly"
110
130
  end
111
131
 
132
+ # ```
112
133
  # { a: 1 }
113
134
  # ^^^^
135
+ # ```
114
136
  def visit_assoc_node(node)
115
137
  [visit(node.key), visit(node.value)]
116
138
  end
117
139
 
140
+ # ```
118
141
  # def foo(**); bar(**); end
119
142
  # ^^
120
143
  #
121
144
  # { **foo }
122
145
  # ^^^^^
146
+ # ```
123
147
  def visit_assoc_splat_node(node)
124
148
  if node.value.nil?
125
149
  [s(node, :kwsplat)]
@@ -128,14 +152,18 @@ module Prism
128
152
  end
129
153
  end
130
154
 
155
+ # ```
131
156
  # $+
132
157
  # ^^
158
+ # ```
133
159
  def visit_back_reference_read_node(node)
134
- s(node, :back_ref, node.name.name.delete_prefix("$").to_sym)
160
+ s(node, :back_ref, node.name.to_s.delete_prefix("$").to_sym)
135
161
  end
136
162
 
163
+ # ```
137
164
  # begin end
138
165
  # ^^^^^^^^^
166
+ # ```
139
167
  def visit_begin_node(node)
140
168
  result = node.statements.nil? ? s(node, :nil) : visit(node.statements)
141
169
 
@@ -167,16 +195,20 @@ module Prism
167
195
  result
168
196
  end
169
197
 
198
+ # ```
170
199
  # foo(&bar)
171
200
  # ^^^^
201
+ # ```
172
202
  def visit_block_argument_node(node)
173
203
  s(node, :block_pass).tap do |result|
174
204
  result << visit(node.expression) unless node.expression.nil?
175
205
  end
176
206
  end
177
207
 
208
+ # ```
178
209
  # foo { |; bar| }
179
210
  # ^^^
211
+ # ```
180
212
  def visit_block_local_variable_node(node)
181
213
  node.name
182
214
  end
@@ -186,8 +218,10 @@ module Prism
186
218
  s(node, :block_pass, visit(node.expression))
187
219
  end
188
220
 
221
+ # ```
189
222
  # def foo(&bar); end
190
223
  # ^^^^
224
+ # ```
191
225
  def visit_block_parameter_node(node)
192
226
  :"&#{node.name}"
193
227
  end
@@ -228,11 +262,13 @@ module Prism
228
262
  result
229
263
  end
230
264
 
265
+ # ```
231
266
  # break
232
267
  # ^^^^^
233
268
  #
234
269
  # break foo
235
270
  # ^^^^^^^^^
271
+ # ```
236
272
  def visit_break_node(node)
237
273
  if node.arguments.nil?
238
274
  s(node, :break)
@@ -243,6 +279,7 @@ module Prism
243
279
  end
244
280
  end
245
281
 
282
+ # ```
246
283
  # foo
247
284
  # ^^^
248
285
  #
@@ -251,6 +288,7 @@ module Prism
251
288
  #
252
289
  # foo.bar() {}
253
290
  # ^^^^^^^^^^^^
291
+ # ```
254
292
  def visit_call_node(node)
255
293
  case node.name
256
294
  when :!~
@@ -289,8 +327,10 @@ module Prism
289
327
  visit_block(node, result, block)
290
328
  end
291
329
 
330
+ # ```
292
331
  # foo.bar += baz
293
332
  # ^^^^^^^^^^^^^^^
333
+ # ```
294
334
  def visit_call_operator_write_node(node)
295
335
  if op_asgn?(node)
296
336
  s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.binary_operator)
@@ -299,8 +339,10 @@ module Prism
299
339
  end
300
340
  end
301
341
 
342
+ # ```
302
343
  # foo.bar &&= baz
303
344
  # ^^^^^^^^^^^^^^^
345
+ # ```
304
346
  def visit_call_and_write_node(node)
305
347
  if op_asgn?(node)
306
348
  s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"&&")
@@ -309,8 +351,10 @@ module Prism
309
351
  end
310
352
  end
311
353
 
354
+ # ```
312
355
  # foo.bar ||= baz
313
356
  # ^^^^^^^^^^^^^^^
357
+ # ```
314
358
  def visit_call_or_write_node(node)
315
359
  if op_asgn?(node)
316
360
  s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"||")
@@ -332,32 +376,42 @@ module Prism
332
376
  node.safe_navigation? ? :"safe_#{type}" : type
333
377
  end
334
378
 
379
+ # ```
335
380
  # foo.bar, = 1
336
381
  # ^^^^^^^
382
+ # ```
337
383
  def visit_call_target_node(node)
338
384
  s(node, :attrasgn, visit(node.receiver), node.name)
339
385
  end
340
386
 
387
+ # ```
341
388
  # foo => bar => baz
342
389
  # ^^^^^^^^^^
390
+ # ```
343
391
  def visit_capture_pattern_node(node)
344
392
  visit(node.target) << visit(node.value)
345
393
  end
346
394
 
395
+ # ```
347
396
  # case foo; when bar; end
348
397
  # ^^^^^^^^^^^^^^^^^^^^^^^
398
+ # ```
349
399
  def visit_case_node(node)
350
400
  s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause)
351
401
  end
352
402
 
403
+ # ```
353
404
  # case foo; in bar; end
354
405
  # ^^^^^^^^^^^^^^^^^^^^^
406
+ # ```
355
407
  def visit_case_match_node(node)
356
408
  s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause)
357
409
  end
358
410
 
411
+ # ```
359
412
  # class Foo; end
360
413
  # ^^^^^^^^^^^^^^
414
+ # ```
361
415
  def visit_class_node(node)
362
416
  name =
363
417
  if node.constant_path.is_a?(ConstantReadNode)
@@ -366,51 +420,67 @@ module Prism
366
420
  visit(node.constant_path)
367
421
  end
368
422
 
369
- if node.body.nil?
370
- s(node, :class, name, visit(node.superclass))
371
- elsif node.body.is_a?(StatementsNode)
372
- compiler = copy_compiler(in_def: false)
373
- s(node, :class, name, visit(node.superclass)).concat(node.body.body.map { |child| child.accept(compiler) })
374
- else
375
- s(node, :class, name, visit(node.superclass), node.body.accept(copy_compiler(in_def: false)))
376
- end
423
+ result =
424
+ if node.body.nil?
425
+ s(node, :class, name, visit(node.superclass))
426
+ elsif node.body.is_a?(StatementsNode)
427
+ compiler = copy_compiler(in_def: false)
428
+ s(node, :class, name, visit(node.superclass)).concat(node.body.body.map { |child| child.accept(compiler) })
429
+ else
430
+ s(node, :class, name, visit(node.superclass), node.body.accept(copy_compiler(in_def: false)))
431
+ end
432
+
433
+ attach_comments(result, node)
434
+ result
377
435
  end
378
436
 
437
+ # ```
379
438
  # @@foo
380
439
  # ^^^^^
440
+ # ```
381
441
  def visit_class_variable_read_node(node)
382
442
  s(node, :cvar, node.name)
383
443
  end
384
444
 
445
+ # ```
385
446
  # @@foo = 1
386
447
  # ^^^^^^^^^
387
448
  #
388
449
  # @@foo, @@bar = 1
389
450
  # ^^^^^ ^^^^^
451
+ # ```
390
452
  def visit_class_variable_write_node(node)
391
453
  s(node, class_variable_write_type, node.name, visit_write_value(node.value))
392
454
  end
393
455
 
456
+ # ```
394
457
  # @@foo += bar
395
458
  # ^^^^^^^^^^^^
459
+ # ```
396
460
  def visit_class_variable_operator_write_node(node)
397
461
  s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.binary_operator, visit_write_value(node.value)))
398
462
  end
399
463
 
464
+ # ```
400
465
  # @@foo &&= bar
401
466
  # ^^^^^^^^^^^^^
467
+ # ```
402
468
  def visit_class_variable_and_write_node(node)
403
469
  s(node, :op_asgn_and, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value)))
404
470
  end
405
471
 
472
+ # ```
406
473
  # @@foo ||= bar
407
474
  # ^^^^^^^^^^^^^
475
+ # ```
408
476
  def visit_class_variable_or_write_node(node)
409
477
  s(node, :op_asgn_or, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value)))
410
478
  end
411
479
 
480
+ # ```
412
481
  # @@foo, = bar
413
482
  # ^^^^^
483
+ # ```
414
484
  def visit_class_variable_target_node(node)
415
485
  s(node, class_variable_write_type, node.name)
416
486
  end
@@ -421,47 +491,61 @@ module Prism
421
491
  in_def ? :cvasgn : :cvdecl
422
492
  end
423
493
 
494
+ # ```
424
495
  # Foo
425
496
  # ^^^
497
+ # ```
426
498
  def visit_constant_read_node(node)
427
499
  s(node, :const, node.name)
428
500
  end
429
501
 
502
+ # ```
430
503
  # Foo = 1
431
504
  # ^^^^^^^
432
505
  #
433
506
  # Foo, Bar = 1
434
507
  # ^^^ ^^^
508
+ # ```
435
509
  def visit_constant_write_node(node)
436
510
  s(node, :cdecl, node.name, visit_write_value(node.value))
437
511
  end
438
512
 
513
+ # ```
439
514
  # Foo += bar
440
515
  # ^^^^^^^^^^^
516
+ # ```
441
517
  def visit_constant_operator_write_node(node)
442
518
  s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.binary_operator, visit_write_value(node.value)))
443
519
  end
444
520
 
521
+ # ```
445
522
  # Foo &&= bar
446
523
  # ^^^^^^^^^^^^
524
+ # ```
447
525
  def visit_constant_and_write_node(node)
448
526
  s(node, :op_asgn_and, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value)))
449
527
  end
450
528
 
529
+ # ```
451
530
  # Foo ||= bar
452
531
  # ^^^^^^^^^^^^
532
+ # ```
453
533
  def visit_constant_or_write_node(node)
454
534
  s(node, :op_asgn_or, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value)))
455
535
  end
456
536
 
537
+ # ```
457
538
  # Foo, = bar
458
539
  # ^^^
540
+ # ```
459
541
  def visit_constant_target_node(node)
460
542
  s(node, :cdecl, node.name)
461
543
  end
462
544
 
545
+ # ```
463
546
  # Foo::Bar
464
547
  # ^^^^^^^^
548
+ # ```
465
549
  def visit_constant_path_node(node)
466
550
  if node.parent.nil?
467
551
  s(node, :colon3, node.name)
@@ -470,35 +554,45 @@ module Prism
470
554
  end
471
555
  end
472
556
 
557
+ # ```
473
558
  # Foo::Bar = 1
474
559
  # ^^^^^^^^^^^^
475
560
  #
476
561
  # Foo::Foo, Bar::Bar = 1
477
562
  # ^^^^^^^^ ^^^^^^^^
563
+ # ```
478
564
  def visit_constant_path_write_node(node)
479
565
  s(node, :cdecl, visit(node.target), visit_write_value(node.value))
480
566
  end
481
567
 
568
+ # ```
482
569
  # Foo::Bar += baz
483
570
  # ^^^^^^^^^^^^^^^
571
+ # ```
484
572
  def visit_constant_path_operator_write_node(node)
485
573
  s(node, :op_asgn, visit(node.target), node.binary_operator, visit_write_value(node.value))
486
574
  end
487
575
 
576
+ # ```
488
577
  # Foo::Bar &&= baz
489
578
  # ^^^^^^^^^^^^^^^^
579
+ # ```
490
580
  def visit_constant_path_and_write_node(node)
491
581
  s(node, :op_asgn_and, visit(node.target), visit_write_value(node.value))
492
582
  end
493
583
 
584
+ # ```
494
585
  # Foo::Bar ||= baz
495
586
  # ^^^^^^^^^^^^^^^^
587
+ # ```
496
588
  def visit_constant_path_or_write_node(node)
497
589
  s(node, :op_asgn_or, visit(node.target), visit_write_value(node.value))
498
590
  end
499
591
 
592
+ # ```
500
593
  # Foo::Bar, = baz
501
594
  # ^^^^^^^^
595
+ # ```
502
596
  def visit_constant_path_target_node(node)
503
597
  inner =
504
598
  if node.parent.nil?
@@ -510,11 +604,13 @@ module Prism
510
604
  s(node, :const, inner)
511
605
  end
512
606
 
607
+ # ```
513
608
  # def foo; end
514
609
  # ^^^^^^^^^^^^
515
610
  #
516
611
  # def self.foo; end
517
612
  # ^^^^^^^^^^^^^^^^^
613
+ # ```
518
614
  def visit_def_node(node)
519
615
  name = node.name_loc.slice.to_sym
520
616
  result =
@@ -524,7 +620,9 @@ module Prism
524
620
  s(node, :defs, visit(node.receiver), name)
525
621
  end
526
622
 
623
+ attach_comments(result, node)
527
624
  result.line(node.name_loc.start_line)
625
+
528
626
  if node.parameters.nil?
529
627
  result << s(node, :args).line(node.name_loc.start_line)
530
628
  else
@@ -541,55 +639,71 @@ module Prism
541
639
  end
542
640
  end
543
641
 
642
+ # ```
544
643
  # defined? a
545
644
  # ^^^^^^^^^^
546
645
  #
547
646
  # defined?(a)
548
647
  # ^^^^^^^^^^^
648
+ # ```
549
649
  def visit_defined_node(node)
550
650
  s(node, :defined, visit(node.value))
551
651
  end
552
652
 
653
+ # ```
553
654
  # if foo then bar else baz end
554
655
  # ^^^^^^^^^^^^
656
+ # ```
555
657
  def visit_else_node(node)
556
658
  visit(node.statements)
557
659
  end
558
660
 
661
+ # ```
559
662
  # "foo #{bar}"
560
663
  # ^^^^^^
664
+ # ```
561
665
  def visit_embedded_statements_node(node)
562
666
  result = s(node, :evstr)
563
667
  result << visit(node.statements) unless node.statements.nil?
564
668
  result
565
669
  end
566
670
 
671
+ # ```
567
672
  # "foo #@bar"
568
673
  # ^^^^^
674
+ # ```
569
675
  def visit_embedded_variable_node(node)
570
676
  s(node, :evstr, visit(node.variable))
571
677
  end
572
678
 
679
+ # ```
573
680
  # begin; foo; ensure; bar; end
574
681
  # ^^^^^^^^^^^^
682
+ # ```
575
683
  def visit_ensure_node(node)
576
684
  node.statements.nil? ? s(node, :nil) : visit(node.statements)
577
685
  end
578
686
 
687
+ # ```
579
688
  # false
580
689
  # ^^^^^
690
+ # ```
581
691
  def visit_false_node(node)
582
692
  s(node, :false)
583
693
  end
584
694
 
695
+ # ```
585
696
  # foo => [*, bar, *]
586
697
  # ^^^^^^^^^^^
698
+ # ```
587
699
  def visit_find_pattern_node(node)
588
700
  s(node, :find_pat, visit_pattern_constant(node.constant), :"*#{node.left.expression&.name}", *visit_all(node.requireds), :"*#{node.right.expression&.name}")
589
701
  end
590
702
 
703
+ # ```
591
704
  # if foo .. bar; end
592
705
  # ^^^^^^^^^^
706
+ # ```
593
707
  def visit_flip_flop_node(node)
594
708
  if node.left.is_a?(IntegerNode) && node.right.is_a?(IntegerNode)
595
709
  s(node, :lit, Range.new(node.left.value, node.right.value, node.exclude_end?))
@@ -598,86 +712,112 @@ module Prism
598
712
  end
599
713
  end
600
714
 
715
+ # ```
601
716
  # 1.0
602
717
  # ^^^
718
+ # ```
603
719
  def visit_float_node(node)
604
720
  s(node, :lit, node.value)
605
721
  end
606
722
 
723
+ # ```
607
724
  # for foo in bar do end
608
725
  # ^^^^^^^^^^^^^^^^^^^^^
726
+ # ```
609
727
  def visit_for_node(node)
610
728
  s(node, :for, visit(node.collection), visit(node.index), visit(node.statements))
611
729
  end
612
730
 
731
+ # ```
613
732
  # def foo(...); bar(...); end
614
733
  # ^^^
734
+ # ```
615
735
  def visit_forwarding_arguments_node(node)
616
736
  s(node, :forward_args)
617
737
  end
618
738
 
739
+ # ```
619
740
  # def foo(...); end
620
741
  # ^^^
742
+ # ```
621
743
  def visit_forwarding_parameter_node(node)
622
744
  s(node, :forward_args)
623
745
  end
624
746
 
747
+ # ```
625
748
  # super
626
749
  # ^^^^^
627
750
  #
628
751
  # super {}
629
752
  # ^^^^^^^^
753
+ # ```
630
754
  def visit_forwarding_super_node(node)
631
755
  visit_block(node, s(node, :zsuper), node.block)
632
756
  end
633
757
 
758
+ # ```
634
759
  # $foo
635
760
  # ^^^^
761
+ # ```
636
762
  def visit_global_variable_read_node(node)
637
763
  s(node, :gvar, node.name)
638
764
  end
639
765
 
766
+ # ```
640
767
  # $foo = 1
641
768
  # ^^^^^^^^
642
769
  #
643
770
  # $foo, $bar = 1
644
771
  # ^^^^ ^^^^
772
+ # ```
645
773
  def visit_global_variable_write_node(node)
646
774
  s(node, :gasgn, node.name, visit_write_value(node.value))
647
775
  end
648
776
 
777
+ # ```
649
778
  # $foo += bar
650
779
  # ^^^^^^^^^^^
780
+ # ```
651
781
  def visit_global_variable_operator_write_node(node)
652
782
  s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.binary_operator, visit(node.value)))
653
783
  end
654
784
 
785
+ # ```
655
786
  # $foo &&= bar
656
787
  # ^^^^^^^^^^^^
788
+ # ```
657
789
  def visit_global_variable_and_write_node(node)
658
790
  s(node, :op_asgn_and, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value)))
659
791
  end
660
792
 
793
+ # ```
661
794
  # $foo ||= bar
662
795
  # ^^^^^^^^^^^^
796
+ # ```
663
797
  def visit_global_variable_or_write_node(node)
664
798
  s(node, :op_asgn_or, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value)))
665
799
  end
666
800
 
801
+ # ```
667
802
  # $foo, = bar
668
803
  # ^^^^
804
+ # ```
669
805
  def visit_global_variable_target_node(node)
670
806
  s(node, :gasgn, node.name)
671
807
  end
672
808
 
809
+ # ```
673
810
  # {}
674
811
  # ^^
812
+ # ```
675
813
  def visit_hash_node(node)
676
814
  s(node, :hash).concat(node.elements.flat_map { |element| visit(element) })
677
815
  end
678
816
 
817
+ # ```
679
818
  # foo => {}
680
819
  # ^^
820
+ # ```
681
821
  def visit_hash_pattern_node(node)
682
822
  result = s(node, :hash_pat, visit_pattern_constant(node.constant)).concat(node.elements.flat_map { |element| visit(element) })
683
823
 
@@ -691,6 +831,7 @@ module Prism
691
831
  result
692
832
  end
693
833
 
834
+ # ```
694
835
  # if foo then bar end
695
836
  # ^^^^^^^^^^^^^^^^^^^
696
837
  #
@@ -699,6 +840,7 @@ module Prism
699
840
  #
700
841
  # foo ? bar : baz
701
842
  # ^^^^^^^^^^^^^^^
843
+ # ```
702
844
  def visit_if_node(node)
703
845
  s(node, :if, visit(node.predicate), visit(node.statements), visit(node.subsequent))
704
846
  end
@@ -708,18 +850,24 @@ module Prism
708
850
  s(node, :lit, node.value)
709
851
  end
710
852
 
853
+ # ```
711
854
  # { foo: }
712
855
  # ^^^^
856
+ # ```
713
857
  def visit_implicit_node(node)
714
858
  end
715
859
 
860
+ # ```
716
861
  # foo { |bar,| }
717
862
  # ^
863
+ # ```
718
864
  def visit_implicit_rest_node(node)
719
865
  end
720
866
 
867
+ # ```
721
868
  # case foo; in bar; end
722
869
  # ^^^^^^^^^^^^^^^^^^^^^
870
+ # ```
723
871
  def visit_in_node(node)
724
872
  pattern =
725
873
  if node.pattern.is_a?(ConstantPathNode)
@@ -731,8 +879,10 @@ module Prism
731
879
  s(node, :in, pattern).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
732
880
  end
733
881
 
882
+ # ```
734
883
  # foo[bar] += baz
735
884
  # ^^^^^^^^^^^^^^^
885
+ # ```
736
886
  def visit_index_operator_write_node(node)
737
887
  arglist = nil
738
888
 
@@ -744,8 +894,10 @@ module Prism
744
894
  s(node, :op_asgn1, visit(node.receiver), arglist, node.binary_operator, visit_write_value(node.value))
745
895
  end
746
896
 
897
+ # ```
747
898
  # foo[bar] &&= baz
748
899
  # ^^^^^^^^^^^^^^^^
900
+ # ```
749
901
  def visit_index_and_write_node(node)
750
902
  arglist = nil
751
903
 
@@ -757,8 +909,10 @@ module Prism
757
909
  s(node, :op_asgn1, visit(node.receiver), arglist, :"&&", visit_write_value(node.value))
758
910
  end
759
911
 
912
+ # ```
760
913
  # foo[bar] ||= baz
761
914
  # ^^^^^^^^^^^^^^^^
915
+ # ```
762
916
  def visit_index_or_write_node(node)
763
917
  arglist = nil
764
918
 
@@ -770,8 +924,10 @@ module Prism
770
924
  s(node, :op_asgn1, visit(node.receiver), arglist, :"||", visit_write_value(node.value))
771
925
  end
772
926
 
927
+ # ```
773
928
  # foo[bar], = 1
774
929
  # ^^^^^^^^
930
+ # ```
775
931
  def visit_index_target_node(node)
776
932
  arguments = visit_all(node.arguments&.arguments || [])
777
933
  arguments << visit(node.block) unless node.block.nil?
@@ -779,53 +935,69 @@ module Prism
779
935
  s(node, :attrasgn, visit(node.receiver), :[]=).concat(arguments)
780
936
  end
781
937
 
938
+ # ```
782
939
  # @foo
783
940
  # ^^^^
941
+ # ```
784
942
  def visit_instance_variable_read_node(node)
785
943
  s(node, :ivar, node.name)
786
944
  end
787
945
 
946
+ # ```
788
947
  # @foo = 1
789
948
  # ^^^^^^^^
790
949
  #
791
950
  # @foo, @bar = 1
792
951
  # ^^^^ ^^^^
952
+ # ```
793
953
  def visit_instance_variable_write_node(node)
794
954
  s(node, :iasgn, node.name, visit_write_value(node.value))
795
955
  end
796
956
 
957
+ # ```
797
958
  # @foo += bar
798
959
  # ^^^^^^^^^^^
960
+ # ```
799
961
  def visit_instance_variable_operator_write_node(node)
800
962
  s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.binary_operator, visit_write_value(node.value)))
801
963
  end
802
964
 
965
+ # ```
803
966
  # @foo &&= bar
804
967
  # ^^^^^^^^^^^^
968
+ # ```
805
969
  def visit_instance_variable_and_write_node(node)
806
970
  s(node, :op_asgn_and, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value)))
807
971
  end
808
972
 
973
+ # ```
809
974
  # @foo ||= bar
810
975
  # ^^^^^^^^^^^^
976
+ # ```
811
977
  def visit_instance_variable_or_write_node(node)
812
978
  s(node, :op_asgn_or, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value)))
813
979
  end
814
980
 
981
+ # ```
815
982
  # @foo, = bar
816
983
  # ^^^^
984
+ # ```
817
985
  def visit_instance_variable_target_node(node)
818
986
  s(node, :iasgn, node.name)
819
987
  end
820
988
 
989
+ # ```
821
990
  # 1
822
991
  # ^
992
+ # ```
823
993
  def visit_integer_node(node)
824
994
  s(node, :lit, node.value)
825
995
  end
826
996
 
997
+ # ```
827
998
  # if /foo #{bar}/ then end
828
999
  # ^^^^^^^^^^^^
1000
+ # ```
829
1001
  def visit_interpolated_match_last_line_node(node)
830
1002
  parts = visit_interpolated_parts(node.parts)
831
1003
  regexp =
@@ -841,8 +1013,10 @@ module Prism
841
1013
  s(node, :match, regexp)
842
1014
  end
843
1015
 
1016
+ # ```
844
1017
  # /foo #{bar}/
845
1018
  # ^^^^^^^^^^^^
1019
+ # ```
846
1020
  def visit_interpolated_regular_expression_node(node)
847
1021
  parts = visit_interpolated_parts(node.parts)
848
1022
 
@@ -856,22 +1030,28 @@ module Prism
856
1030
  end
857
1031
  end
858
1032
 
1033
+ # ```
859
1034
  # "foo #{bar}"
860
1035
  # ^^^^^^^^^^^^
1036
+ # ```
861
1037
  def visit_interpolated_string_node(node)
862
1038
  parts = visit_interpolated_parts(node.parts)
863
1039
  parts.length == 1 ? s(node, :str, parts.first) : s(node, :dstr).concat(parts)
864
1040
  end
865
1041
 
1042
+ # ```
866
1043
  # :"foo #{bar}"
867
1044
  # ^^^^^^^^^^^^^
1045
+ # ```
868
1046
  def visit_interpolated_symbol_node(node)
869
1047
  parts = visit_interpolated_parts(node.parts)
870
1048
  parts.length == 1 ? s(node, :lit, parts.first.to_sym) : s(node, :dsym).concat(parts)
871
1049
  end
872
1050
 
1051
+ # ```
873
1052
  # `foo #{bar}`
874
1053
  # ^^^^^^^^^^^^
1054
+ # ```
875
1055
  def visit_interpolated_x_string_node(node)
876
1056
  source = node.heredoc? ? node.parts.first : node
877
1057
  parts = visit_interpolated_parts(node.parts)
@@ -951,23 +1131,29 @@ module Prism
951
1131
  results
952
1132
  end
953
1133
 
1134
+ # ```
954
1135
  # -> { it }
955
1136
  # ^^
1137
+ # ```
956
1138
  def visit_it_local_variable_read_node(node)
957
1139
  s(node, :call, nil, :it)
958
1140
  end
959
1141
 
1142
+ # ```
960
1143
  # foo(bar: baz)
961
1144
  # ^^^^^^^^
1145
+ # ```
962
1146
  def visit_keyword_hash_node(node)
963
1147
  s(node, :hash).concat(node.elements.flat_map { |element| visit(element) })
964
1148
  end
965
1149
 
1150
+ # ```
966
1151
  # def foo(**bar); end
967
1152
  # ^^^^^
968
1153
  #
969
1154
  # def foo(**); end
970
1155
  # ^^
1156
+ # ```
971
1157
  def visit_keyword_rest_parameter_node(node)
972
1158
  :"**#{node.name}"
973
1159
  end
@@ -976,8 +1162,8 @@ module Prism
976
1162
  def visit_lambda_node(node)
977
1163
  parameters =
978
1164
  case node.parameters
979
- when nil, NumberedParametersNode
980
- s(node, :args)
1165
+ when nil, ItParametersNode, NumberedParametersNode
1166
+ 0
981
1167
  else
982
1168
  visit(node.parameters)
983
1169
  end
@@ -989,8 +1175,10 @@ module Prism
989
1175
  end
990
1176
  end
991
1177
 
1178
+ # ```
992
1179
  # foo
993
1180
  # ^^^
1181
+ # ```
994
1182
  def visit_local_variable_read_node(node)
995
1183
  if node.name.match?(/^_\d$/)
996
1184
  s(node, :call, nil, node.name)
@@ -999,59 +1187,77 @@ module Prism
999
1187
  end
1000
1188
  end
1001
1189
 
1190
+ # ```
1002
1191
  # foo = 1
1003
1192
  # ^^^^^^^
1004
1193
  #
1005
1194
  # foo, bar = 1
1006
1195
  # ^^^ ^^^
1196
+ # ```
1007
1197
  def visit_local_variable_write_node(node)
1008
1198
  s(node, :lasgn, node.name, visit_write_value(node.value))
1009
1199
  end
1010
1200
 
1201
+ # ```
1011
1202
  # foo += bar
1012
1203
  # ^^^^^^^^^^
1204
+ # ```
1013
1205
  def visit_local_variable_operator_write_node(node)
1014
1206
  s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.binary_operator, visit_write_value(node.value)))
1015
1207
  end
1016
1208
 
1209
+ # ```
1017
1210
  # foo &&= bar
1018
1211
  # ^^^^^^^^^^^
1212
+ # ```
1019
1213
  def visit_local_variable_and_write_node(node)
1020
1214
  s(node, :op_asgn_and, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value)))
1021
1215
  end
1022
1216
 
1217
+ # ```
1023
1218
  # foo ||= bar
1024
1219
  # ^^^^^^^^^^^
1220
+ # ```
1025
1221
  def visit_local_variable_or_write_node(node)
1026
1222
  s(node, :op_asgn_or, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value)))
1027
1223
  end
1028
1224
 
1225
+ # ```
1029
1226
  # foo, = bar
1030
1227
  # ^^^
1228
+ # ```
1031
1229
  def visit_local_variable_target_node(node)
1032
1230
  s(node, :lasgn, node.name)
1033
1231
  end
1034
1232
 
1233
+ # ```
1035
1234
  # if /foo/ then end
1036
1235
  # ^^^^^
1236
+ # ```
1037
1237
  def visit_match_last_line_node(node)
1038
1238
  s(node, :match, s(node, :lit, Regexp.new(node.unescaped, node.options)))
1039
1239
  end
1040
1240
 
1241
+ # ```
1041
1242
  # foo in bar
1042
1243
  # ^^^^^^^^^^
1244
+ # ```
1043
1245
  def visit_match_predicate_node(node)
1044
1246
  s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil)
1045
1247
  end
1046
1248
 
1249
+ # ```
1047
1250
  # foo => bar
1048
1251
  # ^^^^^^^^^^
1252
+ # ```
1049
1253
  def visit_match_required_node(node)
1050
1254
  s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil)
1051
1255
  end
1052
1256
 
1257
+ # ```
1053
1258
  # /(?<foo>foo)/ =~ bar
1054
1259
  # ^^^^^^^^^^^^^^^^^^^^
1260
+ # ```
1055
1261
  def visit_match_write_node(node)
1056
1262
  s(node, :match2, visit(node.call.receiver), visit(node.call.arguments.arguments.first))
1057
1263
  end
@@ -1063,8 +1269,10 @@ module Prism
1063
1269
  raise "Cannot visit missing node directly"
1064
1270
  end
1065
1271
 
1272
+ # ```
1066
1273
  # module Foo; end
1067
1274
  # ^^^^^^^^^^^^^^^
1275
+ # ```
1068
1276
  def visit_module_node(node)
1069
1277
  name =
1070
1278
  if node.constant_path.is_a?(ConstantReadNode)
@@ -1073,18 +1281,24 @@ module Prism
1073
1281
  visit(node.constant_path)
1074
1282
  end
1075
1283
 
1076
- if node.body.nil?
1077
- s(node, :module, name)
1078
- elsif node.body.is_a?(StatementsNode)
1079
- compiler = copy_compiler(in_def: false)
1080
- s(node, :module, name).concat(node.body.body.map { |child| child.accept(compiler) })
1081
- else
1082
- s(node, :module, name, node.body.accept(copy_compiler(in_def: false)))
1083
- end
1284
+ result =
1285
+ if node.body.nil?
1286
+ s(node, :module, name)
1287
+ elsif node.body.is_a?(StatementsNode)
1288
+ compiler = copy_compiler(in_def: false)
1289
+ s(node, :module, name).concat(node.body.body.map { |child| child.accept(compiler) })
1290
+ else
1291
+ s(node, :module, name, node.body.accept(copy_compiler(in_def: false)))
1292
+ end
1293
+
1294
+ attach_comments(result, node)
1295
+ result
1084
1296
  end
1085
1297
 
1298
+ # ```
1086
1299
  # foo, bar = baz
1087
1300
  # ^^^^^^^^
1301
+ # ```
1088
1302
  def visit_multi_target_node(node)
1089
1303
  targets = [*node.lefts]
1090
1304
  targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
@@ -1093,8 +1307,10 @@ module Prism
1093
1307
  s(node, :masgn, s(node, :array).concat(visit_all(targets)))
1094
1308
  end
1095
1309
 
1310
+ # ```
1096
1311
  # foo, bar = baz
1097
1312
  # ^^^^^^^^^^^^^^
1313
+ # ```
1098
1314
  def visit_multi_write_node(node)
1099
1315
  targets = [*node.lefts]
1100
1316
  targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode)
@@ -1114,11 +1330,13 @@ module Prism
1114
1330
  s(node, :masgn, s(node, :array).concat(visit_all(targets)), value)
1115
1331
  end
1116
1332
 
1333
+ # ```
1117
1334
  # next
1118
1335
  # ^^^^
1119
1336
  #
1120
1337
  # next foo
1121
1338
  # ^^^^^^^^
1339
+ # ```
1122
1340
  def visit_next_node(node)
1123
1341
  if node.arguments.nil?
1124
1342
  s(node, :next)
@@ -1130,44 +1348,58 @@ module Prism
1130
1348
  end
1131
1349
  end
1132
1350
 
1351
+ # ```
1133
1352
  # nil
1134
1353
  # ^^^
1354
+ # ```
1135
1355
  def visit_nil_node(node)
1136
1356
  s(node, :nil)
1137
1357
  end
1138
1358
 
1359
+ # ```
1139
1360
  # def foo(**nil); end
1140
1361
  # ^^^^^
1362
+ # ```
1141
1363
  def visit_no_keywords_parameter_node(node)
1142
1364
  in_pattern ? s(node, :kwrest, :"**nil") : :"**nil"
1143
1365
  end
1144
1366
 
1367
+ # ```
1145
1368
  # -> { _1 + _2 }
1146
1369
  # ^^^^^^^^^^^^^^
1370
+ # ```
1147
1371
  def visit_numbered_parameters_node(node)
1148
1372
  raise "Cannot visit numbered parameters directly"
1149
1373
  end
1150
1374
 
1375
+ # ```
1151
1376
  # $1
1152
1377
  # ^^
1378
+ # ```
1153
1379
  def visit_numbered_reference_read_node(node)
1154
1380
  s(node, :nth_ref, node.number)
1155
1381
  end
1156
1382
 
1383
+ # ```
1157
1384
  # def foo(bar: baz); end
1158
1385
  # ^^^^^^^^
1386
+ # ```
1159
1387
  def visit_optional_keyword_parameter_node(node)
1160
1388
  s(node, :kwarg, node.name, visit(node.value))
1161
1389
  end
1162
1390
 
1391
+ # ```
1163
1392
  # def foo(bar = 1); end
1164
1393
  # ^^^^^^^
1394
+ # ```
1165
1395
  def visit_optional_parameter_node(node)
1166
1396
  s(node, :lasgn, node.name, visit(node.value))
1167
1397
  end
1168
1398
 
1399
+ # ```
1169
1400
  # a or b
1170
1401
  # ^^^^^^
1402
+ # ```
1171
1403
  def visit_or_node(node)
1172
1404
  left = visit(node.left)
1173
1405
 
@@ -1184,8 +1416,10 @@ module Prism
1184
1416
  end
1185
1417
  end
1186
1418
 
1419
+ # ```
1187
1420
  # def foo(bar, *baz); end
1188
1421
  # ^^^^^^^^^
1422
+ # ```
1189
1423
  def visit_parameters_node(node)
1190
1424
  children =
1191
1425
  node.compact_child_nodes.map do |element|
@@ -1199,8 +1433,10 @@ module Prism
1199
1433
  s(node, :args).concat(children)
1200
1434
  end
1201
1435
 
1436
+ # ```
1202
1437
  # def foo((bar, baz)); end
1203
1438
  # ^^^^^^^^^^
1439
+ # ```
1204
1440
  private def visit_destructured_parameter(node)
1205
1441
  children =
1206
1442
  [*node.lefts, *node.rest, *node.rights].map do |child|
@@ -1219,11 +1455,13 @@ module Prism
1219
1455
  s(node, :masgn).concat(children)
1220
1456
  end
1221
1457
 
1458
+ # ```
1222
1459
  # ()
1223
1460
  # ^^
1224
1461
  #
1225
1462
  # (1)
1226
1463
  # ^^^
1464
+ # ```
1227
1465
  def visit_parentheses_node(node)
1228
1466
  if node.body.nil?
1229
1467
  s(node, :nil)
@@ -1232,14 +1470,18 @@ module Prism
1232
1470
  end
1233
1471
  end
1234
1472
 
1473
+ # ```
1235
1474
  # foo => ^(bar)
1236
1475
  # ^^^^^^
1476
+ # ```
1237
1477
  def visit_pinned_expression_node(node)
1238
1478
  node.expression.accept(copy_compiler(in_pattern: false))
1239
1479
  end
1240
1480
 
1481
+ # ```
1241
1482
  # foo = 1 and bar => ^foo
1242
1483
  # ^^^^
1484
+ # ```
1243
1485
  def visit_pinned_variable_node(node)
1244
1486
  if node.variable.is_a?(LocalVariableReadNode) && node.variable.name.match?(/^_\d$/)
1245
1487
  s(node, :lvar, node.variable.name)
@@ -1263,8 +1505,10 @@ module Prism
1263
1505
  visit(node.statements)
1264
1506
  end
1265
1507
 
1508
+ # ```
1266
1509
  # 0..5
1267
1510
  # ^^^^
1511
+ # ```
1268
1512
  def visit_range_node(node)
1269
1513
  if !in_pattern && !node.left.nil? && !node.right.nil? && ([node.left.type, node.right.type] - %i[nil_node integer_node]).empty?
1270
1514
  left = node.left.value if node.left.is_a?(IntegerNode)
@@ -1285,44 +1529,58 @@ module Prism
1285
1529
  end
1286
1530
  end
1287
1531
 
1532
+ # ```
1288
1533
  # 1r
1289
1534
  # ^^
1535
+ # ```
1290
1536
  def visit_rational_node(node)
1291
1537
  s(node, :lit, node.value)
1292
1538
  end
1293
1539
 
1540
+ # ```
1294
1541
  # redo
1295
1542
  # ^^^^
1543
+ # ```
1296
1544
  def visit_redo_node(node)
1297
1545
  s(node, :redo)
1298
1546
  end
1299
1547
 
1548
+ # ```
1300
1549
  # /foo/
1301
1550
  # ^^^^^
1551
+ # ```
1302
1552
  def visit_regular_expression_node(node)
1303
1553
  s(node, :lit, Regexp.new(node.unescaped, node.options))
1304
1554
  end
1305
1555
 
1556
+ # ```
1306
1557
  # def foo(bar:); end
1307
1558
  # ^^^^
1559
+ # ```
1308
1560
  def visit_required_keyword_parameter_node(node)
1309
1561
  s(node, :kwarg, node.name)
1310
1562
  end
1311
1563
 
1564
+ # ```
1312
1565
  # def foo(bar); end
1313
1566
  # ^^^
1567
+ # ```
1314
1568
  def visit_required_parameter_node(node)
1315
1569
  node.name
1316
1570
  end
1317
1571
 
1572
+ # ```
1318
1573
  # foo rescue bar
1319
1574
  # ^^^^^^^^^^^^^^
1575
+ # ```
1320
1576
  def visit_rescue_modifier_node(node)
1321
1577
  s(node, :rescue, visit(node.expression), s(node.rescue_expression, :resbody, s(node.rescue_expression, :array), visit(node.rescue_expression)))
1322
1578
  end
1323
1579
 
1580
+ # ```
1324
1581
  # begin; rescue; end
1325
1582
  # ^^^^^^^
1583
+ # ```
1326
1584
  def visit_rescue_node(node)
1327
1585
  exceptions =
1328
1586
  if node.exceptions.length == 1 && node.exceptions.first.is_a?(SplatNode)
@@ -1338,26 +1596,32 @@ module Prism
1338
1596
  s(node, :resbody, exceptions).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
1339
1597
  end
1340
1598
 
1599
+ # ```
1341
1600
  # def foo(*bar); end
1342
1601
  # ^^^^
1343
1602
  #
1344
1603
  # def foo(*); end
1345
1604
  # ^
1605
+ # ```
1346
1606
  def visit_rest_parameter_node(node)
1347
1607
  :"*#{node.name}"
1348
1608
  end
1349
1609
 
1610
+ # ```
1350
1611
  # retry
1351
1612
  # ^^^^^
1613
+ # ```
1352
1614
  def visit_retry_node(node)
1353
1615
  s(node, :retry)
1354
1616
  end
1355
1617
 
1618
+ # ```
1356
1619
  # return
1357
1620
  # ^^^^^^
1358
1621
  #
1359
1622
  # return 1
1360
1623
  # ^^^^^^^^
1624
+ # ```
1361
1625
  def visit_return_node(node)
1362
1626
  if node.arguments.nil?
1363
1627
  s(node, :return)
@@ -1369,8 +1633,10 @@ module Prism
1369
1633
  end
1370
1634
  end
1371
1635
 
1636
+ # ```
1372
1637
  # self
1373
1638
  # ^^^^
1639
+ # ```
1374
1640
  def visit_self_node(node)
1375
1641
  s(node, :self)
1376
1642
  end
@@ -1380,33 +1646,42 @@ module Prism
1380
1646
  visit(node.write)
1381
1647
  end
1382
1648
 
1649
+ # ```
1383
1650
  # class << self; end
1384
1651
  # ^^^^^^^^^^^^^^^^^^
1652
+ # ```
1385
1653
  def visit_singleton_class_node(node)
1386
1654
  s(node, :sclass, visit(node.expression)).tap do |sexp|
1387
1655
  sexp << node.body.accept(copy_compiler(in_def: false)) unless node.body.nil?
1388
1656
  end
1389
1657
  end
1390
1658
 
1659
+ # ```
1391
1660
  # __ENCODING__
1392
1661
  # ^^^^^^^^^^^^
1662
+ # ```
1393
1663
  def visit_source_encoding_node(node)
1394
1664
  # TODO
1395
1665
  s(node, :colon2, s(node, :const, :Encoding), :UTF_8)
1396
1666
  end
1397
1667
 
1668
+ # ```
1398
1669
  # __FILE__
1399
1670
  # ^^^^^^^^
1671
+ # ```
1400
1672
  def visit_source_file_node(node)
1401
1673
  s(node, :str, node.filepath)
1402
1674
  end
1403
1675
 
1676
+ # ```
1404
1677
  # __LINE__
1405
1678
  # ^^^^^^^^
1679
+ # ```
1406
1680
  def visit_source_line_node(node)
1407
1681
  s(node, :lit, node.location.start_line)
1408
1682
  end
1409
1683
 
1684
+ # ```
1410
1685
  # foo(*bar)
1411
1686
  # ^^^^
1412
1687
  #
@@ -1415,6 +1690,7 @@ module Prism
1415
1690
  #
1416
1691
  # def foo(*); bar(*); end
1417
1692
  # ^
1693
+ # ```
1418
1694
  def visit_splat_node(node)
1419
1695
  if node.expression.nil?
1420
1696
  s(node, :splat)
@@ -1434,8 +1710,10 @@ module Prism
1434
1710
  end
1435
1711
  end
1436
1712
 
1713
+ # ```
1437
1714
  # "foo"
1438
1715
  # ^^^^^
1716
+ # ```
1439
1717
  def visit_string_node(node)
1440
1718
  unescaped = node.unescaped
1441
1719
 
@@ -1447,8 +1725,10 @@ module Prism
1447
1725
  s(node, :str, unescaped)
1448
1726
  end
1449
1727
 
1728
+ # ```
1450
1729
  # super(foo)
1451
1730
  # ^^^^^^^^^^
1731
+ # ```
1452
1732
  def visit_super_node(node)
1453
1733
  arguments = node.arguments&.arguments || []
1454
1734
  block = node.block
@@ -1461,60 +1741,76 @@ module Prism
1461
1741
  visit_block(node, s(node, :super).concat(visit_all(arguments)), block)
1462
1742
  end
1463
1743
 
1744
+ # ```
1464
1745
  # :foo
1465
1746
  # ^^^^
1747
+ # ```
1466
1748
  def visit_symbol_node(node)
1467
1749
  node.value == "!@" ? s(node, :lit, :"!@") : s(node, :lit, node.unescaped.to_sym)
1468
1750
  end
1469
1751
 
1752
+ # ```
1470
1753
  # true
1471
1754
  # ^^^^
1755
+ # ```
1472
1756
  def visit_true_node(node)
1473
1757
  s(node, :true)
1474
1758
  end
1475
1759
 
1760
+ # ```
1476
1761
  # undef foo
1477
1762
  # ^^^^^^^^^
1763
+ # ```
1478
1764
  def visit_undef_node(node)
1479
1765
  names = node.names.map { |name| s(node, :undef, visit(name)) }
1480
1766
  names.length == 1 ? names.first : s(node, :block).concat(names)
1481
1767
  end
1482
1768
 
1769
+ # ```
1483
1770
  # unless foo; bar end
1484
1771
  # ^^^^^^^^^^^^^^^^^^^
1485
1772
  #
1486
1773
  # bar unless foo
1487
1774
  # ^^^^^^^^^^^^^^
1775
+ # ```
1488
1776
  def visit_unless_node(node)
1489
1777
  s(node, :if, visit(node.predicate), visit(node.else_clause), visit(node.statements))
1490
1778
  end
1491
1779
 
1780
+ # ```
1492
1781
  # until foo; bar end
1493
1782
  # ^^^^^^^^^^^^^^^^^
1494
1783
  #
1495
1784
  # bar until foo
1496
1785
  # ^^^^^^^^^^^^^
1786
+ # ```
1497
1787
  def visit_until_node(node)
1498
1788
  s(node, :until, visit(node.predicate), visit(node.statements), !node.begin_modifier?)
1499
1789
  end
1500
1790
 
1791
+ # ```
1501
1792
  # case foo; when bar; end
1502
1793
  # ^^^^^^^^^^^^^
1794
+ # ```
1503
1795
  def visit_when_node(node)
1504
1796
  s(node, :when, s(node, :array).concat(visit_all(node.conditions))).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body))
1505
1797
  end
1506
1798
 
1799
+ # ```
1507
1800
  # while foo; bar end
1508
1801
  # ^^^^^^^^^^^^^^^^^^
1509
1802
  #
1510
1803
  # bar while foo
1511
1804
  # ^^^^^^^^^^^^^
1805
+ # ```
1512
1806
  def visit_while_node(node)
1513
1807
  s(node, :while, visit(node.predicate), visit(node.statements), !node.begin_modifier?)
1514
1808
  end
1515
1809
 
1810
+ # ```
1516
1811
  # `foo`
1517
1812
  # ^^^^^
1813
+ # ```
1518
1814
  def visit_x_string_node(node)
1519
1815
  result = s(node, :xstr, node.unescaped)
1520
1816
 
@@ -1526,17 +1822,30 @@ module Prism
1526
1822
  result
1527
1823
  end
1528
1824
 
1825
+ # ```
1529
1826
  # yield
1530
1827
  # ^^^^^
1531
1828
  #
1532
1829
  # yield 1
1533
1830
  # ^^^^^^^
1831
+ # ```
1534
1832
  def visit_yield_node(node)
1535
1833
  s(node, :yield).concat(visit_all(node.arguments&.arguments || []))
1536
1834
  end
1537
1835
 
1538
1836
  private
1539
1837
 
1838
+ # Attach prism comments to the given sexp.
1839
+ def attach_comments(sexp, node)
1840
+ return unless node.comments
1841
+ return if node.comments.empty?
1842
+
1843
+ extra = node.location.start_line - node.comments.last.location.start_line
1844
+ comments = node.comments.map(&:slice)
1845
+ comments.concat([nil] * [0, extra].max)
1846
+ sexp.comments = comments.join("\n")
1847
+ end
1848
+
1540
1849
  # Create a new compiler with the given options.
1541
1850
  def copy_compiler(in_def: self.in_def, in_pattern: self.in_pattern)
1542
1851
  Compiler.new(file, in_def: in_def, in_pattern: in_pattern)
@@ -1615,6 +1924,14 @@ module Prism
1615
1924
  translate(Prism.parse_file(filepath, partial_script: true), filepath)
1616
1925
  end
1617
1926
 
1927
+ # Parse the give file and translate it into the
1928
+ # seattlerb/ruby_parser gem's Sexp format. This method is
1929
+ # provided for API compatibility to RubyParser and takes an
1930
+ # optional +timeout+ argument.
1931
+ def process(ruby, file = "(string)", timeout = nil)
1932
+ Timeout.timeout(timeout) { parse(ruby, file) }
1933
+ end
1934
+
1618
1935
  class << self
1619
1936
  # Parse the given source and translate it into the seattlerb/ruby_parser
1620
1937
  # gem's Sexp format.
@@ -1639,6 +1956,7 @@ module Prism
1639
1956
  raise ::RubyParser::SyntaxError, "#{filepath}:#{error.location.start_line} :: #{error.message}"
1640
1957
  end
1641
1958
 
1959
+ result.attach_comments!
1642
1960
  result.value.accept(Compiler.new(filepath))
1643
1961
  end
1644
1962
  end