class RSpec::Mocks::MethodDouble

@private

def add_default_stub(*args, &implementation)

Other tags:
    Private: -
def add_default_stub(*args, &implementation)
  return if stubs.any?
  add_stub(*args, &implementation)
end

def add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation)

Other tags:
    Private: -
def add_expectation(error_generator, expectation_ordering, expected_from, opts, &implementation)
  configure_method
  expectation = MessageExpectation.new(error_generator, expectation_ordering,
                                       expected_from, self, 1, opts, &implementation)
  expectations << expectation
  expectation
end

def add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation)

Other tags:
    Private: -
def add_stub(error_generator, expectation_ordering, expected_from, opts={}, &implementation)
  configure_method
  stub = MessageExpectation.new(error_generator, expectation_ordering, expected_from,
                                self, :any, opts, &implementation)
  stubs.unshift stub
  stub
end

def any_instance_class_recorder_observing_method?(klass)

def any_instance_class_recorder_observing_method?(klass)
  return true if ::RSpec::Mocks.any_instance_recorder_for(klass).already_observing?(@method_name)
  superklass = klass.superclass
  return false if superklass.nil?
  any_instance_class_recorder_observing_method?(superklass)
end

def build_expectation(error_generator, expectation_ordering)

Other tags:
    Private: -
def build_expectation(error_generator, expectation_ordering)
  expected_from = IGNORED_BACKTRACE_LINE
  MessageExpectation.new(error_generator, expectation_ordering, expected_from, self)
end

def clear

Other tags:
    Private: -
def clear
  expectations.clear
  stubs.clear
end

def configure_method

Other tags:
    Private: -
def configure_method
  @original_visibility = visibility_for_method
  @method_stasher.stash unless @method_is_proxied
  define_proxy_method
end

def define_proxy_method

Other tags:
    Private: -
def define_proxy_method
  return if @method_is_proxied
  object_singleton_class.class_eval <<-EOF, __FILE__, __LINE__ + 1
    def #{@method_name}(*args, &block)
      ::RSpec::Mocks.proxy_for(self).message_received :#{@method_name}, *args, &block
    end
    #{visibility_for_method}
  EOF
  @method_is_proxied = true
end

def expectations

Other tags:
    Private: -
def expectations
  self[:expectations]
end

def initialize(object, method_name, proxy)

Other tags:
    Private: -
def initialize(object, method_name, proxy)
  @method_name = method_name
  @object = object
  @proxy = proxy
  @method_stasher = InstanceMethodStasher.new(object_singleton_class, @method_name)
  @method_is_proxied = false
  store(:expectations, [])
  store(:stubs, [])
end

def object_singleton_class

Other tags:
    Private: -
def object_singleton_class
  class << @object; self; end
end

def original_method

Other tags:
    Private: -
def original_method
  if @method_stasher.method_is_stashed?
    # Example: a singleton method defined on @object
    ::RSpec::Mocks.method_handle_for(@object, @method_stasher.stashed_method_name)
  elsif meth = original_unrecorded_any_instance_method
    # Example: a method that has been mocked through
    #   klass.any_instance.should_receive(:msg).and_call_original
    # any_instance.should_receive(:msg) causes the method to be
    # replaced with a proxy method, and then `and_call_original`
    # is recorded and played back on the object instance. We need
    # special handling here to get a handle on the original method
    # object rather than the proxy method.
    meth
  else
    # Example: an instance method defined on one of @object's ancestors.
    original_method_from_ancestry
  end
rescue NameError
  # We have no way of knowing if the object's method_missing
  # will handle this message or not...but we can at least try.
  # If it's not handled, a `NoMethodError` will be raised, just
  # like normally.
  ProcWithBlock.new(@object,@method_name)
end

def original_method_from_ancestor(ancestors)

def original_method_from_ancestor(ancestors)
  klass, *rest = ancestors
  klass.instance_method(@method_name).bind(@object)
