<commit_before>require_relative '../spec_helper'
require_relative 'fixtures/block'

describe "A block yielded a single" do
  before :all do
    def m(a) yield a end
  end

  context "Array" do
    it "assigns the Array to a single argument" do
      m([1, 2]) { |a| a }.should == [1, 2]
    end

    it "receives the identical Array object" do
      ary = [1, 2]
      m(ary) { |a| a }.should equal(ary)
    end

    it "assigns the Array to a single rest argument" do
      m([1, 2, 3]) { |*a| a }.should == [[1, 2, 3]]
    end

    it "assigns the first element to a single argument with trailing comma" do
      m([1, 2]) { |a, | a }.should == 1
    end

    it "assigns elements to required arguments" do
      m([1, 2, 3]) { |a, b| [a, b] }.should == [1, 2]
    end

    it "assigns nil to unassigned required arguments" do
      m([1, 2]) { |a, *b, c, d| [a, b, c, d] }.should == [1, [], 2, nil]
    end

    it "assigns elements to optional arguments" do
      m([1, 2]) { |a=5, b=4, c=3| [a, b, c] }.should == [1, 2, 3]
    end

    it "assigns elements to post arguments" do
      m([1, 2]) { |a=5, b, c, d| [a, b, c, d] }.should == [5, 1, 2, nil]
    end

    it "assigns elements to required arguments when a keyword rest argument is present" do
      m([1, 2]) { |a, **k| [a, k] }.should == [1, {}]
    end

    ruby_version_is ''..."2.8" do
      it "assigns elements to mixed argument types" do
        suppress_keyword_warning do
          result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
          result.should == [1, 2, [], 3, 2, {x: 9}]
        end
      end

      it "assigns symbol keys from a Hash to keyword arguments" do
        suppress_keyword_warning do
          result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
          result.should == [{"a" => 1}, a: 10]
        end
      end

      it "assigns symbol keys from a Hash returned by #to_hash to keyword arguments" do
        suppress_keyword_warning do
          obj = mock("coerce block keyword arguments")
          obj.should_receive(:to_hash).and_return({"a" => 1, b: 2})

          result = m([obj]) { |a=nil, **b| [a, b] }
          result.should == [{"a" => 1}, b: 2]
        end
      end
    end

    ruby_version_is "2.8" do
      it "assigns elements to mixed argument types" do
        result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
        result.should == [1, 2, [3], {x: 9}, 2, {}]
      end

      it "does not treat final Hash as keyword arguments" do
        result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
        result.should == [{"a" => 1, a: 10}, {}]
      end

      it "does not call #to_hash on final argument to get keyword arguments" do
        suppress_keyword_warning do
          obj = mock("coerce block keyword arguments")
          obj.should_not_receive(:to_hash)

          result = m([obj]) { |a=nil, **b| [a, b] }
          result.should == [obj, {}]
        end
      end
    end

    ruby_version_is ""..."2.7" do
      it "calls #to_hash on the argument and uses resulting hash as first argument when optional argument and keyword argument accepted" do
        obj = mock("coerce block keyword arguments")
        obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})

        result = m([obj]) { |a=nil, **b| [a, b] }
        result.should == [{"a" => 1, "b" => 2}, {}]
      end
    end

    ruby_version_is "2.7"...'2.8' do
      it "calls #to_hash on the argument but ignores result when optional argument and keyword argument accepted" do
        obj = mock("coerce block keyword arguments")
        obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})

        result = m([obj]) { |a=nil, **b| [a, b] }
        result.should == [obj, {}]
      end
    end

    ruby_version_is "2.8" do
      it "does not call #to_hash on the argument when optional argument and keyword argument accepted" do
        obj = mock("coerce block keyword arguments")
        obj.should_not_receive(:to_hash)

        result = m([obj]) { |a=nil, **b| [a, b] }
        result.should == [obj, {}]
      end
    end

    describe "when non-symbol keys are in a keyword arguments Hash" do
      ruby_version_is ""..."2.8" do
        it "separates non-symbol keys and symbol keys" do
          suppress_keyword_warning do
            result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
            result.should == [{"a" => 10}, {b: 2}]
          end
        end
      end
      ruby_version_is "2.8" do
        it "does not separates non-symbol keys and symbol keys" do
          suppress_keyword_warning do
            result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
            result.should == [{"a" => 10, b: 2}, {}]
          end
        end
      end
    end

    it "does not treat hashes with string keys as keyword arguments" do
      result = m(["a" => 10]) { |a = nil, **b| [a, b] }
      result.should == [{"a" => 10}, {}]
    end

    ruby_version_is ''...'2.8' do
      it "calls #to_hash on the last element if keyword arguments are present" do
        suppress_keyword_warning do
          obj = mock("destructure block keyword arguments")
          obj.should_receive(:to_hash).and_return({x: 9})

          result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
          result.should == [1, [2], 3, {x: 9}]
        end
      end
<commit_msg>Do not autosplat when calling procs that accept rest and keywords<commit_after>require_relative '../spec_helper'
require_relative 'fixtures/block'

