From 2eec2bc6734b345d8efc9a589bda777a68a2cd85 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Mon, 5 Feb 2024 21:51:49 +0800 Subject: [PATCH 01/10] add rustfmt support --- packages/cli/src/cli/autoformat.rs | 50 ++++++++++++++++++++++++++++-- packages/cli/src/error.rs | 3 ++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 87d780524b..d2e894d821 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -10,6 +10,10 @@ use super::*; /// Format some rsx #[derive(Clone, Debug, Parser)] pub struct Autoformat { + /// Run rustfmt before the dioxus formatter` + #[clap(long)] + pub rustfmt: bool, + /// Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits /// with 1 and prints a diff if formatting is required. #[clap(short, long)] @@ -36,6 +40,7 @@ impl Autoformat { raw, file, split_line_attributes, + rustfmt, .. } = self; @@ -60,14 +65,47 @@ impl Autoformat { // Format single file if let Some(file) = file { - refactor_file(file, split_line_attributes)?; + refactor_file(file, split_line_attributes, rustfmt)?; } Ok(()) } } -fn refactor_file(file: String, split_line_attributes: bool) -> Result<(), Error> { +/// Call rustfmt to format code, i32 as exitcode +fn rustfmt(input: String) -> Result { + use std::thread; + + let mut child = Command::new("rustfmt") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .map_err(|e| Error::IO(e))?; + + let mut stdin = child.stdin.take().unwrap(); + let pass_in = input.to_string(); + let handle = thread::spawn(move || -> Result<()> { + stdin + .write_all(pass_in.as_bytes()) + .map_err(|e| Error::IO(e))?; + Ok(()) + }); + handle.join().unwrap()?; + + let output = child.wait_with_output().map_err(|e| Error::IO(e))?; + + if let Some(exit_code) = output.status.code() { + if exit_code != 0 { + return Err(Error::ExitCodeNotZero(exit_code)); + } + } + + let output = String::from_utf8(output.stdout).map_err(|e| Error::Other(e.into()))?; + + Ok(output) +} + +fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> Result<(), Error> { let indent = indentation_for(".", split_line_attributes)?; let file_content = if file == "-" { let mut contents = String::new(); @@ -76,10 +114,15 @@ fn refactor_file(file: String, split_line_attributes: bool) -> Result<(), Error> } else { fs::read_to_string(&file) }; - let Ok(s) = file_content else { + let Ok(mut s) = file_content else { eprintln!("failed to open file: {}", file_content.unwrap_err()); exit(1); }; + + if do_rustfmt { + s = rustfmt(s)?; + } + let edits = dioxus_autofmt::fmt_file(&s, indent); let out = dioxus_autofmt::apply_formats(&s, edits); @@ -280,6 +323,7 @@ async fn test_auto_fmt() { .to_string(); let fmt = Autoformat { + rustfmt: false, check: false, raw: Some(test_rsx), file: None, diff --git a/packages/cli/src/error.rs b/packages/cli/src/error.rs index 35eea7eabd..98c7fc36b2 100644 --- a/packages/cli/src/error.rs +++ b/packages/cli/src/error.rs @@ -46,6 +46,9 @@ pub enum Error { #[error(transparent)] Other(#[from] anyhow::Error), + + #[error("Child process exited with {0}")] + ExitCodeNotZero(i32), } impl From<&str> for Error { From f40e2f3cef474d5581d7ec560d20069da79e6376 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 20:53:28 +0800 Subject: [PATCH 02/10] replace gitignore with ignore --- Cargo.lock | 12 +-- Cargo.toml | 31 ++++--- packages/autofmt/src/lib.rs | 7 ++ packages/cli/Cargo.toml | 5 +- packages/cli/src/cli/autoformat.rs | 129 ++++++++++++----------------- 5 files changed, 78 insertions(+), 106 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 965954c12e..2fa0eaccde 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2501,11 +2501,11 @@ dependencies = [ "flate2", "fs_extra", "futures-util", - "gitignore", "headers 0.3.9", "html_parser", "hyper 0.14.28", "hyper-rustls 0.23.2", + "ignore", "indicatif", "interprocess-docfix", "lazy_static", @@ -2514,6 +2514,7 @@ dependencies = [ "mlua", "notify", "open", + "rayon", "reqwest", "rsx-rosetta", "serde", @@ -4119,15 +4120,6 @@ dependencies = [ "url", ] -[[package]] -name = "gitignore" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d051488d9a601181a9b90c9ad8ae7e8251d642ddd2463008f2f5019d255bd89" -dependencies = [ - "glob", -] - [[package]] name = "gix-actor" version = "0.28.1" diff --git a/Cargo.toml b/Cargo.toml index a3de517157..31862400d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,23 +58,23 @@ version = "0.4.3" [workspace.dependencies] dioxus = { path = "packages/dioxus", version = "0.4.0" } dioxus-core = { path = "packages/core", version = "0.4.2" } -dioxus-core-macro = { path = "packages/core-macro", version = "0.4.0" } -dioxus-router = { path = "packages/router", version = "0.4.1" } +dioxus-core-macro = { path = "packages/core-macro", version = "0.4.0" } +dioxus-router = { path = "packages/router", version = "0.4.1" } dioxus-router-macro = { path = "packages/router-macro", version = "0.4.1" } -dioxus-html = { path = "packages/html", default-features = false, version = "0.4.0" } -dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.4.0" } +dioxus-html = { path = "packages/html", default-features = false, version = "0.4.0" } +dioxus-html-internal-macro = { path = "packages/html-internal-macro", version = "0.4.0" } dioxus-hooks = { path = "packages/hooks", version = "0.4.0" } -dioxus-web = { path = "packages/web", version = "0.4.0" } -dioxus-ssr = { path = "packages/ssr", version = "0.4.0" } -dioxus-desktop = { path = "packages/desktop", version = "0.4.0" } -dioxus-mobile = { path = "packages/mobile", version = "0.4.0" } +dioxus-web = { path = "packages/web", version = "0.4.0" } +dioxus-ssr = { path = "packages/ssr", version = "0.4.0" } +dioxus-desktop = { path = "packages/desktop", version = "0.4.0" } +dioxus-mobile = { path = "packages/mobile", version = "0.4.0" } dioxus-interpreter-js = { path = "packages/interpreter", version = "0.4.0" } -fermi = { path = "packages/fermi", version = "0.4.0" } -dioxus-liveview = { path = "packages/liveview", version = "0.4.0" } -dioxus-autofmt = { path = "packages/autofmt", version = "0.4.0" } -dioxus-check = { path = "packages/check", version = "0.4.0" } -dioxus-rsx = { path = "packages/rsx", version = "0.4.0" } -dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0" } +fermi = { path = "packages/fermi", version = "0.4.0" } +dioxus-liveview = { path = "packages/liveview", version = "0.4.0" } +dioxus-autofmt = { path = "packages/autofmt", version = "0.4.0" } +dioxus-check = { path = "packages/check", version = "0.4.0" } +dioxus-rsx = { path = "packages/rsx", version = "0.4.0" } +dioxus-tui = { path = "packages/dioxus-tui", version = "0.4.0" } plasmo = { path = "packages/rink", version = "0.4.0" } dioxus-native-core = { path = "packages/native-core", version = "0.4.0" } dioxus-native-core-macro = { path = "packages/native-core-macro", version = "0.4.0" } @@ -83,7 +83,7 @@ dioxus-signals = { path = "packages/signals" } dioxus-cli-config = { path = "packages/cli-config", version = "0.4.1" } generational-box = { path = "packages/generational-box", version = "0.4.3" } dioxus-hot-reload = { path = "packages/hot-reload", version = "0.4.0" } -dioxus-fullstack = { path = "packages/fullstack", version = "0.4.1" } +dioxus-fullstack = { path = "packages/fullstack", version = "0.4.1" } dioxus_server_macro = { path = "packages/server-macro", version = "0.4.1" } tracing = "0.1.37" tracing-futures = "0.2.5" @@ -144,4 +144,3 @@ thiserror = { workspace = true } manganis = { workspace = true } tracing-subscriber = "0.3.17" http-range = "0.1.5" - diff --git a/packages/autofmt/src/lib.rs b/packages/autofmt/src/lib.rs index e40b873d61..953f052b05 100644 --- a/packages/autofmt/src/lib.rs +++ b/packages/autofmt/src/lib.rs @@ -240,3 +240,10 @@ pub(crate) fn write_ifmt(input: &IfmtInput, writable: &mut impl Write) -> std::f let display = DisplayIfmt(input); write!(writable, "{}", display) } + +/// Call rustfmt to format code, i32 as exitcode +pub fn rustfmt(input: &str) -> Option { + let syntax_tree = syn::parse_file(input).ok()?; + let output = prettyplease::unparse(&syntax_tree); + Some(output) +} diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 0be33e9aec..dc53b74424 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -26,7 +26,7 @@ fs_extra = "1.2.0" cargo_toml = "0.18.0" futures-util.workspace = true notify = { version = "5.0.0-pre.16", features = ["serde"] } -html_parser = { workspace = true } +html_parser = { workspace = true } cargo_metadata = "0.18.1" tokio = { version = "1.16.1", features = ["fs", "sync", "rt", "macros"] } atty = "0.2.14" @@ -36,6 +36,7 @@ hyper = "0.14.17" hyper-rustls = "0.23.2" indicatif = "0.17.5" subprocess = "0.2.9" +rayon = "1.8.0" axum = { version = "0.5.1", features = ["ws", "headers"] } axum-server = { version = "0.5.1", features = ["tls-rustls"] } @@ -84,7 +85,7 @@ dioxus-html = { workspace = true, features = ["hot-reload-context"] } dioxus-core = { workspace = true, features = ["serialize"] } dioxus-hot-reload = { workspace = true } interprocess-docfix = { version = "1.2.2" } -gitignore = "1.0.8" +ignore = "0.4.22" [features] default = [] diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index d2e894d821..01612a1093 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -1,6 +1,6 @@ use dioxus_autofmt::{IndentOptions, IndentType}; -use futures_util::{stream::FuturesUnordered, StreamExt}; -use std::{fs, path::Path, process::exit}; +use rayon::prelude::*; +use std::{fs, io, path::Path, process::exit}; use super::*; @@ -40,13 +40,14 @@ impl Autoformat { raw, file, split_line_attributes, - rustfmt, + rustfmt: do_rustfmt, .. } = self; // Default to formatting the project if raw.is_none() && file.is_none() { - if let Err(e) = autoformat_project(check, split_line_attributes).await { + println!("format project !"); + if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt).await { eprintln!("error formatting project: {}", e); exit(1); } @@ -65,46 +66,13 @@ impl Autoformat { // Format single file if let Some(file) = file { - refactor_file(file, split_line_attributes, rustfmt)?; + refactor_file(file, split_line_attributes, do_rustfmt)?; } Ok(()) } } -/// Call rustfmt to format code, i32 as exitcode -fn rustfmt(input: String) -> Result { - use std::thread; - - let mut child = Command::new("rustfmt") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .map_err(|e| Error::IO(e))?; - - let mut stdin = child.stdin.take().unwrap(); - let pass_in = input.to_string(); - let handle = thread::spawn(move || -> Result<()> { - stdin - .write_all(pass_in.as_bytes()) - .map_err(|e| Error::IO(e))?; - Ok(()) - }); - handle.join().unwrap()?; - - let output = child.wait_with_output().map_err(|e| Error::IO(e))?; - - if let Some(exit_code) = output.status.code() { - if exit_code != 0 { - return Err(Error::ExitCodeNotZero(exit_code)); - } - } - - let output = String::from_utf8(output.stdout).map_err(|e| Error::Other(e.into()))?; - - Ok(output) -} - fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> Result<(), Error> { let indent = indentation_for(".", split_line_attributes)?; let file_content = if file == "-" { @@ -120,7 +88,7 @@ fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> }; if do_rustfmt { - s = rustfmt(s)?; + s = dioxus_autofmt::rustfmt(&s).ok_or_else(|| Error::ParseError("Syntax Error".into()))?; } let edits = dioxus_autofmt::fmt_file(&s, indent); @@ -137,25 +105,21 @@ fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> Ok(()) } -fn get_project_files(config: &CrateConfig) -> Vec { - let mut files = vec![]; - - let gitignore_path = config.crate_dir.join(".gitignore"); - if gitignore_path.is_file() { - let gitigno = gitignore::File::new(gitignore_path.as_path()).unwrap(); - if let Ok(git_files) = gitigno.included_files() { - let git_files = git_files - .into_iter() - .filter(|f| f.ends_with(".rs") && !is_target_dir(f)); - files.extend(git_files) - }; - } else { - collect_rs_files(&config.crate_dir, &mut files); +use std::ffi::OsStr; +fn get_project_files() -> Vec { + let mut files = Vec::new(); + for result in ignore::Walk::new("./") { + let path = result.unwrap().into_path(); + if let Some(ext) = path.extension() { + if ext == OsStr::new("rs") { + files.push(path); + } + } } - files } +#[allow(dead_code)] fn is_target_dir(file: &Path) -> bool { let stripped = if let Ok(cwd) = std::env::current_dir() { file.strip_prefix(cwd).unwrap_or(file) @@ -169,18 +133,30 @@ fn is_target_dir(file: &Path) -> bool { } } -async fn format_file( - path: impl AsRef, - indent: IndentOptions, -) -> Result { - let contents = tokio::fs::read_to_string(&path).await?; +fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) -> Result { + let mut contents = fs::read_to_string(&path)?; + let mut if_write = false; + if do_rustfmt { + let formatted = dioxus_autofmt::rustfmt(&contents) + .ok_or_else(|| Error::ParseError("Syntax Error".into()))?; + if contents != formatted { + if_write = true; + contents = formatted; + } + } + + println!("at {} : {:#?}", path.as_ref().display(), &contents); let edits = dioxus_autofmt::fmt_file(&contents, indent); let len = edits.len(); if !edits.is_empty() { + if_write = true; + } + + if if_write { let out = dioxus_autofmt::apply_formats(&contents, edits); - tokio::fs::write(path, out).await?; + fs::write(path, out)?; } Ok(len) @@ -190,11 +166,15 @@ async fn format_file( /// /// Runs using Tokio for multithreading, so it should be really really fast /// -/// Doesn't do mod-descending, so it will still try to format unreachable files. TODO. -async fn autoformat_project(check: bool, split_line_attributes: bool) -> Result<()> { - let crate_config = dioxus_cli_config::CrateConfig::new(None)?; +/// Doesnhttps://www.rustwiki.org.cn/zh-CN/std/'t do mod-descending, so it will still try to format unreachable files. TODO. +async fn autoformat_project( + check: bool, + split_line_attributes: bool, + do_rustfmt: bool, +) -> Result<()> { + let files_to_format = get_project_files(); - let files_to_format = get_project_files(&crate_config); + dbg!(&files_to_format); if files_to_format.is_empty() { return Ok(()); @@ -203,26 +183,18 @@ async fn autoformat_project(check: bool, split_line_attributes: bool) -> Result< let indent = indentation_for(&files_to_format[0], split_line_attributes)?; let counts = files_to_format - .into_iter() - .map(|path| async { - let path_clone = path.clone(); - let res = tokio::spawn(format_file(path, indent.clone())).await; - + .into_par_iter() + .map(|path| { + let res = format_file(&path, indent.clone(), do_rustfmt); match res { + Ok(cnt) => Some(cnt), Err(err) => { - eprintln!("error formatting file: {}\n{err}", path_clone.display()); - None - } - Ok(Err(err)) => { - eprintln!("error formatting file: {}\n{err}", path_clone.display()); + eprintln!("error formatting file : {}\n{:#?}", path.display(), err); None } - Ok(Ok(res)) => Some(res), } }) - .collect::>() - .collect::>() - .await; + .collect::>(); let files_formatted: usize = counts.into_iter().flatten().sum(); @@ -281,6 +253,7 @@ fn indentation_for( )) } +#[allow(dead_code)] fn collect_rs_files(folder: &impl AsRef, files: &mut Vec) { if is_target_dir(folder.as_ref()) { return; From 192fa3471b2b7ceecd16ec4cdca0abeadb1bd182 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 20:56:12 +0800 Subject: [PATCH 03/10] clippy fix --- packages/cli/src/cli/autoformat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 01612a1093..bcf9b266fd 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -1,6 +1,6 @@ use dioxus_autofmt::{IndentOptions, IndentType}; use rayon::prelude::*; -use std::{fs, io, path::Path, process::exit}; +use std::{fs, path::Path, process::exit}; use super::*; From d170304a596198999c0617a94103a17381f903cd Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 21:01:33 +0800 Subject: [PATCH 04/10] remove dead code --- packages/cli/src/cli/autoformat.rs | 43 +----------------------------- 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index bcf9b266fd..b1ec83a66f 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -1,6 +1,6 @@ use dioxus_autofmt::{IndentOptions, IndentType}; use rayon::prelude::*; -use std::{fs, path::Path, process::exit}; +use std::{fs, io, path::Path, process::exit}; use super::*; @@ -119,20 +119,6 @@ fn get_project_files() -> Vec { files } -#[allow(dead_code)] -fn is_target_dir(file: &Path) -> bool { - let stripped = if let Ok(cwd) = std::env::current_dir() { - file.strip_prefix(cwd).unwrap_or(file) - } else { - file - }; - if let Some(first) = stripped.components().next() { - first.as_os_str() == "target" - } else { - false - } -} - fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) -> Result { let mut contents = fs::read_to_string(&path)?; let mut if_write = false; @@ -174,8 +160,6 @@ async fn autoformat_project( ) -> Result<()> { let files_to_format = get_project_files(); - dbg!(&files_to_format); - if files_to_format.is_empty() { return Ok(()); } @@ -253,31 +237,6 @@ fn indentation_for( )) } -#[allow(dead_code)] -fn collect_rs_files(folder: &impl AsRef, files: &mut Vec) { - if is_target_dir(folder.as_ref()) { - return; - } - let Ok(folder) = folder.as_ref().read_dir() else { - return; - }; - // load the gitignore - for entry in folder { - let Ok(entry) = entry else { - continue; - }; - let path = entry.path(); - if path.is_dir() { - collect_rs_files(&path, files); - } - if let Some(ext) = path.extension() { - if ext == "rs" && !is_target_dir(&path) { - files.push(path); - } - } - } -} - #[tokio::test] async fn test_auto_fmt() { let test_rsx = r#" From 71125c22e0fe767a5e0c8e211b50d649fb380058 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 21:03:04 +0800 Subject: [PATCH 05/10] remove unused import --- packages/cli/src/cli/autoformat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index b1ec83a66f..b2e41a6c32 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -1,6 +1,6 @@ use dioxus_autofmt::{IndentOptions, IndentType}; use rayon::prelude::*; -use std::{fs, io, path::Path, process::exit}; +use std::{fs, path::Path, process::exit}; use super::*; From 82fc7acaa5c2712e5b0b0ca7fa2d1593926b1202 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Tue, 6 Feb 2024 21:04:37 +0800 Subject: [PATCH 06/10] remove debug print --- packages/cli/src/cli/autoformat.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index b2e41a6c32..d487afe1ec 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -46,7 +46,6 @@ impl Autoformat { // Default to formatting the project if raw.is_none() && file.is_none() { - println!("format project !"); if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt).await { eprintln!("error formatting project: {}", e); exit(1); @@ -131,8 +130,6 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) } } - println!("at {} : {:#?}", path.as_ref().display(), &contents); - let edits = dioxus_autofmt::fmt_file(&contents, indent); let len = edits.len(); From c89a4b37dc7c1423ef698b25560d081018cb31f0 Mon Sep 17 00:00:00 2001 From: Dangerise <2237556709@qq.com> Date: Wed, 7 Feb 2024 22:35:55 +0800 Subject: [PATCH 07/10] remove the link in comment and unused error variant --- packages/cli/src/cli/autoformat.rs | 4 ++-- packages/cli/src/error.rs | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index d487afe1ec..83fbdc1b85 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -147,9 +147,9 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) /// Read every .rs file accessible when considering the .gitignore and try to format it /// -/// Runs using Tokio for multithreading, so it should be really really fast +/// Runs using rayon for multithreading, so it should be really really fast /// -/// Doesnhttps://www.rustwiki.org.cn/zh-CN/std/'t do mod-descending, so it will still try to format unreachable files. TODO. +/// Doesn't do mod-descending, so it will still try to format unreachable files. TODO. async fn autoformat_project( check: bool, split_line_attributes: bool, diff --git a/packages/cli/src/error.rs b/packages/cli/src/error.rs index 98c7fc36b2..35eea7eabd 100644 --- a/packages/cli/src/error.rs +++ b/packages/cli/src/error.rs @@ -46,9 +46,6 @@ pub enum Error { #[error(transparent)] Other(#[from] anyhow::Error), - - #[error("Child process exited with {0}")] - ExitCodeNotZero(i32), } impl From<&str> for Error { From b88c66d8dfdffdaf3204ff17fb4e99444793ff0a Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 8 Feb 2024 10:00:25 -0600 Subject: [PATCH 08/10] report syn parse errors to the user --- Cargo.lock | 2 ++ packages/autofmt/src/lib.rs | 7 ------ packages/cli/Cargo.toml | 4 ++++ packages/cli/src/cli/autoformat.rs | 34 ++++++++++++++++++++---------- packages/cli/src/main.rs | 1 - 5 files changed, 29 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 471818cf6e..3477f46ca0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2418,12 +2418,14 @@ dependencies = [ "mlua", "notify", "open", + "prettier-please", "rayon", "reqwest", "rsx-rosetta", "serde", "serde_json", "subprocess", + "syn 2.0.48", "tar", "tauri-bundler", "tempfile", diff --git a/packages/autofmt/src/lib.rs b/packages/autofmt/src/lib.rs index 953f052b05..e40b873d61 100644 --- a/packages/autofmt/src/lib.rs +++ b/packages/autofmt/src/lib.rs @@ -240,10 +240,3 @@ pub(crate) fn write_ifmt(input: &IfmtInput, writable: &mut impl Write) -> std::f let display = DisplayIfmt(input); write!(writable, "{}", display) } - -/// Call rustfmt to format code, i32 as exitcode -pub fn rustfmt(input: &str) -> Option { - let syntax_tree = syn::parse_file(input).ok()?; - let output = prettyplease::unparse(&syntax_tree); - Some(output) -} diff --git a/packages/cli/Cargo.toml b/packages/cli/Cargo.toml index 82c16e0dcd..657c70e0f9 100644 --- a/packages/cli/Cargo.toml +++ b/packages/cli/Cargo.toml @@ -75,6 +75,10 @@ toml_edit = "0.21.0" # bundling tauri-bundler = { version = "=1.4.*", features = ["native-tls-vendored"] } +# formatting +syn = { version = "2.0" } +prettyplease = { workspace = true } + manganis-cli-support = { workspace = true, features = ["webp", "html"] } dioxus-autofmt = { workspace = true } diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 2b8093f752..36072b967a 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -33,8 +33,7 @@ pub struct Autoformat { } impl Autoformat { - // Todo: autoformat the entire crate - pub async fn autoformat(self) -> Result<()> { + pub fn autoformat(self) -> Result<()> { let Autoformat { check, raw, @@ -46,7 +45,7 @@ impl Autoformat { // Default to formatting the project if raw.is_none() && file.is_none() { - if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt).await { + if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt) { eprintln!("error formatting project: {}", e); exit(1); } @@ -87,7 +86,7 @@ fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> }; if do_rustfmt { - s = dioxus_autofmt::rustfmt(&s).ok_or_else(|| Error::ParseError("Syntax Error".into()))?; + s = rustfmt(&s)?; } let edits = dioxus_autofmt::fmt_file(&s, indent); @@ -122,8 +121,8 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) let mut contents = fs::read_to_string(&path)?; let mut if_write = false; if do_rustfmt { - let formatted = dioxus_autofmt::rustfmt(&contents) - .ok_or_else(|| Error::ParseError("Syntax Error".into()))?; + let formatted = rustfmt(&contents) + .map_err(|err| Error::ParseError(format!("Syntax Error:\n{}", err)))?; if contents != formatted { if_write = true; contents = formatted; @@ -150,11 +149,7 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) /// Runs using rayon for multithreading, so it should be really really fast /// /// Doesn't do mod-descending, so it will still try to format unreachable files. TODO. -async fn autoformat_project( - check: bool, - split_line_attributes: bool, - do_rustfmt: bool, -) -> Result<()> { +fn autoformat_project(check: bool, split_line_attributes: bool, do_rustfmt: bool) -> Result<()> { let files_to_format = get_project_files(); if files_to_format.is_empty() { @@ -238,6 +233,23 @@ fn indentation_for( )) } +/// Format rust code using prettyplease +pub fn rustfmt(input: &str) -> Result { + let syntax_tree = syn::parse_file(input).map_err(format_syn_error)?; + let output = prettyplease::unparse(&syntax_tree); + Ok(output) +} + +fn format_syn_error(err: syn::Error) -> Error { + let start = err.span().start(); + let line = start.line; + let column = start.column; + Error::ParseError(format!( + "Syntax Error in line {} column {}:\n{}", + line, column, err + )) +} + #[tokio::test] async fn test_auto_fmt() { let test_rsx = r#" diff --git a/packages/cli/src/main.rs b/packages/cli/src/main.rs index 0a57735db5..dae2deb2c6 100644 --- a/packages/cli/src/main.rs +++ b/packages/cli/src/main.rs @@ -70,7 +70,6 @@ async fn main() -> anyhow::Result<()> { Autoformat(opts) => opts .autoformat() - .await .context(error_wrapper("Error autoformatting RSX")), Check(opts) => opts From 23e15ee9c81cd47e2763090d91369d7a65ac1217 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 8 Feb 2024 10:03:52 -0600 Subject: [PATCH 09/10] change rustfmt flag to all_code now that we don't use rustfmt --- packages/cli/src/cli/autoformat.rs | 42 +++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 36072b967a..2855fcbe9a 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -10,9 +10,9 @@ use super::*; /// Format some rsx #[derive(Clone, Debug, Parser)] pub struct Autoformat { - /// Run rustfmt before the dioxus formatter` + /// Format rust code before the formatting the rsx macros #[clap(long)] - pub rustfmt: bool, + pub all_code: bool, /// Run in 'check' mode. Exits with 0 if input is formatted correctly. Exits /// with 1 and prints a diff if formatting is required. @@ -39,13 +39,13 @@ impl Autoformat { raw, file, split_line_attributes, - rustfmt: do_rustfmt, + all_code: format_rust_code, .. } = self; // Default to formatting the project if raw.is_none() && file.is_none() { - if let Err(e) = autoformat_project(check, split_line_attributes, do_rustfmt) { + if let Err(e) = autoformat_project(check, split_line_attributes, format_rust_code) { eprintln!("error formatting project: {}", e); exit(1); } @@ -64,14 +64,18 @@ impl Autoformat { // Format single file if let Some(file) = file { - refactor_file(file, split_line_attributes, do_rustfmt)?; + refactor_file(file, split_line_attributes, format_rust_code)?; } Ok(()) } } -fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> Result<(), Error> { +fn refactor_file( + file: String, + split_line_attributes: bool, + format_rust_code: bool, +) -> Result<(), Error> { let indent = indentation_for(".", split_line_attributes)?; let file_content = if file == "-" { let mut contents = String::new(); @@ -85,8 +89,8 @@ fn refactor_file(file: String, split_line_attributes: bool, do_rustfmt: bool) -> exit(1); }; - if do_rustfmt { - s = rustfmt(&s)?; + if format_rust_code { + s = format_rust(&s)?; } let edits = dioxus_autofmt::fmt_file(&s, indent); @@ -117,11 +121,15 @@ fn get_project_files() -> Vec { files } -fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) -> Result { +fn format_file( + path: impl AsRef, + indent: IndentOptions, + format_rust_code: bool, +) -> Result { let mut contents = fs::read_to_string(&path)?; let mut if_write = false; - if do_rustfmt { - let formatted = rustfmt(&contents) + if format_rust_code { + let formatted = format_rust(&contents) .map_err(|err| Error::ParseError(format!("Syntax Error:\n{}", err)))?; if contents != formatted { if_write = true; @@ -149,7 +157,11 @@ fn format_file(path: impl AsRef, indent: IndentOptions, do_rustfmt: bool) /// Runs using rayon for multithreading, so it should be really really fast /// /// Doesn't do mod-descending, so it will still try to format unreachable files. TODO. -fn autoformat_project(check: bool, split_line_attributes: bool, do_rustfmt: bool) -> Result<()> { +fn autoformat_project( + check: bool, + split_line_attributes: bool, + format_rust_code: bool, +) -> Result<()> { let files_to_format = get_project_files(); if files_to_format.is_empty() { @@ -165,7 +177,7 @@ fn autoformat_project(check: bool, split_line_attributes: bool, do_rustfmt: bool let counts = files_to_format .into_par_iter() .map(|path| { - let res = format_file(&path, indent.clone(), do_rustfmt); + let res = format_file(&path, indent.clone(), format_rust_code); match res { Ok(cnt) => Some(cnt), Err(err) => { @@ -234,7 +246,7 @@ fn indentation_for( } /// Format rust code using prettyplease -pub fn rustfmt(input: &str) -> Result { +fn format_rust(input: &str) -> Result { let syntax_tree = syn::parse_file(input).map_err(format_syn_error)?; let output = prettyplease::unparse(&syntax_tree); Ok(output) @@ -268,7 +280,7 @@ async fn test_auto_fmt() { .to_string(); let fmt = Autoformat { - rustfmt: false, + all_code: false, check: false, raw: Some(test_rsx), file: None, From d1ed15c2ace4efba1dd86a807986de15782a0b86 Mon Sep 17 00:00:00 2001 From: Evan Almloff Date: Thu, 8 Feb 2024 10:13:57 -0600 Subject: [PATCH 10/10] fix autofmt tests --- packages/cli/src/cli/autoformat.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/cli/autoformat.rs b/packages/cli/src/cli/autoformat.rs index 2855fcbe9a..b3d6cedf95 100644 --- a/packages/cli/src/cli/autoformat.rs +++ b/packages/cli/src/cli/autoformat.rs @@ -287,7 +287,7 @@ async fn test_auto_fmt() { split_line_attributes: false, }; - fmt.autoformat().await.unwrap(); + fmt.autoformat().unwrap(); } /*#[test]