Преглед изворни кода

fix: never cache spanless expressions in autofmt (#3297)

* fix: never cache spanless expressions

* clippy
Jonathan Kelley пре 6 месеци
родитељ
комит
aa7d952a72

+ 8 - 1
packages/autofmt/src/writer.rs

@@ -3,6 +3,7 @@ use dioxus_rsx::*;
 use proc_macro2::{LineColumn, Span};
 use quote::ToTokens;
 use std::{
+    borrow::Cow,
     collections::{HashMap, VecDeque},
     fmt::{Result, Write},
 };
@@ -910,9 +911,14 @@ impl<'a> Writer<'a> {
     }
 
     #[allow(clippy::map_entry)]
-    fn retrieve_formatted_expr(&mut self, expr: &Expr) -> &str {
+    fn retrieve_formatted_expr(&mut self, expr: &Expr) -> Cow<'_, str> {
         let loc = expr.span().start();
 
+        // never cache expressions that are spanless
+        if loc.line == 1 && loc.column == 0 {
+            return self.unparse_expr(expr).into();
+        }
+
         if !self.cached_formats.contains_key(&loc) {
             let formatted = self.unparse_expr(expr);
             self.cached_formats.insert(loc, formatted);
@@ -922,6 +928,7 @@ impl<'a> Writer<'a> {
             .get(&loc)
             .expect("Just inserted the parsed expr, so it should be in the cache")
             .as_str()
+            .into()
     }
 
     fn final_span_of_node(node: &BodyNode) -> Span {

+ 2 - 0
packages/autofmt/tests/samples/attributes.rsx

@@ -7,6 +7,8 @@ rsx! {
         class: "asd",
         class: "asd",
         class: "asd",
+        src: asset!("/123.png"),
+        src: asset!("/456.png"),
         blah: 123,
         onclick: move |_| {
             let blah = 120;

+ 17 - 5
packages/autofmt/tests/srcless.rs

@@ -1,17 +1,29 @@
 use dioxus_rsx::CallBody;
-use proc_macro2::TokenStream as TokenStream2;
+use syn::parse_quote;
+
+macro_rules! test_case {
+    (
+        $path:literal
+    ) => {
+        works(include!($path), include_str!($path))
+    };
+}
 
 /// Ensure we can write RSX blocks without a source file
 ///
 /// Useful in code generation use cases where we still want formatted code.
 #[test]
 fn write_block_out() {
-    let src = include_str!("./srcless/basic_expr.rsx");
-
-    let tokens: TokenStream2 = syn::parse_str(src).unwrap();
-    let parsed: CallBody = syn::parse2(tokens).unwrap();
+    test_case!("./srcless/basic_expr.rsx");
+    test_case!("./srcless/asset.rsx");
+}
 
+fn works(parsed: CallBody, src: &str) {
     let block = dioxus_autofmt::write_block_out(&parsed).unwrap();
+    let src = src
+        .trim()
+        .trim_start_matches("parse_quote! {")
+        .trim_end_matches('}');
 
     // normalize line endings for windows tests to pass
     pretty_assertions::assert_eq!(

+ 5 - 0
packages/autofmt/tests/srcless/asset.rsx

@@ -0,0 +1,5 @@
+parse_quote! {
+    img { src: asset!("/assets/logos/123.png") }
+    img { src: asset!("/assets/logos/456.png") }
+    img { src: asset!("/assets/logos/789.png") }
+}

+ 18 - 0
packages/autofmt/tests/srcless/basic_expr.rsx

@@ -1,3 +1,4 @@
+parse_quote! {
     div {
         "hi"
         {children}
@@ -37,6 +38,23 @@
             let b = 40;
             let c = 50;
         },
+        src1: asset!("/123.png"),
+        src2: asset!("/456.png"),
+        src3: asset!("/789.png"),
+        src4: asset!("/101112.png", WithOptions),
         "hi"
     }
+    p {
+        img {
+            src: asset!("/example-book/assets1/logo.png", ImageAssetOptions::new().with_avif()),
+            alt: "some_local1",
+            title: "",
+        }
+        img {
+            src: asset!("/example-book/assets2/logo.png", ImageAssetOptions::new().with_avif()),
+            alt: "some_local2",
+            title: "",
+        }
+    }
     div { class: "asd", "Jon" }
+}