Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 5dcb6e7

Browse files
committedMar 27, 2025
wip
1 parent 3a2ce69 commit 5dcb6e7

File tree

5 files changed

+664
-621
lines changed

5 files changed

+664
-621
lines changed
 

‎lib/elixir/lib/code.ex

+16-10
Original file line numberDiff line numberDiff line change
@@ -1035,9 +1035,7 @@ defmodule Code do
10351035
to_quoted_opts =
10361036
[
10371037
unescape: false,
1038-
literal_encoder: &{:ok, {:__block__, &2, [&1]}},
10391038
include_comments: true,
1040-
token_metadata: true,
10411039
emit_warnings: false
10421040
] ++ opts
10431041

@@ -1291,22 +1289,21 @@ defmodule Code do
12911289

12921290
Process.put(:code_formatter_comments, [])
12931291

1294-
opts =
1292+
opts =
12951293
if include_comments do
1296-
[preserve_comments: &preserve_comments/5,
1294+
[
1295+
preserve_comments: &preserve_comments/5,
12971296
literal_encoder: &{:ok, {:__block__, &2, [&1]}},
1298-
token_metadata: true,
1299-
unescape: false,
1300-
columns: true,
1301-
] ++ opts
1297+
token_metadata: true,
1298+
unescape: false
1299+
] ++ opts
13021300
else
13031301
opts
13041302
end
13051303

13061304
quoted = :elixir.string_to_quoted!(to_charlist(string), line, column, file, opts)
13071305

13081306
if include_comments do
1309-
# quoted = Code.Normalizer.normalize(quoted)
13101307
Code.Comments.merge_comments(quoted, Process.get(:code_formatter_comments))
13111308
else
13121309
quoted
@@ -1425,7 +1422,7 @@ defmodule Code do
14251422
defp next_eol_count([?\r, ?\n | rest], count), do: next_eol_count(rest, count + 1)
14261423
defp next_eol_count(_, count), do: count
14271424

1428-
defp previous_eol_count([{token, {_, _, count}} | _])
1425+
defp previous_eol_count([{token, {_, _, count}} | _] )
14291426
when token in [:eol, :",", :";"] and count > 0 do
14301427
count
14311428
end
@@ -1492,8 +1489,17 @@ defmodule Code do
14921489
@doc since: "1.13.0"
14931490
@spec quoted_to_algebra(Macro.t(), keyword) :: Inspect.Algebra.t()
14941491
def quoted_to_algebra(quoted, opts \\ []) do
1492+
comments = opts[:comments]
1493+
14951494
quoted
14961495
|> Code.Normalizer.normalize(opts)
1496+
|> then(fn quoted ->
1497+
if comments do
1498+
Code.Comments.merge_comments(quoted, comments)
1499+
else
1500+
quoted
1501+
end
1502+
end)
14971503
|> Code.Formatter.to_algebra(opts)
14981504
end
14991505

‎lib/elixir/lib/code/comments.ex

+397-77
Large diffs are not rendered by default.

‎lib/elixir/lib/code/formatter.ex

+209-26
Original file line numberDiff line numberDiff line change
@@ -638,23 +638,46 @@ defmodule Code.Formatter do
638638
paren_fun_to_algebra(paren_fun, min_line, max_line, state)
639639
end
640640

641-
defp block_to_algebra({:__block__, meta, args}, _min_line, _max_line, state) when args in [[], [nil]] do
641+
defp block_to_algebra({:__block__, meta, []}, min_line, max_line, state) do
642642
inner_comments = meta[:inner_comments] || []
643+
643644
comments_docs =
644645
Enum.map(inner_comments, fn comment ->
645646
comment = format_comment(comment)
646647
{comment.text, @empty, 1}
647648
end)
648649

649-
docs = merge_algebra_with_comments(comments_docs, @empty)
650+
comments_docs = merge_algebra_with_comments(comments_docs, @empty)
650651

651-
case docs do
652+
case comments_docs do
652653
[] -> {@empty, state}
653654
[line] -> {line, state}
654655
lines -> {lines |> Enum.reduce(&line(&2, &1)) |> force_unfit(), state}
655656
end
656657
end
657658

