sirop 0.2 → 0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/sirop/injection.rb +11 -0
- data/lib/sirop/prism_ext.rb +24 -0
- data/lib/sirop/sourcifier.rb +453 -63
- data/lib/sirop/version.rb +1 -1
- data/lib/sirop.rb +6 -0
- metadata +6 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6ffcc66301949fc52bae4b2eef554243263b06a9bdf699d6be61d9d38f1ade1
|
4
|
+
data.tar.gz: 6aeba8547c161f56a20e64d7cf219489bfd0f2195063ca8b651c821134944232
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
data/lib/sirop/prism_ext.rb
CHANGED
@@ -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
|
data/lib/sirop/sourcifier.rb
CHANGED
@@ -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
|
-
|
35
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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 =
|
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.
|
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
|
-
|
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
|
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
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.
|
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-
|
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.
|
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.
|
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.
|
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: []
|