sirop 0.2 → 0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1641ee60187094fe9dcdeebefbfc5283c0d2ea535aa161b17f7bf6f720d63854
4
- data.tar.gz: c9abaef1a8b7116760f92e143bcb2e58fbc4424fe3d4afe110bc10bf552852cf
3
+ metadata.gz: b6ffcc66301949fc52bae4b2eef554243263b06a9bdf699d6be61d9d38f1ade1
4
+ data.tar.gz: 6aeba8547c161f56a20e64d7cf219489bfd0f2195063ca8b651c821134944232
5
5
  SHA512:
6
- metadata.gz: 3900ece58c932df6181676abb597fa6deedfbd8801e28f4993cc36cce7584a188e88b73e6ef2b0fea33b5dbc8a8d284949159973cb108e149dd0d9b3ea5dd762
7
- data.tar.gz: 7f848b0e842792a33e3fc7c9b7d6cf72e924040307e2db5ccb0cff16af1e947e7053ee81e54ab688c131532b66432dc1283651ceeef5820ded58c3b8447d193a
6
+ metadata.gz: 8dde7126119287b24f05352b5c62922a5023c80ff9ffb3f258ddf8824b6ce947b7f2551bc1818202036ac152815458e3126a838b3e91d147ed413cb6fb181818
7
+ data.tar.gz: 83856a27062116324228881ff61172c62234ca3ce6992ba5ef8355db3f5a823e018695eb6e9e61b61b852cfa1b497039c1ad3fcbf6e7451bb0a9b14b64801da0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,15 @@
1
+ # 2024-04-29 0.4
2
+
3
+ - Improve sourcifier to support all Ruby syntax, based on Prism test fixtures
4
+ - Update Prism
5
+
6
+ # 2024-04-19 0.3
7
+
8
+ - Add support for injecting (prefixed) parameters to a lambda node
9
+ - Fix whitespace adjustment in DSL compiler
10
+ - Improve DSL compiler to support embedded string expressions
11
+ - Correctly handle eval'd proc
12
+
1
13
  # 2024-02-27 0.2
2
14
 
3
15
  - Update README
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sirop
4
+ class Injection
5
+ attr_reader :slice
6
+
7
+ def initialize(slice)
8
+ @slice = slice
9
+ end
10
+ end
11
+ end
@@ -8,3 +8,27 @@ class Prism::BasicVisitor
8
8
  self
9
9
  end
10
10
  end
11
+
12
+ class Prism::ParametersNode
13
+ attr_accessor :injected_prefix
14
+ end
15
+
16
+ class Prism::BlockParametersNode
17
+ attr_accessor :injected_parameters
18
+ end
19
+
20
+ class Prism::LambdaNode
21
+ # @param params [String] injected parameters
22
+ # @return [void]
23
+ def inject_parameters(params)
24
+ if parameters
25
+ if parameters.parameters
26
+ parameters.parameters.injected_prefix = Sirop::Injection.new(params)
27
+ else
28
+ parameters.injected_parameters = Sirop::Injection.new(params)
29
+ end
30
+ else
31
+ instance_variable_set(:@parameters, Sirop::Injection.new("(#{params})"))
32
+ end
33
+ end
34
+ end
@@ -5,6 +5,90 @@ require 'prism'
5
5
  module Sirop
6
6
  #
7
7
  class Sourcifier < Prism::BasicVisitor