659+
defp block_to_algebra({:__block__, meta, [nil]} = block, min_line, max_line, state) do
660+
inner_comments = meta[:inner_comments] || []
661+
662+
comments_docs =
663+
Enum.map(inner_comments, fn comment ->
664+
comment = format_comment(comment)
665+
{comment.text, @empty, 1}
666+
end)
667+
668+
comments_docs = merge_algebra_with_comments(comments_docs, @empty)
669+
670+
{doc, state} = block_args_to_algebra([block], min_line, max_line, state)
671+
672+
docs = case comments_docs do
673+
[] -> doc
674+
[line] -> line(doc, line)
675+
lines -> doc |> line(lines |> Enum.reduce(&line(&2, &1)) |> force_unfit())
676+
end
677+
678+
{docs, state}
679+
end
680+
658681
defp block_to_algebra({:__block__, _, [_, _ | _] = args}, min_line, max_line, state) do
659682
block_args_to_algebra(args, min_line, max_line, state)
660683
end
@@ -1822,25 +1845,26 @@ defmodule Code.Formatter do
18221845
{{doc, @empty, 1}, state}
18231846
end
18241847

1825-
# If skipping parens, we cannot extract the comments of the first
1826-
# argument as there is no place to move them to, so we handle it now.
1848+
inner_comments = List.wrap(meta[:inner_comments])
1849+
comments_doc =
1850+
Enum.map(inner_comments, fn comment ->
1851+
comment = format_comment(comment)
1852+
{comment.text, @empty, 1}
1853+
end)
1854+
1855+
join = if args == [] and inner_comments != [], do: :line, else: join
1856+
18271857
{args, acc, state} =
18281858
case args do
1829-
[head | tail] when skip_parens? ->
1830-
{doc_triplet, state} = arg_to_algebra.(head, tail, state)
1831-
{tail, [doc_triplet], state}
1859+
[] ->
1860+
{args, comments_doc, state}
18321861

1833-
_ ->
1862+
[_ | _] ->
18341863
{args, [], state}
18351864
end
18361865

18371866
{args_docs, comments?, state} =
1838-
case args do
1839-
[] ->
1840-
quoted_to_algebra_with_comments(args, acc, min_line, max_line, state, arg_to_algebra)
1841-
_ ->
1842-
quoted_to_algebra_with_comments(args, acc, min_line, max_line, state, arg_to_algebra)
1843-
end
1867+
quoted_to_algebra_with_comments(args, acc, min_line, max_line, state, arg_to_algebra)
18441868

18451869
cond do
18461870
args_docs == [] ->
@@ -1881,6 +1905,22 @@ defmodule Code.Formatter do
18811905
|> maybe_force_clauses(clauses, state)
18821906
|> group()
18831907

1908+
leading_comments = meta[:leading_comments] || []
1909+
1910+
comments =
1911+
Enum.map(leading_comments, fn comment ->
1912+
comment = format_comment(comment)
1913+
{comment.text, @empty, 1}
1914+
end)
1915+
1916+
comments = merge_algebra_with_comments(comments, @empty)
1917+
1918+
# If there are any comments before the ->, we hoist them up above the fn
1919+
doc = case comments do
1920+
[] -> doc
1921+
[comments] -> line(comments, doc)
1922+
end
1923+
18841924
{doc, state}
18851925
end
18861926

@@ -2115,36 +2155,63 @@ defmodule Code.Formatter do
21152155
end
21162156

21172157
defp each_quoted_to_algebra_with_comments([arg | args], acc, state, fun, comments?) do
2118-
{doc_triplet, state} = fun.(arg, args, state)
2119-
2120-
21212158
case traverse_line(arg, {@max_line, @min_line}) do
21222159
{@max_line, @min_line} ->
2160+
{doc_triplet, state} = fun.(arg, args, state)
21232161
acc = [doc_triplet | acc]
21242162
each_quoted_to_algebra_with_comments(args, acc, state, fun, comments?)
21252163

21262164
{doc_start, doc_end} ->
2127-
{leading_comments, trailing_comments} =
2165+
{leading_comments, trailing_comments, arg} =
21282166
case arg do
2167+
[{_, _, _} | _] = items ->
2168+
{leading_comments, trailing_comments} =
2169+
Enum.reduce(items, {[], []}, fn {_, meta, _}, {leading_comments, trailing_comments} ->
2170+
item_leading_comments = meta[:leading_comments] || []
2171+
item_trailing_comments = meta[:trailing_comments] || []
2172+
2173+
{leading_comments ++ item_leading_comments, trailing_comments ++ item_trailing_comments}
2174+
end)
2175+
2176+
{leading_comments, trailing_comments, arg}
2177+
2178+
{{_, meta, _}, index} when is_integer(index) ->
2179+
leading_comments = meta[:leading_comments] || []
2180+
trailing_comments = meta[:trailing_comments] || []
2181+
{leading_comments, trailing_comments, arg}
2182+
2183+
{:<<>>, _, _} ->
2184+
extract_interpolation_comments(arg)
2185+
2186+
{{:., _, [List, :to_charlist]}, _, _} ->
2187+
extract_interpolation_comments(arg)
2188+
21292189
{_, meta, _} ->
21302190
leading_comments = meta[:leading_comments] || []
21312191
trailing_comments = meta[:trailing_comments] || []
2132-
{leading_comments, trailing_comments}
2192+
{leading_comments, trailing_comments, arg}
21332193

