Skip to content

Commit 01ad0e4

Browse files
committed
Improve test for Hashes with omitted values
1 parent 2159b53 commit 01ad0e4

File tree

1 file changed

+143
-10
lines changed

1 file changed

+143
-10
lines changed

language/hash_spec.rb

Lines changed: 143 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -254,19 +254,152 @@ def h.to_hash; {:b => 2, :c => 3}; end
254254
eval('{a: 1, :b => 2, "c" => 3, "d": 4, e: 5}').should == h
255255
end
256256

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
263320

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: }
267358
RUBY
268359

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
270403
end
271404

272405
it "raises a SyntaxError when the Hash key ends with `!`" do

0 commit comments

Comments
 (0)