Skip to content

Commit 339c57f

Browse files
committed
Fix value normalization in strict mode
1 parent 76260b0 commit 339c57f

File tree

2 files changed

+52
-5
lines changed

2 files changed

+52
-5
lines changed

lib/elixir/lib/option_parser.ex

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ defmodule OptionParser do
174174
{:error, {:undefined, opt_name, value}, rest}
175175
else
176176
{opt_name, kinds, value} = normalize_option(opt, value, switches)
177-
{value, kinds, rest} = normalize_value(value, kinds, rest)
177+
{value, kinds, rest} = normalize_value(value, kinds, rest, strict)
178178
case validate_option(opt_name, value, kinds) do
179179
{:ok, new_value} -> {:ok, opt_name, new_value, rest}
180180
:invalid -> {:error, {:value, opt_name, value}, rest}
@@ -286,21 +286,22 @@ defmodule OptionParser do
286286
{option, List.wrap(switches[option]), value}
287287
end
288288

289-
defp normalize_value(nil, kinds, t) do
289+
defp normalize_value(nil, kinds, t, strict) do
290+
null = if strict, do: nil, else: true
290291
cond do
291292
:boolean in kinds ->
292293
{true, kinds, t}
293294
value_in_tail?(t) ->
294295
[h|t] = t
295296
{h, kinds, t}
296297
kinds == [] ->
297-
{true, kinds, t}
298+
{null, kinds, t}
298299
true ->
299-
{true, [:invalid], t}
300+
{null, [:invalid], t}
300301
end
301302
end
302303

303-
defp normalize_value(value, kinds, t) do
304+
defp normalize_value(value, kinds, t, _) do
304305
{value, kinds, t}
305306
end
306307

lib/elixir/test/elixir/option_parser_test.exs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,50 @@ defmodule OptionParserTest do
171171
assert OptionParser.parse(args)
172172
== {[source: "from_docs/", verbose: true], ["test/enum_test.exs"], []}
173173
end
174+
175+
test "next strict: good options" do
176+
config = [switches: [str: :string, int: :integer, bool: :boolean], strict: true]
177+
assert OptionParser.next(["--str", "hello", "..."], config)
178+
== {:ok, :str, "hello", ["..."]}
179+
assert OptionParser.next(["--int=13", "..."], config)
180+
== {:ok, :int, 13, ["..."]}
181+
assert OptionParser.next(["--bool=false", "..."], config)
182+
== {:ok, :bool, false, ["..."]}
183+
assert OptionParser.next(["--no-bool", "..."], config)
184+
== {:ok, :bool, false, ["..."]}
185+
assert OptionParser.next(["--bool", "..."], config)
186+
== {:ok, :bool, true, ["..."]}
187+
assert OptionParser.next(["..."], config)
188+
== {:error, ["..."]}
189+
end
190+
191+
test "next strict: unknown options" do
192+
config = [switches: [bool: :boolean], strict: true]
193+
assert OptionParser.next(["--str", "13", "..."], config)
194+
== {:error, {:undefined, :str, nil}, ["13", "..."]}
195+
assert OptionParser.next(["--int=hello", "..."], config)
196+
== {:error, {:undefined, :int, "hello"}, ["..."]}
197+
end
198+
199+
test "next strict: bad type" do
200+
config = [switches: [str: :string, int: :integer, bool: :boolean], strict: true]
201+
assert OptionParser.next(["--str", "13", "..."], config)
202+
== {:ok, :str, "13", ["..."]}
203+
assert OptionParser.next(["--int=hello", "..."], config)
204+
== {:error, {:value, :int, "hello"}, ["..."]}
205+
assert OptionParser.next(["--int", "hello", "..."], config)
206+
== {:error, {:value, :int, "hello"}, ["..."]}
207+
assert OptionParser.next(["--bool=other", "..."], config)
208+
== {:error, {:value, :bool, "other"}, ["..."]}
209+
end
210+
211+
test "next strict: missing value" do
212+
config = [switches: [str: :string, int: :integer, bool: :boolean], strict: true]
213+
assert OptionParser.next(["--str"], config)
214+
== {:error, {:value, :str, nil}, []}
215+
assert OptionParser.next(["--int"], config)
216+
== {:error, {:value, :int, nil}, []}
217+
assert OptionParser.next(["--bool=", "..."], config)
218+
== {:error, {:value, :bool, ""}, ["..."]}
219+
end
174220
end

0 commit comments

Comments
 (0)