rescue NameError
  raise if rest.empty?
  original_method_from_ancestor(rest)
end

def original_method_from_ancestry

In Ruby 2.1, ancestors include the correct ancestors, including the singleton classes
def original_method_from_ancestry
  # Lookup in the ancestry, skipping over the singleton class itself
  original_method_from_ancestor(object_singleton_class.ancestors.drop(1))
end

def original_method_from_ancestry

Other tags:
    Private: -
def original_method_from_ancestry
  original_method_from_ancestor(object_singleton_class.ancestors)
rescue NameError
  raise unless @object.respond_to?(:superclass)
  # Example: a singleton method defined on @object's superclass.
  #
  # Note: we have to give precedence to instance methods
  # defined on @object's class, because in a case like:
  #
  # `klass.should_receive(:new).and_call_original`
  #
  # ...we want `Class#new` bound to `klass` (which will return
  # an instance of `klass`), not `klass.superclass.new` (which
  # would return an instance of `klass.superclass`).
  original_method_from_superclass
end

def original_method_from_superclass

Other tags:
    Private: -
def original_method_from_superclass
  @object.superclass.
          singleton_class.
          instance_method(@method_name).
          bind(@object)
end

def original_method_from_superclass

Other tags:
    Private: -
def original_method_from_superclass
  ::Kernel.warn <<-WARNING.gsub(/^ +\|/, '')
    |
    |WARNING: On ruby 1.8, rspec-mocks is unable to bind the original
    |`#{@method_name}` method to your partial mock object (#{@object})
    |for `and_call_original`. The superclass's `#{@method_name}` is being
    |used instead; however, it may not work correctly when executed due
    |to the fact that `self` will be #{@object.superclass}, not #{@object}.
    |
    |Called from: #{caller[2]}
  WARNING
  @object.superclass.method(@method_name)
end

def original_unrecorded_any_instance_method

def original_unrecorded_any_instance_method
  return nil unless any_instance_class_recorder_observing_method?(@object.class)
  alias_name = ::RSpec::Mocks.any_instance_recorder_for(@object.class).build_alias_method_name(@method_name)
  @object.method(alias_name)
end

def raise_method_not_stubbed_error

Other tags:
    Private: -
def raise_method_not_stubbed_error
  raise MockExpectationError, "The method `#{method_name}` was not stubbed or was already unstubbed"
end

def remove_single_stub(stub)

Other tags:
    Private: -
def remove_single_stub(stub)
  stubs.delete(stub)
  restore_original_method if stubs.empty? && expectations.empty?
end

def remove_stub

Other tags:
    Private: -
def remove_stub
  raise_method_not_stubbed_error if stubs.empty?
  expectations.empty? ? reset : stubs.clear
end

def reset

Other tags:
    Private: -
def reset
  restore_original_method
  clear
end

def restore_original_method

Other tags:
    Private: -
def restore_original_method
  return unless @method_is_proxied
  object_singleton_class.__send__(:remove_method, @method_name)
  @method_stasher.restore
  restore_original_visibility
  @method_is_proxied = false
end

def restore_original_visibility

Other tags:
    Private: -
def restore_original_visibility
  return unless object_singleton_class.method_defined?(@method_name) || object_singleton_class.private_method_defined?(@method_name)
  object_singleton_class.class_eval(@original_visibility, __FILE__, __LINE__)
end

def stubs

Other tags:
    Private: -
def stubs
  self[:stubs]
end

def verify

Other tags:
    Private: -
def verify
  expectations.each {|e| e.verify_messages_received}
end

def visibility

Other tags:
    Private: -
def visibility
  if TestDouble === @object
    'public'
  elsif object_singleton_class.private_method_defined?(@method_name)
    'private'
  elsif object_singleton_class.protected_method_defined?(@method_name)
    'protected'
  else
    'public'
  end
end

def visibility_for_method

Other tags:
    Private: -
def visibility_for_method
  "#{visibility} :#{method_name}"
end