Skip to content

Commit 794bbe4

Browse files
Fix formatter escapes handling
Closes michalmuskala#49 Co-authored-by: JoeBew42 <[email protected]>
1 parent 00650f8 commit 794bbe4

File tree

5 files changed

+29
-21
lines changed

5 files changed

+29
-21
lines changed

formatter_test_suite/nested-maps.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"@id": "http://a/b","http://a/c": [{"@id": "http://a/d"}]}]
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[{"@id":"http://a/b","http://a/c":[{"@id":"http://a/d"}]}]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
{
3+
"@id": "http://a/b",
4+
"http://a/c": [
5+
{
6+
"@id": "http://a/d"
7+
}
8+
]
9+
}
10+
]

lib/formatter.ex

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -216,36 +216,27 @@ defmodule Jason.Formatter do
216216
{output_acc, &pp_string(&1, &2, in_bs, cont)}
217217
end
218218

219-
defp pp_string(<<?", rest::binary>>, output_acc, true = _in_bs, cont) do
220-
pp_string(rest, [output_acc, ?"], false, cont)
219+
defp pp_string(<<byte, rest::binary>>, output_acc, true = _in_bs, cont) do
220+
pp_string(rest, [output_acc, byte], false, cont)
221221
end
222222

223223
defp pp_string(<<?", rest::binary>>, output_acc, false = _in_bs, cont) do
224224
cont.(rest, [output_acc, ?"])
225225
end
226226

227-
defp pp_string(<<byte>>, output_acc, in_bs, cont) do
228-
in_bs = not in_bs and byte == ?\\
229-
{[output_acc, byte], &pp_string(&1, &2, in_bs, cont)}
227+
defp pp_string(<<?\\, rest::binary>>, output_acc, false = _in_bs, cont) do
228+
pp_string(rest, [output_acc, ?\\], true, cont)
230229
end
231230

232-
defp pp_string(binary, output_acc, _in_bs, cont) when is_binary(binary) do
233-
size = byte_size(binary)
234-
235-
case :binary.match(binary, "\"") do
231+
defp pp_string(binary, output_acc, false = _in_bs, cont) when is_binary(binary) do
232+
case :binary.match(binary, ["\"", "\\"]) do
236233
:nomatch ->
237-
skip = size - 2
238-
<<_::binary-size(skip), prev, last>> = binary
239-
in_bs = not (prev == ?\\ and last == ?\\) or last == ?\\
240-
{[output_acc | binary], &pp_string(&1, &2, in_bs, cont)}
241-
234+
{[output_acc | binary], &pp_string(&1, &2, false, cont)}
242235
{pos, 1} ->
243-
{leading, tail} = :erlang.split_binary(binary, pos + 1)
244-
output = [output_acc | leading]
245-
246-
case :binary.at(binary, pos - 1) do
247-
?\\ -> pp_string(tail, output, false, cont)
248-
_ -> cont.(tail, output)
236+
{head, tail} = :erlang.split_binary(binary, pos + 1)
237+
case :binary.at(binary, pos) do
238+
?\\ -> pp_string(tail, [output_acc | head], true, cont)
239+
?" -> cont.(tail, [output_acc | head])
249240
end
250241
end
251242
end

test/formatter_test.exs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ defmodule Jason.FormatterTest do
1010
"simple-object",
1111
"multiple-objects",
1212
"backslash-string",
13-
"empty-nest"
13+
"empty-nest",
14+
"nested-maps"
1415
]
1516

1617
for name <- @test_cases do
@@ -97,5 +98,9 @@ defmodule Jason.FormatterTest do
9798
input = ["\"abc\\", "\\", ?"]
9899
output = ~S|"abc\\"|
99100
assert(minimize(input) == output)
101+
102+
input = ~s|["a\\\\"]|
103+
output = ~s|[\n "a\\\\"\n]|
104+
assert(pretty_print(input) == output)
100105
end
101106
end

0 commit comments

Comments
 (0)