Skip to content

Commit 984495f

Browse files
author
José Valim
committed
Preserve user choice on calls without parens when we have one arg per line
Signed-off-by: José Valim <[email protected]>
1 parent a0d5c4f commit 984495f

File tree

3 files changed

+93
-54
lines changed

3 files changed

+93
-54
lines changed

lib/elixir/lib/code.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -343,14 +343,14 @@ defmodule Code do
343343
344344
[foo, bar]
345345
346-
You can also force keywords to be rendered on multiple lines by
347-
having each entry on its own line:
346+
You can also force function calls and keywords to be rendered on multiple
347+
lines by having each entry on its own line:
348348
349349
defstruct name: nil,
350350
age: 0
351351
352352
The code above will be kept with one keyword entry per line by the
353-
formatter. To avoid that, just keep everything on a single line.
353+
formatter. To avoid that, just squash everything into a single line.
354354
355355
### Parens and no parens in function calls
356356

lib/elixir/lib/code/formatter.ex

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -420,11 +420,11 @@ defmodule Code.Formatter do
420420
# {}
421421
# {1, 2}
422422
defp quoted_to_algebra({:{}, meta, args}, _context, state) do
423-
tuple_to_algebra(meta, args, :flex_glue, state)
423+
tuple_to_algebra(meta, args, :flex_break, state)
424424
end
425425

426426
defp quoted_to_algebra({:__block__, meta, [{left, right}]}, _context, state) do
427-
tuple_to_algebra(meta, [left, right], :flex_glue, state)
427+
tuple_to_algebra(meta, [left, right], :flex_break, state)
428428
end
429429

430430
defp quoted_to_algebra({:__block__, meta, [list]}, _context, state) when is_list(list) do
@@ -960,7 +960,7 @@ defmodule Code.Formatter do
960960
# expression.{arguments}
961961
defp remote_to_algebra({{:., _, [target, :{}]}, meta, args}, _context, state) do
962962
{target_doc, state} = remote_target_to_algebra(target, state)
963-
{call_doc, state} = tuple_to_algebra(meta, args, :glue, state)
963+
{call_doc, state} = tuple_to_algebra(meta, args, :break, state)
964964
{concat(concat(target_doc, "."), call_doc), state}
965965
end
966966

@@ -1087,7 +1087,7 @@ defmodule Code.Formatter do
10871087
#
10881088
defp call_args_to_algebra([], meta, _context, _parens, _list_to_keyword?, state) do
10891089
{args_doc, _join, state} =
1090-
args_to_algebra_with_comments([], meta, false, :none, :glue, state, &{&1, &2})
1090+
args_to_algebra_with_comments([], meta, false, :none, :break, state, &{&1, &2})
10911091

10921092
{{surround("(", args_doc, ")"), state}, false}
10931093
end
@@ -1121,7 +1121,6 @@ defmodule Code.Formatter do
11211121

11221122
defp call_args_to_algebra_no_blocks(meta, args, skip_parens?, list_to_keyword?, extra, state) do
11231123
{left, right} = split_last(args)
1124-
generators_count = count_generators(args)
11251124
{keyword?, right} = last_arg_to_keyword(right, list_to_keyword?)
11261125

11271126
context =
@@ -1131,15 +1130,14 @@ defmodule Code.Formatter do
11311130
if skip_parens?, do: :no_parens_arg, else: :parens_arg
11321131
end
11331132

1134-
if left != [] and keyword? and skip_parens? and generators_count == 0 do
1133+
if left != [] and keyword? and skip_parens? and no_generators?(args) do
11351134
call_args_to_algebra_with_no_parens_keywords(meta, left, right, context, extra, state)
11361135
else
1137-
force_keyword? = keyword? and force_keyword?(right)
1138-
non_empty_eol? = left != [] and Keyword.get(meta, :eol, false)
1139-
join = if generators_count > 1 or force_keyword? or non_empty_eol?, do: :line, else: :glue
11401136
args = if keyword?, do: left ++ right, else: left ++ [right]
1137+
many_eol? = match?([_, _ | _], args) and Keyword.get(meta, :eol, false)
1138+
join = if force_args?(args) or many_eol?, do: :line, else: :break
11411139

1142-
next_break_fits? = join == :glue and next_break_fits?(right, state)
1140+
next_break_fits? = join == :break and next_break_fits?(right, state)
11431141
last_arg_mode = if next_break_fits?, do: :next_break_fits, else: :none
11441142

11451143
{args_doc, _join, state} =
@@ -1181,14 +1179,17 @@ defmodule Code.Formatter do
11811179

11821180
defp call_args_to_algebra_with_no_parens_keywords(meta, left, right, context, extra, state) do
11831181
to_algebra_fun = &quoted_to_algebra(&1, context, &2)
1182+
join = if force_args?(left), do: :line, else: :break
11841183

