Skip to content

Commit 965915b

Browse files
committed
Dont add [] for last arg keyword lists in tuples, lists and when/2
1 parent a711bef commit 965915b

File tree

2 files changed

+62
-26
lines changed

2 files changed

+62
-26
lines changed

lib/elixir/lib/macro.ex

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ defmodule Macro do
4949
end
5050

5151
@doc """
52-
Breaks a pipeline expression into a list.
53-
52+
Breaks a pipeline expression into a list.
53+
5454
Raises if the pipeline is ill-formed.
5555
"""
5656
@spec unpipe(Macro.t) :: [Macro.t]
@@ -152,8 +152,8 @@ defmodule Macro do
152152
end
153153

154154
@doc %S"""
155-
Unescape the given chars.
156-
155+
Unescape the given chars.
156+
157157
This is the unescaping behavior
158158
used by default in Elixir single- and double-quoted strings.
159159
Check `unescape_string/2` for information on how to customize
@@ -298,7 +298,14 @@ defmodule Macro do
298298

299299
# Tuple containers
300300
def to_string({ :{}, _, args } = ast, fun) do
301-
fun.(ast, "{" <> Enum.map_join(args, ", ", &to_string(&1, fun)) <> "}")
301+
if match?([_], args) do
302+
tuple = "{" <> Enum.map_join(args, ", ", &to_string(&1, fun)) <> "}"
303+
else
304+
args = args_to_string(args, fun)
305+
tuple = "{" <> args <> "}"
306+
end
307+
308+
fun.(ast, tuple)
302309
end
303310

304311
# Fn keyword
@@ -321,6 +328,17 @@ defmodule Macro do
321328
fun.(ast, "(" <> arrow_to_string(ast, fun, true) <> ")")
322329
end
323330

331+
# left when right
332+
def to_string({ :when, _, [left, right] } = ast, fun) do
333+
if right != [] and Keyword.keyword?(right) do
334+
right = kw_list_to_string(right, fun)
335+
else
336+
right = fun.(ast, op_to_string(right, fun, :when, :right))
337+
end
338+
339+
fun.(ast, op_to_string(left, fun, :when, :left) <> " when " <> right)
340+
end
341+
324342
# Binary ops
325343
def to_string({ op, _, [left, right] } = ast, fun) when op in @binary_ops do
326344
fun.(ast, op_to_string(left, fun, op, :left) <> " #{op} " <> op_to_string(right, fun, op, :right))
@@ -362,11 +380,15 @@ defmodule Macro do
362380

363381
# Lists
364382
def to_string(list, fun) when is_list(list) do
365-
if Keyword.keyword?(list) do
366-
fun.(list, "[" <> kw_list_to_string(list, fun) <> "]")
367-
else
368-
fun.(list, "[" <> Enum.map_join(list, ", ", &to_string(&1, fun)) <> "]")
369-
end
383+
fun.(list, cond do
384+
Keyword.keyword?(list) ->
385+
"[" <> kw_list_to_string(list, fun) <> "]"
386+
not match?([_], list) ->
387+
args = args_to_string(list, fun)
388+
"[" <> args <> "]"
389+
true ->
390+
"[" <> Enum.map_join(list, ", ", &to_string(&1, fun)) <> "]"
391+
end)
370392
end
371393

372394
# All other structures
@@ -389,18 +411,20 @@ defmodule Macro do
389411
defp call_to_string(other, fun), do: to_string(other, fun)
390412

391413
defp call_to_string_with_args(target, args, fun) do
392-
{ list, last } = :elixir_utils.split_last(args)
393414
target = call_to_string(target, fun)
415+
args = args_to_string(args, fun)
416+
target <> "(" <> args <> ")"
417+
end
394418

395-
case last != [] and Keyword.keyword?(last) do
396-
true ->
397-
args = Enum.map_join(list, ", ", &to_string(&1, fun))
398-
if list != [], do: args = args <> ", "
399-
args = args <> kw_list_to_string(last, fun)
400-
target <> "(" <> args <> ")"
401-
false ->
402-
args = Enum.map_join(args, ", ", &to_string(&1, fun))
403-
target <> "(" <> args <> ")"
419+
defp args_to_string(args, fun) do
420+
{ list, last } = :elixir_utils.split_last(args)
421+
422+
if last != [] and Keyword.keyword?(last) do
423+
args = Enum.map_join(list, ", ", &to_string(&1, fun))
424+
if list != [], do: args = args <> ", "
425+
args <> kw_list_to_string(last, fun)
426+
else
427+
Enum.map_join(args, ", ", &to_string(&1, fun))
404428
end
405429
end
406430

@@ -483,8 +507,8 @@ defmodule Macro do
483507
end
484508

485509
@doc """
486-
Receives an AST node and expands it once.
487-
510+
Receives an AST node and expands it once.
511+
488512
The following contents are expanded:
489513
490514
* Macros (local or remote);
@@ -665,8 +689,8 @@ defmodule Macro do
665689

