<commit_before>module RR
  class DoubleDefinitionCreator # :nodoc
    NO_SUBJECT_ARG = Object.new

    attr_reader :space
    include Errors

    def initialize(space)
      @space = space
      @core_strategy = nil
      @using_proxy_strategy = false
      @instance_of_called = nil
    end
    
    def mock(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      add_strategy(subject, method_name, definition) do
        verify_no_core_strategy
        @core_strategy = :mock
      end
    end

    def stub(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      add_strategy(subject, method_name, definition) do
        verify_no_core_strategy
        @core_strategy = :stub
      end
    end

    def dont_allow(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      add_strategy(subject, method_name, definition) do
        verify_no_core_strategy
        proxy_when_dont_allow_error if @using_proxy_strategy
        @core_strategy = :dont_allow
      end
    end
    alias_method :do_not_allow, :dont_allow
    alias_method :dont_call, :dont_allow
    alias_method :do_not_call, :dont_allow

    def proxy(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      add_strategy(subject, method_name, definition) do
        proxy_when_dont_allow_error if @core_strategy == :dont_allow
        @using_proxy_strategy = true
      end
    end
    alias_method :probe, :proxy

    def instance_of(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      if subject != NO_SUBJECT_ARG && !subject.is_a?(Class)
        raise ArgumentError, "instance_of only accepts class objects" unless subject.is_a?(Class)
      end
      add_strategy(subject, method_name, definition) do
        @instance_of_called = true
        return self if subject === NO_SUBJECT_ARG
      end
    end

    def create(subject, method_name, *args, &handler)
      @args = args
      @handler = handler
      if @instance_of_called
        setup_doubles_for_class_instances(subject, method_name)
      else
        setup_double(subject, method_name)
      end
      transform
      @definition
    end
    
    protected
    def add_strategy(subject, method_name, definition)
      if method_name && definition
        raise ArgumentError, "Cannot pass in a method name and a block"
      end
      yield
      if subject.__id__ === NO_SUBJECT_ARG.__id__
        self
      elsif method_name
        create subject, method_name, &definition
      else
        space.double_definition_creator_proxy(self, subject, &definition)
      end
    end

    def setup_double(subject, method_name)
      @double_injection = @space.double_injection(subject, method_name)
      @double = @space.double(@double_injection)
      @definition = @double.definition
    end

    def setup_doubles_for_class_instances(subject, method_name)
      class_double = @space.double_injection(subject, :new)
      class_double = @space.double(class_double)

      instance_method_name = method_name

      @definition = @space.double_definition
      class_handler = proc do |return_value|
        double_injection = @space.double_injection(return_value, instance_method_name)
        @space.double(double_injection, @definition)
        return_value
      end<commit_msg>Extracted DoubleDefinitionCreator#set_core_strategy helper method. Going to use a more constrained private state transition interface.<commit_after>module RR
  class DoubleDefinitionCreator # :nodoc
    NO_SUBJECT_ARG = Object.new

    attr_reader :space
    include Errors

    def initialize(space)
      @space = space
      @core_strategy = nil
      @using_proxy_strategy = false
      @instance_of_called = nil
    end
    
    def mock(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      add_strategy(subject, method_name, definition) do
        set_core_strategy :mock
      end
    end

    def stub(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      add_strategy(subject, method_name, definition) do
        set_core_strategy :stub
      end
    end

    def dont_allow(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      add_strategy(subject, method_name, definition) do
        set_core_strategy :dont_allow
      end
    end
    alias_method :do_not_allow, :dont_allow
    alias_method :dont_call, :dont_allow
    alias_method :do_not_call, :dont_allow

    def proxy(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      add_strategy(subject, method_name, definition) do
        proxy_when_dont_allow_error if @core_strategy == :dont_allow
        @using_proxy_strategy = true
      end
    end
    alias_method :probe, :proxy

    def instance_of(subject=NO_SUBJECT_ARG, method_name=nil, &definition) # :nodoc
      if subject != NO_SUBJECT_ARG && !subject.is_a?(Class)
        raise ArgumentError, "instance_of only accepts class objects" unless subject.is_a?(Class)
      end
      add_strategy(subject, method_name, definition) do
        @instance_of_called = true
        return self if subject === NO_SUBJECT_ARG
      end
    end

    def create(subject, method_name, *args, &handler)
      @args = args
      @handler = handler
      if @instance_of_called
        setup_doubles_for_class_instances(subject, method_name)
      else
        setup_double(subject, method_name)
      end
      transform
      @definition
    end
    
    protected
    def add_strategy(subject, method_name, definition)
      if method_name && definition
        raise ArgumentError, "Cannot pass in a method name and a block"
      end
      yield
      if subject.__id__ === NO_SUBJECT_ARG.__id__
        self
      elsif method_name
        create subject, method_name, &definition
      else
        space.double_definition_creator_proxy(self, subject, &definition)
      end
    end

    def set_core_strategy(strategy)
      verify_no_core_strategy
      @core_strategy = strategy
      proxy_when_dont_allow_error if strategy == :dont_allow && @using_proxy_strategy
    end

    def setup_double(subject, method_name)
      @double_injection = @space.double_injection(subject, method_name)
      @double = @space.double(@double_injection)
      @definition = @double.definition
    end

    def setup_doubles_for_class_instances(subject, method_name)
      class_double = @space.double_injection(subject, :new)
      class_double = @space.double(class_double)

      instance_method_name = method_name

      @definition = @space.double_definition
      class_handler = proc do |return_value|
        double_injection = @space.double_injection(return_value, instance_method_name)
        @space.double(double_injection, @definition)
        return_value
      end
{'fraction_non_alphanumeric': 0.06932460577209164, 'fraction_numerical': 0.0, 'mean_word_length': 3.1705955334987594, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '802791', 'n_tokens_mistral': 2061, 'n_tokens_neox': 2022, 'n_words': 457}