Use `line_endings` macro for the edit tool tests (#26642)

张小白 created

This aligns with how we handle other tests on Windows.

Release Notes:

- N/A

Change summary

crates/assistant_tools/src/edit_files_tool/edit_action.rs | 52 ++------
crates/util/src/util.rs                                   |  2 
crates/util_macros/src/util_macros.rs                     | 26 ++++
3 files changed, 42 insertions(+), 38 deletions(-)

Detailed changes

crates/assistant_tools/src/edit_files_tool/edit_action.rs 🔗

@@ -355,6 +355,7 @@ impl std::fmt::Display for ParseError {
 mod tests {
     use super::*;
     use rand::prelude::*;
+    use util::line_endings;
 
     #[test]
     fn test_simple_edit_action() {
@@ -798,19 +799,17 @@ fn new_utils_func() {}
             EditAction::Replace {
                 file_path: PathBuf::from("mathweb/flask/app.py"),
                 old: "from flask import Flask".to_string(),
-                new: "import math\nfrom flask import Flask".to_string(),
-            }
-            .fix_lf(),
+                new: line_endings!("import math\nfrom flask import Flask").to_string(),
+            },
         );
 
         assert_eq!(
             actions[1],
             EditAction::Replace {
                 file_path: PathBuf::from("mathweb/flask/app.py"),
-                old: "def factorial(n):\n    \"compute factorial\"\n\n    if n == 0:\n        return 1\n    else:\n        return n * factorial(n-1)\n".to_string(),
+                old: line_endings!("def factorial(n):\n    \"compute factorial\"\n\n    if n == 0:\n        return 1\n    else:\n        return n * factorial(n-1)\n").to_string(),
                 new: "".to_string(),
             }
-            .fix_lf()
         );
 
         assert_eq!(
@@ -819,28 +818,30 @@ fn new_utils_func() {}
                 file_path: PathBuf::from("mathweb/flask/app.py"),
                 old: "    return str(factorial(n))".to_string(),
                 new: "    return str(math.factorial(n))".to_string(),
-            }
-            .fix_lf(),
+            },
         );
 
         assert_eq!(
             actions[3],
             EditAction::Write {
                 file_path: PathBuf::from("hello.py"),
-                content: "def hello():\n    \"print a greeting\"\n\n    print(\"hello\")"
-                    .to_string(),
-            }
-            .fix_lf(),
+                content: line_endings!(
+                    "def hello():\n    \"print a greeting\"\n\n    print(\"hello\")"
+                )
+                .to_string(),
+            },
         );
 
         assert_eq!(
             actions[4],
             EditAction::Replace {
                 file_path: PathBuf::from("main.py"),
-                old: "def hello():\n    \"print a greeting\"\n\n    print(\"hello\")".to_string(),
+                old: line_endings!(
+                    "def hello():\n    \"print a greeting\"\n\n    print(\"hello\")"
+                )
+                .to_string(),
                 new: "from hello import hello".to_string(),
-            }
-            .fix_lf(),
+            },
         );
 
         // The system prompt includes some text that would produce errors
@@ -860,29 +861,6 @@ fn new_utils_func() {}
         );
     }
 
-    impl EditAction {
-        fn fix_lf(self: EditAction) -> EditAction {
-            #[cfg(windows)]
-            match self {
-                EditAction::Replace {
-                    file_path,
-                    old,
-                    new,
-                } => EditAction::Replace {
-                    file_path: file_path.clone(),
-                    old: old.replace("\n", "\r\n"),
-                    new: new.replace("\n", "\r\n"),
-                },
-                EditAction::Write { file_path, content } => EditAction::Write {
-                    file_path: file_path.clone(),
-                    content: content.replace("\n", "\r\n"),
-                },
-            }
-            #[cfg(not(windows))]
-            self
-        }
-    }
-
     #[test]
     fn test_print_error() {
         let input = r#"src/main.rs

crates/util/src/util.rs 🔗

@@ -29,7 +29,7 @@ use anyhow::{anyhow, Context as _};
 
 pub use take_until::*;
 #[cfg(any(test, feature = "test-support"))]
-pub use util_macros::{separator, uri};
+pub use util_macros::{line_endings, separator, uri};
 
 #[macro_export]
 macro_rules! debug_panic {

crates/util_macros/src/util_macros.rs 🔗

@@ -54,3 +54,29 @@ pub fn uri(input: TokenStream) -> TokenStream {
         #uri
     })
 }
+
+/// This macro replaces the line endings `\n` with `\r\n` for Windows.
+/// But if the target OS is not Windows, the line endings are returned as is.
+///
+/// # Example
+/// ```rust
+/// use util_macros::line_endings;
+///
+/// let text = line_endings!("Hello\nWorld");
+/// #[cfg(target_os = "windows")]
+/// assert_eq!(text, "Hello\r\nWorld");
+/// #[cfg(not(target_os = "windows"))]
+/// assert_eq!(text, "Hello\nWorld");
+/// ```
+#[proc_macro]
+pub fn line_endings(input: TokenStream) -> TokenStream {
+    let text = parse_macro_input!(input as LitStr);
+    let text = text.value();
+
+    #[cfg(target_os = "windows")]
+    let text = text.replace("\n", "\r\n");
+
+    TokenStream::from(quote! {
+        #text
+    })
+}