8
+ VISIT_PLANS = {
9
+ alias_global_variable: [:keyword_loc, :new_name, :old_name],
10
+ alias_method: [:keyword_loc, :new_name, :old_name],
11
+ and: [:left, :operator_loc, :right],
12
+ assoc: [:key, :operator_loc, :value],
13
+ assoc_splat: [:operator_loc, :value],
14
+ back_reference_read: :emit_verbatim,
15
+ block: [:opening_loc, :parameters, :body, :closing_loc],
16
+ block_argument: [:operator_loc, :expression],
17
+ block_local_variable: :emit_verbatim,
18
+ block_parameter: [:operator_loc, :name_loc],
19
+ break: [:keyword_loc, :arguments],
20
+ capture_pattern: [:value, :operator_loc, :target],
21
+ class_variable_read: :emit_verbatim,
22
+ class_variable_target: :emit_verbatim,
23
+ class_variable_write: [:name_loc, :operator_loc, :value],
24
+ constant_path: [:parent, :delimiter_loc, :child],
25
+ constant_path_write: [:target, :operator_loc, :value],
26
+ constant_read: :emit_verbatim,
27
+ constant_write: [:name_loc, :operator_loc, :value],
28
+ defined: [:keyword_loc, :lparen_loc, :value, :rparen_loc],
29
+ embedded_statements: [:opening_loc, :statements, :closing_loc],
30
+ embedded_variable: [:operator_loc, :variable],
31
+ false: :emit_verbatim,
32
+ flip_flop: [:left, :operator_loc, :right],
33
+ float: :emit_verbatim,
34
+ forwarding_arguments: :emit_verbatim,
35
+ forwarding_parameter: :emit_verbatim,
36
+ forwarding_super: :emit_verbatim,
37
+ global_variable_read: :emit_verbatim,
38
+ global_variable_target: :emit_verbatim,
39
+ global_variable_write: [:name_loc, :operator_loc, :value],
40
+ imaginary: :emit_verbatim,
41
+ implicit: :emit_nothing,
42
+ implicit_rest: :emit_nothing,
43
+ in: [:in_loc, :pattern, :then_loc],
44
+ index_target: [:receiver, :opening_loc, :arguments, :closing_loc],
45
+ instance_variable_read: :emit_verbatim,
46
+ instance_variable_target: :emit_verbatim,
47
+ instance_variable_write: [:name_loc, :operator_loc, :value],
48
+ integer: :emit_verbatim,
49
+ keyword_rest_parameter: [:operator_loc, :name_loc],
50
+ keyword_parameter: :emit_verbatim,
51
+ local_variable_and_write: [:name_loc, :operator_loc, :value],
52
+ local_variable_operator_write: [:name_loc, :operator_loc, :value],
53
+ local_variable_or_write: [:name_loc, :operator_loc, :value],
54
+ local_variable_read: :emit_verbatim,
55
+ local_variable_target: :emit_verbatim,
56
+ local_variable_write: [:name_loc, :operator_loc, :value],
57
+ match_predicate: [:value, :operator_loc, :pattern],
58
+ match_required: [:value, :operator_loc, :pattern],
59
+ match_write: [:call],
60
+ next: [:keyword_loc, :arguments],
61
+ nil: :emit_verbatim,
62
+ no_keywords_parameter: :emit_verbatim,
63
+ numbered_parameters: :emit_nothing,
64
+ optional_parameter: [:name_loc, :operator_loc, :value],
65
+ optional_keyword_parameter: [:name_loc, :value],
66
+ or: [:left, :operator_loc, :right],
67
+ parentheses: [:opening_loc, :body, :closing_loc],
68
+ pinned_expression: [:operator_loc, :lparen_loc, :expression, :rparen_loc],
69
+ pinned_variable: [:operator_loc, :variable],
70
+ range: [:left, :operator_loc, :right],
71
+ rational: :emit_verbatim,
72
+ redo: :emit_verbatim,
73
+ regular_expression: :emit_verbatim,
74
+ required_parameter: :emit_verbatim,
75
+ required_keyword_parameter: :emit_verbatim,
76
+ rescue_modifier: [:expression, :keyword_loc, :rescue_expression],
77
+ rest_parameter: [:operator_loc, :name_loc],
78
+ retry: :emit_verbatim,
79
+ return: [:keyword_loc, :arguments],
80
+ self: :emit_verbatim,
81
+ source_encoding: :emit_verbatim,
82
+ source_file: :emit_verbatim,
83
+ source_line: :emit_verbatim,
84
+ splat: [:operator_loc, :expression],
85
+ string: [:opening_loc, :content_loc, :closing_loc],
86
+ symbol: :emit_verbatim,
87
+ true: :emit_verbatim,
88
+ x_string: :emit_verbatim,
89
+ yield: [:keyword_loc, :lparen_loc, :arguments, :rparen_loc]
90
+ }
91
+
8
92
  attr_reader :buffer
9
93
 
10
94
  def initialize
@@ -30,11 +114,14 @@ module Sirop
30
114
  end
31
115
 
32
116
  def adjust_whitespace(loc)
