bram209 / leptosfmt

A formatter for the leptos view! macro
Apache License 2.0
253 stars 27 forks source link

Leptosfmt removes neccesary curly brackets #138

Open niklass-l opened 1 month ago

niklass-l commented 1 month ago

I have this code inside a view:

                            view! {
                                <option value={Into::<&'static str>::into(std)}>{std.pretty()}</option>
                            }

Which compiles just fine. But if I run leptosfmt, it is formatted to this:

                            view! {
                                <option value=Into::<
                                    &'static str,
                                >::into(std)>{std.pretty()}</option>
                            }

Where the curly brackets around the Into call are removed. This leads to a parser error from the view macro:

error: failed to parse expression: unexpected end of input, expected one of: for, parentheses, fn, unsafe, extern, identifier, ::, <, dyn, square brackets, *, &, !, impl, _, lifetime --> src/components/slides/report/one.rs:60:51 | 60 | ... <option value=Into::< | ^^^^

Since the end of the Into call generic is interpreted as the end of the <option tag

bram209 commented 4 weeks ago

Since the end of the Into call generic is interpreted as the end of the <option tag

I don't think that is true, as rstml parses a valid syn::expr::Expr as attribute value.

See:

https://github.com/rs-tml/rstml/blob/23ba0d346337a6019826d32e4124aa41bac82c27/rstml/src/node/attribute.rs#L254C28-L254C50 and https://github.com/rs-tml/rstml/blob/23ba0d346337a6019826d32e4124aa41bac82c27/rstml/src/node/parse.rs#L387

and from the readme:

Attribute values can be any valid syn expression without requiring braces

That said, this behaviour can be customized through the transform_block configuration (see: https://github.com/rs-tml/rstml/blob/23ba0d346337a6019826d32e4124aa41bac82c27/rstml/src/node/parse.rs#L367), I will double-check if leptos does something that could cause issues.

Could you provide me a full stacktrace so that I can see where the error originated from? Or a minimum reproducible example? In the meantime, you could try to set the attr_value_brace_style to Preserve, as this will leave the braces intact.

bram209 commented 4 weeks ago

And which leptos version are you using?

niklass-l commented 4 weeks ago

Sure, here is a minimal example. I'm on leptos 0.7.0-beta so maybe the view macro changed?

Cargo.toml:

[package]
name = "t"
version = "0.1.0"
edition = "2021"

[dependencies]
leptos = { version = "0.7.0-beta" }
strum = { version = "0.26.3", features = ["derive"] }

src/main.rs:

use leptos::prelude::*;
use strum::{Display, EnumIter, IntoStaticStr};

#[derive(Clone, Debug, Display, EnumIter, IntoStaticStr)]
enum AnEnum {
    One,
    Two,
    Three,
}

#[component]
fn App() -> impl IntoView {
    let variants = vec![AnEnum::One, AnEnum::Two, AnEnum::Three];
    view! {
        <select>
            {variants
                .into_iter()
                .map(|variant| {
                    view! {
                        <option value={Into::<&'static str>::into(variant)}>{variant.to_string()}</option>
                    }
                })
                .collect_view()}
        </select>
    }
}

fn main() {
    mount_to_body(App)
}

Which compiles just fine.

After running:

> leptosfmt src
max_width = 100
tab_spaces = 4
indentation_style = "Auto"
newline_style = "Auto"
attr_value_brace_style = "WhenRequired"
closing_tag_style = "Preserve"
macro_names = [
    "leptos::view",
    "view",
]
[attr_values]
✅ src/main.rs
ℹ️  Formatted 1 files in 3 ms
>

I get this:

use leptos::prelude::*;
use strum::{Display, EnumIter, IntoStaticStr};

#[derive(Clone, Debug, Display, EnumIter, IntoStaticStr)]
enum AnEnum {
    One,
    Two,
    Three,
}

#[component]
fn App() -> impl IntoView {
    let variants = vec![AnEnum::One, AnEnum::Two, AnEnum::Three];
    view! {
        <select>
            {variants
                .into_iter()
                .map(|variant| {
                    view! {
                        <option value=Into::<
                            &'static str,
                        >::into(variant)>{variant.to_string()}</option>
                    }
                })
                .collect_view()}
        </select>
    }
}

fn main() {
    mount_to_body(App)
}

Which doesn't compile:

error: failed to parse expression: unexpected end of input, expected one of: `for`, parentheses, `fn`, `unsafe`, `extern`, identifier, `::`, `<`, `dyn`, square brackets, `*`, `&`, `!`, `impl`, `_`, lifetime
  --> src/main.rs:21:39
   |
21 |                         <option value=Into::<
   |                                       ^^^^
error: could not compile `t` (bin "t") due to 1 previous error
niklass-l commented 4 weeks ago

Also I'm on leptosfmt version 0.1.30

bram209 commented 4 weeks ago

Thanks!

I will try to check it somewhere this week. Does using the attr_value_brace_style configuration option as Preserve unblock you from using leptosfmt?

Regarding leptos 0.7 beta, there are some discussions about enforcing braces, but that PR has not been merged yet: https://github.com/leptos-rs/leptos/pull/2769

niklass-l commented 4 weeks ago

Oops sorry missed that part of your message, yes, attr_value_brace_style=Preserve fixes the issue, thanks!