describe "A block yielded a single" do
  before :all do
    def m(a) yield a end
  end

  context "Array" do
    it "assigns the Array to a single argument" do
      m([1, 2]) { |a| a }.should == [1, 2]
    end

    it "receives the identical Array object" do
      ary = [1, 2]
      m(ary) { |a| a }.should equal(ary)
    end

    it "assigns the Array to a single rest argument" do
      m([1, 2, 3]) { |*a| a }.should == [[1, 2, 3]]
    end

    it "assigns the first element to a single argument with trailing comma" do
      m([1, 2]) { |a, | a }.should == 1
    end

    it "assigns elements to required arguments" do
      m([1, 2, 3]) { |a, b| [a, b] }.should == [1, 2]
    end

    it "assigns nil to unassigned required arguments" do
      m([1, 2]) { |a, *b, c, d| [a, b, c, d] }.should == [1, [], 2, nil]
    end

    it "assigns elements to optional arguments" do
      m([1, 2]) { |a=5, b=4, c=3| [a, b, c] }.should == [1, 2, 3]
    end

    it "assigns elements to post arguments" do
      m([1, 2]) { |a=5, b, c, d| [a, b, c, d] }.should == [5, 1, 2, nil]
    end

    it "assigns elements to required arguments when a keyword rest argument is present" do
      m([1, 2]) { |a, **k| [a, k] }.should == [1, {}]
    end

    ruby_version_is ''..."2.8" do
      it "assigns elements to mixed argument types" do
        suppress_keyword_warning do
          result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
          result.should == [1, 2, [], 3, 2, {x: 9}]
        end
      end

      it "assigns symbol keys from a Hash to keyword arguments" do
        suppress_keyword_warning do
          result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
          result.should == [{"a" => 1}, a: 10]
        end
      end

      it "assigns symbol keys from a Hash returned by #to_hash to keyword arguments" do
        suppress_keyword_warning do
          obj = mock("coerce block keyword arguments")
          obj.should_receive(:to_hash).and_return({"a" => 1, b: 2})

          result = m([obj]) { |a=nil, **b| [a, b] }
          result.should == [{"a" => 1}, b: 2]
        end
      end
    end

    ruby_version_is "2.8" do
      it "assigns elements to mixed argument types" do
        result = m([1, 2, 3, {x: 9}]) { |a, b=5, *c, d, e: 2, **k| [a, b, c, d, e, k] }
        result.should == [1, 2, [3], {x: 9}, 2, {}]
      end

      it "does not treat final Hash as keyword arguments and does not autosplat" do
        result = m(["a" => 1, a: 10]) { |a=nil, **b| [a, b] }
        result.should == [[{"a" => 1, a: 10}], {}]
      end

      it "does not call #to_hash on final argument to get keyword arguments and does not autosplat" do
        suppress_keyword_warning do
          obj = mock("coerce block keyword arguments")
          obj.should_not_receive(:to_hash)

          result = m([obj]) { |a=nil, **b| [a, b] }
          result.should == [[obj], {}]
        end
      end
    end

    ruby_version_is ""..."2.7" do
      it "calls #to_hash on the argument and uses resulting hash as first argument when optional argument and keyword argument accepted" do
        obj = mock("coerce block keyword arguments")
        obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})

        result = m([obj]) { |a=nil, **b| [a, b] }
        result.should == [{"a" => 1, "b" => 2}, {}]
      end
    end

    ruby_version_is "2.7"...'2.8' do
      it "calls #to_hash on the argument but ignores result when optional argument and keyword argument accepted" do
        obj = mock("coerce block keyword arguments")
        obj.should_receive(:to_hash).and_return({"a" => 1, "b" => 2})

        result = m([obj]) { |a=nil, **b| [a, b] }
        result.should == [obj, {}]
      end
    end

    ruby_version_is "2.8" do
      it "does not call #to_hash on the argument when optional argument and keyword argument accepted and does not autosplat" do
        obj = mock("coerce block keyword arguments")
        obj.should_not_receive(:to_hash)

        result = m([obj]) { |a=nil, **b| [a, b] }
        result.should == [[obj], {}]
      end
    end

    describe "when non-symbol keys are in a keyword arguments Hash" do
      ruby_version_is ""..."2.8" do
        it "separates non-symbol keys and symbol keys" do
          suppress_keyword_warning do
            result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
            result.should == [{"a" => 10}, {b: 2}]
          end
        end
      end
      ruby_version_is "2.8" do
        it "does not separate non-symbol keys and symbol keys and does not autosplat" do
          suppress_keyword_warning do
            result = m(["a" => 10, b: 2]) { |a=nil, **b| [a, b] }
            result.should == [[{"a" => 10, b: 2}], {}]
          end
        end
      end
    end

    ruby_version_is ""..."2.8" do
      it "does not treat hashes with string keys as keyword arguments" do
        result = m(["a" => 10]) { |a = nil, **b| [a, b] }
        result.should == [{"a" => 10}, {}]
      end
    end

    ruby_version_is "2.8" do
      it "does not treat hashes with string keys as keyword arguments and does not autosplat" do
        result = m(["a" => 10]) { |a = nil, **b| [a, b] }
        result.should == [[{"a" => 10}], {}]
      end
    end

    ruby_version_is ''...'2.8' do
      it "calls #to_hash on the last element if keyword arguments are present" do
        suppress_keyword_warning do
          obj = mock("destructure block keyword arguments")
          obj.should_receive(:to_hash).and_return({x: 9})

          result = m([1, 2, 3, obj]) { |a, *b, c, **k| [a, b, c, k] }
          result.should == [1, [2], 3, {x: 9}]
        end
      end

{'fraction_non_alphanumeric': 0.1579794367456415, 'fraction_numerical': 0.023424228877961556, 'mean_word_length': 2.142134831460674, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 41, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2093948', 'n_tokens_mistral': 4094, 'n_tokens_neox': 3843, 'n_words': 1404}