Merge pull request #1215 from eventualbuddha/feat/check/rules-of-hooks
feat(check): adds `dx check`
This commit is contained in:
13 files changed
+1504
-18
No files matched your search
@@ -77,6 +77,7 @@ toml_edit = "0.19.11"
|
||||
# dioxus-rsx = "0.0.1"
|
||||
|
||||
dioxus-autofmt = { workspace = true }
|
||||
dioxus-check = { workspace = true }
|
||||
rsx-rosetta = { workspace = true }
|
||||
dioxus-rsx = { workspace = true }
|
||||
dioxus-html = { workspace = true, features = ["hot-reload-context"] }
|
||||
|
||||
@@ -5,22 +5,25 @@ In this chapter we will introduce all `dioxus-cli` commands.
|
||||
> You can also use `dx --help` to get cli help info.
|
||||
|
||||
```
|
||||
dx
|
||||
Build, bundle, & ship your Dioxus app
|
||||
Build, Bundle & Ship Dioxus Apps
|
||||
|
||||
USAGE:
|
||||
dx [OPTIONS] <SUBCOMMAND>
|
||||
Usage: dx [OPTIONS] <COMMAND>
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Print help information
|
||||
-v Enable verbose logging
|
||||
Commands:
|
||||
build Build the Rust WASM app and all of its assets
|
||||
translate Translate some source file into Dioxus code
|
||||
serve Build, watch & serve the Rust WASM app and all of its assets
|
||||
create Init a new project for Dioxus
|
||||
clean Clean output artifacts
|
||||
version Print the version of this extension
|
||||
fmt Format some rsx
|
||||
check Check the Rust files in the project for issues
|
||||
config Dioxus config file controls
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
|
||||
SUBCOMMANDS:
|
||||
build Build the Dioxus application and all of its assets
|
||||
clean Clean output artifacts
|
||||
config Dioxus config file controls
|
||||
create Init a new project for Dioxus
|
||||
help Print this message or the help of the given subcommand(s)
|
||||
serve Build, watch & serve the Rust WASM app and all of its assets
|
||||
translate Translate some html file into a Dioxus component
|
||||
Options:
|
||||
-v Enable verbose logging
|
||||
--bin <BIN> Specify bin target
|
||||
-h, --help Print help
|
||||
-V, --version Print version
|
||||
```
|
||||
@@ -0,0 +1,128 @@
|
||||
use futures::{stream::FuturesUnordered, StreamExt};
|
||||
use std::{path::Path, process::exit};
|
||||
|
||||
use super::*;
|
||||
|
||||
// For reference, the rustfmt main.rs file
|
||||
// https://github.com/rust-lang/rustfmt/blob/master/src/bin/main.rs
|
||||
|
||||
/// Check the Rust files in the project for issues.
|
||||
#[derive(Clone, Debug, Parser)]
|
||||
pub struct Check {
|
||||
/// Input file
|
||||
#[clap(short, long)]
|
||||
pub file: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Check {
|
||||
// Todo: check the entire crate
|
||||
pub async fn check(self) -> Result<()> {
|
||||
match self.file {
|
||||
// Default to checking the project
|
||||
None => {
|
||||
if let Err(e) = check_project_and_report().await {
|
||||
eprintln!("error checking project: {}", e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
Some(file) => {
|
||||
if let Err(e) = check_file_and_report(file).await {
|
||||
eprintln!("failed to check file: {}", e);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
async fn check_file_and_report(path: PathBuf) -> Result<()> {
|
||||
check_files_and_report(vec![path]).await
|
||||
}
|
||||
|
||||
/// Read every .rs file accessible when considering the .gitignore and check it
|
||||
///
|
||||
/// Runs using Tokio for multithreading, so it should be really really fast
|
||||
///
|
||||
/// Doesn't do mod-descending, so it will still try to check unreachable files. TODO.
|
||||
async fn check_project_and_report() -> Result<()> {
|
||||
let crate_config = crate::CrateConfig::new(None)?;
|
||||
|
||||
let mut files_to_check = vec![];
|
||||
collect_rs_files(&crate_config.crate_dir, &mut files_to_check);
|
||||
check_files_and_report(files_to_check).await
|
||||
}
|
||||
|
||||
/// Check a list of files and report the issues.
|
||||
async fn check_files_and_report(files_to_check: Vec<PathBuf>) -> Result<()> {
|
||||
let issue_reports = files_to_check
|
||||
.into_iter()
|
||||
.filter(|file| file.components().all(|f| f.as_os_str() != "target"))
|
||||
.map(|path| async move {
|
||||
let _path = path.clone();
|
||||
let res = tokio::spawn(async move {
|
||||
tokio::fs::read_to_string(&_path)
|
||||
.await
|
||||
.map(|contents| dioxus_check::check_file(_path, &contents))
|
||||
})
|
||||
.await;
|
||||
|
||||
if res.is_err() {
|
||||
eprintln!("error checking file: {}", path.display());
|
||||
}
|
||||
|
||||
res
|
||||
})
|
||||
.collect::<FuturesUnordered<_>>()
|
||||
.collect::<Vec<_>>()
|
||||
.await;
|
||||
|
||||
// remove error results which we've already printed
|
||||
let issue_reports = issue_reports
|
||||
.into_iter()
|
||||
.flatten()
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let total_issues = issue_reports.iter().map(|r| r.issues.len()).sum::<usize>();
|
||||
|
||||
for report in issue_reports.into_iter() {
|
||||
if !report.issues.is_empty() {
|
||||
println!("{}", report);
|
||||
}
|
||||
}
|
||||
|
||||
match total_issues {
|
||||
0 => println!("No issues found."),
|
||||
1 => println!("1 issue found."),
|
||||
_ => println!("{} issues found.", total_issues),
|
||||
}
|
||||
|
||||
match total_issues {
|
||||
0 => exit(0),
|
||||
_ => exit(1),
|
||||
}
|
||||
}
|
||||
|
||||
fn collect_rs_files(folder: &Path, files: &mut Vec<PathBuf>) {
|
||||
let Ok(folder) = folder.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" {
|
||||
files.push(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
pub mod autoformat;
|
||||
pub mod build;
|
||||
pub mod cfg;
|
||||
pub mod check;
|
||||
pub mod clean;
|
||||
pub mod config;
|
||||
pub mod create;
|
||||
@@ -67,6 +68,9 @@ pub enum Commands {
|
||||
#[clap(name = "fmt")]
|
||||
Autoformat(autoformat::Autoformat),
|
||||
|
||||
#[clap(name = "check")]
|
||||
Check(check::Check),
|
||||
|
||||
/// Dioxus config file controls.
|
||||
#[clap(subcommand)]
|
||||
Config(config::Config),
|
||||
@@ -88,6 +92,7 @@ impl Display for Commands {
|
||||
Commands::Config(_) => write!(f, "config"),
|
||||
Commands::Version(_) => write!(f, "version"),
|
||||
Commands::Autoformat(_) => write!(f, "fmt"),
|
||||
Commands::Check(_) => write!(f, "check"),
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
Commands::Plugin(_) => write!(f, "plugin"),
|
||||
|
||||
@@ -103,6 +103,11 @@ async fn main() -> anyhow::Result<()> {
|
||||
.await
|
||||
.map_err(|e| anyhow!("🚫 Error autoformatting RSX: {}", e)),
|
||||
|
||||
Check(opts) => opts
|
||||
.check()
|
||||
.await
|
||||
.map_err(|e| anyhow!("🚫 Error checking RSX: {}", e)),
|
||||
|
||||
Version(opt) => {
|
||||
let version = opt.version();
|
||||
println!("{}", version);
|
||||
|
||||
Reference in new issue
Block a user