Skip to content

Commit

Permalink
Change error to accept param for generating arity message
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrmurach committed Apr 11, 2020
1 parent 8716c66 commit 1a445a7
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 60 deletions.
29 changes: 28 additions & 1 deletion lib/tty/option/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,34 @@ module Option
InvalidArgument = Class.new(Error)

# Raised when number of arguments doesn't match
InvalidArity = Class.new(Error)
class InvalidArity < Error
def initialize(param_or_message, arity = nil)
if param_or_message.is_a?(Parameter)
param = param_or_message
prefix = param.arity < 0 ? "at least " : ""
expected_arity = param.arity < 0 ? param.arity.abs - 1 : param.arity

message = format(
"expected %s %s to appear %s but appeared %s",
param.to_sym,
param.name.inspect,
prefix + pluralize("time", expected_arity),
pluralize("time", arity)
)
else
message = param_or_message
end

super(message)
end

# Pluralize a noun
#
# @api private
def pluralize(noun, count = 1)
"#{count} #{noun}#{'s' unless count == 1}"
end
end

# Raised when conversion provided with unexpected argument
InvalidConversionArgument = Class.new(Error)
Expand Down
26 changes: 16 additions & 10 deletions lib/tty/option/parser/arguments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,8 @@ def process_exact_arity(arg)

if 0 < values.size && values.size < arg.arity &&
Array(@defaults[arg.name]).size < arg.arity
record_error(InvalidArity, format(
"expected argument %s to appear %d times but appeared %d times",
arg.name.inspect, arg.arity, values.size), arg)
error = InvalidArity.new(arg, values.size)
record_error(error, error.message, arg)
end

values
Expand Down Expand Up @@ -124,8 +123,8 @@ def process_infinite_arity(arg)
end

if values.size < arity && Array(@defaults[arg.name]).size < arity
record_error(InvalidArity, format(
"expected argument %s to appear at least %d times but appeared %d times", arg.name.inspect, arity, values.size, arg))
error = InvalidArity.new(arg, values.size)
record_error(error, error.message, arg)
end

values
Expand Down Expand Up @@ -170,17 +169,24 @@ def keyword?(value)
# Record or raise an error
#
# @api private
def record_error(type, message, arg = nil)
def record_error(error, message, param = nil)
is_class = error.is_a?(Class)

if @raise_if_missing
raise type, message
if is_class
raise error, message
else
raise error
end
end

type_key = type.to_s.split("::").last
type_name = is_class ? error.name : error.class.name
type_key = type_name.to_s.split("::").last
.gsub(/([a-z]+)([A-Z])/, "\\1_\\2")
.downcase.to_sym

if arg
(@errors[arg.name] ||= {}).merge!(type_key => message)
if param
(@errors[param.name] ||= {}).merge!(type_key => message)
else
@errors[:invalid] = message
end
Expand Down
40 changes: 16 additions & 24 deletions lib/tty/option/parser/keywords.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,23 @@ def assign_keyword(kwarg, value)
# Record or raise an error
#
# @api private
def record_error(type, message, arg = nil)
def record_error(error, message, param = nil)
is_class = error.is_a?(Class)

if @raise_if_missing
raise type, message
if is_class
raise error, message
else
raise error
end
end

type_key = type.to_s.split("::").last
type_name = is_class ? error.name : error.class.name
type_key = type_name.to_s.split("::").last
.gsub(/([a-z]+)([A-Z])/, "\\1_\\2")
.downcase.to_sym

if arg
(@errors[arg.name] ||= {}).merge!(type_key => message)
if param
(@errors[param.name] ||= {}).merge!(type_key => message)
else
@errors[:invalid] = message
end
Expand All @@ -144,30 +150,16 @@ def record_error(type, message, arg = nil)
#
# @api private
def check_arity
@multiplies.each do |name, kwarg|
@multiplies.each do |name, param|
arity = @arities[name]

if 0 < kwarg.arity.abs && arity < kwarg.arity.abs
prefix = kwarg.arity < 0 ? "at least " : ""
expected_arity = kwarg.arity < 0 ? kwarg.arity.abs - 1 : kwarg.arity

record_error(InvalidArity, format(
"expected keyword %s to appear %s but appeared %s",
name.inspect,
prefix + pluralize("time", expected_arity),
pluralize("time", arity)
))
if 0 < param.arity.abs && arity < param.arity.abs
error = InvalidArity.new(param, arity)
record_error(error, error.message, param)
end
end
end

# Pluralize a noun
#
# @api private
def pluralize(noun, count = 1)
"#{count} #{noun}#{'s' unless count == 1}"
end

# Check if required parameters are provided
#
# @raise [MissingParameter]
Expand Down
38 changes: 16 additions & 22 deletions lib/tty/option/parser/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,18 +242,27 @@ def option?(value)
!value.match(/^-./).nil?
end

# Record or raise an error
#
# @api private
def record_error(type, message, opt = nil)
def record_error(error, message, param = nil)
is_class = error.is_a?(Class)

if @raise_if_missing
raise type, message
if is_class
raise error, message
else
raise error
end
end

type_key = type.to_s.split("::").last
type_name = is_class ? error.name : error.class.name
type_key = type_name.to_s.split("::").last
.gsub(/([a-z]+)([A-Z])/, "\\1_\\2")
.downcase.to_sym

if opt
(@errors[opt.name] ||= {}).merge!(type_key => message)
if param
(@errors[param.name] ||= {}).merge!(type_key => message)
else
@errors[:invalid] = message
end
Expand Down Expand Up @@ -293,27 +302,12 @@ def check_arity
arity = @arities[name]

if 0 < param.arity.abs && arity < param.arity.abs
prefix = param.arity < 0 ? "at least " : ""
expected_arity = param.arity < 0 ? param.arity.abs - 1 : param.arity

record_error(InvalidArity, format(
"expected %s %s to appear %s but appeared %s",
param.to_sym,
name.inspect,
prefix + pluralize("time", expected_arity),
pluralize("time", arity)
), param)
error = InvalidArity.new(param, arity)
record_error(error, error.message, param)
end
end
end

# Pluralize a noun
#
# @api private
def pluralize(noun, count = 1)
"#{count} #{noun}#{'s' unless count == 1}"
end

# Check if required options are provided
#
# @raise [MissingParameter]
Expand Down
6 changes: 3 additions & 3 deletions spec/unit/parser/arguments_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,15 @@ def parse(argv, args, **config)
parse(%w[a], arg(:foo, arity: 2))
}.to raise_error(TTY::Option::InvalidArity,
"expected argument :foo to appear 2 times but " \
"appeared 1 times")
"appeared 1 time")
end

it "doesn't find enough arguments to match at least arity" do
expect {
parse(%w[a], arg(:foo, arity: -3))
}.to raise_error(TTY::Option::InvalidArity,
"expected argument :foo to appear at least 2 times but " \
"appeared 1 times")
"appeared 1 time")
end

it "doesn't find any arguments to match zero or more arity" do
Expand Down Expand Up @@ -70,7 +70,7 @@ def parse(argv, args, **config)

expect(args[:foo]).to eq("a")
expect(rest).to eq([])
expect(errors[:foo]).to eq({invalid_arity: "expected argument :foo to appear 2 times but appeared 1 times"})
expect(errors[:foo]).to eq({invalid_arity: "expected argument :foo to appear 2 times but appeared 1 time"})
end

it "parses zero or more arguments" do
Expand Down

0 comments on commit 1a445a7

Please sign in to comment.