117
+ return if loc.is_a?(Sirop::Injection)
118
+
33
119
  if @last_loc_start
34
- if @last_loc_end.first != loc.start_line
35
- @buffer << "\n" * (loc.start_line - @last_loc_end.first)
120
+ line_diff = loc.start_line - @last_loc_end.first
121
+ if line_diff > 0
122
+ @buffer << "\n" * line_diff
36
123
  @buffer << ' ' * loc.start_column
37
- else
124
+ elsif line_diff == 0
38
125
  ofs = loc.start_column - @last_loc_end.last
39
126
  if ofs > 0
40
127
  @buffer << ' ' * ofs
@@ -49,20 +136,34 @@ module Sirop
49
136
  @last_loc_end = loc_end(loc)
50
137
  end
51
138
 
52
- def emit_code(loc, semicolon: false)
139
+ def emit_code(loc, semicolon: false, chomp: false)
53
140
  return if !loc
54
141
 
142
+ if @last_loc
143
+ loc_loc = loc.is_a?(Prism::Node) ? loc.location : loc
144
+ return if loc_loc.slice == @last_loc.slice && loc_loc.start_line == @last_loc.start_line &&
145
+ loc_loc.start_column == @last_loc.start_column
146
+ end
147
+
148
+ semicolon ||= @semicolon
149
+ @semicolon = false
55
150
  emit_semicolon(loc) if semicolon
56
151
  return visit(loc) if loc.is_a?(Prism::Node)
57
152
 
58
153
  adjust_whitespace(loc)
59
- emit(loc.slice)
154
+ str = loc.slice
155
+ str = str.chomp if chomp
156
+ emit(str)
60
157
  end
61
158
 
62
159
  def emit_verbatim(node)
63
160
  emit_code(node.location)
64
161
  end
65
162
 
163
+ def emit_nothing(node)
164
+ # emit nothing
165
+ end
166
+
66
167
  def emit_str(str)
67
168
  emit(str)
68
169
  @last_loc_end[1] += str.size
@@ -74,7 +175,11 @@ module Sirop
74
175
 
75
176
  def emit_semicolon(loc)
76
177
  loc = loc.location if loc.is_a?(Prism::Node)
77
- emit_str(';') if loc.start_line == @last_loc.end_line
178
+ if @last_loc && loc.start_line == @last_loc.end_line
179
+ if @buffer[-1] != ';' && loc.start_column > @last_loc_end[1]
180
+ emit_str(';')
181
+ end
182
+ end
78
183
  end
79
184
 
80
185
  def method_missing(sym, node, *args)
@@ -84,41 +189,6 @@ module Sirop
84
189
  visit_child_nodes(node)
85
190
  end
86
191
 
87
- VISIT_PLANS = {
88
- and: [:left, :operator_loc, :right],
89
- assoc: :visit_child_nodes,
90
- assoc_splat: [:operator_loc, :value],
91
- block: [:opening_loc, :parameters, :body, :closing_loc],
92
- block_argument: [:operator_loc, :expression],
93
- block_parameter: [:operator_loc, :name_loc],
94
- block_parameters: [:opening_loc, :parameters, :closing_loc],
95
- break: [:keyword_loc, :arguments],
96
- constant_path: [:parent, :delimiter_loc, :child],
97
- constant_read: :emit_verbatim,
98
- else: [:else_keyword_loc, :statements],
99
- embedded_statements: [:opening_loc, :statements, :closing_loc],
100
- false: :emit_verbatim,
101
- integer: :emit_verbatim,
102
- keyword_rest_parameter: [:operator_loc, :name_loc],
103
- lambda: [:operator_loc, :parameters, :opening_loc, :body,
104
- :closing_loc],
105
- local_variable_read: :emit_verbatim,
106
- local_variable_write: [:name_loc, :operator_loc, :value],
107
- next: [:keyword_loc, :arguments],
108
- nil: :emit_verbatim,
109
- optional_parameter: [:name_loc, :operator_loc, :value],
110
- or: [:left, :operator_loc, :right],
111
- parentheses: [:opening_loc, :body, :closing_loc],
112
- required_parameter: :emit_verbatim,
113
- rest_parameter: [:operator_loc, :name_loc],
114
- splat: [:operator_loc, :expression],
115
- statements: :visit_child_nodes,
116
- string: :emit_verbatim,
117
- symbol: :emit_verbatim,
118
- true: :emit_verbatim,
119
- yield: [:keyword_loc, :lparen_loc, :arguments, :rparen_loc],
120
- }
121
-
122
192
  VISIT_PLANS.each do |key, plan|
