Skip to content

Commit

Permalink
Merge branch 'main' into me/docs
Browse files Browse the repository at this point in the history
  • Loading branch information
novaugust committed May 16, 2024
2 parents e857163 + da99d87 commit de4c83b
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 37 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ See the moduledoc for `Styler.Style.Configs` for more.
* `@derive`: move `@derive` before `defstruct|schema|embedded_schema` declarations (fixes compiler warning!) #134
* strings: rewrite double-quoted strings to use `~s` when there's 4+ escaped double-quotes
(`"\"\"\"\""` -> `~s("""")`) (`Credo.Check.Readability.StringSigils`) #146
* `Map.drop(foo, [single_key])` => `Map.delete(foo, single_key)` #161
* `Keyword.drop(foo, [single_key])` => `Keyword.delete(foo, single_key)` #161
* `Map.drop(foo, [single_key])` => `Map.delete(foo, single_key)` #161 (also in pipes)
* `Keyword.drop(foo, [single_key])` => `Keyword.delete(foo, single_key)` #161 (also in pipes)
* `lhs |> Enum.reverse() |> Kernel.++(enum)` => `lhs |> Enum.reverse(enum)`

### Fixes

Expand Down
21 changes: 11 additions & 10 deletions lib/style/pipes.ex
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,17 @@ defmodule Styler.Style.Pipes do
{:|>, [line: meta[:line]], [lhs, {reverse, [line: meta[:line]], [enum]}]}
end

# `lhs |> Enum.reverse() |> Enum.concat(enum)` => `lhs |> Enum.reverse(enum)`
defp fix_pipe(
pipe_chain(
lhs,
{{:., _, [{_, _, [:Enum]}, :reverse]} = reverse, meta, []},
{{:., _, [{_, _, [:Kernel]}, :++]}, _, [enum]}
)
) do
{:|>, [line: meta[:line]], [lhs, {reverse, [line: meta[:line]], [enum]}]}
end

