Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions lib/elixir/lib/code/normalizer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -347,14 +347,14 @@ defmodule Code.Normalizer do
args = normalize_args(args, %{state | parent_meta: meta})
{form, meta, args}

Keyword.has_key?(meta, :do) or match?([{{:__block__, _, [:do]}, _} | _], last) ->
Keyword.has_key?(meta, :do) ->
# def foo do :ok end
# def foo, do: :ok
normalize_kw_blocks(form, meta, args, state)

match?([{:do, _} | _], last) and Keyword.keyword?(last) ->
# Non normalized kw blocks
line = state.parent_meta[:line]
line = state.parent_meta[:line] || meta[:line]
meta = meta ++ [do: [line: line], end: [line: line]]
normalize_kw_blocks(form, meta, args, state)

Expand All @@ -364,10 +364,19 @@ defmodule Code.Normalizer do

last_args =
case last_arg do
{:__block__, _, [[{{:__block__, key_meta, _}, _} | _]] = last_args} ->
if key_meta[:format] == :keyword do
last_args
else
{:__block__, _meta, [[{{:__block__, key_meta, _}, _} | _] = keyword]} ->
cond do
key_meta[:format] == :keyword ->
[keyword]

block_keyword?(keyword) ->
[
Enum.map(keyword, fn {{:__block__, meta, args}, value} ->
{{:__block__, [format: :keyword] ++ meta, args}, value}
end)
]

true ->
[last_arg]
end

Expand All @@ -382,6 +391,12 @@ defmodule Code.Normalizer do
end
end

defp block_keyword?([{{:__block__, _, [key]}, _val} | tail]) when is_atom(key),
do: block_keyword?(tail)

defp block_keyword?([]), do: true
defp block_keyword?(_), do: false

defp allow_keyword?(:when, 2), do: true
defp allow_keyword?(:{}, _), do: false
defp allow_keyword?(op, arity), do: not is_atom(op) or not Macro.operator?(op, arity)
Expand Down
30 changes: 30 additions & 0 deletions lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,36 @@ defmodule Code.Normalizer.QuotedASTTest do
assert quoted_to_string(quote(do: foo |> [bar: :baz])) == "foo |> [bar: :baz]"
end

test "keyword arg with cursor" do
input = "def foo, do: :bar, __cursor__()"
expected = "def foo, [{:do, :bar}, __cursor__()]"

ast = Code.string_to_quoted!(input)
assert quoted_to_string(ast) == expected

encoder = &{:ok, {:__block__, &2, [&1]}}
ast = Code.string_to_quoted!(input, literal_encoder: encoder)
assert quoted_to_string(ast) == expected

ast = Code.string_to_quoted!(input, token_metadata: true)
assert quoted_to_string(ast) == expected

ast = Code.string_to_quoted!(input, literal_encoder: encoder, token_metadata: true)
assert quoted_to_string(ast) == expected
end

test "keyword arg with literal encoder and no metadata" do
input = """
foo(Bar) do
:ok
end
"""

encoder = &{:ok, {:__block__, &2, [&1]}}
ast = Code.string_to_quoted!(input, literal_encoder: encoder)
assert quoted_to_string(ast) == "foo(Bar, do: :ok)"
end

test "list in module attribute" do
assert quoted_to_string(
quote do
Expand Down
Loading