summaryrefslogtreecommitdiff
path: root/spec/ruby/language/variables_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/language/variables_spec.rb')
-rw-r--r--spec/ruby/language/variables_spec.rb110
1 files changed, 92 insertions, 18 deletions
diff --git a/spec/ruby/language/variables_spec.rb b/spec/ruby/language/variables_spec.rb
index c900c03d37..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
@@ -824,22 +909,11 @@ end
describe "Instance variables" do
context "when instance variable is uninitialized" do
- ruby_version_is ""..."3.0" do
- it "warns about accessing uninitialized instance variable" do
- obj = Object.new
- def obj.foobar; a = @a; end
-
- -> { obj.foobar }.should complain(/warning: instance variable @a not initialized/, verbose: true)
- end
- end
-
- ruby_version_is "3.0" do
- it "doesn't warn about accessing uninitialized instance variable" do
- obj = Object.new
- def obj.foobar; a = @a; end
+ it "doesn't warn about accessing uninitialized instance variable" do
+ obj = Object.new
+ def obj.foobar; a = @a; end
- -> { obj.foobar }.should_not complain(verbose: true)
- end
+ -> { obj.foobar }.should_not complain(verbose: true)
end
it "doesn't warn at lazy initialization" do
@@ -856,7 +930,7 @@ describe "Instance variables" 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)
+ -> { obj.foobar }.should complain(/warning: global variable [`']\$specs_uninitialized_global_variable' not initialized/, verbose: true)
end
it "doesn't warn at lazy initialization" do