# `lhs |> Enum.filter(filterer) |> Enum.count()` => `lhs |> Enum.count(count)`
defp fix_pipe(
pipe_chain(
Expand Down Expand Up @@ -285,16 +296,6 @@ defmodule Styler.Style.Pipes do
Style.set_line({:|>, [], [lhs, {new, nm, [mapper]}]}, nm[:line])
end

# lhs |> Map.merge(%{key: value}) => lhs |> Map.put(key, value)
defp fix_pipe({:|>, pm, [lhs, {{:., dm, [{_, _, [mod]} = module, :merge]}, m, [{:%{}, _, [{key, value}]}]}]})
when mod in [:Map, :Keyword],
do: {:|>, pm, [lhs, {{:., dm, [module, :put]}, m, [key, value]}]}

# lhs |> Map.merge(key: value) => lhs |> Map.put(:key, value)
defp fix_pipe({:|>, pm, [lhs, {{:., dm, [{_, _, [mod]} = module, :merge]}, m, [[{key, value}]]}]})
when mod in [:Map, :Keyword],
do: {:|>, pm, [lhs, {{:., dm, [module, :put]}, m, [key, value]}]}

defp fix_pipe(node), do: node

defp valid_pipe_start?({op, _, _}) when op in @special_ops, do: true
Expand Down
20 changes: 16 additions & 4 deletions lib/style/single_node.ex
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,29 @@ defmodule Styler.Style.SingleNode do
if new_collectable, do: {new_collectable, funm, [enum | rest]}, else: node
end

for mod <- [:Map, :Keyword] do
for m <- [:Map, :Keyword] do
# lhs |> Map.merge(%{key: value}) => lhs |> Map.put(key, value)
defp style({:|>, pm, [lhs, {{:., dm, [{_, _, [unquote(m)]} = module, :merge]}, m, [{:%{}, _, [{key, value}]}]}]}),
do: {:|>, pm, [lhs, {{:., dm, [module, :put]}, m, [key, value]}]}

# lhs |> Map.merge(key: value) => lhs |> Map.put(:key, value)
defp style({:|>, pm, [lhs, {{:., dm, [{_, _, [unquote(m)]} = module, :merge]}, m, [[{key, value}]]}]}),
do: {:|>, pm, [lhs, {{:., dm, [module, :put]}, m, [key, value]}]}

# Map.merge(foo, %{one_key: :bar}) => Map.put(foo, :one_key, :bar)
defp style({{:., dm, [{_, _, [unquote(mod)]} = module, :merge]}, m, [lhs, {:%{}, _, [{key, value}]}]}),
defp style({{:., dm, [{_, _, [unquote(m)]} = module, :merge]}, m, [lhs, {:%{}, _, [{key, value}]}]}),
do: {{:., dm, [module, :put]}, m, [lhs, key, value]}

# Map.merge(foo, one_key: :bar) => Map.put(foo, :one_key, :bar)
defp style({{:., dm, [{_, _, [unquote(mod)]} = module, :merge]}, m, [lhs, [{key, value}]]}),
defp style({{:., dm, [{_, _, [unquote(m)]} = module, :merge]}, m, [lhs, [{key, value}]]}),
do: {{:., dm, [module, :put]}, m, [lhs, key, value]}

# lhs |> Map.drop([key]) => lhs |> Map.delete(key)
defp style({:|>, pm, [lhs, {{:., dm, [{_, _, [unquote(m)]} = module, :drop]}, m, [{:__block__, _, [[key]]}]}]}),
do: {:|>, pm, [lhs, {{:., dm, [module, :delete]}, m, [key]}]}

# Map.drop(foo, [one_key]) => Map.delete(foo, one_key)
defp style({{:., dm, [{_, _, [unquote(mod)]} = module, :drop]}, m, [lhs, {:__block__, _, [[key]]}]}),
defp style({{:., dm, [{_, _, [unquote(m)]} = module, :drop]}, m, [lhs, {:__block__, _, [[key]]}]}),
do: {{:., dm, [module, :delete]}, m, [lhs, key]}
end

Expand Down
6 changes: 0 additions & 6 deletions test/style/pipes_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -482,12 +482,6 @@ defmodule Styler.Style.PipesTest do
end

describe "simple rewrites" do
test "{Keyword/Map}.merge/2 of a single key => *.put/3" do
for module <- ~w(Map Keyword) do
assert_style("foo |> #{module}.merge(%{one_key: :bar}) |> bop()", "foo |> #{module}.put(:one_key, :bar) |> bop()")
end
end

test "rewrites anon fun def ahd invoke to use then" do
assert_style("a |> (& &1).()", "then(a, & &1)")
assert_style("a |> (& {&1, &2}).(b)", "(&{&1, &2}).(a, b)")
Expand Down
50 changes: 35 additions & 15 deletions test/style/single_node_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -27,24 +27,44 @@ defmodule Styler.Style.SingleNodeTest do
assert_style ~s/"\\"\\"\\"\\" \/>']|})"/, ~s|~s("""" />']\|}\\))|
end

test "{Map/Keyword}.merge with a single static key" do
for module <- ~w(Map Keyword) do
assert_style("#{module}.merge(foo, %{one_key: :bar})", "#{module}.put(foo, :one_key, :bar)")
assert_style("#{module}.merge(foo, one_key: :bar)", "#{module}.put(foo, :one_key, :bar)")
# # doesn't rewrite if there's a custom merge strategy
assert_style("#{module}.merge(foo, %{one_key: :bar}, custom_merge_strategy)")
# # doesn't rewrite if > 1 key
assert_style("#{module}.merge(foo, %{a: :b, c: :d})")
describe "{Keyword/Map}.merge/2 of a single key => *.put/3" do
test "in a pipe" do
for module <- ~w(Map Keyword) do
assert_style("foo |> #{module}.merge(%{one_key: :bar}) |> bop()", "foo |> #{module}.put(:one_key, :bar) |> bop()")
end
end

test "normal call" do
for module <- ~w(Map Keyword) do
assert_style("#{module}.merge(foo, %{one_key: :bar})", "#{module}.put(foo, :one_key, :bar)")
assert_style("#{module}.merge(foo, one_key: :bar)", "#{module}.put(foo, :one_key, :bar)")
# # doesn't rewrite if there's a custom merge strategy
assert_style("#{module}.merge(foo, %{one_key: :bar}, custom_merge_strategy)")
# # doesn't rewrite if > 1 key
assert_style("#{module}.merge(foo, %{a: :b, c: :d})")
end
end
end

test "{Map/Keyword}.drop with a single key" do
for module <- ~w(Map Keyword) do
assert_style("#{module}.drop(foo, [key])", "#{module}.delete(foo, key)")
assert_style("#{module}.drop(foo, [:key])", "#{module}.delete(foo, :key)")
assert_style("#{module}.drop(foo, [])")
assert_style("#{module}.drop(foo, [a, b])")
assert_style("#{module}.drop(foo, keys)")
describe "{Map/Keyword}.drop with a single key" do
test "in a pipe" do
for module <- ~w(Map Keyword) do
assert_style("foo |> #{module}.drop([key]) |> bar()", "foo |> #{module}.delete(key) |> bar()")
assert_style("foo |> #{module}.drop([:key]) |> bar()", "foo |> #{module}.delete(:key) |> bar()")
assert_style("foo |> #{module}.drop([]) |> bar()")
assert_style("foo |> #{module}.drop([a, b]) |> bar()")
assert_style("foo |> #{module}.drop(keys) |> bar()")
end
end

test "normal call" do
for module <- ~w(Map Keyword) do
assert_style("#{module}.drop(foo, [key])", "#{module}.delete(foo, key)")
assert_style("#{module}.drop(foo, [:key])", "#{module}.delete(foo, :key)")
assert_style("#{module}.drop(foo, [])")
assert_style("#{module}.drop(foo, [a, b])")
assert_style("#{module}.drop(foo, keys)")
end
end
end

Expand Down

0 comments on commit de4c83b

Please sign in to comment.