21342194
{{_, left_meta, _}, {_, right_meta, _}} ->
21352195
leading_comments = left_meta[:leading_comments] || []
21362196
trailing_comments = right_meta[:trailing_comments] || []
21372197

2138-
{leading_comments, trailing_comments}
2198+
{leading_comments, trailing_comments, arg}
2199+
{{_, context}, {_, meta, _}} when context in [:left, :right, :operand, :parens_arg] ->
2200+
leading_comments = meta[:leading_comments] || []
2201+
trailing_comments = meta[:trailing_comments] || []
2202+
2203+
{leading_comments, trailing_comments, arg}
21392204
_ ->
2140-
{[], []}
2205+
{[], [], arg}
21412206
end
21422207

21432208
comments? = leading_comments != [] or trailing_comments != []
21442209

21452210
leading_docs = build_leading_comments([], leading_comments, doc_start)
21462211
trailing_docs = build_trailing_comments([], trailing_comments)
21472212

2213+
{doc_triplet, state} = fun.(arg, args, state)
2214+
21482215
doc_triplet = adjust_trailing_newlines(doc_triplet, doc_end, trailing_comments)
21492216

21502217
acc = Enum.concat([trailing_docs, [doc_triplet], leading_docs, acc])
@@ -2153,6 +2220,114 @@ defmodule Code.Formatter do
21532220
end
21542221
end
21552222

2223+
defp extract_interpolation_comments({:<<>>, meta, entries} = quoted) when is_list(entries) do
2224+
node_leading = List.wrap(meta[:leading_comments])
2225+
node_trailing = List.wrap(meta[:trailing_comments])
2226+
2227+
if interpolated?(entries) do
2228+
{entries, comments} =
2229+
Macro.postwalk(entries, [], fn
2230+
{form, meta, args}, acc ->
2231+
leading = List.wrap(meta[:leading_comments])
2232+
trailing = List.wrap(meta[:trailing_comments])
2233+
2234+
acc = Enum.concat([leading, trailing, acc])
2235+
meta = Keyword.drop(meta, [:leading_comments, :trailing_comments])
2236+
quoted = {form, meta, args}
2237+
2238+
{quoted, acc}
2239+
2240+
quoted, acc ->
2241+
{quoted, acc}
2242+
end)
2243+
2244+
quoted = {:<<>>, meta, entries}
2245+
2246+
comments = Enum.sort_by(comments, & &1.line)
2247+
2248+
last_value =
2249+
for {:"::", _, [{_, _, [last_value]}, _]} <- entries, reduce: nil do
2250+
_ -> last_value
2251+
end
2252+
2253+
{_, last_node_line} =
2254+
Macro.postwalk(last_value, 0, fn
2255+
{_, meta, _} = quoted, max_seen ->
2256+
line = meta[:line] || max_seen
2257+
2258+
{quoted, max(max_seen, line)}
2259+
2260+
quoted, max_seen ->
2261+
{quoted, max_seen}
2262+
end)
2263+
2264+
{leading, trailing} =
2265+
Enum.split_with(comments, fn comment ->
2266+
comment.line <= last_node_line
2267+
end)
2268+
2269+
{node_leading ++ leading, node_trailing ++ trailing, quoted}
2270+
2271+
else
2272+
{node_leading, node_trailing, quoted}
2273+
end
2274+
end
2275+
2276+
defp extract_interpolation_comments({{:., _, [List, :to_charlist]} = dot, meta, [entries]} = quoted) when is_list(entries) do
2277+
node_leading = List.wrap(meta[:leading_comments])
2278+
node_trailing = List.wrap(meta[:trailing_comments])
2279+
2280+
if meta[:delimiter] do
2281+
{entries, comments} =
2282+
Macro.postwalk(entries, [], fn
2283+
{form, meta, args}, acc ->
2284+
leading = List.wrap(meta[:leading_comments])
2285+
trailing = List.wrap(meta[:trailing_comments])
2286+
2287+
acc = Enum.concat([leading, trailing, acc])
2288+
meta = Keyword.drop(meta, [:leading_comments, :trailing_comments])
2289+
quoted = {form, meta, args}
2290+
2291+
{quoted, acc}
2292+
2293+
quoted, acc ->
2294+
{quoted, acc}
2295+
end)
2296+
2297+
quoted = {dot, meta, [entries]}
2298+
2299+
comments = Enum.sort_by(comments, & &1.line)
2300+
2301+
last_value =
2302+
for {{:., _, [Kernel, :to_string]}, _, [last_value]} <- entries, reduce: nil do
2303+
_ -> last_value
2304+
end
2305+
2306+
{_, last_node_line} =
2307+
Macro.postwalk(last_value, 0, fn
2308+
{_, meta, _} = quoted, max_seen ->
2309+
line = meta[:line] || max_seen
2310+
2311+
{quoted, max(max_seen, line)}
2312+
2313+
quoted, max_seen ->
2314+
{quoted, max_seen}
2315+
end)
2316+
2317+
{leading, trailing} =
2318+
Enum.split_with(comments, fn comment ->
2319+
comment.line <= last_node_line
2320+
end)
2321+
2322+
{node_leading ++ leading, node_trailing ++ trailing, quoted}
2323+
2324+
else
2325+
{node_leading, node_trailing, quoted}
2326+
end
2327+
end
2328+
2329+
defp extract_interpolation_comments(quoted), do: {[], [], quoted}
2330+
21562331
defp build_leading_comments(acc, [], _), do: acc
21572332

