From 58325daae3beefda13ed100782cd19a89cc68771 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sat, 24 Oct 2020 11:52:30 -0700 Subject: Make String methods return String instances when called on a subclass instance This modifies the following String methods to return String instances instead of subclass instances: * String#* * String#capitalize * String#center * String#chomp * String#chop * String#delete * String#delete_prefix * String#delete_suffix * String#downcase * String#dump * String#each/#each_line * String#gsub * String#ljust * String#lstrip * String#partition * String#reverse * String#rjust * String#rpartition * String#rstrip * String#scrub * String#slice! * String#slice/#[] * String#split * String#squeeze * String#strip * String#sub * String#succ/#next * String#swapcase * String#tr * String#tr_s * String#upcase This also fixes a bug in String#swapcase where it would return the receiver instead of a copy of the receiver if the receiver was the empty string. Some string methods were left to return subclass instances: * String#+@ * String#-@ Both of these methods will return the receiver (subclass instance) in some cases, so it is best to keep the returned class consistent. Fixes [#10845] --- spec/ruby/core/string/capitalize_spec.rb | 15 +++- spec/ruby/core/string/center_spec.rb | 25 ++++-- spec/ruby/core/string/chomp_spec.rb | 15 +++- spec/ruby/core/string/chop_spec.rb | 12 ++- spec/ruby/core/string/delete_prefix_spec.rb | 15 +++- spec/ruby/core/string/delete_spec.rb | 12 ++- spec/ruby/core/string/delete_suffix_spec.rb | 15 +++- spec/ruby/core/string/downcase_spec.rb | 12 ++- spec/ruby/core/string/dump_spec.rb | 12 ++- spec/ruby/core/string/gsub_spec.rb | 21 +++-- spec/ruby/core/string/ljust_spec.rb | 25 ++++-- spec/ruby/core/string/rjust_spec.rb | 25 ++++-- spec/ruby/core/string/shared/each_line.rb | 18 ++++- spec/ruby/core/string/shared/slice.rb | 114 ++++++++++++++++++++------ spec/ruby/core/string/shared/succ.rb | 18 ++++- spec/ruby/core/string/slice_spec.rb | 92 ++++++++++++++++----- spec/ruby/core/string/split_spec.rb | 120 ++++++++++++++++++++-------- spec/ruby/core/string/squeeze_spec.rb | 12 ++- spec/ruby/core/string/sub_spec.rb | 21 +++-- spec/ruby/core/string/swapcase_spec.rb | 15 +++- spec/ruby/core/string/tr_s_spec.rb | 12 ++- spec/ruby/core/string/tr_spec.rb | 12 ++- spec/ruby/core/string/upcase_spec.rb | 12 ++- spec/ruby/shared/string/times.rb | 18 ++++- 24 files changed, 516 insertions(+), 152 deletions(-) (limited to 'spec/ruby') diff --git a/spec/ruby/core/string/capitalize_spec.rb b/spec/ruby/core/string/capitalize_spec.rb index e6cf365ac3..21df18a5ae 100644 --- a/spec/ruby/core/string/capitalize_spec.rb +++ b/spec/ruby/core/string/capitalize_spec.rb @@ -80,9 +80,18 @@ describe "String#capitalize" do -> { "abc".capitalize(:invalid_option) }.should raise_error(ArgumentError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("hello").capitalize.should be_an_instance_of(String) + StringSpecs::MyString.new("Hello").capitalize.should be_an_instance_of(String) + end end end diff --git a/spec/ruby/core/string/center_spec.rb b/spec/ruby/core/string/center_spec.rb index 8a4be0a81e..b66015172c 100644 --- a/spec/ruby/core/string/center_spec.rb +++ b/spec/ruby/core/string/center_spec.rb @@ -91,13 +91,26 @@ describe "String#center with length, padding" do -> { "hello".center(0, "") }.should raise_error(ArgumentError) end - it "returns subclass instances when called on subclasses" do - StringSpecs::MyString.new("").center(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on subclasses" do + StringSpecs::MyString.new("").center(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + + "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end + end - "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) - "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + ruby_version_is '3.0' do + it "returns String instances when called on subclasses" do + StringSpecs::MyString.new("").center(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").center(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + + "".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".center(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/spec/ruby/core/string/chomp_spec.rb b/spec/ruby/core/string/chomp_spec.rb index 7a1118d534..3d6207f876 100644 --- a/spec/ruby/core/string/chomp_spec.rb +++ b/spec/ruby/core/string/chomp_spec.rb @@ -46,9 +46,18 @@ describe "String#chomp" do end end - it "returns subclass instances when called on a subclass" do - str = StringSpecs::MyString.new("hello\n").chomp - str.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + str = StringSpecs::MyString.new("hello\n").chomp + str.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + str = StringSpecs::MyString.new("hello\n").chomp + str.should be_an_instance_of(String) + end end it "removes trailing characters that match $/ when it has been assigned a value" do diff --git a/spec/ruby/core/string/chop_spec.rb b/spec/ruby/core/string/chop_spec.rb index 582d3c58c5..9b4e7363c6 100644 --- a/spec/ruby/core/string/chop_spec.rb +++ b/spec/ruby/core/string/chop_spec.rb @@ -61,8 +61,16 @@ describe "String#chop" do end end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("hello\n").chop.should be_an_instance_of(String) + end end end diff --git a/spec/ruby/core/string/delete_prefix_spec.rb b/spec/ruby/core/string/delete_prefix_spec.rb index bd5b56a312..8469791f74 100644 --- a/spec/ruby/core/string/delete_prefix_spec.rb +++ b/spec/ruby/core/string/delete_prefix_spec.rb @@ -41,9 +41,18 @@ describe "String#delete_prefix" do 'hello'.delete_prefix(o).should == 'o' end - it "returns a subclass instance when called on a subclass instance" do - s = StringSpecs::MyString.new('hello') - s.delete_prefix('hell').should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance when called on a subclass instance" do + s = StringSpecs::MyString.new('hello') + s.delete_prefix('hell').should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance when called on a subclass instance" do + s = StringSpecs::MyString.new('hello') + s.delete_prefix('hell').should be_an_instance_of(String) + end end end diff --git a/spec/ruby/core/string/delete_spec.rb b/spec/ruby/core/string/delete_spec.rb index b6e54f8386..ebca0b7dae 100644 --- a/spec/ruby/core/string/delete_spec.rb +++ b/spec/ruby/core/string/delete_spec.rb @@ -93,8 +93,16 @@ describe "String#delete" do -> { "hello world".delete(mock('x')) }.should raise_error(TypeError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("oh no!!!").delete("!").should be_an_instance_of(String) + end end end diff --git a/spec/ruby/core/string/delete_suffix_spec.rb b/spec/ruby/core/string/delete_suffix_spec.rb index dbb5f9df9e..12d0ee175e 100644 --- a/spec/ruby/core/string/delete_suffix_spec.rb +++ b/spec/ruby/core/string/delete_suffix_spec.rb @@ -41,9 +41,18 @@ describe "String#delete_suffix" do 'hello'.delete_suffix(o).should == 'h' end - it "returns a subclass instance when called on a subclass instance" do - s = StringSpecs::MyString.new('hello') - s.delete_suffix('ello').should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance when called on a subclass instance" do + s = StringSpecs::MyString.new('hello') + s.delete_suffix('ello').should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance when called on a subclass instance" do + s = StringSpecs::MyString.new('hello') + s.delete_suffix('ello').should be_an_instance_of(String) + end end end diff --git a/spec/ruby/core/string/downcase_spec.rb b/spec/ruby/core/string/downcase_spec.rb index 8c840bdcc4..4427c9df10 100644 --- a/spec/ruby/core/string/downcase_spec.rb +++ b/spec/ruby/core/string/downcase_spec.rb @@ -76,8 +76,16 @@ describe "String#downcase" do end end - it "returns a subclass instance for subclasses" do - StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance for subclasses" do + StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance for subclasses" do + StringSpecs::MyString.new("FOObar").downcase.should be_an_instance_of(String) + end end end diff --git a/spec/ruby/core/string/dump_spec.rb b/spec/ruby/core/string/dump_spec.rb index ebdd0167aa..817dec6c4d 100644 --- a/spec/ruby/core/string/dump_spec.rb +++ b/spec/ruby/core/string/dump_spec.rb @@ -19,8 +19,16 @@ describe "String#dump" do "foo".freeze.dump.should_not.frozen? end - it "returns a subclass instance" do - StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance" do + StringSpecs::MyString.new.dump.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance" do + StringSpecs::MyString.new.dump.should be_an_instance_of(String) + end end it "wraps string with \"" do diff --git a/spec/ruby/core/string/gsub_spec.rb b/spec/ruby/core/string/gsub_spec.rb index 23e0ad2260..54a2be0fed 100644 --- a/spec/ruby/core/string/gsub_spec.rb +++ b/spec/ruby/core/string/gsub_spec.rb @@ -236,11 +236,22 @@ describe "String#gsub with pattern and replacement" do -> { "hello".gsub(/[aeiou]/, nil) }.should raise_error(TypeError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").gsub(//, "").should be_an_instance_of(String) + StringSpecs::MyString.new("").gsub(/foo/, "").should be_an_instance_of(String) + StringSpecs::MyString.new("foo").gsub(/foo/, "").should be_an_instance_of(String) + StringSpecs::MyString.new("foo").gsub("foo", "").should be_an_instance_of(String) + end end # Note: $~ cannot be tested because mspec messes with it diff --git a/spec/ruby/core/string/ljust_spec.rb b/spec/ruby/core/string/ljust_spec.rb index 481ef77ca8..0c3b2a2f44 100644 --- a/spec/ruby/core/string/ljust_spec.rb +++ b/spec/ruby/core/string/ljust_spec.rb @@ -74,13 +74,26 @@ describe "String#ljust with length, padding" do -> { "hello".ljust(10, '') }.should raise_error(ArgumentError) end - it "returns subclass instances when called on subclasses" do - StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on subclasses" do + StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + + "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end + end - "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) - "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + ruby_version_is '3.0' do + it "returns String instances when called on subclasses" do + StringSpecs::MyString.new("").ljust(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").ljust(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + + "".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".ljust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/spec/ruby/core/string/rjust_spec.rb b/spec/ruby/core/string/rjust_spec.rb index bf39f4fdb9..f51aacff44 100644 --- a/spec/ruby/core/string/rjust_spec.rb +++ b/spec/ruby/core/string/rjust_spec.rb @@ -74,13 +74,26 @@ describe "String#rjust with length, padding" do -> { "hello".rjust(10, '') }.should raise_error(ArgumentError) end - it "returns subclass instances when called on subclasses" do - StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on subclasses" do + StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(StringSpecs::MyString) + + "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end + end - "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) - "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + ruby_version_is '3.0' do + it "returns String instances when called on subclasses" do + StringSpecs::MyString.new("").rjust(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").rjust(10).should be_an_instance_of(String) + StringSpecs::MyString.new("foo").rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + + "".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + "foo".rjust(10, StringSpecs::MyString.new("x")).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/spec/ruby/core/string/shared/each_line.rb b/spec/ruby/core/string/shared/each_line.rb index 156565ff13..f9c910596a 100644 --- a/spec/ruby/core/string/shared/each_line.rb +++ b/spec/ruby/core/string/shared/each_line.rb @@ -93,10 +93,20 @@ describe :string_each_line, shared: true do end end - it "yields subclass instances for subclasses" do - a = [] - StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class } - a.should == [StringSpecs::MyString, StringSpecs::MyString] + ruby_version_is ''...'3.0' do + it "yields subclass instances for subclasses" do + a = [] + StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class } + a.should == [StringSpecs::MyString, StringSpecs::MyString] + end + end + + ruby_version_is '3.0' do + it "yields String instances for subclasses" do + a = [] + StringSpecs::MyString.new("hello\nworld").send(@method) { |s| a << s.class } + a.should == [String, String] + end end it "returns self" do diff --git a/spec/ruby/core/string/shared/slice.rb b/spec/ruby/core/string/shared/slice.rb index 6b6f37217a..69997b7c1d 100644 --- a/spec/ruby/core/string/shared/slice.rb +++ b/spec/ruby/core/string/shared/slice.rb @@ -163,11 +163,22 @@ describe :string_slice_index_length, shared: true do -> { "hello".send(@method, 0, bignum_value) }.should raise_error(RangeError) end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, 0,0).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, 0,4).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, 1,4).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, 0,0).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, 0,4).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, 1,4).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, 0,0).should be_an_instance_of(String) + s.send(@method, 0,4).should be_an_instance_of(String) + s.send(@method, 1,4).should be_an_instance_of(String) + end end it "handles repeated application" do @@ -252,11 +263,22 @@ describe :string_slice_range, shared: true do end end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, 0...0).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, 0..4).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, 1..4).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, 0...0).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, 0..4).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, 1..4).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, 0...0).should be_an_instance_of(String) + s.send(@method, 0..4).should be_an_instance_of(String) + s.send(@method, 1..4).should be_an_instance_of(String) + end end it "calls to_int on range arguments" do @@ -348,10 +370,20 @@ describe :string_slice_regexp, shared: true do end end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, //).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, /../).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, //).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, /../).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, //).should be_an_instance_of(String) + s.send(@method, /../).should be_an_instance_of(String) + end end it "sets $~ to MatchData when there is a match and nil when there's none" do @@ -436,10 +468,20 @@ describe :string_slice_regexp_index, shared: true do -> { "hello".send(@method, /(.)(.)(.)/, nil) }.should raise_error(TypeError) end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, /(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString) - s.send(@method, /(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, /(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString) + s.send(@method, /(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, /(.)(.)/, 0).should be_an_instance_of(String) + s.send(@method, /(.)(.)/, 1).should be_an_instance_of(String) + end end it "sets $~ to MatchData when there is a match and nil when there's none" do @@ -493,11 +535,22 @@ describe :string_slice_string, shared: true do -> { "hello".send(@method, o) }.should raise_error(TypeError) end - it "returns a subclass instance when given a subclass instance" do - s = StringSpecs::MyString.new("el") - r = "hello".send(@method, s) - r.should == "el" - r.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance when given a subclass instance" do + s = StringSpecs::MyString.new("el") + r = "hello".send(@method, s) + r.should == "el" + r.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance when given a subclass instance" do + s = StringSpecs::MyString.new("el") + r = "hello".send(@method, s) + r.should == "el" + r.should be_an_instance_of(String) + end end end @@ -567,9 +620,18 @@ describe :string_slice_regexp_group, shared: true do -> { "hello".send(@method, /(?)/, '') }.should raise_error(IndexError) end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.send(@method, /(?.)/, 'q').should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, /(?.)/, 'q').should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.send(@method, /(?.)/, 'q').should be_an_instance_of(String) + end end it "sets $~ to MatchData when there is a match and nil when there's none" do diff --git a/spec/ruby/core/string/shared/succ.rb b/spec/ruby/core/string/shared/succ.rb index 7ca488dd88..25602103b6 100644 --- a/spec/ruby/core/string/shared/succ.rb +++ b/spec/ruby/core/string/shared/succ.rb @@ -59,10 +59,20 @@ describe :string_succ, shared: true do "\xFF\xFF".send(@method).should == "\x01\x00\x00" end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("").send(@method).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").send(@method).should be_an_instance_of(String) + StringSpecs::MyString.new("a").send(@method).should be_an_instance_of(String) + StringSpecs::MyString.new("z").send(@method).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/spec/ruby/core/string/slice_spec.rb b/spec/ruby/core/string/slice_spec.rb index bd0a63971b..83b475c8b5 100644 --- a/spec/ruby/core/string/slice_spec.rb +++ b/spec/ruby/core/string/slice_spec.rb @@ -142,12 +142,21 @@ describe "String#slice! with index, length" do "hello".slice!(obj, obj).should == "ll" end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.slice!(0, 0).should be_an_instance_of(StringSpecs::MyString) - s.slice!(0, 4).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(0, 0).should be_an_instance_of(StringSpecs::MyString) + s.slice!(0, 4).should be_an_instance_of(StringSpecs::MyString) + end end + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(0, 0).should be_an_instance_of(String) + s.slice!(0, 4).should be_an_instance_of(String) + end + end it "returns the substring given by the character offsets" do "hellö there".slice!(1,0).should == "" @@ -196,10 +205,20 @@ describe "String#slice! Range" do end end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.slice!(0...0).should be_an_instance_of(StringSpecs::MyString) - s.slice!(0..4).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(0...0).should be_an_instance_of(StringSpecs::MyString) + s.slice!(0..4).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(0...0).should be_an_instance_of(String) + s.slice!(0..4).should be_an_instance_of(String) + end end it "calls to_int on range arguments" do @@ -299,10 +318,20 @@ describe "String#slice! with Regexp" do end end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.slice!(//).should be_an_instance_of(StringSpecs::MyString) - s.slice!(/../).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(//).should be_an_instance_of(StringSpecs::MyString) + s.slice!(/../).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(//).should be_an_instance_of(String) + s.slice!(/../).should be_an_instance_of(String) + end end it "returns the matching portion of self with a multi byte character" do @@ -383,10 +412,20 @@ describe "String#slice! with Regexp, index" do "har".slice!(/(.)(.)(.)/, obj).should == "a" end - it "returns subclass instances" do - s = StringSpecs::MyString.new("hello") - s.slice!(/(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString) - s.slice!(/(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(/(.)(.)/, 0).should be_an_instance_of(StringSpecs::MyString) + s.slice!(/(.)(.)/, 1).should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + s = StringSpecs::MyString.new("hello") + s.slice!(/(.)(.)/, 0).should be_an_instance_of(String) + s.slice!(/(.)(.)/, 1).should be_an_instance_of(String) + end end it "returns the encoding aware capture for the given index" do @@ -461,11 +500,22 @@ describe "String#slice! with String" do -> { "hello".slice!(o) }.should raise_error(TypeError) end - it "returns a subclass instance when given a subclass instance" do - s = StringSpecs::MyString.new("el") - r = "hello".slice!(s) - r.should == "el" - r.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance when given a subclass instance" do + s = StringSpecs::MyString.new("el") + r = "hello".slice!(s) + r.should == "el" + r.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a subclass instance when given a subclass instance" do + s = StringSpecs::MyString.new("el") + r = "hello".slice!(s) + r.should == "el" + r.should be_an_instance_of(String) + end end it "raises a FrozenError if self is frozen" do diff --git a/spec/ruby/core/string/split_spec.rb b/spec/ruby/core/string/split_spec.rb index 7ac8d7815c..c5441e3a49 100644 --- a/spec/ruby/core/string/split_spec.rb +++ b/spec/ruby/core/string/split_spec.rb @@ -159,28 +159,48 @@ describe "String#split with String" do "foo".split("bar", 3).should == ["foo"] end - it "returns subclass instances based on self" do - ["", "x.y.z.", " x y "].each do |str| - ["", ".", " "].each do |pat| - [-1, 0, 1, 2].each do |limit| - StringSpecs::MyString.new(str).split(pat, limit).each do |x| - x.should be_an_instance_of(StringSpecs::MyString) - end + ruby_version_is ''...'3.0' do + it "returns subclass instances based on self" do + ["", "x.y.z.", " x y "].each do |str| + ["", ".", " "].each do |pat| + [-1, 0, 1, 2].each do |limit| + StringSpecs::MyString.new(str).split(pat, limit).each do |x| + x.should be_an_instance_of(StringSpecs::MyString) + end - str.split(StringSpecs::MyString.new(pat), limit).each do |x| - x.should be_an_instance_of(String) + str.split(StringSpecs::MyString.new(pat), limit).each do |x| + x.should be_an_instance_of(String) + end end end end end + + it "does not call constructor on created subclass instances" do + # can't call should_not_receive on an object that doesn't yet exist + # so failure here is signalled by exception, not expectation failure + + s = StringSpecs::StringWithRaisingConstructor.new('silly:string') + s.split(':').first.should == 'silly' + end end - it "does not call constructor on created subclass instances" do - # can't call should_not_receive on an object that doesn't yet exist - # so failure here is signalled by exception, not expectation failure + ruby_version_is '3.0' do + it "returns String instances based on self" do + ["", "x.y.z.", " x y "].each do |str| + ["", ".", " "].each do |pat| + [-1, 0, 1, 2].each do |limit| + StringSpecs::MyString.new(str).split(pat, limit).each do |x| + x.should be_an_instance_of(String) + end - s = StringSpecs::StringWithRaisingConstructor.new('silly:string') - s.split(':').first.should == 'silly' + str.split(StringSpecs::MyString.new(pat), limit).each do |x| + x.should be_an_instance_of(String) + end + end + end + end + end end ruby_version_is ''...'2.7' do @@ -355,24 +375,40 @@ describe "String#split with Regexp" do "foo".split(/bar/, 3).should == ["foo"] end - it "returns subclass instances based on self" do - ["", "x:y:z:", " x y "].each do |str| - [//, /:/, /\s+/].each do |pat| - [-1, 0, 1, 2].each do |limit| - StringSpecs::MyString.new(str).split(pat, limit).each do |x| - x.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances based on self" do + ["", "x:y:z:", " x y "].each do |str| + [//, /:/, /\s+/].each do |pat| + [-1, 0, 1, 2].each do |limit| + StringSpecs::MyString.new(str).split(pat, limit).each do |x| + x.should be_an_instance_of(StringSpecs::MyString) + end end end end end - end - it "does not call constructor on created subclass instances" do - # can't call should_not_receive on an object that doesn't yet exist - # so failure here is signalled by exception, not expectation failure + it "does not call constructor on created subclass instances" do + # can't call should_not_receive on an object that doesn't yet exist + # so failure here is signalled by exception, not expectation failure + + s = StringSpecs::StringWithRaisingConstructor.new('silly:string') + s.split(/:/).first.should == 'silly' + end + end - s = StringSpecs::StringWithRaisingConstructor.new('silly:string') - s.split(/:/).first.should == 'silly' + ruby_version_is '3.0' do + it "returns String instances based on self" do + ["", "x:y:z:", " x y "].each do |str| + [//, /:/, /\s+/].each do |pat| + [-1, 0, 1, 2].each do |limit| + StringSpecs::MyString.new(str).split(pat, limit).each do |x| + x.should be_an_instance_of(String) + end + end + end + end + end end ruby_version_is ''...'2.7' do @@ -493,16 +529,32 @@ describe "String#split with Regexp" do end describe "for a String subclass" do - it "yields instances of the same subclass" do - a = [] - StringSpecs::MyString.new("a|b").split("|") { |str| a << str } - first, last = a + ruby_version_is ''...'3.0' do + it "yields instances of the same subclass" do + a = [] + StringSpecs::MyString.new("a|b").split("|") { |str| a << str } + first, last = a + + first.should be_an_instance_of(StringSpecs::MyString) + first.should == "a" - first.should be_an_instance_of(StringSpecs::MyString) - first.should == "a" + last.should be_an_instance_of(StringSpecs::MyString) + last.should == "b" + end + end + + ruby_version_is '3.0' do + it "yields instances of String" do + a = [] + StringSpecs::MyString.new("a|b").split("|") { |str| a << str } + first, last = a - last.should be_an_instance_of(StringSpecs::MyString) - last.should == "b" + first.should be_an_instance_of(String) + first.should == "a" + + last.should be_an_instance_of(String) + last.should == "b" + end end end end diff --git a/spec/ruby/core/string/squeeze_spec.rb b/spec/ruby/core/string/squeeze_spec.rb index 5a7fbb59de..6f75402c9c 100644 --- a/spec/ruby/core/string/squeeze_spec.rb +++ b/spec/ruby/core/string/squeeze_spec.rb @@ -80,8 +80,16 @@ describe "String#squeeze" do -> { "hello world".squeeze(mock('x')) }.should raise_error(TypeError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("oh no!!!").squeeze("!").should be_an_instance_of(String) + end end end diff --git a/spec/ruby/core/string/sub_spec.rb b/spec/ruby/core/string/sub_spec.rb index 80cf8622d5..5ae9a4bbf3 100644 --- a/spec/ruby/core/string/sub_spec.rb +++ b/spec/ruby/core/string/sub_spec.rb @@ -192,11 +192,22 @@ describe "String#sub with pattern, replacement" do -> { "hello".sub(/[aeiou]/, 99) }.should raise_error(TypeError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").sub(//, "").should be_an_instance_of(String) + StringSpecs::MyString.new("").sub(/foo/, "").should be_an_instance_of(String) + StringSpecs::MyString.new("foo").sub(/foo/, "").should be_an_instance_of(String) + StringSpecs::MyString.new("foo").sub("foo", "").should be_an_instance_of(String) + end end it "sets $~ to MatchData of match and nil when there's none" do diff --git a/spec/ruby/core/string/swapcase_spec.rb b/spec/ruby/core/string/swapcase_spec.rb index 0b50cc35c4..32b358607e 100644 --- a/spec/ruby/core/string/swapcase_spec.rb +++ b/spec/ruby/core/string/swapcase_spec.rb @@ -73,9 +73,18 @@ describe "String#swapcase" do -> { "abc".swapcase(:invalid_option) }.should raise_error(ArgumentError) end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("").swapcase.should be_an_instance_of(StringSpecs::MyString) - StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("").swapcase.should be_an_instance_of(StringSpecs::MyString) + StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("").swapcase.should be_an_instance_of(String) + StringSpecs::MyString.new("hello").swapcase.should be_an_instance_of(String) + end end end diff --git a/spec/ruby/core/string/tr_s_spec.rb b/spec/ruby/core/string/tr_s_spec.rb index cdf5667ea3..c6ad12139e 100644 --- a/spec/ruby/core/string/tr_s_spec.rb +++ b/spec/ruby/core/string/tr_s_spec.rb @@ -45,8 +45,16 @@ describe "String#tr_s" do "bla".tr_s(from_str, to_str).should == "BlA" end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances when called on a subclass" do + StringSpecs::MyString.new("hello").tr_s("e", "a").should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/spec/ruby/core/string/tr_spec.rb b/spec/ruby/core/string/tr_spec.rb index 212d06f679..06be1e6641 100644 --- a/spec/ruby/core/string/tr_spec.rb +++ b/spec/ruby/core/string/tr_spec.rb @@ -57,8 +57,16 @@ describe "String#tr" do "bla".tr(from_str, to_str).should == "BlA" end - it "returns subclass instances when called on a subclass" do - StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances when called on a subclass" do + StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns Stringinstances when called on a subclass" do + StringSpecs::MyString.new("hello").tr("e", "a").should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do diff --git a/spec/ruby/core/string/upcase_spec.rb b/spec/ruby/core/string/upcase_spec.rb index 13ebd09a95..6cf44b4703 100644 --- a/spec/ruby/core/string/upcase_spec.rb +++ b/spec/ruby/core/string/upcase_spec.rb @@ -73,8 +73,16 @@ describe "String#upcase" do end end - it "returns a subclass instance for subclasses" do - StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(StringSpecs::MyString) + ruby_version_is ''...'3.0' do + it "returns a subclass instance for subclasses" do + StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(StringSpecs::MyString) + end + end + + ruby_version_is '3.0' do + it "returns a String instance for subclasses" do + StringSpecs::MyString.new("fooBAR").upcase.should be_an_instance_of(String) + end end end diff --git a/spec/ruby/shared/string/times.rb b/spec/ruby/shared/string/times.rb index 4dd59884c8..cd4edf5340 100644 --- a/spec/ruby/shared/string/times.rb +++ b/spec/ruby/shared/string/times.rb @@ -32,10 +32,20 @@ describe :string_times, shared: true do @object.call("", max_long).should == "" end - it "returns subclass instances" do - @object.call(MyString.new("cool"), 0).should be_an_instance_of(MyString) - @object.call(MyString.new("cool"), 1).should be_an_instance_of(MyString) - @object.call(MyString.new("cool"), 2).should be_an_instance_of(MyString) + ruby_version_is ''...'3.0' do + it "returns subclass instances" do + @object.call(MyString.new("cool"), 0).should be_an_instance_of(MyString) + @object.call(MyString.new("cool"), 1).should be_an_instance_of(MyString) + @object.call(MyString.new("cool"), 2).should be_an_instance_of(MyString) + end + end + + ruby_version_is '3.0' do + it "returns String instances" do + @object.call(MyString.new("cool"), 0).should be_an_instance_of(String) + @object.call(MyString.new("cool"), 1).should be_an_instance_of(String) + @object.call(MyString.new("cool"), 2).should be_an_instance_of(String) + end end ruby_version_is ''...'2.7' do -- cgit v1.2.3