From 676dfc27fee8424919840c384203e1bdbfc25cc9 Mon Sep 17 00:00:00 2001 From: Emily Guthrie Date: Fri, 28 Feb 2025 06:16:05 -0800 Subject: [PATCH] Clean up --- lib/style/blocks.ex | 4 +- lib/style/comment_directives.ex | 72 ++++++++++++--------------------- lib/zipper.ex | 4 +- 3 files changed, 32 insertions(+), 48 deletions(-) diff --git a/lib/style/blocks.ex b/lib/style/blocks.ex index c2e99b2..5c7bb42 100644 --- a/lib/style/blocks.ex +++ b/lib/style/blocks.ex @@ -102,7 +102,9 @@ defmodule Quokka.Style.Blocks do # `with (head_statements) do: x (else ...)` do_block? -> # head statements can be the empty list, if it matters - {head_statements, [[{{:__block__, _, [:do]}, body} | _]]} = Enum.split_while(children, &(not Style.do_block?(&1))) + {head_statements, [[{{:__block__, _, [:do]}, body} | _]]} = + Enum.split_while(children, &(not Style.do_block?(&1))) + [first | rest] = head_statements ++ [body] # replace this `with` statement with its headers + body zipper = zipper |> Zipper.replace(first) |> Zipper.insert_siblings(rest) diff --git a/lib/style/comment_directives.ex b/lib/style/comment_directives.ex index 701caff..6237c6b 100644 --- a/lib/style/comment_directives.ex +++ b/lib/style/comment_directives.ex @@ -52,68 +52,48 @@ defmodule Quokka.Style.CommentDirectives do if Enum.empty?(autosort_types) do zipper else - {zipper, skip_sort_lines} = - Enum.reduce( - Enum.filter(ctx.comments, &(&1.text == "# quokka:skip-sort")), - {zipper, MapSet.new()}, - fn comment, {z, lines} -> - {z, lines |> MapSet.put(comment.line) |> MapSet.put(comment.line + 1)} - end - ) + skip_sort_lines = collect_skip_sort_lines(ctx.comments) Zipper.traverse(zipper, fn z -> node = Zipper.node(z) node_line = Style.meta(node)[:line] - # Skip sorting if the node has a skip-sort directive on its line or the line above should_skip = node_line && MapSet.member?(skip_sort_lines, node_line) + has_comments = has_comments_inside?(node, ctx.comments) + is_sortable = get_node_type(node) in autosort_types - # Skip sorting nodes with comments to avoid disrupting comment placement. Can still force sorting with # quokka:sort - case !should_skip && !has_comments_inside?(node, ctx.comments) && node do - {:%{}, _, _} -> - if :map in autosort_types do - {sorted, _} = sort(node, []) - Zipper.replace(z, sorted) - else - z - end - - {:%, _, [_, {:%{}, _, _}]} -> - if :map in autosort_types do - {sorted, _} = sort(node, []) - Zipper.replace(z, sorted) - else - z - end - - {:defstruct, _, _} -> - if :defstruct in autosort_types do - {sorted, _} = sort(node, []) - Zipper.replace(z, sorted) - else - z - end - - _ -> - z + if should_skip || has_comments || !is_sortable do + z + else + {sorted, _} = sort(node, []) + Zipper.replace(z, sorted) end end) end end - # Check if there are any comments within the line range of a node + defp collect_skip_sort_lines(comments) do + comments + |> Enum.filter(&(&1.text == "# quokka:skip-sort")) + |> Enum.reduce(MapSet.new(), fn comment, lines -> + lines |> MapSet.put(comment.line) |> MapSet.put(comment.line + 1) + end) + end + + defp get_node_type(node) do + case node do + {:%{}, _, _} -> :map + {:%, _, [_, {:%{}, _, _}]} -> :map + {:defstruct, _, _} -> :defstruct + _ -> nil + end + end + defp has_comments_inside?(node, comments) do start_line = Style.meta(node)[:line] || 0 end_line = Style.max_line(node) || start_line - # If the node spans multiple lines, check for comments within that range - if end_line > start_line do - Enum.any?(comments, fn comment -> - comment.line > start_line && comment.line < end_line - end) - else - false - end + end_line > start_line && Enum.any?(comments, &(&1.line > start_line && &1.line < end_line)) end # defstruct with a syntax-sugared keyword list hits here diff --git a/lib/zipper.ex b/lib/zipper.ex index dafd0b4..ed41f7a 100644 --- a/lib/zipper.ex +++ b/lib/zipper.ex @@ -188,7 +188,9 @@ defmodule Quokka.Zipper do Enum.reduce(siblings, zipper, &Zipper.insert_left(&2, &1)) """ @spec prepend_siblings(zipper, [tree]) :: zipper - def prepend_siblings({node, nil}, siblings), do: {:__block__, [], siblings ++ [node]} |> zip() |> down() |> rightmost() + def prepend_siblings({node, nil}, siblings), + do: {:__block__, [], siblings ++ [node]} |> zip() |> down() |> rightmost() + def prepend_siblings({tree, meta}, siblings), do: {tree, %{meta | l: Enum.reverse(siblings, meta.l)}} @doc """