Skip to content

Commit 2e4aa9f

Browse files
committed
Add :migrate_call_parens_on_pipe formatter option
1 parent e3bbef3 commit 2e4aa9f

File tree

3 files changed

+59
-1
lines changed

3 files changed

+59
-1
lines changed

lib/elixir/lib/code.ex

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,13 @@ defmodule Code do
696696
modifiers, where `<<foo::custom_type>>` becomes `<<foo::custom_type()>>`.
697697
Defaults to the value of the `:migrate` option. This option changes the AST.
698698
699+
* `:migrate_call_parens_on_pipe` (since v1.19.0) - when `true`,
700+
formats local calls on the right-hand side of the pipe operator to always
701+
include parentheses, for example `foo |> bar` becomes `foo |> bar()`.
702+
Parentheses are always added for qualified calls like `foo |> Bar.bar`
703+
disregarding of this option.
704+
Defaults to the value of the `:migrate` option. This option changes the AST.
705+
699706
* `:migrate_charlists_as_sigils` (since v1.18.0) - when `true`,
700707
formats charlists as [`~c`](`Kernel.sigil_c/2`) sigils, for example
701708
`'foo'` becomes `~c"foo"`.

lib/elixir/lib/code/formatter.ex

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ defmodule Code.Formatter do
191191
sigils = Keyword.get(opts, :sigils, [])
192192
migrate = Keyword.get(opts, :migrate, false)
193193
migrate_bitstring_modifiers = Keyword.get(opts, :migrate_bitstring_modifiers, migrate)
194+
migrate_call_parens_on_pipe = Keyword.get(opts, :migrate_call_parens_on_pipe, migrate)
194195
migrate_charlists_as_sigils = Keyword.get(opts, :migrate_charlists_as_sigils, migrate)
195196
migrate_unless = Keyword.get(opts, :migrate_unless, migrate)
196197
syntax_colors = Keyword.get(opts, :syntax_colors, [])
@@ -218,6 +219,7 @@ defmodule Code.Formatter do
218219
sigils: sigils,
219220
file: file,
220221
migrate_bitstring_modifiers: migrate_bitstring_modifiers,
222+
migrate_call_parens_on_pipe: migrate_call_parens_on_pipe,
221223
migrate_charlists_as_sigils: migrate_charlists_as_sigils,
222224
migrate_unless: migrate_unless,
223225
inspect_opts: %Inspect.Opts{syntax_colors: syntax_colors}
@@ -487,7 +489,16 @@ defmodule Code.Formatter do
487489
binary_op_to_algebra(:in, "not in", meta, left, right, context, state)
488490
end
489491

490-
# disable migrate_unless within defmacro
492+
# disable migrate_call_parens_on_pipe within defmacro
493+
defp quoted_to_algebra(
494+
{atom, _, [{:|>, _, _}, _]} = ast,
495+
context,
496+
%{migrate_call_parens_on_pipe: true} = state
497+
)
498+
when atom in [:defmacro, :defmacrop] do
499+
quoted_to_algebra(ast, context, %{state | migrate_call_parens_on_pipe: false})
500+
end
501+
491502
defp quoted_to_algebra(
492503
{atom, _, [{:unless, _, _}, _]} = ast,
493504
context,
@@ -832,6 +843,20 @@ defmodule Code.Formatter do
832843
{wrap_in_parens(doc), state}
833844
end
834845

846+
defp binary_operand_to_algebra(
847+
{var, meta, atom},
848+
context,
849+
%{migrate_call_parens_on_pipe: true} = state,
850+
:|>,
851+
_parent_info,
852+
:right,
853+
_nesting
854+
)
855+
when is_atom(var) and is_atom(atom) do
856+
operand = {var, meta, []}
857+
quoted_to_algebra(operand, context, state)
858+
end
859+
835860
defp binary_operand_to_algebra(operand, context, state, parent_op, parent_info, side, nesting) do
836861
{parent_assoc, parent_prec} = parent_info
837862

lib/elixir/test/elixir/code_formatter/migration_test.exs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,24 @@ defmodule Code.Formatter.MigrationTest do
2727
end
2828
end
2929

30+
describe "migrate_call_parens_on_pipe: true" do
31+
@opts [migrate_call_parens_on_pipe: true]
32+
33+
test "adds parentheses on the right operand" do
34+
assert_format "x |> y", "x |> y()", @opts
35+
assert_format "x |> y |> z", "x |> y() |> z()", @opts
36+
end
37+
38+
test "does nothing within defmacro" do
39+
assert_same "defmacro left |> right, do: ...", @opts
40+
end
41+
42+
test "does nothing without the migrate_unless option" do
43+
assert_same "x |> y"
44+
assert_same "x |> y |> z"
45+
end
46+
end
47+
3048
describe "migrate_charlists_as_sigils: true" do
3149
@opts [migrate_charlists_as_sigils: true]
3250

@@ -281,6 +299,14 @@ defmodule Code.Formatter.MigrationTest do
281299
assert_format "<<foo::binary()>>", "<<foo::binary>>", migrate: true
282300
end
283301

302+
test "enables :migrate_call_parens_on_pipe" do
303+
bad = "x |> y"
304+
305+
good = "x |> y()"
306+
307+
assert_format bad, good, migrate: true
308+
end
309+
284310
test "enables :migrate_charlists_as_sigils" do
285311
assert_format ~S['abc'], ~S[~c"abc"], migrate: true
286312
end

0 commit comments

Comments
 (0)