Skip to content
This repository has been archived by the owner on Nov 30, 2024. It is now read-only.

Commit

Permalink
[bugfix] Properly detect kwargs hashes vs optional positional args
Browse files Browse the repository at this point in the history
  • Loading branch information
malcolmohare committed Feb 25, 2024
1 parent 8cbf7f9 commit 97cbf4e
Showing 1 changed file with 24 additions and 5 deletions.
29 changes: 24 additions & 5 deletions lib/rspec/support/method_signature_verifier.rb
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,31 @@ def invalid_kw_args_from(given_kw_args)
given_kw_args - @allowed_kw_args
end

# If the last argument is Hash, Ruby will treat only symbol keys as keyword arguments
# the rest will be grouped in another Hash and passed as positional argument.
# Considering the arg types, are there kw_args?
def has_kw_args_in?(args)
Hash === args.last &&
could_contain_kw_args?(args) &&
(RubyFeatures.kw_arg_separation? || args.last.empty? || args.last.keys.any? { |x| x.is_a?(Symbol) })
if RubyFeatures.kw_arg_separation?
# If the last arg is a hash, depending on the signature it could be kw_args or a positional parameter.
return false unless Hash === args.last && could_contain_kw_args?(args)

# If the method signature contains **kwargs, the last argument being a hash means its the kwargs hash.
# The hash being a required positional argument is considered inside could_contain_kw_args
return true if @allows_any_kw_args

# If the position of the hash is beyond the count of required and optional positional
# args then it is the kwargs hash
return true if args.count > @max_non_kw_args

# Otherwise, the hash could be defined kw_args or an optional positional parameter
# inspect the keys against known kwargs to determine what it is
return args.last.keys.all? { |x| @allowed_kw_args.include?(x) }
else
# Version <= Ruby 2.7
# If the last argument is Hash, Ruby will treat only symbol keys as keyword arguments
# the rest will be grouped in another Hash and passed as positional argument.
Hash === args.last &&
could_contain_kw_args?(args) &&
(args.last.empty? || args.last.keys.any? { |x| x.is_a?(Symbol) })
end
end

# Without considering what the last arg is, could it
Expand Down

0 comments on commit 97cbf4e

Please sign in to comment.