123
193
  sym = :"visit_#{key}_node"
124
194
  define_method(sym) { |n| visit_plan(plan, n) }
@@ -142,7 +212,7 @@ module Sirop
142
212
 
143
213
  def visit_comma_separated_nodes(list, comma = false)
144
214
  if list
145
- list.each_with_index do |child, idx|
215
+ list.each do |child|
146
216
  emit_comma if comma
147
217
  emit_code(child)
148
218
  comma = true
@@ -151,15 +221,40 @@ module Sirop
151
221
  comma
152
222
  end
153
223
 
224
+ def visit_space_separated_nodes(list)
225
+ if list
226
+ list.each do |child|
227
+ emit_code(child)
228
+ end
229
+ end
230
+ end
231
+
154
232
  def visit_parameters_node(node)
155
- comma = visit_comma_separated_nodes(node.requireds)
233
+ comma = false
234
+ # injected_prefix is a custom attribute added by Sirop to the
235
+ # ParametersNode class (in lib/sirop/prism_ext.rb). It is used
236
+ # as a way to add a first parameter to a block or method.
237
+ if node.injected_prefix
238
+ emit_code(node.injected_prefix)
239
+ # adjust last_loc_end for proper whitespace after comma
240
+ @last_loc_end[1] -= 2 if @last_loc_end
241
+ # binding.irb
242
+ comma = true
243
+ end
244
+ comma = visit_comma_separated_nodes(node.requireds, comma)
156
245
  comma = visit_comma_separated_nodes(node.optionals, comma)
157
- comma = visit_comma_separated_nodes(node.posts, comma)
158
246
  if node.rest
159
247
  emit_comma if comma
160
- comma = true
161
248
  emit_code(node.rest)
249
+ comma = true
162
250
  end
251
+ comma = visit_comma_separated_nodes(node.posts, comma)
252
+ comma = visit_comma_separated_nodes(node.keywords, comma)
253
+ # if node.rest
254
+ # emit_comma if comma
255
+ # comma = true
256
+ # emit_code(node.rest)
257
+ # end
163
258
  if node.keyword_rest
164
259
  emit_comma if comma
165
260
  comma = true
@@ -172,8 +267,8 @@ module Sirop
172
267
  end
173
268
  end
174
269
 
175
- def visit_arguments_node(node)
176
- visit_comma_separated_nodes(node.arguments)
270
+ def visit_arguments_node(node, subscript = 0..-1)
271
+ visit_comma_separated_nodes(node.arguments[subscript])
177
272
  end
178
273
 
179
274
  def visit_keyword_hash_node(node)
@@ -190,9 +285,9 @@ module Sirop
190
285
  emit_code(node.if_keyword_loc)
191
286
  emit_code(node.predicate)
192
287
  emit_code(node.then_keyword_loc)
193
- emit_code(node.statements)
288
+ emit_code(node.statements, semicolon: true)
194
289
  emit_code(node.consequent) if node.consequent
195
- emit_code(node.end_keyword_loc) if node.if_keyword_loc.slice == 'if'
290
+ emit_code(node.end_keyword_loc, semicolon: true) if node.if_keyword_loc.slice == 'if'
196
291
  end
197
292
 
198
293
  def visit_if_node_ternary(node)
@@ -208,18 +303,38 @@ module Sirop
208
303
  emit_code(node.predicate)
209
304
  end
210
305
 
306
+ def visit_unless_node(node)
307
+ if !node.end_keyword_loc
308
+ return visit_unless_node_guard(node)
309
+ end
310
+
311
+ emit_code(node.keyword_loc)
312
+ emit_code(node.predicate)
313
+ emit_code(node.then_keyword_loc)
314
+ @semicolon = true
315
+ emit_code(node.statements)
316
+ emit_code(node.consequent) if node.consequent
317
+ emit_code(node.end_keyword_loc, semicolon: true) if node.keyword_loc.slice == 'unless'
318
+ end
319
+
320
+ def visit_unless_node_guard(node)
321
+ emit_code(node.statements)
322
+ emit_code(node.keyword_loc)
323
+ emit_code(node.predicate)
324
+ end
325
+
211
326
  def visit_case_node(node)
