ripper_ruby_parser 1.4.2 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -1
  3. data/README.md +41 -9
  4. data/Rakefile +2 -0
  5. data/lib/ripper_ruby_parser.rb +2 -0
  6. data/lib/ripper_ruby_parser/commenting_ripper_parser.rb +23 -45
  7. data/lib/ripper_ruby_parser/parser.rb +11 -1
  8. data/lib/ripper_ruby_parser/sexp_handlers.rb +2 -6
  9. data/lib/ripper_ruby_parser/sexp_handlers/assignment.rb +49 -35
  10. data/lib/ripper_ruby_parser/sexp_handlers/blocks.rb +78 -39
  11. data/lib/ripper_ruby_parser/sexp_handlers/conditionals.rb +16 -15
  12. data/lib/ripper_ruby_parser/sexp_handlers/helper_methods.rb +19 -15
  13. data/lib/ripper_ruby_parser/sexp_handlers/literals.rb +138 -30
  14. data/lib/ripper_ruby_parser/sexp_handlers/loops.rb +10 -6
  15. data/lib/ripper_ruby_parser/sexp_handlers/method_calls.rb +59 -14
  16. data/lib/ripper_ruby_parser/sexp_handlers/methods.rb +56 -32
  17. data/lib/ripper_ruby_parser/sexp_handlers/operators.rb +20 -27
  18. data/lib/ripper_ruby_parser/sexp_processor.rb +40 -10
  19. data/lib/ripper_ruby_parser/syntax_error.rb +2 -0
  20. data/lib/ripper_ruby_parser/unescape.rb +32 -11
  21. data/lib/ripper_ruby_parser/version.rb +3 -1
  22. data/test/end_to_end/comments_test.rb +2 -0
  23. data/test/end_to_end/comparison_test.rb +2 -0
  24. data/test/end_to_end/lib_comparison_test.rb +2 -0
  25. data/test/end_to_end/line_numbering_test.rb +2 -0
  26. data/test/end_to_end/samples_comparison_test.rb +5 -29
  27. data/test/end_to_end/test_comparison_test.rb +2 -0
  28. data/test/pt_testcase/pt_test.rb +2 -0
  29. data/test/ripper_ruby_parser/commenting_ripper_parser_test.rb +16 -2
  30. data/test/ripper_ruby_parser/parser_test.rb +17 -688
  31. data/test/ripper_ruby_parser/sexp_handlers/assignment_test.rb +459 -26
  32. data/test/ripper_ruby_parser/sexp_handlers/blocks_test.rb +152 -82
  33. data/test/ripper_ruby_parser/sexp_handlers/conditionals_test.rb +91 -0
  34. data/test/ripper_ruby_parser/sexp_handlers/literals_test.rb +331 -24
  35. data/test/ripper_ruby_parser/sexp_handlers/loops_test.rb +88 -0
  36. data/test/ripper_ruby_parser/sexp_handlers/method_calls_test.rb +58 -5
  37. data/test/ripper_ruby_parser/sexp_handlers/methods_test.rb +392 -0
  38. data/test/ripper_ruby_parser/sexp_handlers/operators_test.rb +174 -12
  39. data/test/ripper_ruby_parser/sexp_processor_test.rb +8 -18
  40. data/test/ripper_ruby_parser/version_test.rb +2 -0
  41. data/test/samples/comments.rb +13 -0
  42. data/test/samples/conditionals.rb +23 -0
  43. data/test/samples/loops.rb +36 -0
  44. data/test/samples/misc.rb +157 -5
  45. data/test/samples/number.rb +7 -0
  46. data/test/samples/strings.rb +39 -0
  47. data/test/test_helper.rb +22 -1
  48. metadata +18 -12
  49. data/lib/ripper_ruby_parser/sexp_handlers/arguments.rb +0 -29
  50. data/lib/ripper_ruby_parser/sexp_handlers/arrays.rb +0 -21
  51. data/lib/ripper_ruby_parser/sexp_handlers/hashes.rb +0 -48
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../../test_helper.rb', File.dirname(__FILE__))
2
4
 
3
5
  describe RipperRubyParser::Parser do
@@ -58,6 +60,34 @@ describe RipperRubyParser::Parser do
58
60
  s(:call, s(:call, nil, :foo), :=~, s(:call, nil, :bar)),
