@@ -254,19 +254,152 @@ def h.to_hash; {:b => 2, :c => 3}; end
254
254
eval ( '{a: 1, :b => 2, "c" => 3, "d": 4, e: 5}' ) . should == h
255
255
end
256
256
257
- it "works with methods and local vars" do
258
- a = Class . new
259
- a . class_eval ( <<-RUBY )
260
- def bar
261
- "baz"
262
- end
257
+ # Copied from Prism::Translation::Ripper
258
+ keywords = [
259
+ "alias" ,
260
+ "and" ,
261
+ "begin" ,
262
+ "BEGIN" ,
263
+ "break" ,
264
+ "case" ,
265
+ "class" ,
266
+ "def" ,
267
+ "defined?" ,
268
+ "do" ,
269
+ "else" ,
270
+ "elsif" ,
271
+ "end" ,
272
+ "END" ,
273
+ "ensure" ,
274
+ "false" ,
275
+ "for" ,
276
+ "if" ,
277
+ "in" ,
278
+ "module" ,
279
+ "next" ,
280
+ "nil" ,
281
+ "not" ,
282
+ "or" ,
283
+ "redo" ,
284
+ "rescue" ,
285
+ "retry" ,
286
+ "return" ,
287
+ "self" ,
288
+ "super" ,
289
+ "then" ,
290
+ "true" ,
291
+ "undef" ,
292
+ "unless" ,
293
+ "until" ,
294
+ "when" ,
295
+ "while" ,
296
+ "yield" ,
297
+ "__ENCODING__" ,
298
+ "__FILE__" ,
299
+ "__LINE__"
300
+ ]
301
+
302
+ invalid_kw_param_names = [
303
+ "BEGIN" ,
304
+ "END" ,
305
+ "defined?" ,
306
+ ]
307
+
308
+ invalid_method_names = [
309
+ "BEGIN" ,
310
+ "END" ,
311
+ "defined?" ,
312
+ ]
313
+
314
+ it "can resolve local variables" do
315
+ a = 1
316
+ b = 2
317
+
318
+ eval ( '{ a:, b: }.should == { a: 1, b: 2 }' )
319
+ end
263
320
264
- def foo(val)
265
- {bar:, val:}
266
- end
321
+ it "cannot find dynamically defined local variables" do
322
+ b = binding
323
+ b . local_variable_set ( :abc , "a dynamically defined local var" )
324
+
325
+ eval <<~RUBY
326
+ # The local variable definitely exists:
327
+ b.local_variable_get(:abc).should == "a dynamically defined local var"
328
+ # but we can't get it via value omission:
329
+ -> { { abc: } }.should raise_error(NameError)
330
+ RUBY
331
+ end
332
+
333
+ it "can call methods" do
334
+ result = sandboxed_eval <<~RUBY
335
+ def m = "a statically defined method"
336
+
337
+ { m: }
338
+ RUBY
339
+
340
+ result . should == { m : "a statically defined method" }
341
+ end
342
+
343
+ it "can call dynamically defined methods" do
344
+ result = sandboxed_eval <<~RUBY
345
+ define_method(:m) { "a dynamically defined method" }
346
+
347
+ { m: }
348
+ RUBY
349
+
350
+ result . should == { m : "a dynamically defined method" }
351
+ end
352
+
353
+ it "prefers local variables over methods" do
354
+ result = sandboxed_eval <<~RUBY
355
+ x = "from a local var"
356
+ def x; "from a method"; end
357
+ { x: }
267
358
RUBY
268
359
269
- a . new . foo ( 1 ) . should == { bar : "baz" , val : 1 }
360
+ result . should == { x : "from a local var" }
361
+ end
362
+
363
+ describe "handling keywords" do
364
+ keywords . each do |kw |
365
+ describe "keyword '#{ kw } '" do
366
+ # None of these keywords can be used as local variables,
367
+ # so it's not possible to resolve them via shorthand Hash syntax.
368
+ # See `reserved_keywords.rb`
369
+
370
+ unless invalid_kw_param_names . include? ( kw )
371
+ it "can resolve to a parameter whose name is a keyword" do
372
+ result = sandboxed_eval <<~RUBY
373
+ def m(#{ kw } :) = { #{ kw } : }
374
+
375
+ m(#{ kw } : "an argument to '#{ kw } '")
376
+ RUBY
377
+
378
+ result . should == { kw . to_sym => "an argument to '#{ kw } '" }
379
+ end
380
+ end
381
+
382
+ unless invalid_method_names . include? ( kw )
383
+ it "can resolve to a method whose name is a keyword" do
384
+ result = sandboxed_eval <<~RUBY
385
+ def #{ kw } = "a method named '#{ kw } '"
386
+
387
+ { #{ kw } : }
388
+ RUBY
389
+
390
+ result . should == { kw . to_sym => "a method named '#{ kw } '" }
391
+ end
392
+ end
393
+ end
394
+ end
395
+
396
+ describe "keyword 'self:'" do
397
+ it "does not refer to actual 'self'" do
398
+ eval <<~RUBY
399
+ -> { { self: } }.should raise_error(NameError)
400
+ RUBY
401
+ end
402
+ end
270
403
end
271
404
272
405
it "raises a SyntaxError when the Hash key ends with `!`" do
0 commit comments