Merge pull request #1215 from eventualbuddha/feat/check/rules-of-hooks

feat(check): adds `dx check`
This commit is contained in:
Jonathan Kelley authored and GitHub committed 2023-07-25 11:57:02 -07:00
commit 6751d5941b
13 files changed
+1504 -18

No files matched your search

+1
View File
@@ -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"] }
+18 -15
View File
@@ -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
```
+128
View File
@@ -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);
}
}
}
}
+5
View File
@@ -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"),
+5
View File
@@ -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);