Skip to content

Commit c240a49

Browse files
author
José Valim
committed
Ensure doc_line resets algebra formatting line buffer, closes #2014
1 parent e89b371 commit c240a49

File tree

2 files changed

+50
-39
lines changed

2 files changed

+50
-39
lines changed

lib/elixir/lib/inspect/algebra.ex

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ defmodule Inspect.Algebra do
7373

7474
# Functional interface to `doc` records
7575

76-
@type t :: :doc_nil | doc_cons_t | doc_nest_t | doc_break_t | doc_group_t | binary
76+
@type t :: :doc_nil | :doc_line | doc_cons_t | doc_nest_t | doc_break_t | doc_group_t | binary
7777
defrecordp :doc_cons, left: :doc_nil :: t, right: :doc_nil :: t
7878
defrecordp :doc_nest, indent: 1 :: non_neg_integer, doc: :doc_nil :: t
7979
defrecordp :doc_break, str: " " :: binary
@@ -94,7 +94,7 @@ defmodule Inspect.Algebra do
9494
defp do_is_doc(doc) do
9595
quote do
9696
is_binary(unquote(doc)) or
97-
unquote(doc) == :doc_nil or
97+
unquote(doc) in [:doc_nil, :doc_line] or
9898
(is_tuple(unquote(doc)) and
9999
elem(unquote(doc), 0) in [:doc_cons, :doc_nest, :doc_break, :doc_group])
100100
end
@@ -274,7 +274,7 @@ defmodule Inspect.Algebra do
274274

275275
"""
276276
@spec line(t, t) :: doc_cons_t
277-
def line(x, y), do: concat(x, concat(@newline, y))
277+
def line(x, y), do: concat(x, concat(:doc_line, y))
278278

279279
@doc """
280280
Folds a list of document entities into a document entity
@@ -397,6 +397,7 @@ defmodule Inspect.Algebra do
397397
@spec fits?(integer, [{ integer, mode, t }]) :: boolean
398398
def fits?(w, _) when w < 0, do: false
399399
def fits?(_, []), do: true
400+
def fits?(_, [{_, _, :doc_line} | _]), do: true
400401
def fits?(w, [{_, _, :doc_nil} | t]), do: fits?(w, t)
401402
def fits?(w, [{i, m, doc_cons(left: x, right: y)} | t]), do: fits?(w, [{i, m, x} | [{i, m, y} | t]])
402403
def fits?(w, [{i, m, doc_nest(indent: j, doc: x)} | t]), do: fits?(w, [{i + j, m, x} | t])
@@ -408,6 +409,7 @@ defmodule Inspect.Algebra do
408409
@doc false
409410
@spec format(integer | :infinity, integer, [{ integer, mode, t }]) :: [binary]
410411
def format(_, _, []), do: []
412+
def format(w, _, [{i, _, :doc_line} | t]), do: [indent(i) | format(w, i, t)]
411413
def format(w, k, [{_, _, :doc_nil} | t]), do: format(w, k, t)
412414
def format(w, k, [{i, m, doc_cons(left: x, right: y)} | t]), do: format(w, k, [{i, m, x} | [{i, m, y} | t]])
413415
def format(w, k, [{i, m, doc_nest(indent: j, doc: x)} | t]), do: format(w, k, [{i + j, m, x} | t])
@@ -420,11 +422,13 @@ defmodule Inspect.Algebra do
420422
if w == :infinity or fits?(w - k, t) do
421423
[s | format(w, k, t)]
422424
else
423-
prefix = :binary.copy(" ", i)
424-
[@newline, prefix | format(w, i, t)]
425+
[indent(i) | format(w, i, t)]
425426
end
426427
end
427428

429+
defp indent(0), do: @newline
430+
defp indent(i), do: @newline <> :binary.copy(" ", i)
431+
428432
@doc false
429433
@spec render([binary]) :: binary
430434
def render(sdoc) do

lib/elixir/test/elixir/inspect/algebra_test.exs

Lines changed: 41 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -17,94 +17,93 @@ defmodule Inspect.AlgebraTest do
1717

1818
def factor(doc, w), do: format(w, 0, [{0, :flat, group(doc)}])
1919

20-
test :empty do
20+
test "empty doc" do
2121
# Consistence with definitions
2222
assert empty == :doc_nil
23+
2324
# Consistence of corresponding sdoc
2425
assert factor(empty, 80) == []
26+
2527
# Consistent formatting
2628
assert pretty(empty, 80) == ""
2729
end
2830

