diff --git a/lib/elixir/lib/code.ex b/lib/elixir/lib/code.ex index 7c2d5c3189..3fa2df2669 100644 --- a/lib/elixir/lib/code.ex +++ b/lib/elixir/lib/code.ex @@ -1865,21 +1865,12 @@ defmodule Code do end defp comments_boundaries(:., _meta, boundary), do: {boundary, boundary} + defp comments_boundaries(:->, _meta, boundary), do: {boundary, boundary} defp comments_boundaries(_form, meta, boundary) do case comments_end_line(meta, [:end, :closing]) do - nil -> - {comments_boundary(meta, boundary), boundary} - - line -> - {min_comments_boundary(line, boundary), boundary} - end - end - - defp comments_boundary(meta, boundary) do - case comments_end_line(meta, [:end_of_expression]) do - nil -> boundary - line -> min_comments_boundary(line, boundary) + nil -> {nil, boundary} + line -> {min_comments_boundary(line, boundary), boundary} end end diff --git a/lib/elixir/lib/code/formatter.ex b/lib/elixir/lib/code/formatter.ex index 9cbd324c8b..a4c4204635 100644 --- a/lib/elixir/lib/code/formatter.ex +++ b/lib/elixir/lib/code/formatter.ex @@ -1657,14 +1657,17 @@ defmodule Code.Formatter do {surround(left_bracket, args_doc, right_bracket), state} end - defp map_to_algebra(meta, name_doc, [{:|, _, [left, right]}], state) do - join = if eol?(meta, state), do: :line, else: :break + defp map_to_algebra(meta, name_doc, [{:|, pipe_meta, [left, right]}], state) do + trailing_comments = Keyword.get(pipe_meta, :trailing_comments, []) + join = if eol?(meta, state) or trailing_comments != [], do: :line, else: :break fun = "ed_to_algebra(&1, :parens_arg, &2) {left_doc, state} = fun.(left, state) {right_doc, _join, state} = args_to_algebra_with_comments(right, meta, false, :none, join, state, fun) + right_doc = append_comments(right_doc, trailing_comments) + args_doc = left_doc |> wrap_in_parens_if_binary_operator(left) diff --git a/lib/elixir/test/elixir/code_formatter/comments_test.exs b/lib/elixir/test/elixir/code_formatter/comments_test.exs index de8e3ef2a5..f2bfe04443 100644 --- a/lib/elixir/test/elixir/code_formatter/comments_test.exs +++ b/lib/elixir/test/elixir/code_formatter/comments_test.exs @@ -442,6 +442,24 @@ defmodule Code.Formatter.CommentsTest do ) """ end + + test "with trailing comments on single expression" do + bad = ~S""" + foo do + ( + hello + world + # comment + ) + end + """ + + assert_format bad, ~S""" + foo do + hello + world + # comment + end + """ + end end describe "access" do @@ -1159,6 +1177,43 @@ defmodule Code.Formatter.CommentsTest do """ end + test "with comments after operators" do + assert_same """ + foo( + a + b + # comment + ) + """ + + assert_same """ + [ + @foo + # comment + ] + """ + + assert_same """ + [ + a | b + # comment + ] + """ + + bad = """ + %{foo | bar: a + b + # comment + } + """ + + assert_format bad, """ + %{ + foo + | bar: a + b + # comment + } + """ + end + test "handles nodes without meta info" do assert_same "(a -> b) |> (c -> d)" assert_same "(a -> b) when c: d" diff --git a/lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs b/lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs index 1a7b9b6327..33bd8c7b5d 100644 --- a/lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs +++ b/lib/elixir/test/elixir/code_normalizer/quoted_ast_test.exs @@ -760,6 +760,23 @@ defmodule Code.Normalizer.QuotedASTTest do end ) == "@foo [1, foo: :bar]" end + + test "comments after nodes without closing metadata" do + comments = [ + %{line: 2, column: 3, previous_eol_count: 1, next_eol_count: 1, text: "# comment"} + ] + + list = &{:__block__, [line: 1, closing: [line: 3]], [[&1]]} + + assert quoted_to_string(list.({:{}, [line: 1], [:a, :b, [c: :d]]}), comments: comments) == + "[\n {:a, :b, c: :d}\n # comment\n]" + + assert quoted_to_string(list.({:foo, [], [1]}), comments: comments) == + "[\n foo(1)\n # comment\n]" + + assert quoted_to_string(list.({:+, [], [1, 2]}), comments: comments) == + "[\n 1 + 2\n # comment\n]" + end end describe "quoted_to_algebra/2 escapes" do