212
327
  emit_code(node.case_keyword_loc)
213
328
  emit_code(node.predicate)
214
- node.conditions.each { |c| emit_code(c) }
215
- emit_code(node.consequent)
216
- emit_code(node.end_keyword_loc)
329
+ node.conditions.each { |c| emit_code(c, semicolon: true) }
330
+ emit_code(node.consequent, semicolon: true)
331
+ emit_code(node.end_keyword_loc, semicolon: true)
217
332
  end
218
333
 
219
334
  def visit_when_node(node)
220
335
  emit_code(node.keyword_loc)
221
336
  visit_comma_separated_nodes(node.conditions)
222
- emit_code(node.statements)
337
+ emit_code(node.statements, semicolon: true)
223
338
  end
224
339
 
225
340
  def visit_interpolated_symbol_node(node)
@@ -230,36 +345,49 @@ module Sirop
230
345
  alias_method :visit_interpolated_string_node, :visit_interpolated_symbol_node
231
346
 
232
347
  def visit_def_node(node)
233
- emit_code(node.def_keyword_loc)
348
+ emit_code(node.def_keyword_loc, semicolon: true)
349
+ emit_code(node.receiver)
350
+ emit_code(node.operator_loc)
234
351
  emit_code(node.name_loc)
235
- last_loc = node.name_loc
236
352
 
353
+ emit_code(node.lparen_loc)
237
354
  if node.parameters
238
- emit_str('(')
239
355
  emit_code(node.parameters)
240
- emit_str(')')
241
- last_loc = node.parameters.location
242
356
  end
243
-
244
- emit_code(node.body, semicolon: true)
357
+ emit_code(node.rparen_loc)
358
+ emit_code(node.equal_loc)
359
+ emit_code(node.body, semicolon: !node.equal_loc)
245
360
  emit_code(node.end_keyword_loc, semicolon: true)
361
+ @semicolon = true
246
362
  end
247
363
 
248
364
  def visit_call_node(node)
249
- if node.receiver && !node.call_operator_loc && !node.arguments
365
+ if node.receiver && !node.call_operator_loc && !node.arguments && node.name != :[]
366
+ return visit_call_node_unary_op(node)
367
+ end
368
+
369
+ if node.receiver && !node.call_operator_loc && node.name == :!
250
370
  return visit_call_node_unary_op(node)
251
371
  end
252
372
 
373
+ if node.attribute_write?
374
+ return visit_call_node_attribute_write(node)
375
+ end
376
+
253
377
  block = node.block
254
378
 
255
379
  emit_code(node.receiver)
256
380
  emit_code(node.call_operator_loc)
257
- emit_code(node.message_loc)
381
+ if (ml = node.message_loc)
382
+ ol = node.opening_loc
383
+ emit_message_loc = !ol || (ol.start_line != ml.start_line) || (ol.start_column != ml.start_column)
384
+ emit_code(node.message_loc) if emit_message_loc
385
+ end
258
386
  emit_code(node.opening_loc)
259
387
  emit_code(node.arguments)
260
388
 
261
389
  if block.is_a?(Prism::BlockArgumentNode)
262
- emit_comma if node.arguments&.arguments.size > 0
390
+ emit_comma if node.arguments && node.arguments.arguments.size > 0
263
391
  emit_code(block)
264
392
  block = nil
265
393
  end
@@ -269,7 +397,33 @@ module Sirop
269
397
 
270
398
  def visit_call_node_unary_op(node)
271
399
  emit_code(node.message_loc)
400
+ emit_code(node.opening_loc)
401
+ emit_code(node.receiver)
402
+ emit_code(node.closing_loc)
403
+ end
404
+
405
+ def visit_call_node_attribute_write(node)
406
+ emit_code(node.receiver)
407
+ if node.call_operator_loc
408
+ emit_code(node.call_operator_loc)
409
+ emit_code(node.message_loc)
410
+ end
411
+ emit_code(node.opening_loc)
412
+ comma = visit_arguments_node(node.arguments, 0..-2)
413
+ if node.block
414
+ emit_comma if comma
415
+ emit_code(node.block)
416
+ end
417
+ emit_code(node.closing_loc)
418
+ emit_str(" = ")
419
+ emit_code(node.arguments.arguments[-1])
420
+ return
421
+ end
422
+
423
+ def visit_call_target_node(node)
272
424
  emit_code(node.receiver)