59
61
  s(:call, nil, :baz), true)
60
62
  end
63
+
64
+ it 'cleans up begin..end block in condition' do
65
+ 'while begin foo end; bar; end'.
66
+ must_be_parsed_as s(:while,
67
+ s(:call, nil, :foo),
68
+ s(:call, nil, :bar), true)
69
+ end
70
+
71
+ it 'cleans up begin..end block in condition in the postfix case' do
72
+ 'foo while begin bar end'.
73
+ must_be_parsed_as s(:while,
74
+ s(:call, nil, :bar),
75
+ s(:call, nil, :foo), true)
76
+ end
77
+
78
+ it 'works with do and an empty body' do
79
+ 'while foo do; end'.
80
+ must_be_parsed_as s(:while,
81
+ s(:call, nil, :foo),
82
+ nil, true)
83
+ end
84
+
85
+ it 'works without do and with an empty body' do
86
+ 'while foo; end'.
87
+ must_be_parsed_as s(:while,
88
+ s(:call, nil, :foo),
89
+ nil, true)
90
+ end
61
91
  end
62
92
 
63
93
  describe 'for the until statement' do
@@ -116,6 +146,64 @@ describe RipperRubyParser::Parser do
116
146
  s(:call, s(:call, nil, :foo), :=~, s(:call, nil, :bar)),
117
147
  s(:call, nil, :baz), true)
118
148
  end
149
+
150
+ it 'cleans up begin..end block in condition' do
151
+ 'until begin foo end; bar; end'.
152
+ must_be_parsed_as s(:until,
153
+ s(:call, nil, :foo),
154
+ s(:call, nil, :bar), true)
155
+ end
156
+
157
+ it 'cleans up begin..end block in condition in the postfix case' do
158
+ 'foo until begin bar end'.
159
+ must_be_parsed_as s(:until,
160
+ s(:call, nil, :bar),
161
+ s(:call, nil, :foo), true)
162
+ end
163
+ end
164
+
165
+ describe 'for the for statement' do
166
+ it 'works with do' do
167
+ 'for foo in bar do; baz; end'.
168
+ must_be_parsed_as s(:for,
169
+ s(:call, nil, :bar),
170
+ s(:lasgn, :foo),
171
+ s(:call, nil, :baz))
172
+ end
173
+
174
+ it 'works without do' do
175
+ 'for foo in bar; baz; end'.
176
+ must_be_parsed_as s(:for,
177
+ s(:call, nil, :bar),
178
+ s(:lasgn, :foo),
179
+ s(:call, nil, :baz))
180
+ end
181
+
182
+ it 'works with an empty body' do
183
+ 'for foo in bar; end'.
184
+ must_be_parsed_as s(:for,
185
+ s(:call, nil, :bar),
186
+ s(:lasgn, :foo))
187
+ end
188
+
189
+ it 'works with explicit multiple assignment' do
190
+ 'for foo, bar in baz; end'.
191
+ must_be_parsed_as s(:for,
192
+ s(:call, nil, :baz),
193
+ s(:masgn,
194
+ s(:array,
195
+ s(:lasgn, :foo),
196
+ s(:lasgn, :bar))))
197
+ end
198
+
199
+ it 'works with multiple assignment with trailing comma' do
200
+ 'for foo, in bar; end'.
201
+ must_be_parsed_as s(:for,
202
+ s(:call, nil, :bar),
203
+ s(:masgn,
204
+ s(:array,
205
+ s(:lasgn, :foo))))
206
+ end
119
207
  end
120
208
  end
121
209
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require File.expand_path('../../test_helper.rb', File.dirname(__FILE__))
2
4
 
3
- describe RipperRubyParser::Parser do
4
- describe '#parse' do
5
+ describe RipperRubyParser::SexpHandlers::MethodCalls do
6
+ describe 'when parsing with RipperRubyParser::Parser#parse' do
5
7
  describe 'for method calls' do
6
8
  describe 'without a receiver' do
7
9
  it 'works without parentheses' do
@@ -135,13 +137,34 @@ describe RipperRubyParser::Parser do
135
137
  s(:call, nil, :baz,
136
138
  s(:call, nil, :qux)))
137
139
  end
