Skip to content

Commit 8cb6abf

Browse files
authored
Formatter fix: next_break_fits respects line_length (#13792)
* Refactor fits to return :fit | :no_fit * Formatter fix: next_break_fits respects line_length
1 parent 7bfe5ca commit 8cb6abf

File tree

3 files changed

+66
-48
lines changed

3 files changed

+66
-48
lines changed

lib/elixir/lib/inspect/algebra.ex

+58-46
Original file line numberDiff line numberDiff line change
@@ -973,20 +973,17 @@ defmodule Inspect.Algebra do
973973
#
974974
# * flat - represents a document with breaks as flats (a break may fit, as it may break)
975975
# * break - represents a document with breaks as breaks (a break always fits, since it breaks)
976-
#
977-
# The following modes are exclusive to fitting:
978-
#
979976
# * flat_no_break - represents a document with breaks as flat not allowed to enter in break mode
980977
# * break_no_flat - represents a document with breaks as breaks not allowed to enter in flat mode
981978
#
982979
@typep mode :: :flat | :flat_no_break | :break | :break_no_flat
983980

984-
@spec fits?(
981+
@spec fits(
985982
width :: non_neg_integer() | :infinity,
986983
column :: non_neg_integer(),
987984
break? :: boolean(),
988985
entries
989-
) :: boolean()
986+
) :: :fit | :no_fit | :break_next
990987
when entries:
991988
maybe_improper_list({integer(), mode(), t()}, {:tail, boolean(), entries} | [])
992989

@@ -995,63 +992,68 @@ defmodule Inspect.Algebra do
995992
#
996993
# In case we have groups and the group fits, we need to consider the group
997994
# parent without the child breaks, hence {:tail, b?, t} below.
998-
defp fits?(w, k, b?, _) when k > w and b?, do: false
999-
defp fits?(_, _, _, []), do: true
1000-
defp fits?(w, k, _, {:tail, b?, t}), do: fits?(w, k, b?, t)
995+
defp fits(w, k, b?, _) when k > w and b?, do: :no_fit
996+
defp fits(_, _, _, []), do: :fit
997+
defp fits(w, k, _, {:tail, b?, t}), do: fits(w, k, b?, t)
1001998

1002999
## Flat no break
10031000

1004-
defp fits?(w, k, b?, [{i, _, doc_fits(x, :disabled)} | t]),
1005-
do: fits?(w, k, b?, [{i, :flat_no_break, x} | t])
1001+
defp fits(w, k, b?, [{i, _, doc_fits(x, :disabled)} | t]),
1002+
do: fits(w, k, b?, [{i, :flat_no_break, x} | t])
10061003

1007-
defp fits?(w, k, b?, [{i, :flat_no_break, doc_fits(x, _)} | t]),
1008-
do: fits?(w, k, b?, [{i, :flat_no_break, x} | t])
1004+
defp fits(w, k, b?, [{i, :flat_no_break, doc_fits(x, _)} | t]),
1005+
do: fits(w, k, b?, [{i, :flat_no_break, x} | t])
10091006

10101007
## Breaks no flat
10111008

1012-
defp fits?(w, k, b?, [{i, _, doc_fits(x, :enabled)} | t]),
1013-
do: fits?(w, k, b?, [{i, :break_no_flat, x} | t])
1009+
defp fits(w, k, b?, [{i, _, doc_fits(x, :enabled)} | t]),
1010+
do: fits(w, k, b?, [{i, :break_no_flat, x} | t])
10141011

1015-
defp fits?(w, k, b?, [{i, :break_no_flat, doc_force(x)} | t]),
1016-
do: fits?(w, k, b?, [{i, :break_no_flat, x} | t])
1012+
defp fits(w, k, b?, [{i, :break_no_flat, doc_force(x)} | t]),
1013+
do: fits(w, k, b?, [{i, :break_no_flat, x} | t])
10171014

1018-
defp fits?(_, _, _, [{_, :break_no_flat, doc_break(_, _)} | _]), do: true
1019-
defp fits?(_, _, _, [{_, :break_no_flat, :doc_line} | _]), do: true
1015+
defp fits(w, k, b?, [{i, :break_no_flat, x} | t])
1016+
when x == :doc_line or (is_tuple(x) and elem(x, 0) == :doc_break) do
1017+
case fits(w, k, b?, [{i, :flat, x} | t]) do
1018+
:no_fit -> :break_next
1019+
fits -> fits
1020+
end
1021+
end
10201022

10211023
## Breaks
10221024

1023-
defp fits?(_, _, _, [{_, :break, doc_break(_, _)} | _]), do: true
1024-
defp fits?(_, _, _, [{_, :break, :doc_line} | _]), do: true
1025+
defp fits(_, _, _, [{_, :break, doc_break(_, _)} | _]), do: :fit
1026+
defp fits(_, _, _, [{_, :break, :doc_line} | _]), do: :fit
10251027

1026-
defp fits?(w, k, b?, [{i, :break, doc_group(x, _)} | t]),
1027-
do: fits?(w, k, b?, [{i, :flat, x} | {:tail, b?, t}])
1028+
defp fits(w, k, b?, [{i, :break, doc_group(x, _)} | t]),
1029+
do: fits(w, k, b?, [{i, :flat, x} | {:tail, b?, t}])
10281030

10291031
## Catch all
10301032

1031-
defp fits?(w, _, _, [{i, _, :doc_line} | t]), do: fits?(w, i, false, t)
1032-
defp fits?(w, k, b?, [{_, _, :doc_nil} | t]), do: fits?(w, k, b?, t)
1033-
defp fits?(w, _, b?, [{i, _, doc_collapse(_)} | t]), do: fits?(w, i, b?, t)
1034-
defp fits?(w, k, b?, [{i, m, doc_color(x, _)} | t]), do: fits?(w, k, b?, [{i, m, x} | t])
1035-
defp fits?(w, k, b?, [{_, _, doc_string(_, l)} | t]), do: fits?(w, k + l, b?, t)
1036-
defp fits?(w, k, b?, [{_, _, s} | t]) when is_binary(s), do: fits?(w, k + byte_size(s), b?, t)
1037-
defp fits?(_, _, _, [{_, _, doc_force(_)} | _]), do: false
1038-
defp fits?(w, k, _, [{_, _, doc_break(s, _)} | t]), do: fits?(w, k + byte_size(s), true, t)
1039-
defp fits?(w, k, b?, [{i, m, doc_nest(x, _, :break)} | t]), do: fits?(w, k, b?, [{i, m, x} | t])
1033+
defp fits(w, _, _, [{i, _, :doc_line} | t]), do: fits(w, i, false, t)
1034+
defp fits(w, k, b?, [{_, _, :doc_nil} | t]), do: fits(w, k, b?, t)
1035+
defp fits(w, _, b?, [{i, _, doc_collapse(_)} | t]), do: fits(w, i, b?, t)
1036+
defp fits(w, k, b?, [{i, m, doc_color(x, _)} | t]), do: fits(w, k, b?, [{i, m, x} | t])
1037+
defp fits(w, k, b?, [{_, _, doc_string(_, l)} | t]), do: fits(w, k + l, b?, t)
1038+
defp fits(w, k, b?, [{_, _, s} | t]) when is_binary(s), do: fits(w, k + byte_size(s), b?, t)
1039+
defp fits(_, _, _, [{_, _, doc_force(_)} | _]), do: :no_fit
1040+
defp fits(w, k, _, [{_, _, doc_break(s, _)} | t]), do: fits(w, k + byte_size(s), true, t)
1041+
defp fits(w, k, b?, [{i, m, doc_nest(x, _, :break)} | t]), do: fits(w, k, b?, [{i, m, x} | t])
10401042

1041-
defp fits?(w, k, b?, [{i, m, doc_nest(x, j, _)} | t]),
1042-
do: fits?(w, k, b?, [{apply_nesting(i, k, j), m, x} | t])
1043+
defp fits(w, k, b?, [{i, m, doc_nest(x, j, _)} | t]),
1044+
do: fits(w, k, b?, [{apply_nesting(i, k, j), m, x} | t])
10431045

1044-
defp fits?(w, k, b?, [{i, m, doc_cons(x, y)} | t]),
1045-
do: fits?(w, k, b?, [{i, m, x}, {i, m, y} | t])
1046+
defp fits(w, k, b?, [{i, m, doc_cons(x, y)} | t]),
1047+
do: fits(w, k, b?, [{i, m, x}, {i, m, y} | t])
10461048

1047-
defp fits?(w, k, b?, [{i, m, doc_group(x, _)} | t]),
1048-
do: fits?(w, k, b?, [{i, m, x} | {:tail, b?, t}])
1049+
defp fits(w, k, b?, [{i, m, doc_group(x, _)} | t]),
1050+
do: fits(w, k, b?, [{i, m, x} | {:tail, b?, t}])
10491051

1050-
defp fits?(w, k, b?, [{i, m, doc_limit(x, :infinity)} | t]) when w != :infinity,
1051-
do: fits?(:infinity, k, b?, [{i, :flat, x}, {i, m, doc_limit(empty(), w)} | t])
1052+
defp fits(w, k, b?, [{i, m, doc_limit(x, :infinity)} | t]) when w != :infinity,
1053+
do: fits(:infinity, k, b?, [{i, :flat, x}, {i, m, doc_limit(empty(), w)} | t])
10521054

1053-
defp fits?(_w, k, b?, [{i, m, doc_limit(x, w)} | t]),
1054-
do: fits?(w, k, b?, [{i, m, x} | t])
1055+
defp fits(_w, k, b?, [{i, m, doc_limit(x, w)} | t]),
1056+
do: fits(w, k, b?, [{i, m, x} | t])
10551057

10561058
@spec format(
10571059
width :: non_neg_integer() | :infinity,
@@ -1066,14 +1068,18 @@ defmodule Inspect.Algebra do
10661068
defp format(w, k, [{_, _, doc_string(s, l)} | t]), do: [s | format(w, k + l, t)]
10671069
defp format(w, k, [{_, _, s} | t]) when is_binary(s), do: [s | format(w, k + byte_size(s), t)]
10681070
defp format(w, k, [{i, m, doc_force(x)} | t]), do: format(w, k, [{i, m, x} | t])
1071+
1072+
defp format(w, k, [{i, :flat_no_break, doc_fits(x, :enabled)} | t]),
1073+
do: format(w, k, [{i, :break_no_flat, x} | t])
1074+
10691075
defp format(w, k, [{i, m, doc_fits(x, _)} | t]), do: format(w, k, [{i, m, x} | t])
10701076
defp format(w, _, [{i, _, doc_collapse(max)} | t]), do: collapse(format(w, i, t), max, 0, i)
10711077

10721078
# Flex breaks are not conditional to the mode
10731079
defp format(w, k, [{i, m, doc_break(s, :flex)} | t]) do
10741080
k = k + byte_size(s)
10751081

1076-
if w == :infinity or m == :flat or fits?(w, k, true, t) do
1082+
if w == :infinity or m == :flat or fits(w, k, true, t) != :no_fit do
10771083
[s | format(w, k, t)]
10781084
else
10791085
[indent(i) | format(w, i, t)]
@@ -1103,11 +1109,17 @@ defmodule Inspect.Algebra do
11031109
format(w, k, [{i, :break, x} | t])
11041110
end
11051111

1112+
defp format(w, k, [{i, :break_no_flat, doc_group(x, _)} | t]) do
1113+
format(w, k, [{i, :break, x} | t])
1114+
end
1115+
11061116
defp format(w, k, [{i, _, doc_group(x, _)} | t]) do
1107-
if w == :infinity or fits?(w, k, false, [{i, :flat, x}]) do
1108-
format(w, k, [{i, :flat, x} | t])
1109-
else
1110-
format(w, k, [{i, :break, x} | t])
1117+
fits = if w == :infinity, do: :fit, else: fits(w, k, false, [{i, :flat, x}])
1118+
1119+
case fits do
1120+
:fit -> format(w, k, [{i, :flat, x} | t])
1121+
:no_fit -> format(w, k, [{i, :break, x} | t])
1122+
:break_next -> format(w, k, [{i, :flat_no_break, x} | t])
11111123
end
11121124
end
11131125

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

+5
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,11 @@ defmodule Code.Formatter.CallsTest do
165165

166166
assert_format bad, good, @short_length
167167
end
168+
169+
test "for maps" do
170+
assert_same "a(%{x: 1})", @short_length
171+
assert_format "ab(%{x: 1})", "ab(%{\n x: 1\n})", @short_length
172+
end
168173
end
169174

170175
describe "local calls" do

lib/elixir/test/elixir/config/provider_test.exs

+3-2
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,9 @@ defmodule Config.ProviderTest do
4141
{:elixir, [:unknown, :nested, :key], {:ok, :value}}
4242
]) == :ok
4343

44-
assert Config.Provider.validate_compile_env([{:elixir, [:unknown, :nested, :unknown], :error}]) ==
45-
:ok
44+
assert Config.Provider.validate_compile_env([
45+
{:elixir, [:unknown, :nested, :unknown], :error}
46+
]) == :ok
4647

4748
assert {:error, msg} =
4849
Config.Provider.validate_compile_env([{:elixir, [:unknown, :nested], :error}])

0 commit comments

Comments
 (0)