666690
@doc """
667691
Receives an AST node and expands it until it no longer represents
668-
a macro.
669-
692+
a macro.
693+
670694
Check `expand_once/2` for more information on how
671695
expansion works.
672696
"""
@@ -715,7 +739,7 @@ defmodule Macro do
715739
@doc """
716740
Recursively traverses the quoted expression checking if all sub-terms are
717741
safe.
718-
742+
719743
Terms are considered safe if they represent data structures and don't actually
720744
evaluate code. Returns `:ok` unless a given term is unsafe,
721745
which is returned as `{ :unsafe, term }`.

lib/elixir/test/elixir/macro_test.exs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ defmodule MacroTest do
3939
test :escape_works_recursively do
4040
assert [1,{:{}, [], [:a,:b,:c]}, 3] == Macro.escape([1, { :a, :b, :c }, 3])
4141
end
42-
42+
4343
test :escape_improper do
4444
assert [{:|, [], [1,2]}] == Macro.escape([1|2])
4545
assert [1,{:|, [], [2,3]}] == Macro.escape([1,2|3])
@@ -330,6 +330,8 @@ defmodule MacroTest do
330330
end
331331

332332
test :containers_to_string do
333+
assert Macro.to_string(quote do: {}) == "{}"
334+
assert Macro.to_string(quote do: []) == "[]"
333335
assert Macro.to_string(quote do: { 1, 2, 3 }) == "{1, 2, 3}"
334336
assert Macro.to_string(quote do: [ 1, 2, 3 ]) == "[1, 2, 3]"
335337
assert Macro.to_string(quote do: << 1, 2, 3 >>) == "<<1, 2, 3>>"
@@ -366,10 +368,20 @@ defmodule MacroTest do
366368
end
367369

368370
test :last_arg_kw_list do
371+
assert Macro.to_string(quote do: foo([])) == "foo([])"
369372
assert Macro.to_string(quote do: foo(x: y)) == "foo(x: y)"
370373
assert Macro.to_string(quote do: foo(x: 1 + 2)) == "foo(x: 1 + 2)"
371374
assert Macro.to_string(quote do: foo(x: y, p: q)) == "foo(x: y, p: q)"
372375
assert Macro.to_string(quote do: foo(a, x: y, p: q)) == "foo(a, x: y, p: q)"
376+
377+
378+
assert Macro.to_string(quote do: { [] }) == "{[]}"
379+
assert Macro.to_string(quote do: { [a: b] }) == "{[a: b]}"
380+
assert Macro.to_string(quote do: { x, a: b }) == "{x, a: b}"
381+
assert Macro.to_string(quote do: []) == "[]"
382+
assert Macro.to_string(quote do: [a: b]) == "[a: b]"
383+
assert Macro.to_string(quote do: [[a: b]]) == "[[a: b]]"
384+
assert Macro.to_string(quote do: [x, a: b]) == "[x, a: b]"
373385
end
374386

375387
test :to_string_with_fun do

0 commit comments

Comments
 (0)