425
+ emit_code(node.call_operator_loc)
426
+ emit_code(node.message_loc)
273
427
  end
274
428
 
275
429
  def visit_while_node(node)
@@ -286,5 +440,241 @@ module Sirop
286
440
  emit_code(node.keyword_loc)
287
441
  emit_code(node.predicate)
288
442
  end
443
+
444
+ def visit_until_node(node)
445
+ return visit_until_node_guard(node) if !node.closing_loc
446
+
447
+ emit_code(node.keyword_loc)
448
+ emit_code(node.predicate)
449
+ emit_code(node.statements, semicolon: true)
450
+ emit_code(node.closing_loc, semicolon: true)
451
+ end
452
+
453
+ def visit_until_node_guard(node)
454
+ emit_code(node.statements)
455
+ emit_code(node.keyword_loc)
456
+ emit_code(node.predicate)
457
+ end
458
+
459
+ def visit_hash_node(node)
460
+ emit_code(node.opening_loc)
461
+ visit_comma_separated_nodes(node.elements)
462
+ emit_code(node.closing_loc)
463
+ end
464
+
465
+ def visit_array_node(node)
466
+ emit_code(node.opening_loc)
467
+ if node.opening_loc && node.opening_loc.slice =~ /^%/
468
+ visit_space_separated_nodes(node.elements)
469
+ else
470
+ visit_comma_separated_nodes(node.elements)
471
+ end
472
+ emit_code(node.closing_loc)
473
+ end
474
+
475
+ def visit_multi_write_node(node)
476
+ emit_code(node.lparen_loc)
477
+ comma = visit_comma_separated_nodes(node.lefts)
478
+ if node.rest
479
+ emit_comma if comma
480
+ emit_code(node.rest)
481
+ comma = true
482
+ end
483
+ visit_comma_separated_nodes(node.rights, comma)
484
+ emit_code(node.rparen_loc)
485
+ emit_code(node.operator_loc)
486
+ emit_code(node.value)
487
+ end
488
+
489
+ def visit_rescue_node(node)
490
+ emit_code(node.keyword_loc, semicolon: true)
491
+ visit_comma_separated_nodes(node.exceptions)
492
+ emit_code(node.operator_loc)
493
+ emit_code(node.reference)
494
+ emit_code(node.statements, semicolon: true)
495
+ emit_code(node.consequent)
496
+ end
497
+
498
+ def visit_begin_node(node)
499
+ emit_code(node.begin_keyword_loc) #, semicolon: true)
500
+ emit_code(node.statements, semicolon: true)
501
+ emit_code(node.rescue_clause)
502
+ emit_code(node.else_clause)
503
+ emit_code(node.ensure_clause)
504
+ emit_code(node.end_keyword_loc, semicolon: true) if node.begin_keyword_loc
505
+ end
506
+
507
+ def visit_index_operator_write_node(node)
508
+ emit_code(node.receiver)
509
+ emit_code(node.opening_loc)
510
+ emit_code(node.arguments)
511
+ if node.block
512
+ if !node.arguments.arguments.empty?
513
+ emit_comma
514
+ end
515
+ emit_code(node.block)
516
+ end
517
+ emit_code(node.closing_loc)
518
+ emit_code(node.operator_loc)
519
+ emit_code(node.value)
520
+ end
521
+ alias_method :visit_index_and_write_node, :visit_index_operator_write_node
522
+ alias_method :visit_index_or_write_node, :visit_index_operator_write_node
523
+
524
+ def visit_ensure_node(node)
525
+ emit_code(node.ensure_keyword_loc, semicolon: true)
526
+ emit_code(node.statements, semicolon: true)
527
+ emit_code(node.end_keyword_loc, semicolon: true)
528
+ end
529
+
530
+ def visit_else_node(node)
531
+ emit_code(node.else_keyword_loc, semicolon: node.else_keyword_loc.slice == 'else')
532
+ emit_code(node.statements, semicolon: node.else_keyword_loc.slice == 'else')
533
+ end
534
+
535
+ def visit_case_match_node(node)
536
+ emit_code(node.case_keyword_loc)
537
+ emit_code(node.predicate)
538
+ @semicolon = true
539
+ visit_comma_separated_nodes(node.conditions)
540
+ emit_code(node.end_keyword_loc)
541
+ end
542
+
543
+ def visit_class_node(node)
544
+ emit_code(node.class_keyword_loc)
545
+ emit_code(node.constant_path)
546
+ emit_code(node.inheritance_operator_loc)
547
+ emit_code(node.superclass)
548
+ emit_code(node.body, semicolon: true)
549
+ emit_code(node.end_keyword_loc, semicolon: true)
550
+ end
551
+
552
+ def visit_module_node(node)
553
+ emit_code(node.module_keyword_loc)
554
+ emit_code(node.constant_path)
555
+ emit_code(node.body, semicolon: true)
556
+ emit_code(node.end_keyword_loc, semicolon: true)
557
+ end
558
+
559
+ def visit_singleton_class_node(node)
560
+ emit_code(node.class_keyword_loc)
561
+ emit_code(node.operator_loc)
562
+ emit_code(node.expression)
563
+ emit_code(node.body, semicolon: true)
564
+ emit_code(node.end_keyword_loc, semicolon: true)
565
+ end
566
+
567
+ def visit_interpolated_x_string_node(node)
568
+ emit_code(node.opening_loc)
569
+ node.parts.each { |p| emit_code(p) }
570
+ emit_code(node.closing_loc, chomp: true)
571
+ end
572
+
573
+ def visit_for_node(node)
574
+ emit_code(node.for_keyword_loc)
575
+ emit_code(node.index)
576
+ emit_code(node.in_keyword_loc)
577
+ emit_code(node.collection)
578
+ emit_code(node.do_keyword_loc)
579
+ emit_code(node.statements, semicolon: true)
580
+ emit_code(node.end_keyword_loc, semicolon: true)
581
+ end
582
+
583
+ def visit_multi_target_node(node)
584
+ emit_code(node.lparen_loc)
585
+ comma = visit_comma_separated_nodes(node.lefts)
586
+ if node.rest
587
+ emit_comma if comma
588
+ emit_code(node.rest)
589
+ comma = true
590
+ end
591
+ visit_comma_separated_nodes(node.rights, comma)
592
+ emit_code(node.rparen_loc)
593
+ end
594
+
595
+ def visit_find_pattern_node(node)
596
+ emit_code(node.constant)
597
+ emit_code(node.opening_loc)
598
+ emit_code(node.left)
599
+ comma = node.left
600
+ comma = visit_comma_separated_nodes(node.requireds, comma)
601
+ if node.right
602
+ emit_comma if comma
603
+ emit_code(node.right)
604
+ end
605
+ emit_code(node.closing_loc)
606
+ end
607
+
608
+ def visit_array_pattern_node(node)
609
+ emit_code(node.constant)
610
+ emit_code(node.opening_loc)
611
+ comma = visit_comma_separated_nodes(node.requireds, comma)
612
+ if node.rest
613
+ emit_comma if comma
614
+ emit_code(node.rest)
615
+ comma = true
616
+ end
617
+ visit_comma_separated_nodes(node.posts, comma)
618
+ emit_code(node.closing_loc)
619
+ end
620
+
621
+ def visit_hash_pattern_node(node)
622
+ emit_code(node.constant)
623
+ emit_code(node.opening_loc)
624
+ visit_comma_separated_nodes(node.elements)
625
+ emit_code(node.closing_loc)
626
+ end
627
+
628
+ def visit_statements_node(node)
629
+ first = true
630
+ node.body&.each do |n|
631
+ @semicolon = !first
632
+ visit(n)
633
+ first = false
634
+ end
635
+ end
636
+
637
+ def visit_block_parameters_node(node)
638
+ emit_code(node.opening_loc)
639
+ emit_code(node.injected_parameters)
640
+ emit_code(node.parameters)
641
+ @semicolon = true if node.parameters
642
+ visit_comma_separated_nodes(node.locals)
643
+ emit_code(node.closing_loc)
644
+ @semicolon = false
645
+ end
646
+
647
+ def visit_lambda_node(node)
648
+ emit_code(node.operator_loc)
649
+ emit_code(node.parameters)
650
+ emit_code(node.opening_loc)
651
+ emit_code(node.body, semicolon: node.opening_loc.slice == 'do')
652
+ emit_code(node.closing_loc, semicolon: node.closing_loc.slice == 'end')
653
+ end
654
+
655
+ def visit_interpolated_regular_expression_node(node)
656
+ emit_code(node.opening_loc)
657
+ node.parts.each { |p| emit_code(p) }
658
+ emit_code(node.closing_loc)
659
+ end
660
+
661
+ def visit_super_node(node)
662
+ emit_code(node.keyword_loc)
663
+ emit_code(node.lparen_loc)
664
+ emit_code(node.arguments)
665
+ emit_block_pre_rparen = node.block.is_a?(Prism::BlockArgumentNode)
666
+ if emit_block_pre_rparen
667
+ emit_comma if node.arguments
668
+ emit_code(node.block)
669
+ end
670
+ emit_code(node.rparen_loc)
671
+ emit_code(node.block) if !emit_block_pre_rparen
672
+ end
673
+
674
+ def visit_undef_node(node)
675
+ emit_code(node.keyword_loc)
676
+ visit_comma_separated_nodes(node.names)
677
+ end
678
+
289
679
  end