11851184
{left_doc, _join, state} =
1186-
args_to_algebra_with_comments(left, meta, true, :force_comma, :glue, state, to_algebra_fun)
1185+
args_to_algebra_with_comments(left, meta, true, :force_comma, join, state, to_algebra_fun)
1186+
1187+
join = if force_args?(right) or force_args?(left ++ right), do: :line, else: :break
11871188

11881189
{right_doc, _join, state} =
1189-
args_to_algebra_with_comments(right, meta, false, :none, :glue, state, to_algebra_fun)
1190+
args_to_algebra_with_comments(right, meta, false, :none, join, state, to_algebra_fun)
11901191

1191-
right_doc = break() |> concat(right_doc) |> force_keyword(right) |> group(:inherit)
1192+
right_doc = apply(Inspect.Algebra, join, []) |> concat(right_doc) |> group(:inherit)
11921193

11931194
doc =
11941195
with_next_break_fits(true, right_doc, fn right_doc ->
@@ -1213,8 +1214,8 @@ defmodule Code.Formatter do
12131214
end)
12141215
end
12151216

1216-
defp count_generators(args) do
1217-
Enum.count(args, &match?({:<-, _, [_, _]}, &1))
1217+
defp no_generators?(args) do
1218+
not Enum.any?(args, &match?({:<-, _, [_, _]}, &1))
12181219
end
12191220

12201221
defp do_end_blocks([{{:__block__, meta, [:do]}, _} | _] = blocks) do
@@ -1326,15 +1327,15 @@ defmodule Code.Formatter do
13261327

13271328
defp bitstring_to_algebra(meta, args, state) do
13281329
last = length(args) - 1
1329-
join = if Keyword.get(meta, :eol, false), do: :line, else: :flex_glue
1330+
join = if Keyword.get(meta, :eol, false), do: :line, else: :flex_break
13301331
to_algebra_fun = &bitstring_segment_to_algebra(&1, &2, last)
13311332

13321333
{args_doc, join, state} =
13331334
args
13341335
|> Enum.with_index()
13351336
|> args_to_algebra_with_comments(meta, false, :none, join, state, to_algebra_fun)
13361337

1337-
if join == :flex_glue do
1338+
if join == :flex_break do
13381339
{"<<" |> concat(args_doc) |> nest(2) |> concat(">>") |> group(), state}
13391340
else
13401341
{surround("<<", args_doc, ">>"), state}
@@ -1387,7 +1388,7 @@ defmodule Code.Formatter do
13871388
## Literals
13881389

13891390
defp list_to_algebra(meta, args, state) do
1390-
join = if Keyword.get(meta, :eol, false), do: :line, else: :glue
1391+
join = if Keyword.get(meta, :eol, false), do: :line, else: :break
13911392
fun = &quoted_to_algebra(&1, :parens_arg, &2)
13921393

13931394
{args_doc, _join, state} =
@@ -1397,7 +1398,7 @@ defmodule Code.Formatter do
13971398
end
13981399

13991400
defp map_to_algebra(meta, name_doc, [{:|, _, [left, right]}], state) do
1400-
join = if Keyword.get(meta, :eol, false), do: :line, else: :glue
1401+
join = if Keyword.get(meta, :eol, false), do: :line, else: :break
14011402
fun = &quoted_to_algebra(&1, :parens_arg, &2)
14021403
{left_doc, state} = fun.(left, state)
14031404

@@ -1414,7 +1415,7 @@ defmodule Code.Formatter do
14141415
end
14151416

14161417
defp map_to_algebra(meta, name_doc, args, state) do
1417-
join = if Keyword.get(meta, :eol, false), do: :line, else: :glue
1418+
join = if Keyword.get(meta, :eol, false), do: :line, else: :break
14181419
fun = &quoted_to_algebra(&1, :parens_arg, &2)
14191420

14201421
{args_doc, _join, state} =
@@ -1431,7 +1432,7 @@ defmodule Code.Formatter do
14311432
{args_doc, join, state} =
14321433
args_to_algebra_with_comments(args, meta, false, :none, join, state, fun)
14331434

1434-
if join == :flex_glue do
1435+
if join == :flex_break do
14351436
{"{" |> concat(args_doc) |> nest(1) |> concat("}") |> group(), state}
14361437
else
14371438
{surround("{", args_doc, "}"), state}
@@ -1579,11 +1580,11 @@ defmodule Code.Formatter do
15791580
join == :line or comments? ->
15801581
{args_docs |> Enum.reduce(&line(&2, &1)) |> force_unfit(), :line, state}
15811582

1582-
join == :glue ->
1583-
{args_docs |> Enum.reduce(&glue(&2, &1)), :glue, state}
1583+
join == :break ->
1584+
{args_docs |> Enum.reduce(&glue(&2, &1)), :break, state}
15841585