21582333
defp build_leading_comments(acc, [comment | rest], doc_start) do
@@ -2165,16 +2340,18 @@ defmodule Code.Formatter do
21652340
build_leading_comments(acc, rest, doc_start)
21662341
end
21672342

2168-
defp add_previous_to_acc([{doc, next_line, newlines} | acc], previous) when newlines < previous,
2169-
do: [{doc, next_line, previous} | acc]
2343+
defp add_previous_to_acc([{doc, next_line, newlines} | acc], previous) when newlines < previous do
2344+
IO.inspect({doc, next_line, newlines, previous})
2345+
[{doc, next_line, previous} | acc]
2346+
end
21702347

21712348
defp add_previous_to_acc(acc, _previous),
21722349
do: acc
21732350
defp build_trailing_comments(acc, []), do: acc
21742351

21752352
defp build_trailing_comments(acc, [comment | rest]) do
21762353
comment = format_comment(comment)
2177-
%{previous_eol_count: previous, next_eol_count: next, text: doc} = comment
2354+
%{next_eol_count: next, text: doc} = comment
21782355
acc = [{doc, @empty, next} | acc]
21792356
build_trailing_comments(acc, rest)
21802357
end
@@ -2186,6 +2363,11 @@ defmodule Code.Formatter do
21862363
{doc, next_line, 1}
21872364
end
21882365

2366+
defp adjust_trailing_newlines({doc, next_line, newlines}, doc_end, [%{line: line, previous_eol_count: previous} | _])
2367+
when newlines == 1 and line > doc_end + 1 do
2368+
{doc, next_line, 2}
2369+
end
2370+
21892371
defp adjust_trailing_newlines(doc_triplet, _, _), do: doc_triplet
21902372

21912373

@@ -2391,11 +2573,12 @@ defmodule Code.Formatter do
23912573
false
23922574
end
23932575

2394-
defp eol_or_comments?(meta, %{comments: comments} = state) do
2576+
defp eol_or_comments?(meta, state) do
23952577
eol?(meta, state) or
23962578
(
23972579
min_line = line(meta)
23982580
max_line = closing_line(meta)
2581+
comments = meta[:trailing_comments] || []
23992582
Enum.any?(comments, fn %{line: line} -> line > min_line and line < max_line end)
24002583
)
24012584
end

‎lib/elixir/test/elixir/code/ast_comments_test.exs