290
680
  end
data/lib/sirop/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Sirop
2
2
  # Sirop version
3
- VERSION = '0.2'
3
+ VERSION = '0.4'
4
4
  end
data/lib/sirop.rb CHANGED
@@ -1,11 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'prism'
4
+ require 'sirop/injection'
4
5
  require 'sirop/prism_ext'
5
6
  require 'sirop/finder'
6
7
  require 'sirop/sourcifier'
7
8
 
8
9
  module Sirop
10
+ class Error < StandardError
11
+ end
12
+
9
13
  class << self
10
14
  def to_ast(obj)
11
15
  case obj
@@ -43,6 +47,8 @@ module Sirop
43
47
  super(node)
44
48
  end
45
49
  end
50
+ rescue Errno::ENOENT
51
+ raise Sirop::Error, "Could not get source for proc"
46
52
  end
47
53
 
48
54
  def method_ast(method)
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sirop
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.2'
4
+ version: '0.4'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-02-27 00:00:00.000000000 Z
10
+ date: 2024-04-29 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: prism
@@ -16,14 +15,14 @@ dependencies:
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: 0.19.0
18
+ version: 0.27.0
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: 0.19.0
25
+ version: 0.27.0
27
26
  - !ruby/object:Gem::Dependency
28
27
  name: minitest
