summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@plataformatec.com.br>2018-04-17 08:52:47 +0200
committerJosé Valim <jose.valim@plataformatec.com.br>2018-04-17 08:53:21 +0200
commit718123157c2bc08e0dbaf84efa8679e63143d59f (patch)
treee5658cee713d3f7b112195a48a95c893d3bd9ad0
parentbe46a1f999392e19aae13773732c3379eb15b22d (diff)
downloadelixir-718123157c2bc08e0dbaf84efa8679e63143d59f.tar.gz
Fix formatter for tilde inside bitstrings, closes #7558
Signed-off-by: José Valim <jose.valim@plataformatec.com.br>
-rw-r--r--lib/elixir/lib/code/formatter.ex29
-rw-r--r--lib/elixir/test/elixir/code_formatter/containers_test.exs10
-rw-r--r--lib/elixir/test/elixir/kernel/expansion_test.exs2
3 files changed, 27 insertions, 14 deletions
diff --git a/lib/elixir/lib/code/formatter.ex b/lib/elixir/lib/code/formatter.ex
index 744198547..96e5a5753 100644
--- a/lib/elixir/lib/code/formatter.ex
+++ b/lib/elixir/lib/code/formatter.ex
@@ -1351,8 +1351,17 @@ defmodule Code.Formatter do
defp bitstring_segment_to_algebra({{:::, _, [segment, spec]}, i}, state, last) do
{doc, state} = quoted_to_algebra(segment, :parens_arg, state)
{spec, state} = bitstring_spec_to_algebra(spec, state)
- doc = concat(concat(doc, "::"), wrap_in_parens_if_inspected_atom(spec))
- {bitstring_wrap_parens(doc, i, last), state}
+
+ spec = wrap_in_parens_if_inspected_atom(spec)
+ spec = if i == last, do: bitstring_wrap_parens(spec, i, last), else: spec
+
+ doc =
+ doc
+ |> bitstring_wrap_parens(i, -1)
+ |> concat("::")
+ |> concat(spec)
+
+ {doc, state}
end
defp bitstring_segment_to_algebra({segment, i}, state, last) do
@@ -1370,21 +1379,19 @@ defmodule Code.Formatter do
quoted_to_algebra_with_parens_if_operator(spec, :parens_arg, state)
end
- defp bitstring_wrap_parens(doc, i, last) do
- if i == 0 or i == last do
- string = format_to_string(doc)
+ defp bitstring_wrap_parens(doc, i, last) when i == 0 or i == last do
+ string = format_to_string(doc)
- if (i == 0 and String.starts_with?(string, "<<")) or
- (i == last and String.ends_with?(string, ">>")) do
- wrap_in_parens(doc)
- else
- doc
- end
+ if (i == 0 and String.starts_with?(string, ["~", "<<"])) or
+ (i == last and String.ends_with?(string, [">>"])) do
+ wrap_in_parens(doc)
else
doc
end
end
+ defp bitstring_wrap_parens(doc, _, _), do: doc
+
## Literals
defp list_to_algebra(meta, args, state) do
diff --git a/lib/elixir/test/elixir/code_formatter/containers_test.exs b/lib/elixir/test/elixir/code_formatter/containers_test.exs
index 0c3b5fc27..138ae36c2 100644
--- a/lib/elixir/test/elixir/code_formatter/containers_test.exs
+++ b/lib/elixir/test/elixir/code_formatter/containers_test.exs
@@ -247,13 +247,19 @@ defmodule Code.Formatter.ContainersTest do
assert_format "<<1,2,3>>", "<<1, 2, 3>>"
end
- test "add parens on first and last in case of ambiguity" do
+ test "add parens on first and last in case of binary ambiguity" do
assert_format "<< <<>> >>", "<<(<<>>)>>"
assert_format "<< <<>> + <<>> >>", "<<(<<>> + <<>>)>>"
assert_format "<< 1 + <<>> >>", "<<(1 + <<>>)>>"
assert_format "<< <<>> + 1 >>", "<<(<<>> + 1)>>"
assert_format "<< <<>>, <<>>, <<>> >>", "<<(<<>>), <<>>, (<<>>)>>"
- assert_format "<< <<>>::1, <<>>::2, <<>>::3 >>", "<<(<<>>::1), <<>>::2, <<>>::3>>"
+ assert_format "<< <<>>::1, <<>>::2, <<>>::3 >>", "<<(<<>>)::1, <<>>::2, <<>>::3>>"
+ assert_format "<< <<>>::<<>> >>", "<<(<<>>)::(<<>>)>>"
+ end
+
+ test "add parens on first in case of operator ambiguity" do
+ assert_format "<< ~~~1::8 >>", "<<(~~~1)::8>>"
+ assert_format "<< ~s[foo]::binary >>", "<<(~s[foo])::binary>>"
end
test "with modifiers" do
diff --git a/lib/elixir/test/elixir/kernel/expansion_test.exs b/lib/elixir/test/elixir/kernel/expansion_test.exs
index cddbe58e4..0c76ce150 100644
--- a/lib/elixir/test/elixir/kernel/expansion_test.exs
+++ b/lib/elixir/test/elixir/kernel/expansion_test.exs
@@ -1945,7 +1945,7 @@ defmodule Kernel.ExpansionTest do
message = ~r"literal <<>> in bitstring supports only type specifiers"
assert_raise CompileError, message, fn ->
- expand(quote(do: <<(<<"foo">>::32)>>))
+ expand(quote(do: <<(<<"foo">>)::32>>))
end
end