29-
test :break do
31+
test "break doc" do
3032
# Consistence with definitions
31-
## Normal case
3233
assert break("break") == { :doc_break, "break" }
33-
## Degeneracy
3434
assert break("") == { :doc_break, "" }
35-
## ong argument type
35+
36+
# Wrong argument type
3637
assert_raise FunctionClauseError, fn -> break(42) end
38+
3739
# Consistence of corresponding sdoc
3840
assert factor(break("_"), 80) == ["_"]
41+
3942
# Consistent formatting
4043
assert pretty(break("_"), 80) == "_"
4144
end
4245

43-
test :glue do
46+
test "glue doc" do
4447
# Consistence with definitions
4548
assert glue("a", "->", "b") == { :doc_cons,
4649
"a", { :doc_cons, { :doc_break, "->" }, "b" }
4750
}
4851
assert glue("a", "b") == glue("a", " ", "b")
4952

50-
## Wrong argument type
53+
# Wrong argument type
5154
assert_raise FunctionClauseError, fn -> glue("a", 42, "b") end
5255
end
5356

54-
test :text do
55-
# Consistence of corresponding docfactor
57+
test "text doc" do
58+
# Consistence of corresponding sdoc
5659
assert factor("_", 80) == ["_"]
60+
5761
# Consistent formatting
5862
assert pretty("_", 80) == "_"
5963
end
6064

61-
test :space do
65+
test "space doc" do
6266
# Consistency with definitions
6367
assert space("a", "b") == { :doc_cons,
6468
"a", { :doc_cons, " ", "b" }
6569
}
6670
end
6771

68-
test :nest do
72+
test "nest doc" do
6973
# Consistence with definitions
70-
## Normal case
7174
assert nest(empty, 1) == { :doc_nest, 1, empty }
72-
## Degeneracy
7375
assert nest(empty, 0) == :doc_nil
74-
## ong argument type
76+
77+
# Wrong argument type
7578
assert_raise FunctionClauseError, fn -> nest("foo", empty) end
7679

77-
a1 = fn -> nest("a", 1) end
78-
alb1 = fn -> nest(glue("a", "b"), 1) end
7980
# Consistence of corresponding sdoc
80-
## Trivial case
81-
assert factor(a1.(), 80) == ["a"]
82-
## Correctly indenting line forcing linebreak
83-
assert format(2, 0, [{0, :break, alb1.()}]) == ["a", "\n", " ", "b"]
81+
assert factor(nest("a", 1), 80) == ["a"]
82+
assert format(2, 0, [{0, :break, nest(glue("a", "b"), 1)}]) == ["a", "\n ", "b"]
8483

8584
# Consistent formatting
86-
## Trivial case
87-
assert pretty(a1.(), 80) == "a"
88-
## Correctly indenting line
89-
assert render(format 2, 0, [{0, :break, alb1.()}]) == "a\n b"
85+
assert pretty(nest("a", 1), 80) == "a"
86+
assert render(format 2, 0, [{0, :break, nest(glue("a", "b"), 1)}]) == "a\n b"
9087
end
9188

92-
test :infinity do
93-
# w = :infinity should disable pretty printer
94-
s = String.duplicate "x", 50
95-
g = ";"
96-
big_document = group(glue(s, g, s) |> glue(g, s) |> glue(g, s) |> glue(g, s))
89+
test "line doc" do
90+
# Consistency with definitions
91+
assert line("a", "b") ==
92+
{ :doc_cons, "a", { :doc_cons, :doc_line, "b" } }
93+
94+
# Consistence of corresponding sdoc
95+
assert factor(line("a", "b"), 1) == ["a", "\n", "b"]
96+
assert factor(line("a", "b"), 9) == ["a", "\n", "b"]
9797

98-
assert pretty(big_document, :infinity) == s <> g <> s <> g <> s <> g <> s <> g <> s
98+
# Consistent formatting
99+
assert pretty(line(glue("aaa", "bbb"), glue("ccc", "ddd")), 10) ==
100+
"aaa bbb\nccc ddd"
99101
end
100102

101-
test :group do
103+
test "group doc" do
102104
# Consistency with definitions
103-
## Normal case
104105
assert group(glue("a", "b")) ==
105106
{ :doc_group, { :doc_cons, "a", concat(break, "b") }}
106-
107-
## Degeneracy
108107
assert group(empty) == { :doc_group, empty }
109108

110109
# Consistence of corresponding sdoc
@@ -115,4 +114,12 @@ defmodule Inspect.AlgebraTest do
115114
assert pretty(helloabcd, 5) == "hello\na b\ncd"
116115
assert pretty(helloabcd, 80) == "hello a b cd"
117116
end
117+
118+
test "formatting with infinity" do
119+
s = String.duplicate "x", 50
120+
g = ";"
121+
doc = group(glue(s, g, s) |> glue(g, s) |> glue(g, s) |> glue(g, s))
122+
123+
assert pretty(doc, :infinity) == s <> g <> s <> g <> s <> g <> s <> g <> s
124+
end
118125
end

0 commit comments

Comments
 (0)