29
28
  requirement: !ruby/object:Gem::Requirement
@@ -38,7 +37,6 @@ dependencies:
38
37
  - - "~>"
39
38
  - !ruby/object:Gem::Version
40
39
  version: 5.22.0
41
- description:
42
40
  email: sharon@noteflakes.com
43
41
  executables: []
44
42
  extensions: []
@@ -49,6 +47,7 @@ files:
49
47
  - README.md
50
48
  - lib/sirop.rb
51
49
  - lib/sirop/finder.rb
50
+ - lib/sirop/injection.rb
52
51
  - lib/sirop/prism_ext.rb
53
52
  - lib/sirop/sourcifier.rb
54
53
  - lib/sirop/version.rb
@@ -59,7 +58,6 @@ metadata:
59
58
  homepage_uri: https://github.com/digital-fabric/sirop
60
59
  documentation_uri: https://www.rubydoc.info/gems/sirop
61
60
  changelog_uri: https://github.com/digital-fabric/sirop/blob/main/CHANGELOG.md
62
- post_install_message:
63
61
  rdoc_options:
64
62
  - "--title"
65
63
  - Sirop
@@ -78,8 +76,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
76
  - !ruby/object:Gem::Version
79
77
  version: '0'
80
78
  requirements: []
81
- rubygems_version: 3.5.3
82
- signing_key:
79
+ rubygems_version: 3.6.0.dev
83
80
  specification_version: 4
84
81
  summary: 'Sirop: Ruby code rewriter'
85
82
  test_files: []