Skip to content

Commit 677ad61

Browse files
committed
Fix charlist formatting issue on '\"' (elixir-lang#13364)
1 parent ff30974 commit 677ad61

File tree

2 files changed

+29
-16
lines changed

2 files changed

+29
-16
lines changed

lib/elixir/lib/code/formatter.ex

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ defmodule Code.Formatter do
66
@double_heredoc "\"\"\""
77
@single_quote "'"
88
@single_heredoc "'''"
9-
@sigil_c "~c\""
9+
@sigil_c_double "~c\""
10+
@sigil_c_single "~c'"
1011
@sigil_c_heredoc "~c\"\"\""
1112
@newlines 2
1213
@min_line 0
@@ -299,7 +300,7 @@ defmodule Code.Formatter do
299300
remote_to_algebra(quoted, context, state)
300301

301302
meta[:delimiter] == ~s['''] ->
302-
{opener, quotes} = get_charlist_quotes(true, state)
303+
{opener, quotes} = get_charlist_quotes(:heredoc, state)
303304

304305
{doc, state} =
305306
entries
@@ -309,7 +310,7 @@ defmodule Code.Formatter do
309310
{force_unfit(doc), state}
310311

311312
true ->
312-
{opener, quotes} = get_charlist_quotes(false, state)
313+
{opener, quotes} = get_charlist_quotes({:regular, entries}, state)
313314
list_interpolation_to_algebra(entries, quotes, state, opener, quotes)
314315
end
315316
end
@@ -368,13 +369,14 @@ defmodule Code.Formatter do
368369
defp quoted_to_algebra({:__block__, meta, [list]}, _context, state) when is_list(list) do
369370
case meta[:delimiter] do
370371
~s['''] ->
371-
{opener, quotes} = get_charlist_quotes(true, state)
372+
{opener, quotes} = get_charlist_quotes(:heredoc, state)
372373
string = list |> List.to_string() |> escape_heredoc(quotes)
373374
{opener |> concat(string) |> concat(quotes) |> force_unfit(), state}
374375

375376
~s['] ->
376-
{opener, quotes} = get_charlist_quotes(false, state)
377-
string = list |> List.to_string() |> escape_string(quotes)
377+
string = list |> List.to_string()
378+
{opener, quotes} = get_charlist_quotes({:regular, [string]}, state)
379+
string = escape_string(string, quotes)
378380
{opener |> concat(string) |> concat(quotes), state}
379381

380382
_other ->
@@ -2410,19 +2412,23 @@ defmodule Code.Formatter do
24102412
{left, right}
24112413
end
24122414

2413-
defp get_charlist_quotes(_heredoc = false, state) do
2415+
defp get_charlist_quotes(:heredoc, state) do
24142416
if state.normalize_charlists_as_sigils do
2415-
{@sigil_c, @double_quote}
2417+
{@sigil_c_heredoc, @double_heredoc}
24162418
else
2417-
{@single_quote, @single_quote}
2419+
{@single_heredoc, @single_heredoc}
24182420
end
24192421
end
24202422

2421-
defp get_charlist_quotes(_heredoc = true, state) do
2422-
if state.normalize_charlists_as_sigils do
2423-
{@sigil_c_heredoc, @double_heredoc}
2424-
else
2425-
{@single_heredoc, @single_heredoc}
2423+
defp get_charlist_quotes({:regular, chunks}, state) do
2424+
cond do
2425+
!state.normalize_charlists_as_sigils -> {@single_quote, @single_quote}
2426+
Enum.any?(chunks, &has_double_quote?/1) -> {@sigil_c_single, @single_quote}
2427+
true -> {@sigil_c_double, @double_quote}
24262428
end
24272429
end
2430+
2431+
defp has_double_quote?(chunk) do
2432+
is_binary(chunk) and chunk =~ @double_quote
2433+
end
24282434
end

lib/elixir/test/elixir/code_formatter/literals_test.exs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,15 @@ defmodule Code.Formatter.LiteralsTest do
210210
test "with escapes" do
211211
assert_format ~S['f\a\b\ro'], ~S[~c"f\a\b\ro"]
212212
assert_format ~S['single \' quote'], ~S[~c"single ' quote"]
213-
assert_format ~S['double " quote'], ~S[~c"double \" quote"]
213+
assert_format ~S['double " quote'], ~S[~c'double " quote']
214+
assert_format ~S['escaped \" quote'], ~S[~c'escaped \" quote']
215+
assert_format ~S['\\"'], ~S[~c'\\"']
214216

215217
assert_same ~S['f\a\b\ro'], @keep_charlists
216218
assert_same ~S['single \' quote'], @keep_charlists
219+
assert_same ~S['double " quote'], @keep_charlists
220+
assert_same ~S['escaped \" quote'], @keep_charlists
221+
assert_same ~S['\\"'], @keep_charlists
217222
end
218223

219224
test "keeps literal new lines" do
@@ -235,13 +240,15 @@ defmodule Code.Formatter.LiteralsTest do
235240

236241
test "with interpolation" do
237242
assert_format ~S['one #{2} three'], ~S[~c"one #{2} three"]
243+
assert_format ~S['#{1}\n \\ " \"'], ~S[~c'#{1}\n \\ " \"']
238244

239245
assert_same ~S['one #{2} three'], @keep_charlists
246+
assert_same ~S['#{1}\n \\ " \"'], @keep_charlists
240247
end
241248

242249
test "with escape and interpolation" do
243250
assert_format ~S['one\n\'#{2}\'\nthree'], ~S[~c"one\n'#{2}'\nthree"]
244-
assert_format ~S['one\n"#{2}"\nthree'], ~S[~c"one\n\"#{2}\"\nthree"]
251+
assert_format ~S['one\n"#{2}"\nthree'], ~S[~c'one\n"#{2}"\nthree']
245252

246253
assert_same ~S['one\n\'#{2}\'\nthree'], @keep_charlists
247254
end

0 commit comments

Comments
 (0)