prism 1.9.0 → 2.0.0.rc2

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