class RSpec::Matchers::BuiltIn::ChangeDetails

the ‘actual_before` value before applying the change.
Instead, matchers must pass a block to `perform_change`, which yields
matchers do that properly, we do not expose the `actual_before` value.
applying the change in the `expect` block. To ensure that all `change`
they are lazily computed as needed. We must pre-compute them before
etc, which are derived from the `before` value may not be accurate if
returned by the value proc, which means that failure message snippets,
value. Some usages of the `change` matcher mutate a specific object
as needed, but it intentionally does not expose the `actual_before`
matchers above to derive failure messages, etc from the value on demand
Note that this class exposes the `actual_after` value, to allow the
Encapsulates the details of the before/after values.
@private

def actual_delta

def actual_delta
  @actual_after - @actual_before
end

def changed?

def changed?
  # Consider it changed if either:
  #
  # - The before/after values are unequal
  # - The before/after values have different hash values
  #
  # The latter case specifically handles the case when the value proc
  # returns the exact same object, but it has been mutated.
  #
  # Note that it is not sufficient to only check the hashes; it is
  # possible for two values to be unequal (and of different classes)
  # but to return the same hash value. Also, some objects may change
  # their hash after being compared with `==`/`!=`.
  @actual_before != @actual_after || @before_hash != @actual_hash
end

def evaluate_value_proc

def evaluate_value_proc
  @value_proc ? @value_proc.call : @receiver.__send__(@message)
end

def extract_value_block_snippet

def extract_value_block_snippet
  return nil unless @value_proc
  Expectations::BlockSnippetExtractor.try_extracting_single_line_body_of(@value_proc, @matcher_name)
end

def extract_value_block_snippet

:nocov:
def extract_value_block_snippet
  nil
end

def initialize(matcher_name, receiver=nil, message=nil, &block)

def initialize(matcher_name, receiver=nil, message=nil, &block)
  if receiver && !message
    raise(
      ArgumentError,
      "`change` requires either an object and message " \
      "(`change(obj, :msg)`) or a block (`change { }`). " \
      "You passed an object but no message."
    )
  end
  @matcher_name = matcher_name
  @receiver = receiver
  @message = message
  @value_proc = block
  # TODO: temporary measure to mute warning of access to an initialized
  # instance variable when a deprecated implicit block expectation
  # syntax is used. This may be removed once `fail` is used, and the
  # matcher never issues this warning.
  @actual_after = UNDEFINED
end

def message_notation(receiver, message)

def message_notation(receiver, message)
  case receiver
  when Module
    "#{receiver}.#{message}"
  else
    "#{Support.class_of(receiver)}##{message}"
  end
end

def perform_change(event_proc)

def perform_change(event_proc)
  @actual_before = evaluate_value_proc
  @before_hash = @actual_before.hash
  yield @actual_before if block_given?
  return false unless Proc === event_proc
  event_proc.call
  @actual_after = evaluate_value_proc
  @actual_hash = @actual_after.hash
  true
end

def value_representation

def value_representation
  @value_representation ||=
    if @message
      "`#{message_notation(@receiver, @message)}`"
    elsif (value_block_snippet = extract_value_block_snippet)
      "`#{value_block_snippet}`"
    else
      'result'
    end
end