+24
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@ defmodule Code.AstCommentsTest do
210210
#trailing 3
211211
] # trailing outside
212212
""")
213+
|> IO.inspect()
213214

214215
assert {:__block__, list_meta,
215216
[
@@ -647,5 +648,28 @@ defmodule Code.AstCommentsTest do
647648

648649
assert [%{line: 10, text: "# after body"}] = world_meta[:trailing_comments]
649650
end
651+
652+
test "merges leading comments into the stab if left side is empty" do
653+
quoted =
654+
parse_string!("""
655+
fn
656+
# leading
657+
->
658+
hello
659+
hello
660+
end
661+
""")
662+
663+
assert {:fn, _,
664+
[
665+
{:->, stab_meta,
666+
[
667+
[],
668+
_
669+
]}
670+
]} = quoted
671+
672+
assert [%{line: 2, text: "# leading"}] = stab_meta[:leading_comments]
673+
end
650674
end
651675
end

‎lib/elixir/test/elixir/code_formatter/ast_comments_test.exs

+18-508
Original file line numberDiff line numberDiff line change
@@ -3,519 +3,29 @@ Code.require_file("../test_helper.exs", __DIR__)
33
defmodule Code.Formatter.AstCommentsTest do
44
use ExUnit.Case, async: true
55

6-
def parse_string!(string) do
7-
Code.string_to_quoted!(string, include_comments: true)
8-
end
9-
10-
describe "merge_comments/2" do
11-
test "merges comments in empty AST" do
12-
quoted =
13-
parse_string!("""
14-
# some comment
15-
# another comment
16-
""")
17-
18-
assert {:__block__, meta, []} = quoted
19-
20-
assert [%{line: 1, text: "# some comment"}, %{line: 2, text: "# another comment"}] =
21-
meta[:inner_comments]
22-
end
23-
24-
test "merges leading comments in assorted terms" do
25-
quoted =
26-
parse_string!("""
27-
# leading var
28-
var
29-
# trailing var
30-
""")
31-
32-
assert {:var, meta, _} = quoted
33-
34-
assert [%{line: 1, text: "# leading var"}] = meta[:leading_comments]
35-
assert [%{line: 3, text: "# trailing var"}] = meta[:trailing_comments]
36-
37-
quoted =
38-
parse_string!("""
39-
# leading 1
40-
1
41-
# trailing 1
42-
""")
43-
44-
assert {:__block__, one_meta, [1]} = quoted
45-
46-
assert [%{line: 1, text: "# leading 1"}] = one_meta[:leading_comments]
47-
assert [%{line: 3, text: "# trailing 1"}] = one_meta[:trailing_comments]
48-
49-
quoted =
50-
parse_string!("""
51-
# leading qualified call
52-
Foo.bar(baz)
53-
# trailing qualified call
54-
""")
55-
56-
assert {{:., _, [_Foo, _bar]}, meta, _} = quoted
57-
58-
assert [%{line: 1, text: "# leading qualified call"}] = meta[:leading_comments]
59-
assert [%{line: 3, text: "# trailing qualified call"}] = meta[:trailing_comments]
60-
61-
quoted =
62-
parse_string!("""
63-
# leading qualified call
64-
Foo.
65-
# leading bar
66-
bar(baz)
67-
# trailing qualified call
68-
""")
69-
70-
assert {{:., _, [_Foo, _]}, meta,
71-
[
72-
{:baz, _, _}
73-
]} = quoted
74-
75-
assert [%{line: 1, text: "# leading qualified call"}, %{line: 3, text: "# leading bar"}] =
76-
meta[:leading_comments]
77-
78-
assert [%{line: 5, text: "# trailing qualified call"}] = meta[:trailing_comments]
79-
end
80-
81-
# Do/end blocks
82-
83-
test "merges comments in do/end block" do
84-
quoted =
85-
parse_string!("""
86-
def a do
87-
foo()
88-
:ok
89-
# A
90-
end # B
91-
""")
92-
93-
assert {:def, def_meta,
94-
[
95-
{:a, _, _},
96-
[
97-
{{:__block__, _, [:do]},
98-
{:__block__, _,
99-
[
100-
{:foo, _, _},
101-
{:__block__, meta, [:ok]}
102-
]}}
103-
]
104-
]} =
105-
quoted
106-
107-
assert [%{line: 4, text: "# A"}] = meta[:trailing_comments]
108-
109-
assert [%{line: 5, text: "# B"}] = def_meta[:trailing_comments]
110-
end
111-
112-
test "merges comments for named do/end blocks" do
113-
quoted =
114-
parse_string!("""
115-
def a do
116-
# leading var1
117-
var1
118-
# trailing var1
119-
else
120-
# leading var2
121-
var2
122-
# trailing var2
123-
catch
124-
# leading var3
125-
var3
126-
# trailing var3
127-
rescue
128-
# leading var4
129-
var4
130-
# trailing var4
131-
after
132-
# leading var5
133-
var5
134-
# trailing var5
135-
end
136-
""")
137-
138-
assert {:def, _,
139-
[
140-
{:a, _, _},
141-
[
142-
{{:__block__, _, [:do]}, {:var1, var1_meta, _}},
143-
{{:__block__, _, [:else]}, {:var2, var2_meta, _}},
144-
{{:__block__, _, [:catch]}, {:var3, var3_meta, _}},
145-
{{:__block__, _, [:rescue]}, {:var4, var4_meta, _}},
146-
{{:__block__, _, [:after]}, {:var5, var5_meta, _}}
147-
]
148-
]} =
149-
quoted
150-
151-
assert [%{line: 2, text: "# leading var1"}] = var1_meta[:leading_comments]
152-
assert [%{line: 4, text: "# trailing var1"}] = var1_meta[:trailing_comments]
153-
assert [%{line: 6, text: "# leading var2"}] = var2_meta[:leading_comments]
154-
assert [%{line: 8, text: "# trailing var2"}] = var2_meta[:trailing_comments]
155-
assert [%{line: 10, text: "# leading var3"}] = var3_meta[:leading_comments]
156-
assert [%{line: 12, text: "# trailing var3"}] = var3_meta[:trailing_comments]
157-
assert [%{line: 14, text: "# leading var4"}] = var4_meta[:leading_comments]
158-
assert [%{line: 16, text: "# trailing var4"}] = var4_meta[:trailing_comments]
159-
assert [%{line: 18, text: "# leading var5"}] = var5_meta[:leading_comments]
160-
assert [%{line: 20, text: "# trailing var5"}] = var5_meta[:trailing_comments]
161-
end
162-
163-
test "merges inner comments for empty named do/end blocks" do
164-
quoted =
165-
parse_string!("""
166-
def a do
167-
# inside do
168-
else
169-
# inside else
170-
catch
171-
# inside catch
172-
rescue
173-
# inside rescue
174-
after
175-
# inside after
176-
end
177-
""")
178-
179-
assert {:def, _,
180-
[
181-
{:a, _, _},
182-
[
183-
{{:__block__, _, [:do]}, {:__block__, do_meta, _}},
184-
{{:__block__, _, [:else]}, {:__block__, else_meta, _}},
185-
{{:__block__, _, [:catch]}, {:__block__, catch_meta, _}},
186-
{{:__block__, _, [:rescue]}, {:__block__, rescue_meta, _}},
187-
{{:__block__, _, [:after]}, {:__block__, after_meta, _}}
188-
]
189-
]} =
190-
quoted
191-
192-
assert [%{line: 2, text: "# inside do"}] = do_meta[:inner_comments]
193-
assert [%{line: 4, text: "# inside else"}] = else_meta[:inner_comments]
194-
assert [%{line: 6, text: "# inside catch"}] = catch_meta[:inner_comments]
195-
assert [%{line: 8, text: "# inside rescue"}] = rescue_meta[:inner_comments]
196-
assert [%{line: 10, text: "# inside after"}] = after_meta[:inner_comments]
197-
end
198-
199-
# Lists
200-
201-
test "merges comments in list" do
202-
quoted =
203-
parse_string!("""
204-
[
205-
#leading 1
206-
1,
207-
#leading 2
208-
2,
209-
3
210-
#trailing 3
211-
] # trailing outside
212-
""")
213-
214-
assert {:__block__, list_meta,
215-
[
216-
[
217-
{:__block__, one_meta, [1]},
218-
{:__block__, two_meta, [2]},
219-
{:__block__, three_meta, [3]}
220-
]
221-
]} = quoted
222-
223-
assert [%{line: 2, text: "#leading 1"}] = one_meta[:leading_comments]
224-
assert [%{line: 4, text: "#leading 2"}] = two_meta[:leading_comments]
225-
assert [%{line: 7, text: "#trailing 3"}] = three_meta[:trailing_comments]
226-
assert [%{line: 8, text: "# trailing outside"}] = list_meta[:trailing_comments]
227-
end
228-
229-
test "merges inner comments in empty list" do
230-
quoted =
231-
parse_string!("""
232-
[
233-
# inner 1
234-
# inner 2
235-
] # trailing outside
236-
""")
237-
238-
assert {:__block__, list_meta, [[]]} = quoted
239-
240-
assert [%{line: 2, text: "# inner 1"}, %{line: 3, text: "# inner 2"}] =
241-
list_meta[:inner_comments]
242-
243-
assert [%{line: 4, text: "# trailing outside"}] = list_meta[:trailing_comments]
244-
end
6+
@string ~S"""
7+
case decomposition do
8+
# Decomposition
9+
<<h, _::binary>> when h != ?< ->
10+
decomposition =
11+
decomposition
12+
|> :binary.split(" ", [:global])
13+
|> Enum.map(&String.to_integer(&1, 16))
24514
246-
# Keyword lists
15+
Map.put(dacc, String.to_integer(codepoint, 16), decomposition)
24716
248-
test "merges comments in keyword list" do
249-
quoted =
250-
parse_string!("""
251-
[
252-
#leading a
253-
a: 1,
254-
#leading b
255-
b: 2,
256-
c: 3
257-
#trailing 3
258-
] # trailing outside
259-
""")
260-
261-
assert {:__block__, keyword_list_meta,
262-
[
263-
[
264-
{
265-
{:__block__, a_key_meta, [:a]},
266-
{:__block__, _, [1]}
267-
},
268-
{
269-
{:__block__, b_key_meta, [:b]},
270-
{:__block__, _, [2]}
271-
},
272-
{
273-
{:__block__, _, [:c]},
274-
{:__block__, c_value_meta, [3]}
275-
}
276-
]
277-
]} = quoted
278-
279-
assert [%{line: 2, text: "#leading a"}] = a_key_meta[:leading_comments]
280-
assert [%{line: 4, text: "#leading b"}] = b_key_meta[:leading_comments]
281-
assert [%{line: 7, text: "#trailing 3"}] = c_value_meta[:trailing_comments]
282-
assert [%{line: 8, text: "# trailing outside"}] = keyword_list_meta[:trailing_comments]
283-
end
284-
285-
test "merges comments in partial keyword list" do
286-
quoted =
287-
parse_string!("""
288-
[
289-
#leading 1
290-
1,
291-
#leading b
292-
b: 2
293-
#trailing b
294-
] # trailing outside
295-
""")
296-
297-
assert {:__block__, keyword_list_meta,
298-
[
299-
[
300-
{:__block__, one_key_meta, [1]},
301-
{
302-
{:__block__, b_key_meta, [:b]},
303-
{:__block__, b_value_meta, [2]}
304-
}
305-
]
306-
]} = quoted
307-
308-
assert [%{line: 2, text: "#leading 1"}] = one_key_meta[:leading_comments]
309-
assert [%{line: 4, text: "#leading b"}] = b_key_meta[:leading_comments]
310-
assert [%{line: 6, text: "#trailing b"}] = b_value_meta[:trailing_comments]
311-
assert [%{line: 7, text: "# trailing outside"}] = keyword_list_meta[:trailing_comments]
312-
end
313-
314-
# Tuples
315-
316-
test "merges comments in n-tuple" do
317-
quoted =
318-
parse_string!("""
319-
{
320-
#leading 1
321-
1,
322-
#leading 2
323-
2,
324-
3
325-
#trailing 3
326-
} # trailing outside
327-
""")
328-
329-
assert {:{}, tuple_meta,
330-
[
331-
{:__block__, one_meta, [1]},
332-
{:__block__, two_meta, [2]},
333-
{:__block__, three_meta, [3]}
334-
]} = quoted
335-
336-
assert [%{line: 2, text: "#leading 1"}] = one_meta[:leading_comments]
337-
assert [%{line: 4, text: "#leading 2"}] = two_meta[:leading_comments]
338-
assert [%{line: 7, text: "#trailing 3"}] = three_meta[:trailing_comments]
339-
assert [%{line: 8, text: "# trailing outside"}] = tuple_meta[:trailing_comments]
17+
_ ->
18+
dacc
34019
end
20+
"""
34121

342-
test "merges comments in 2-tuple" do
343-
quoted =
344-
parse_string!("""
345-
{
346-
#leading 1
347-
1,
348-
#leading 2
349-
2
350-
#trailing 2
351-
} # trailing outside
352-
""")
353-
354-
assert {:__block__, tuple_meta,
355-
[
356-
{
357-
{:__block__, one_meta, [1]},
358-
{:__block__, two_meta, [2]}
359-
}
360-
]} = quoted
361-
362-
assert [%{line: 2, text: "#leading 1"}] = one_meta[:leading_comments]
363-
assert [%{line: 4, text: "#leading 2"}] = two_meta[:leading_comments]
364-
assert [%{line: 6, text: "#trailing 2"}] = two_meta[:trailing_comments]
365-
assert [%{line: 7, text: "# trailing outside"}] = tuple_meta[:trailing_comments]
366-
end
367-
368-
test "merges inner comments in empty tuple" do
369-
quoted =
370-
parse_string!("""
371-
{
372-
# inner 1
373-
# inner 2
374-
} # trailing outside
375-
""")
376-
377-
assert {:{}, tuple_meta, []} = quoted
378-
379-
assert [%{line: 2, text: "# inner 1"}, %{line: 3, text: "# inner 2"}] =
380-
tuple_meta[:inner_comments]
381-
382-
assert [%{line: 4, text: "# trailing outside"}] = tuple_meta[:trailing_comments]
383-
end
384-
385-
# Maps
386-
387-
test "merges comments in maps" do
388-
quoted =
389-
parse_string!("""
390-
%{
391-
#leading 1
392-
1 => 1,
393-
#leading 2
394-
2 => 2,
395-
3 => 3
396-
#trailing 3
397-
} # trailing outside
398-
""")
399-
400-
assert {:%{}, map_meta,
401-
[
402-
{
403-
{:__block__, one_key_meta, [1]},
404-
{:__block__, _, [1]}
405-
},
406-
{
407-
{:__block__, two_key_meta, [2]},
408-
{:__block__, _, [2]}
409-
},
410-
{
411-
{:__block__, _, [3]},
412-
{:__block__, three_value_meta, [3]}
413-
}
414-
]} = quoted
415-
416-
assert [%{line: 2, text: "#leading 1"}] = one_key_meta[:leading_comments]
417-
assert [%{line: 4, text: "#leading 2"}] = two_key_meta[:leading_comments]
418-
assert [%{line: 7, text: "#trailing 3"}] = three_value_meta[:trailing_comments]
419-
assert [%{line: 8, text: "# trailing outside"}] = map_meta[:trailing_comments]
420-
end
421-
422-
test "merges inner comments in empty maps" do
423-
quoted =
424-
parse_string!("""
425-
%{
426-
# inner 1
427-
# inner 2
428-
} # trailing outside
429-
""")
430-
431-
assert {:%{}, map_meta, []} = quoted
432-
433-
assert [%{line: 2, text: "# inner 1"}, %{line: 3, text: "# inner 2"}] =
434-
map_meta[:inner_comments]
435-
436-
assert [%{line: 4, text: "# trailing outside"}] = map_meta[:trailing_comments]
437-
end
22+
test "wip" do
23+
Code.format_string!(@string)
24+
|> IO.puts()
43825
end
43926

440-
test "handles the presence of unquote_splicing" do
441-
quoted =
442-
parse_string!("""
443-
%{
444-
# leading baz
445-
:baz => :bat,
446-
:quux => :quuz,
447-
# leading unquote splicing
448-
unquote_splicing(foo: :bar)
449-
# trailing unquote splicing
450-
}
451-
""")
452-
453-
assert {:%{}, _,
454-
[
455-
{{:__block__, baz_key_meta, [:baz]}, {:__block__, _, [:bat]}},
456-
{{:__block__, _, [:quux]}, {:__block__, _, [:quuz]}},
457-
{:unquote_splicing, unquote_splicing_meta, _}
458-
]} = quoted
459-
460-
assert [%{line: 2, text: "# leading baz"}] = baz_key_meta[:leading_comments]
461-
462-
assert [%{line: 5, text: "# leading unquote splicing"}] =
463-
unquote_splicing_meta[:leading_comments]
464-
465-
assert [%{line: 7, text: "# trailing unquote splicing"}] =
466-
unquote_splicing_meta[:trailing_comments]
467-
end
468-
469-
# Structs
470-
471-
test "merges comments in structs" do
472-
quoted =
473-
parse_string!("""
474-
%SomeStruct{
475-
#leading 1
476-
a: 1,
477-
#leading 2
478-
b: 2,
479-
c: 3
480-
#trailing 3
481-
} # trailing outside
482-
""")
483-
484-
assert {:%, struct_meta,
485-
[
486-
{:__aliases__, _, [:SomeStruct]},
487-
{:%{}, _,
488-
[
489-
{{:__block__, a_key_meta, [:a]}, {:__block__, _, [1]}},
490-
{{:__block__, b_key_meta, [:b]}, {:__block__, _, [2]}},
491-
{{:__block__, _, [:c]}, {:__block__, c_value_meta, [3]}}
492-
]}
493-
]} = quoted
494-
495-
assert [%{line: 2, text: "#leading 1"}] = a_key_meta[:leading_comments]
496-
assert [%{line: 4, text: "#leading 2"}] = b_key_meta[:leading_comments]
497-
assert [%{line: 7, text: "#trailing 3"}] = c_value_meta[:trailing_comments]
498-
assert [%{line: 8, text: "# trailing outside"}] = struct_meta[:trailing_comments]
499-
end
500-
501-
test "merges inner comments in structs" do
502-
quoted =
503-
parse_string!("""
504-
%SomeStruct{
505-
# inner 1
506-
# inner 2
507-
} # trailing outside
508-
""")
509-
510-
assert {:%, struct_meta,
511-
[
512-
{:__aliases__, _, [:SomeStruct]},
513-
{:%{}, args_meta, []}
514-
]} = quoted
515-
516-
assert [%{line: 2, text: "# inner 1"}, %{line: 3, text: "# inner 2"}] =
517-
args_meta[:inner_comments]
518-
519-
assert [%{line: 4, text: "# trailing outside"}] = struct_meta[:trailing_comments]
27+
test "test" do
28+
Code.string_to_quoted!(@string, include_comments: true, unescape: false)
29+
# |> IO.inspect()
52030
end
52131
end

0 commit comments

Comments
 (0)
Please sign in to comment.