140
+
141
+ it 'does not keep :begin around a method receiver' do
142
+ 'begin; foo; end.bar'.
143
+ must_be_parsed_as s(:call, s(:call, nil, :foo), :bar)
144
+ end
138
145
  end
139
146
 
140
- describe 'safe call' do
141
- before do
142
- skip 'This is not valid syntax below Ruby 2.3' if RUBY_VERSION < '2.3.0'
147
+ describe 'for collection indexing' do
148
+ it 'works in the simple case' do
149
+ 'foo[bar]'.
150
+ must_be_parsed_as s(:call,
151
+ s(:call, nil, :foo),
152
+ :[],
153
+ s(:call, nil, :bar))
154
+ end
155
+
156
+ it 'works without any indexes' do
157
+ 'foo[]'.must_be_parsed_as s(:call, s(:call, nil, :foo),
158
+ :[])
159
+ end
160
+
161
+ it 'works with self[]' do
162
+ 'self[foo]'.must_be_parsed_as s(:call, s(:self), :[],
163
+ s(:call, nil, :foo))
143
164
  end
165
+ end
144
166
 
167
+ describe 'safe call' do
145
168
  it 'works without arguments' do
146
169
  'foo&.bar'.must_be_parsed_as s(:safe_call, s(:call, nil, :foo), :bar)
147
170
  end
@@ -211,4 +234,34 @@ describe RipperRubyParser::Parser do
211
234
  must_be_parsed_as s(:call, s(:call, nil, :foo), :call)
212
235
  end
213
236
  end
237
+
238
+ describe 'when processing a Sexp' do
239
+ let(:processor) { RipperRubyParser::SexpProcessor.new }
240
+
241
+ describe '#process_command_call' do
242
+ it 'processes a Ruby 2.5 style period Sexp' do
243
+ sexp = s(:call,
244
+ s(:vcall, s(:@ident, 'foo', s(1, 0))),
245
+ :'.',
246
+ s(:@ident, 'bar', s(1, 4)))
247
+ processor.process(sexp).must_equal s(:call, s(:call, nil, :foo), :bar)
248
+ end
249
+
250
+ it 'processes a Ruby 2.6 style period Sexp' do
251
+ sexp = s(:call,
252
+ s(:vcall, s(:@ident, 'foo', s(1, 0))),
253
+ s(:@period, '.', s(1, 3)),
254
+ s(:@ident, 'bar', s(1, 4)))
255
+ processor.process(sexp).must_equal s(:call, s(:call, nil, :foo), :bar)
256
+ end
257
+
258
+ it 'raises an error for an unknown call operator' do
259
+ sexp = s(:call,
260
+ s(:vcall, s(:@ident, 'foo', s(1, 0))),
261
+ :'>.',
262
+ s(:@ident, 'bar', s(1, 4)))
263
+ -> { processor.process(sexp) }.must_raise
264
+ end
265
+ end
266
+ end
214
267
  end
