class Mocha::ParameterMatchers::PositionalOrKeywordHash

@private

def deprecation_warning(actual, expected)

def deprecation_warning(actual, expected)
  details1 = "Expectation #{expectation_definition} expected #{hash_type(expected)} (#{expected.mocha_inspect}),".squeeze(' ')
  details2 = "but received #{hash_type(actual)} (#{actual.mocha_inspect})."
  sentence1 = 'These will stop matching when strict keyword argument matching is enabled.'
  sentence2 = 'See the documentation for Mocha::Configuration#strict_keyword_argument_matching=.'
  Deprecation.warning([details1, details2, sentence1, sentence2].join(' '))
end

def expectation_definition

def expectation_definition
  return nil unless @expectation
  "defined at #{@expectation.definition_location}"
end

def extract_actual_value(actual_values)

def extract_actual_value(actual_values)
  [actual_values.shift, actual_values.empty?]
end

def hash_type(hash)

def hash_type(hash)
  ruby2_keywords_hash?(hash) ? 'keyword arguments' : 'positional hash'
end

def initialize(expected_value, expectation, last_expected_value)

def initialize(expected_value, expectation, last_expected_value)
  @expected_value = expected_value
  @expectation = expectation
  @last_expected_value = last_expected_value
end

def last_expected_value_is_positional_hash?

def last_expected_value_is_positional_hash?
  @last_expected_value && !ruby2_keywords_hash?(@expected_value)
end

def matches?(actual_values)

def matches?(actual_values)
  actual_value, is_last_actual_value = extract_actual_value(actual_values)
  if !matches_entries_exactly?(actual_value)
    false
  elsif is_last_actual_value
    matches_last_actual_value?(actual_value)
  else
    true
  end
end

def matches_entries_exactly?(actual_value)

def matches_entries_exactly?(actual_value)
  HasEntries.new(@expected_value, exact: true).matches?([actual_value])
end

def matches_last_actual_value?(actual_value)

def matches_last_actual_value?(actual_value)
  if same_type_of_hash?(actual_value, @expected_value)
    true
  elsif last_expected_value_is_positional_hash? # rubocop:disable Lint/DuplicateBranch
    true
  elsif Mocha.configuration.strict_keyword_argument_matching?
    false
  else
    deprecation_warning(actual_value, @expected_value) if Mocha::RUBY_V27_PLUS
    true
  end
end

def mocha_inspect

def mocha_inspect
  @expected_value.mocha_inspect
end

def ruby2_keywords_hash?(hash)

def ruby2_keywords_hash?(hash)
  hash.is_a?(Hash) && ::Hash.ruby2_keywords_hash?(hash)
end

def same_type_of_hash?(actual, expected)

def same_type_of_hash?(actual, expected)
  ruby2_keywords_hash?(actual) == ruby2_keywords_hash?(expected)
end