changed CHANGELOG.md
 
@@ -5,6 +5,12 @@ they can and will change without that change being reflected in Styler's semanti
5
5
6
6
## main
7
7
8
+ ## 1.4.2
9
+
10
+ ### Fixes
11
+
12
+ - fix comment misplacement for large comment blocks in config files and `# styler:sort` (#230, h/t @cschmatzler)
13
+
8
14
## 1.4.1
9
15
10
16
### Improvements
 
@@ -24,7 +30,7 @@ they can and will change without that change being reflected in Styler's semanti
24
30
25
31
- fixed styler raising when encountering invalid function definition ast
26
32
27
- ## 1.4
33
+ ## 1.4.0
28
34
29
35
- A very nice change in alias lifting means Styler will make sure that your code is _using_ the aliases that it's specified.
30
36
- Shoutout to the smartrent folks for finding pipifying recursion issues
changed hex_metadata.config
 
@@ -1,12 +1,9 @@
1
1
{<<"links">>,[{<<"GitHub">>,<<"https://github.com/adobe/elixir-styler">>}]}.
2
2
{<<"name">>,<<"styler">>}.
3
- {<<"version">>,<<"1.4.1">>}.
3
+ {<<"version">>,<<"1.4.2">>}.
4
4
{<<"description">>,
5
5
<<"A code-style enforcer that will just FIFY instead of complaining">>}.
6
6
{<<"elixir">>,<<"~> 1.15">>}.
7
- {<<"app">>,<<"styler">>}.
8
- {<<"licenses">>,[<<"Apache-2.0">>]}.
9
- {<<"requirements">>,[]}.
10
7
{<<"files">>,
11
8
[<<"lib">>,<<"lib/zipper.ex">>,<<"lib/style">>,
12
9
<<"lib/style/single_node.ex">>,<<"lib/style/defs.ex">>,
 
@@ -16,4 +13,7 @@
16
13
<<"lib/alias_env.ex">>,<<"lib/styler">>,<<"lib/styler/config.ex">>,
17
14
<<"lib/style_error.ex">>,<<"lib/styler.ex">>,<<".formatter.exs">>,
18
15
<<"mix.exs">>,<<"README.md">>,<<"LICENSE">>,<<"CHANGELOG.md">>]}.
16
+ {<<"app">>,<<"styler">>}.
17
+ {<<"licenses">>,[<<"Apache-2.0">>]}.
18
+ {<<"requirements">>,[]}.
19
19
{<<"build_tools">>,[<<"mix">>]}.
changed lib/style.ex
 
@@ -173,67 +173,47 @@ defmodule Styler.Style do
173
173
def max_line([_ | _] = list), do: list |> List.last() |> max_line()
174
174
175
175
def max_line(ast) do
176
- meta =
177
- case ast do
178
- {_, meta, _} ->
179
- meta
176
+ meta = meta(ast)
180
177
181
- _ ->
182
- []
183
- end
178
+ cond do
179
+ line = meta[:end_of_expression][:line] ->
180
+ line
184
181
185
- if max_line = meta[:closing][:line] do
186
- max_line
187
- else
188
- {_, max_line} =
189
- Macro.prewalk(ast, 0, fn
190
- {_, meta, _} = ast, max -> {ast, max(meta[:line] || max, max)}
191
- ast, max -> {ast, max}
192
- end)
182
+ line = meta[:closing][:line] ->
183
+ line
193
184
194
- max_line
185
+ true ->
186
+ {_, max_line} =
187
+ Macro.prewalk(ast, 0, fn
188
+ {_, meta, _} = ast, max -> {ast, max(meta[:line] || max, max)}
189
+ ast, max -> {ast, max}
190
+ end)
191
+
192
+ max_line
195
193
end
196
194
end
197
195
196
+ @doc "Sets the nodes' meta line and comments' line numbers to fit the ordering of the nodes list."
197
+ # TODO this doesn't grab comments which are floating as their own paragrpah, unconnected to a node
198
+ # they'll just be left floating where they were, then mangled with the re-ordered comments..
198
199
def order_line_meta_and_comments(nodes, comments, first_line) do
199
- {nodes, comments, node_comments} = fix_lines(nodes, comments, first_line, [], [])
200
- {nodes, Enum.sort_by(comments ++ node_comments, & &1.line)}
201
- end
202
-
203
- defp fix_lines([], comments, _, node_acc, c_acc), do: {Enum.reverse(node_acc), comments, c_acc}
204
-
205
- defp fix_lines([node | nodes], comments, start_line, n_acc, c_acc) do
206
- meta = meta(node)
207
- line = meta[:line]
208
- last_line = meta[:end_of_expression][:line] || max_line(node)
209
-
210
- {node, node_comments, comments} =
211
- if start_line == line do
212
- {node, [], comments}
213
- else
200
+ {nodes, shifted_comments, comments, _line} =
201
+ Enum.reduce(nodes, {[], [], comments, first_line}, fn node, {n_acc, c_acc, comments, move_to_line} ->
202
+ meta = meta(node)
203
+ line = meta[:line]
204
+ last_line = max_line(node)
214
205
{mine, comments} = comments_for_lines(comments, line, last_line)
215
- line_with_comments = (List.first(mine)[:line] || line) - (List.first(mine)[:previous_eol_count] || 1) + 1
216
206
217
- if line_with_comments == start_line do
218
- {node, mine, comments}
219
- else
220
- shift = start_line - line_with_comments
221
- # fix the node's line
222
- node = shift_line(node, shift)
223
- # fix the comment's line
224
- mine = Enum.map(mine, &%{&1 | line: &1.line + shift})
225
- {node, mine, comments}
226
- end
227
- end
207
+ shift = move_to_line - (List.first(mine)[:line] || line) + 1
208
+ shifted_node = shift_line(node, shift)
209
+ shifted_comments = Enum.map(mine, &%{&1 | line: &1.line + shift})
228
210
229
- meta = meta(node)
230
- # @TODO what about comments that were free floating between blocks? i'm just ignoring them and maybe always will...
231
- # kind of just want to shove them to the end though, so that they don't interrupt existing stanzas.
232
- # i think that's accomplishable by doing a final call above that finds all comments in the comments list that weren't moved
233
- # and which are in the range of start..finish and sets their lines to finish!
234
- last_line = meta[:end_of_expression][:line] || max_line(node)
235
- last_line = (meta[:end_of_expression][:newlines] || 1) + last_line
236
- fix_lines(nodes, comments, last_line, [node | n_acc], node_comments ++ c_acc)
211
+ move_to_line = last_line + shift + (meta[:end_of_expression][:newlines] || 0)
212
+
213
+ {[shifted_node | n_acc], shifted_comments ++ c_acc, comments, move_to_line}
214
+ end)
215
+
216
+ {Enum.reverse(nodes), Enum.sort_by(comments ++ shifted_comments, & &1.line)}
237
217
end
238
218
239
219
# typical node
 
@@ -243,13 +223,9 @@ defmodule Styler.Style do
243
223
def meta(_), do: nil
244
224
245
225
@doc """
246
- Returns all comments "for" a node, including on the line before it.
247
- see `comments_for_lines` for more
226
+ Returns all comments "for" a node, including on the line before it. see `comments_for_lines` for more
248
227
"""
249
- def comments_for_node({_, m, _} = node, comments) do
250
- last_line = m[:end_of_expression][:line] || max_line(node)
251
- comments_for_lines(comments, m[:line], last_line)
252
- end
228
+ def comments_for_node({_, m, _} = node, comments), do: comments_for_lines(comments, m[:line], max_line(node))
253
229
254
230
@doc """
255
231
Gets all comments in range start_line..last_line, and any comments immediately before start_line.s
 
@@ -268,10 +244,6 @@ defmodule Styler.Style do
268
244
comments |> Enum.reverse() |> comments_for_lines(start_line, last_line, [], [])
269
245
end
270
246
271
- defp comments_for_lines(reversed_comments, start, last, match, acc)
272
-
273
- defp comments_for_lines([], _, _, match, acc), do: {Enum.reverse(match), acc}
274
-
275
247
defp comments_for_lines([%{line: line} = comment | rev_comments], start, last, match, acc) do
276
248
cond do
277
249
# after our block - no match
 
@@ -285,4 +257,6 @@ defmodule Styler.Style do
285
257
true -> {match, Enum.reverse(rev_comments, [comment | acc])}
286
258
end
287
259
end
260
+
261
+ defp comments_for_lines([], _, _, match, acc), do: {match, acc}
288
262
end
changed lib/style/configs.ex
 
@@ -86,7 +86,7 @@ defmodule Styler.Style.Configs do
86
86
# the first node of `rest` is greater than the highest line in configs, assignments
87
87
# config line is the first line to be used as part of this block
88
88
{node_comments, _} = Style.comments_for_node(config, comments)
89
- first_line = min(List.last(node_comments)[:line] || cfm[:line], cfm[:line])
89
+ first_line = min(List.first(node_comments)[:line] || cfm[:line], cfm[:line])
90
90
Style.order_line_meta_and_comments(nodes, comments, first_line)
91
91
else
92
92
{nodes, comments}
changed mix.exs
 
@@ -12,7 +12,7 @@ defmodule Styler.MixProject do
12
12
use Mix.Project
13
13
14
14
# Don't forget to bump the README when doing non-patch version changes
15
- @version "1.4.1"
15
+ @version "1.4.2"
16
16
@url "https://github.com/adobe/elixir-styler"
17
17
18
18
def project do