From e3f9a5adb1d57a5b9c60606961f9b18f0fb2639b Mon Sep 17 00:00:00 2001 From: 魏曹先生 <1992414357@qq.com> Date: Tue, 4 Aug 2026 20:39:00 +0800 Subject: refactor(linter): rename cmd_mlint to cmd_lint --- mingling_cli/src/linter.rs | 4 +- mingling_cli/src/linter/cmd_lint.rs | 138 +++++++++++++++++++++++++++++++++++ mingling_cli/src/linter/cmd_mlint.rs | 138 ----------------------------------- 3 files changed, 140 insertions(+), 140 deletions(-) create mode 100644 mingling_cli/src/linter/cmd_lint.rs delete mode 100644 mingling_cli/src/linter/cmd_mlint.rs (limited to 'mingling_cli/src') diff --git a/mingling_cli/src/linter.rs b/mingling_cli/src/linter.rs index 3182b4a..3b7069d 100644 --- a/mingling_cli/src/linter.rs +++ b/mingling_cli/src/linter.rs @@ -3,9 +3,9 @@ use mingling::{ metadata::Description, }; -use crate::{linter::cmd_mlint::EntryLint, metadata::setup::ResUsingJson}; +use crate::{linter::cmd_lint::EntryLint, metadata::setup::ResUsingJson}; -pub mod cmd_mlint; +pub mod cmd_lint; pub mod mlint_attr; pub mod mlint_report; diff --git a/mingling_cli/src/linter/cmd_lint.rs b/mingling_cli/src/linter/cmd_lint.rs new file mode 100644 index 0000000..57a78ad --- /dev/null +++ b/mingling_cli/src/linter/cmd_lint.rs @@ -0,0 +1,138 @@ +use crate::linter::mlint_report::{MlintReport, StateLintReports}; +use cargo_metadata::Metadata; +use mingling::LazyRes; +use mingling::consts::REMAINS; +use mingling::macros::{arg, chain, dispatcher, metadata, pack}; +use mingling::metadata::Description; +use mingling::picker::EntryPicker; +use tokio::task::JoinSet; + +dispatcher!("lint", CMDLint => EntryLint); + +#[metadata(EntryLint)] +pub fn desc_lint() -> Description { + "Mingling Linter".to_string().into() +} + +/// Main linting function that processes all packages in the metadata. +/// +/// Iterates through all packages and their targets (e.g., binaries, libraries, tests), +/// reads Rust source files (`.rs`), parses them into ASTs, runs lint checks, +/// and enriches each report with metadata information. +async fn linter_main(metadata: &Metadata) -> Vec { + let mut join_set = JoinSet::new(); + + for package in &metadata.packages { + for target in &package.targets { + let path = &target.src_path; + // Only process Rust source files (with `.rs` extension) + if !path.as_str().ends_with(".rs") { + continue; + } + + // Clone/move all data needed inside the blocking closure + let path_str = path.as_str().to_string(); + let package_id = package.id.to_string(); + let target_name = target.name.clone(); + let target_kind = target.kind.first().map(|k| k.to_string()); + + join_set.spawn_blocking(move || { + // Read the source file content + let source = std::fs::read_to_string(&path_str).ok()?; + // Parse the source file into an AST + let ast = syn::parse_file(&source).ok()?; + // Run all lint checks and collect reports + let reports = crate::lints::run_all_lints(&ast, &source); + + // Enrich each report with metadata information + let enriched: Vec = reports + .into_iter() + .map(|mut r| { + r.file_name = path_str.clone(); + r.source_code = source.clone(); + r.package_id = Some(package_id.clone()); + r.target_name = Some(target_name.clone()); + r.target_kind = target_kind.clone(); + r.target_src_path = Some(path_str.clone()); + r + }) + .collect(); + + Some(enriched) + }); + } + } + + let mut all_reports = Vec::new(); + while let Some(res) = join_set.join_next().await { + // `spawn_blocking` panics are propagated, `None` means task skipped (read/parse failure) + if let Ok(Some(reports)) = res { + all_reports.extend(reports); + } + } + + all_reports +} + +pack!(StateBeginLinter = ()); + +#[chain] +pub fn handle_lint(args: EntryLint) -> StateBeginLinter { + let (with_checker, checker_args) = args + .pick_or(&arg![with_checker: Option], || { + Some("cargo,check".to_string()) + }) + .pick(&REMAINS) + .unwrap(); + + // If with_checker is not set, proceed directly to the mingling lint phase + let Some(with_checker) = with_checker else { + return StateBeginLinter::new(()); + }; + + let with_checker: Vec<&str> = with_checker.split(',').collect(); + let checker_args: Vec = checker_args.into(); + + // Run the outer checker (e.g. cargo check) with output passed through directly + execute_checker(&with_checker, checker_args.as_slice()); + + StateBeginLinter::new(()) +} + +/// Run the outer checker (e.g. cargo check) with output passed through directly. +fn execute_checker(with_checker: &[&str], checker_args: &[String]) { + if with_checker.is_empty() { + return; + } + + let checker_str = with_checker.join(" "); + let args_str = checker_args.join(" "); + let full_cmd = if args_str.is_empty() { + checker_str + } else { + format!("{} {}", checker_str, args_str) + }; + + let mut cmd = if cfg!(target_os = "windows") { + let mut c = std::process::Command::new("cmd"); + c.args(["/C", &full_cmd]); + c + } else { + let mut c = std::process::Command::new("sh"); + c.args(["-c", &full_cmd]); + c + }; + + // Pass through stdin/stdout/stderr so the user sees everything + let _ = cmd.status(); +} + +#[chain] +pub async fn handle_state_begin_linter( + _: StateBeginLinter, + metadata: &mut LazyRes, +) -> StateLintReports { + let metadata = metadata.get_ref().data(); + let reports = linter_main(metadata).await; + StateLintReports::new(reports) +} diff --git a/mingling_cli/src/linter/cmd_mlint.rs b/mingling_cli/src/linter/cmd_mlint.rs deleted file mode 100644 index 57a78ad..0000000 --- a/mingling_cli/src/linter/cmd_mlint.rs +++ /dev/null @@ -1,138 +0,0 @@ -use crate::linter::mlint_report::{MlintReport, StateLintReports}; -use cargo_metadata::Metadata; -use mingling::LazyRes; -use mingling::consts::REMAINS; -use mingling::macros::{arg, chain, dispatcher, metadata, pack}; -use mingling::metadata::Description; -use mingling::picker::EntryPicker; -use tokio::task::JoinSet; - -dispatcher!("lint", CMDLint => EntryLint); - -#[metadata(EntryLint)] -pub fn desc_lint() -> Description { - "Mingling Linter".to_string().into() -} - -/// Main linting function that processes all packages in the metadata. -/// -/// Iterates through all packages and their targets (e.g., binaries, libraries, tests), -/// reads Rust source files (`.rs`), parses them into ASTs, runs lint checks, -/// and enriches each report with metadata information. -async fn linter_main(metadata: &Metadata) -> Vec { - let mut join_set = JoinSet::new(); - - for package in &metadata.packages { - for target in &package.targets { - let path = &target.src_path; - // Only process Rust source files (with `.rs` extension) - if !path.as_str().ends_with(".rs") { - continue; - } - - // Clone/move all data needed inside the blocking closure - let path_str = path.as_str().to_string(); - let package_id = package.id.to_string(); - let target_name = target.name.clone(); - let target_kind = target.kind.first().map(|k| k.to_string()); - - join_set.spawn_blocking(move || { - // Read the source file content - let source = std::fs::read_to_string(&path_str).ok()?; - // Parse the source file into an AST - let ast = syn::parse_file(&source).ok()?; - // Run all lint checks and collect reports - let reports = crate::lints::run_all_lints(&ast, &source); - - // Enrich each report with metadata information - let enriched: Vec = reports - .into_iter() - .map(|mut r| { - r.file_name = path_str.clone(); - r.source_code = source.clone(); - r.package_id = Some(package_id.clone()); - r.target_name = Some(target_name.clone()); - r.target_kind = target_kind.clone(); - r.target_src_path = Some(path_str.clone()); - r - }) - .collect(); - - Some(enriched) - }); - } - } - - let mut all_reports = Vec::new(); - while let Some(res) = join_set.join_next().await { - // `spawn_blocking` panics are propagated, `None` means task skipped (read/parse failure) - if let Ok(Some(reports)) = res { - all_reports.extend(reports); - } - } - - all_reports -} - -pack!(StateBeginLinter = ()); - -#[chain] -pub fn handle_lint(args: EntryLint) -> StateBeginLinter { - let (with_checker, checker_args) = args - .pick_or(&arg![with_checker: Option], || { - Some("cargo,check".to_string()) - }) - .pick(&REMAINS) - .unwrap(); - - // If with_checker is not set, proceed directly to the mingling lint phase - let Some(with_checker) = with_checker else { - return StateBeginLinter::new(()); - }; - - let with_checker: Vec<&str> = with_checker.split(',').collect(); - let checker_args: Vec = checker_args.into(); - - // Run the outer checker (e.g. cargo check) with output passed through directly - execute_checker(&with_checker, checker_args.as_slice()); - - StateBeginLinter::new(()) -} - -/// Run the outer checker (e.g. cargo check) with output passed through directly. -fn execute_checker(with_checker: &[&str], checker_args: &[String]) { - if with_checker.is_empty() { - return; - } - - let checker_str = with_checker.join(" "); - let args_str = checker_args.join(" "); - let full_cmd = if args_str.is_empty() { - checker_str - } else { - format!("{} {}", checker_str, args_str) - }; - - let mut cmd = if cfg!(target_os = "windows") { - let mut c = std::process::Command::new("cmd"); - c.args(["/C", &full_cmd]); - c - } else { - let mut c = std::process::Command::new("sh"); - c.args(["-c", &full_cmd]); - c - }; - - // Pass through stdin/stdout/stderr so the user sees everything - let _ = cmd.status(); -} - -#[chain] -pub async fn handle_state_begin_linter( - _: StateBeginLinter, - metadata: &mut LazyRes, -) -> StateLintReports { - let metadata = metadata.get_ref().data(); - let reports = linter_main(metadata).await; - StateLintReports::new(reports) -} -- cgit