1585-
join == :flex_glue ->
1586-
{args_docs |> Enum.reduce(&flex_glue(&2, &1)), :flex_glue, state}
1586+
join == :flex_break ->
1587+
{args_docs |> Enum.reduce(&flex_glue(&2, &1)), :flex_break, state}
15871588
end
15881589
end
15891590

@@ -1766,7 +1767,7 @@ defmodule Code.Formatter do
17661767
fun = &clause_args_to_algebra/2
17671768

17681769
{args_docs, _join, state} =
1769-
args_to_algebra_with_comments([args], meta, false, :none, :glue, state, fun)
1770+
args_to_algebra_with_comments([args], meta, false, :none, :break, state, fun)
17701771

17711772
{args_docs, state}
17721773
end
@@ -2083,26 +2084,32 @@ defmodule Code.Formatter do
20832084
{false, arg}
20842085
end
20852086

2086-
defp force_keyword?(keyword) do
2087-
match?([{_, _}, _ | _], keyword) and force_keyword?(keyword, MapSet.new())
2087+
defp force_args?(args) do
2088+
match?([_, _ | _], args) and force_args?(args, MapSet.new())
2089+
end
2090+
2091+
defp force_args?([[arg | _] | args], lines) do
2092+
force_args?([arg | args], lines)
20882093
end
20892094

2090-
defp force_keyword?([{{_, meta, _}, _} | keyword], lines) do
2091-
line = line(meta)
2095+
defp force_args?([arg | args], lines) do
2096+
line =
2097+
case arg do
2098+
{{_, meta, _}, _} -> line(meta)
2099+
{_, meta, _} -> line(meta)
2100+
end
20922101

20932102
if MapSet.member?(lines, line) do
20942103
false
20952104
else
2096-
force_keyword?(keyword, MapSet.put(lines, line))
2105+
force_args?(args, MapSet.put(lines, line))
20972106
end
20982107
end
20992108

2100-
defp force_keyword?([], _lines) do
2101-
true
2102-
end
2109+
defp force_args?([], _lines), do: true
21032110

21042111
defp force_keyword(doc, arg) do
2105-
if force_keyword?(arg), do: force_unfit(doc), else: doc
2112+
if force_args?(arg), do: force_unfit(doc), else: doc
21062113
end
21072114

21082115
defp keyword?([{key, _} | list]) do

lib/elixir/test/elixir/code_formatter/calls_test.exs

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@ defmodule Code.Formatter.CallsTest do
218218

219219
test "with keyword lists" do
220220
assert_same "foo(foo: 1, bar: 2)"
221-
222221
assert_same "foo(:hello, foo: 1, bar: 2)"
223222

224223
bad = """
@@ -235,8 +234,14 @@ defmodule Code.Formatter.CallsTest do
235234

236235
assert_format bad, good, @short_length
237236

238-
# Check it preserves multiline.
239-
assert_same good
237+
bad = """
238+
foo(:hello, foo: 1,
239+
bar: 2)
240+
"""
241+
242+
assert_format bad, """
243+
foo(:hello, foo: 1, bar: 2)
244+
"""
240245
end
241246

242247
test "with lists maybe rewritten as keyword lists" do
@@ -250,21 +255,19 @@ defmodule Code.Formatter.CallsTest do
250255
assert_same "bar = if foo, do: bar, else: baz"
251256

252257
assert_same """
253-
for :one,
254-
:two,
255-
:three,
256-
fn ->
257-
:ok
258-
end
259-
""",
260-
@short_length
258+
for :one,
259+
:two,
260+
:three,
261+
fn ->
262+
:ok
263+
end
264+
"""
261265

262266
assert_same """
263-
for :one, fn ->
264-
:ok
265-
end
266-
""",
267-
@medium_length
267+
for :one, fn ->
268+
:ok
269+
end
270+
"""
268271
end
269272

270273
test "without parens on line limit" do
@@ -301,6 +304,35 @@ defmodule Code.Formatter.CallsTest do
301304
"""
302305

303306
assert_same """
307+
config :app,
308+
foo: 1
309+
"""
310+
311+
assert_same """
312+
config :app,
313+
foo: 1,
314+
bar: 2
315+
"""
316+
317+
assert_same """
318+
config :app, :key,
319+
foo: 1,
320+
bar: 2
321+
"""
322+
323+
assert_same """
324+
config :app,
325+
:key,
326+
foo: 1,
327+
bar: 2
328+
"""
329+
330+
bad = """
331+
config :app, foo: 1,
332+
bar: 2
333+
"""
334+
335+
assert_format bad, """
304336
config :app,
305337
foo: 1,
306338
bar: 2

0 commit comments

Comments
 (0)