diff options
Diffstat (limited to 'spec/ruby/language/variables_spec.rb')
-rw-r--r-- | spec/ruby/language/variables_spec.rb | 144 |
1 files changed, 132 insertions, 12 deletions
diff --git a/spec/ruby/language/variables_spec.rb b/spec/ruby/language/variables_spec.rb index 7d6969e659..01be61a9dc 100644 --- a/spec/ruby/language/variables_spec.rb +++ b/spec/ruby/language/variables_spec.rb @@ -1,6 +1,86 @@ require_relative '../spec_helper' require_relative 'fixtures/variables' +describe "Evaluation order during assignment" do + context "with single assignment" do + it "evaluates from left to right" do + obj = VariablesSpecs::EvalOrder.new + obj.instance_eval do + foo[0] = a + end + + obj.order.should == ["foo", "a", "foo[]="] + end + end + + context "with multiple assignment" do + ruby_version_is ""..."3.1" do + it "does not evaluate from left to right" do + obj = VariablesSpecs::EvalOrder.new + + obj.instance_eval do + foo[0], bar.baz = a, b + end + + obj.order.should == ["a", "b", "foo", "foo[]=", "bar", "bar.baz="] + end + + it "cannot be used to swap variables with nested method calls" do + node = VariablesSpecs::EvalOrder.new.node + + original_node = node + original_node_left = node.left + original_node_left_right = node.left.right + + node.left, node.left.right, node = node.left.right, node, node.left + # Should evaluate in the order of: + # RHS: node.left.right, node, node.left + # LHS: + # * node(original_node), original_node.left = original_node_left_right + # * node(original_node), node.left(changed in the previous assignment to original_node_left_right), + # original_node_left_right.right = original_node + # * node = original_node_left + + node.should == original_node_left + node.right.should_not == original_node + node.right.left.should_not == original_node_left_right + end + end + + ruby_version_is "3.1" do + it "evaluates from left to right, receivers first then methods" do + obj = VariablesSpecs::EvalOrder.new + obj.instance_eval do + foo[0], bar.baz = a, b + end + + obj.order.should == ["foo", "bar", "a", "b", "foo[]=", "bar.baz="] + end + + it "can be used to swap variables with nested method calls" do + node = VariablesSpecs::EvalOrder.new.node + + original_node = node + original_node_left = node.left + original_node_left_right = node.left.right + + node.left, node.left.right, node = node.left.right, node, node.left + # Should evaluate in the order of: + # LHS: node, node.left(original_node_left) + # RHS: original_node_left_right, original_node, original_node_left + # Ops: + # * node(original_node), original_node.left = original_node_left_right + # * original_node_left.right = original_node + # * node = original_node_left + + node.should == original_node_left + node.right.should == original_node + node.right.left.should == original_node_left_right + end + end + end +end + describe "Multiple assignment" do context "with a single RHS value" do it "assigns a simple MLHS" do @@ -287,8 +367,13 @@ describe "Multiple assignment" do it "assigns indexed elements" do a = [] - a[1], a[2] = 1 - a.should == [nil, 1, nil] + a[1], a[2] = 1, 2 + a.should == [nil, 1, 2] + + # with splatted argument + a = [] + a[*[1]], a[*[2]] = 1, 2 + a.should == [nil, 1, 2] end it "assigns constants" do @@ -797,8 +882,21 @@ describe 'Local variable shadowing' do end describe 'Allowed characters' do - # new feature in 2.6 -- https://bugs.ruby-lang.org/issues/13770 - it 'does not allow non-ASCII upcased characters at the beginning' do + it 'allows non-ASCII lowercased characters at the beginning' do + result = nil + + eval <<-CODE + def test + μ = 1 + end + + result = test + CODE + + result.should == 1 + end + + it 'parses a non-ASCII upcased character as a constant identifier' do -> do eval <<-CODE def test @@ -807,18 +905,40 @@ describe 'Allowed characters' do CODE end.should raise_error(SyntaxError, /dynamic constant assignment/) end +end - it 'allows non-ASCII lowercased characters at the beginning' do - result = nil +describe "Instance variables" do + context "when instance variable is uninitialized" do + it "doesn't warn about accessing uninitialized instance variable" do + obj = Object.new + def obj.foobar; a = @a; end - eval <<-CODE - def test - μ = 1 + -> { obj.foobar }.should_not complain(verbose: true) + end + + it "doesn't warn at lazy initialization" do + obj = Object.new + def obj.foobar; @a ||= 42; end + + -> { obj.foobar }.should_not complain(verbose: true) + end + end + + describe "global variable" do + context "when global variable is uninitialized" do + it "warns about accessing uninitialized global variable in verbose mode" do + obj = Object.new + def obj.foobar; a = $specs_uninitialized_global_variable; end + + -> { obj.foobar }.should complain(/warning: global variable [`']\$specs_uninitialized_global_variable' not initialized/, verbose: true) end - result = test - CODE + it "doesn't warn at lazy initialization" do + obj = Object.new + def obj.foobar; $specs_uninitialized_global_variable_lazy ||= 42; end - result.should == 1 + -> { obj.foobar }.should_not complain(verbose: true) + end + end end end |