phoenixframework / phoenix_live_view

Rich, real-time user experiences with server-rendered HTML
https://hex.pm/packages/phoenix_live_view
MIT License
6.24k stars 934 forks source link

function arguments indentation is not fixed if followed by `do` when formatting heex file #3275

Open michallepicki opened 6 months ago

michallepicki commented 6 months ago

Environment

Elixir 1.16.2 (compiled with Erlang/OTP 26)

* Phoenix LiveView version (mix deps): main
* Operating system: MacOS, Ubuntu

### Actual behavior

```elixir
# formatter_bug.exs

Mix.install([
  {:phoenix_live_view, github: "phoenixframework/phoenix_live_view", branch: "main", override: true},
])

html =
"""
<%= link(
  to: "some/path",
            class: "btn"
    ) do %>
  asdf
<% end %>
"""

dbg(Phoenix.LiveView.HTMLFormatter.format(html, heex_line_length: 100) == html)
$ elixir formatter_bug.exs
[formatter_bug.exs:17: (file)]
Phoenix.LiveView.HTMLFormatter.format(html, heex_line_length: 100) == html #=> true

Expected behavior

I would expect the snippet to be formatted e.g. this way:

<%= link(
  to: "some/path",
  class: "btn"
) do %>
  asdf
<% end %>

i.e. function arguments / keyword list elements to be aligned consistently with an indentation that makes some logical sense

SteffenDE commented 6 months ago

Hi @michallepicki, this is documented behavior: https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.HTMLFormatter.html#module-formatting

This formatter does not format Elixir expressions with do...end. The content within it will be formatted accordingly though. Therefore, the given input:

<%= live_redirect(
       to: "/my/path",
  class: "my class"
) do %>
        My Link
<% end %>

Will be formatted to

<%= live_redirect(
       to: "/my/path",
  class: "my class"
) do %>
  My Link
<% end %>

I don't know the reasons why it is the way it is, but I assume we'd probably accept a PR to implement this.

michallepicki commented 6 months ago

Thanks, I must have missed this part of the docs! Or if there are good reasons it is the way it is, maybe it should be mentioned in the docs why

michallepicki commented 5 months ago

Maybe @feliperenan remembers why the formatter doesn't handle such cases?

josevalim commented 5 months ago

It doesn't handle such cases because we would need to build an incomplete Elixir expression and then give it to the Elixir formatter. But the formatter does not accept incomplete Elixir expressions in the first place.

Another option would be to complete the expression yourself, by attaching the end node, and then remove it out before formatting, but there may be caveats too.