@@ -0,0 +1,392 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path('../../test_helper.rb', File.dirname(__FILE__))
4
+
5
+ describe RipperRubyParser::Parser do
6
+ describe '#parse' do
7
+ describe 'for instance method definitions' do
8
+ it 'treats kwargs as a local variable' do
9
+ 'def foo(**bar); bar; end'.
10
+ must_be_parsed_as s(:defn,
11
+ :foo,
12
+ s(:args, :"**bar"),
13
+ s(:lvar, :bar))
14
+ end
15
+
16
+ it 'treats kwargs as a local variable when other arguments are present' do
17
+ 'def foo(bar, **baz); baz; end'.
18
+ must_be_parsed_as s(:defn,
19
+ :foo,
20
+ s(:args, :bar, :"**baz"),
21
+ s(:lvar, :baz))
22
+ end
23
+
24
+ it 'treats kwargs as a local variable when an explicit block is present' do
25
+ 'def foo(**bar, &baz); bar; end'.
26
+ must_be_parsed_as s(:defn,
27
+ :foo,
28
+ s(:args, :"**bar", :"&baz"),
29
+ s(:lvar, :bar))
30
+ end
31
+
32
+ it 'treats block kwargs as lvars' do
33
+ 'def foo(**bar); baz { |**qux| bar; qux }; end'.
34
+ must_be_parsed_as s(:defn, :foo,
35
+ s(:args, :"**bar"),
36
+ s(:iter,
37
+ s(:call, nil, :baz),
38
+ s(:args, :"**qux"),
39
+ s(:block,
40
+ s(:lvar, :bar),
41
+ s(:lvar, :qux))))
42
+ end
43
+
44
+ it 'works with a method argument with a default value' do
45
+ 'def foo bar=nil; end'.
46
+ must_be_parsed_as s(:defn,
47
+ :foo,
48
+ s(:args, s(:lasgn, :bar, s(:nil))),
49
+ s(:nil))
50
+ end
51
+
52
+ it 'works with several method arguments with default values' do
53
+ 'def foo bar=1, baz=2; end'.
54
+ must_be_parsed_as s(:defn,
55
+ :foo,
56
+ s(:args,
57
+ s(:lasgn, :bar, s(:lit, 1)),
58
+ s(:lasgn, :baz, s(:lit, 2))),
59
+ s(:nil))
60
+ end
61
+
62
+ it 'works with parentheses around the parameter list' do
63
+ 'def foo(bar); end'.
64
+ must_be_parsed_as s(:defn, :foo, s(:args, :bar), s(:nil))
65
+ end
66
+
67
+ it 'works with a simple splat' do
68
+ 'def foo *bar; end'.
69
+ must_be_parsed_as s(:defn, :foo, s(:args, :"*bar"), s(:nil))
70
+ end
71
+
72
+ it 'works with a regular argument plus splat' do
73
+ 'def foo bar, *baz; end'.
74
+ must_be_parsed_as s(:defn, :foo, s(:args, :bar, :"*baz"), s(:nil))
75
+ end
76
+
77
+ it 'works with a nameless splat' do
78
+ 'def foo *; end'.
79
+ must_be_parsed_as s(:defn,
80
+ :foo,
81
+ s(:args, :"*"),
82
+ s(:nil))
83
+ end
84
+
85
+ it 'works for a simple case with explicit block parameter' do
86
+ 'def foo &bar; end'.
87
+ must_be_parsed_as s(:defn,
88
+ :foo,
89
+ s(:args, :"&bar"),
90
+ s(:nil))
91
+ end
92
+
93
+ it 'works with a regular argument plus explicit block parameter' do
94
+ 'def foo bar, &baz; end'.
95
+ must_be_parsed_as s(:defn,
96
+ :foo,
97
+ s(:args, :bar, :"&baz"),
98
+ s(:nil))
99
+ end
100
+
101
+ it 'works with a default value plus explicit block parameter' do
102
+ 'def foo bar=1, &baz; end'.
103
+ must_be_parsed_as s(:defn,
104
+ :foo,
105
+ s(:args,
106
+ s(:lasgn, :bar, s(:lit, 1)),
107
+ :"&baz"),
108
+ s(:nil))
109
+ end
110
+
111
+ it 'works with a default value plus mandatory argument' do
112
+ 'def foo bar=1, baz; end'.
113
+ must_be_parsed_as s(:defn,
114
+ :foo,
115
+ s(:args,
116
+ s(:lasgn, :bar, s(:lit, 1)),
117
+ :baz),
118
+ s(:nil))
119
+ end
120
+
121
+ it 'works with a splat plus explicit block parameter' do
122
+ 'def foo *bar, &baz; end'.
123
+ must_be_parsed_as s(:defn,
124
+ :foo,
125
+ s(:args, :"*bar", :"&baz"),
126
+ s(:nil))
127
+ end
128
+
129
+ it 'works with a default value plus splat' do
130
+ 'def foo bar=1, *baz; end'.
131
+ must_be_parsed_as s(:defn,
132
+ :foo,
133
+ s(:args,
134
+ s(:lasgn, :bar, s(:lit, 1)),
135
+ :"*baz"),
136
+ s(:nil))
137
+ end
138
+
139
+ it 'works with a default value, splat, plus final mandatory arguments' do
140
+ 'def foo bar=1, *baz, qux, quuz; end'.
141
+ must_be_parsed_as s(:defn,
142
+ :foo,
143
+ s(:args,
144
+ s(:lasgn, :bar, s(:lit, 1)),
145
+ :"*baz", :qux, :quuz),
146
+ s(:nil))
147
+ end
148
+
149
+ it 'works with a named argument with a default value' do
150
+ 'def foo bar: 1; end'.
151
+ must_be_parsed_as s(:defn,
152
+ :foo,
153
+ s(:args,
154
+ s(:kwarg, :bar, s(:lit, 1))),
155
+ s(:nil))
156
+ end
157
+
158
+ it 'works with a named argument with no default value' do
159
+ 'def foo bar:; end'.
160
+ must_be_parsed_as s(:defn,
161
+ :foo,
162
+ s(:args,
163
+ s(:kwarg, :bar)),
164
+ s(:nil))
165
+ end
166
+
167
+ it 'works with a double splat' do
168
+ 'def foo **bar; end'.
169
+ must_be_parsed_as s(:defn,
170
+ :foo,
171
+ s(:args, :'**bar'),
172
+ s(:nil))
173
+ end
174
+
175
+ it 'works when the method name is an operator' do
176
+ 'def +; end'.
177
+ must_be_parsed_as s(:defn, :+, s(:args),
178
+ s(:nil))
179
+ end
180
+ end
181
+
182
+ describe 'for singleton method definitions' do
183
+ it 'works with empty body' do
184
+ 'def foo.bar; end'.
185
+ must_be_parsed_as s(:defs,
186
+ s(:call, nil, :foo),
187
+ :bar,
188
+ s(:args),
189
+ s(:nil))
190
+ end
191
+
192
+ it 'works with a body with multiple statements' do
193
+ 'def foo.bar; baz; qux; end'.
194
+ must_be_parsed_as s(:defs,
195
+ s(:call, nil, :foo),
196
+ :bar,
197
+ s(:args),
198
+ s(:call, nil, :baz),
199
+ s(:call, nil, :qux))
200
+ end
201
+
202
+ it 'works with a simple splat' do
203
+ 'def foo.bar *baz; end'.
204
+ must_be_parsed_as s(:defs,
205
+ s(:call, nil, :foo),
206
+ :bar,
207
+ s(:args, :"*baz"),
208
+ s(:nil))
209
+ end
210
+ end
211
+
212
+ describe 'for the alias statement' do
213
+ it 'works with regular barewords' do
214
+ 'alias foo bar'.
215
+ must_be_parsed_as s(:alias,
216
+ s(:lit, :foo), s(:lit, :bar))
217
+ end
218
+
219
+ it 'works with symbols' do
220
+ 'alias :foo :bar'.
221
+ must_be_parsed_as s(:alias,
222
+ s(:lit, :foo), s(:lit, :bar))
223
+ end
224
+
225
+ it 'works with operator barewords' do
226
+ 'alias + -'.
227
+ must_be_parsed_as s(:alias,
228
+ s(:lit, :+), s(:lit, :-))
229
+ end
230
+
231
+ it 'treats keywords as symbols' do
232
+ 'alias next foo'.
233
+ must_be_parsed_as s(:alias, s(:lit, :next), s(:lit, :foo))
234
+ end
235
+
236
+ it 'works with global variables' do
237
+ 'alias $foo $bar'.
238
+ must_be_parsed_as s(:valias, :$foo, :$bar)
239
+ end
240
+ end
241
+
242
+ describe 'for the undef statement' do
243
+ it 'works with a single bareword identifier' do
244
+ 'undef foo'.
245
+ must_be_parsed_as s(:undef, s(:lit, :foo))
246
+ end
247
+
248
+ it 'works with a single symbol' do
249
+ 'undef :foo'.
250
+ must_be_parsed_as s(:undef, s(:lit, :foo))
251
+ end
252
+
253
+ it 'works with multiple bareword identifiers' do
254
+ 'undef foo, bar'.
255
+ must_be_parsed_as s(:block,
256
+ s(:undef, s(:lit, :foo)),
257
+ s(:undef, s(:lit, :bar)))
258
+ end
259
+
260
+ it 'works with multiple bareword symbols' do
261
+ 'undef :foo, :bar'.
262
+ must_be_parsed_as s(:block,
263
+ s(:undef, s(:lit, :foo)),
264
+ s(:undef, s(:lit, :bar)))
265
+ end
266
+ end
267
+
268
+ describe 'for the return statement' do
269
+ it 'works with no arguments' do
270
+ 'return'.
271
+ must_be_parsed_as s(:return)
272
+ end
273
+
274
+ it 'works with one argument' do
275
+ 'return foo'.
276
+ must_be_parsed_as s(:return,
277
+ s(:call, nil, :foo))
278
+ end
279
+
280
+ it 'works with a splat argument' do
281
+ 'return *foo'.
282
+ must_be_parsed_as s(:return,
283
+ s(:svalue,
284
+ s(:splat,
285
+ s(:call, nil, :foo))))
286
+ end
287
+
288
+ it 'works with multiple arguments' do
289
+ 'return foo, bar'.
290
+ must_be_parsed_as s(:return,
291
+ s(:array,
292
+ s(:call, nil, :foo),
293
+ s(:call, nil, :bar)))
294
+ end
295
+
296
+ it 'works with a regular argument and a splat argument' do
297
+ 'return foo, *bar'.
298
+ must_be_parsed_as s(:return,
299
+ s(:array,
300
+ s(:call, nil, :foo),
301
+ s(:splat,
302
+ s(:call, nil, :bar))))
303
+ end
304
+
305
+ it 'works with a function call with parentheses' do
306
+ 'return foo(bar)'.
307
+ must_be_parsed_as s(:return,
308
+ s(:call, nil, :foo,
309
+ s(:call, nil, :bar)))
310
+ end
311
+
312
+ it 'works with a function call without parentheses' do
313
+ 'return foo bar'.
314
+ must_be_parsed_as s(:return,
315
+ s(:call, nil, :foo,
316
+ s(:call, nil, :bar)))
317
+ end
318
+ end
319
+
320
+ describe 'for yield' do
321
+ it 'works with no arguments and no parentheses' do
322
+ 'yield'.
323
+ must_be_parsed_as s(:yield)
324
+ end
325
+
326
+ it 'works with parentheses but no arguments' do
327
+ 'yield()'.
328
+ must_be_parsed_as s(:yield)
329
+ end
330
+
331
+ it 'works with one argument and no parentheses' do
332
+ 'yield foo'.
333
+ must_be_parsed_as s(:yield, s(:call, nil, :foo))
334
+ end
335
+
336
+ it 'works with one argument and parentheses' do
337
+ 'yield(foo)'.
338
+ must_be_parsed_as s(:yield, s(:call, nil, :foo))
339
+ end
340
+
341
+ it 'works with multiple arguments and no parentheses' do
342
+ 'yield foo, bar'.
343
+ must_be_parsed_as s(:yield,
344
+ s(:call, nil, :foo),
345
+ s(:call, nil, :bar))
346
+ end
347
+
348
+ it 'works with multiple arguments and parentheses' do
349
+ 'yield(foo, bar)'.
350
+ must_be_parsed_as s(:yield,
351
+ s(:call, nil, :foo),
352
+ s(:call, nil, :bar))
353
+ end
354
+
355
+ it 'works with splat' do
356
+ 'yield foo, *bar'.
357
+ must_be_parsed_as s(:yield,
358
+ s(:call, nil, :foo),
359
+ s(:splat, s(:call, nil, :bar)))
360
+ end
361
+
362
+ it 'works with a function call with parentheses' do
363
+ 'yield foo(bar)'.
364
+ must_be_parsed_as s(:yield,
365
+ s(:call, nil, :foo,
366
+ s(:call, nil, :bar)))
367
+ end
368
+
369
+ it 'works with a function call without parentheses' do
370
+ 'yield foo bar'.
371
+ must_be_parsed_as s(:yield,
372
+ s(:call, nil, :foo,
373
+ s(:call, nil, :bar)))
374
+ end
375
+ end
376
+
377
+ describe 'when extra compatibility is turned on' do
378
+ it 'treats block kwargs as calls' do
379
+ 'def foo(**bar); baz { |**qux| bar; qux }; end'.
380
+ must_be_parsed_as s(:defn, :foo,
381
+ s(:args, :"**bar"),
382
+ s(:iter,
383
+ s(:call, nil, :baz),
384
+ s(:args, :"**qux"),
385
+ s(:block,
386
+ s(:lvar, :bar),
387
+ s(:call, nil, :qux)))),
388
+ extra_compatible: true
389
+ end
390
+ end
391
+ end
392
+ end