diff options
Diffstat (limited to 'mingling_cli/src/linter')
| -rw-r--r-- | mingling_cli/src/linter/cmd_mlint.rs | 69 | ||||
| -rw-r--r-- | mingling_cli/src/linter/mlint_report.rs | 12 |
2 files changed, 47 insertions, 34 deletions
diff --git a/mingling_cli/src/linter/cmd_mlint.rs b/mingling_cli/src/linter/cmd_mlint.rs index 90871af..55dd15c 100644 --- a/mingling_cli/src/linter/cmd_mlint.rs +++ b/mingling_cli/src/linter/cmd_mlint.rs @@ -4,6 +4,7 @@ use mingling::LazyRes; use mingling::consts::REMAINS; use mingling::macros::{arg, chain, dispatcher, pack}; use mingling::picker::EntryPicker; +use tokio::task::JoinSet; dispatcher!("lint", CMDMinglingLinter => EntryMinglingLinter); @@ -13,42 +14,54 @@ dispatcher!("lint", CMDMinglingLinter => EntryMinglingLinter); /// 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<MlintReport> { - // Vector to accumulate all lint reports - let mut all_reports = Vec::new(); + let mut join_set = JoinSet::new(); - // Iterate over all packages in the metadata for package in &metadata.packages { - // Iterate over all targets within a package (e.g., bin, lib, test, etc.) 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; } - // Read the source file content - let source = match std::fs::read_to_string(path.as_str()) { - Ok(s) => s, - Err(_) => continue, - }; - // Parse the source file into an AST (Abstract Syntax Tree) - let ast = match syn::parse_file(&source) { - Ok(f) => f, - Err(_) => continue, - }; - - // Run all lint checks and collect reports - let reports = crate::lints::run_all_lints(&ast, &source); - // - for mut r in reports { - // Enrich report with metadata information - r.file_name = path.as_str().to_string(); - r.source_code = source.clone(); - r.package_id = Some(package.id.to_string()); - r.target_name = Some(target.name.clone()); - r.target_kind = target.kind.first().map(|k| k.to_string()); - r.target_src_path = Some(path.as_str().to_string()); - all_reports.push(r); - } + + // 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<MlintReport> = 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); } } diff --git a/mingling_cli/src/linter/mlint_report.rs b/mingling_cli/src/linter/mlint_report.rs index 8195f77..0472056 100644 --- a/mingling_cli/src/linter/mlint_report.rs +++ b/mingling_cli/src/linter/mlint_report.rs @@ -51,8 +51,8 @@ pub struct MlintReport { /// Compilation target source file path that this report belongs to pub target_src_path: Option<String>, - /// A suggestion for automatic fix (shown as diff in annotated output) - pub suggestion: Option<LintSuggestion>, + /// Suggestions for automatic fix (shown as diff in annotated output) + pub suggestions: Vec<LintSuggestion>, } /// Report severity level, indicating the seriousness of the Lint result. @@ -248,8 +248,8 @@ impl MlintReport { group = group.element(msg); } - // Render suggestion as a diff (Element::Suggestion) - if let Some(sugg) = &self.suggestion { + // Render suggestions as diffs + for sugg in &self.suggestions { let patch_snippet = Snippet::source(sugg.source.clone()) .line_start(sugg.line_start) .path(&self.file_name) @@ -404,8 +404,8 @@ impl MlintReport { .collect::<Vec<_>>(), ) .label(span.label.clone()) - .suggested_replacement(self.suggestion.as_ref().map(|s| s.replacement.clone())) - .suggestion_applicability(if self.suggestion.is_some() { + .suggested_replacement(self.suggestions.first().map(|s| s.replacement.clone())) + .suggestion_applicability(if !self.suggestions.is_empty() { Some(cargo_metadata::diagnostic::Applicability::MachineApplicable) } else { None |
