diff --git a/apps/oxlint/src/lint.rs b/apps/oxlint/src/lint.rs index e0e1010e2e341..5a5a23daab815 100644 --- a/apps/oxlint/src/lint.rs +++ b/apps/oxlint/src/lint.rs @@ -41,13 +41,6 @@ impl Runner for LintRunner { let format_str = self.options.output_options.format; let output_formatter = OutputFormatter::new(format_str); - if self.options.list_rules { - if let Some(output) = output_formatter.all_rules() { - print_and_flush_stdout(stdout, &output); - } - return CliRunResult::None; - } - let LintCommand { paths, filter, @@ -254,6 +247,13 @@ impl Runner for LintRunner { let lint_config = config_builder.build(); + if self.options.list_rules { + if let Some(output) = output_formatter.all_rules(Some(&lint_config)) { + print_and_flush_stdout(stdout, &output); + } + return CliRunResult::None; + } + let report_unused_directives = match inline_config_options.report_unused_directives { ReportUnusedDirectives::WithoutSeverity(true) => Some(AllowWarnDeny::Warn), ReportUnusedDirectives::WithSeverity(Some(severity)) => Some(severity), diff --git a/apps/oxlint/src/output_formatter/default.rs b/apps/oxlint/src/output_formatter/default.rs index 6e4c6ac77d3cb..1b56a0a475b80 100644 --- a/apps/oxlint/src/output_formatter/default.rs +++ b/apps/oxlint/src/output_formatter/default.rs @@ -5,19 +5,21 @@ use oxc_diagnostics::{ Error, GraphicalReportHandler, reporter::{DiagnosticReporter, DiagnosticResult}, }; -use oxc_linter::table::RuleTable; +use oxc_linter::{Config, table::RuleTable}; #[derive(Debug)] pub struct DefaultOutputFormatter; impl InternalFormatter for DefaultOutputFormatter { - fn all_rules(&self) -> Option { + fn all_rules(&self, config: Option<&Config>) -> Option { let mut output = String::new(); - let table = RuleTable::default(); + let table = RuleTable::new(None, config); for section in table.sections { output.push_str(section.render_markdown_table(None).as_str()); output.push('\n'); } + + output.push_str(format!("Enabled: {}\n", table.enabled_count).as_str()); output.push_str(format!("Default: {}\n", table.turned_on_by_default_count).as_str()); output.push_str(format!("Total: {}\n", table.total).as_str()); Some(output) @@ -164,7 +166,7 @@ mod test { #[test] fn all_rules() { let formatter = DefaultOutputFormatter; - let result = formatter.all_rules(); + let result = formatter.all_rules(None); assert!(result.is_some()); } diff --git a/apps/oxlint/src/output_formatter/json.rs b/apps/oxlint/src/output_formatter/json.rs index ae49add3b337d..e76e3a9643288 100644 --- a/apps/oxlint/src/output_formatter/json.rs +++ b/apps/oxlint/src/output_formatter/json.rs @@ -5,7 +5,7 @@ use oxc_diagnostics::{ Error, reporter::{DiagnosticReporter, DiagnosticResult}, }; -use oxc_linter::{RuleCategory, rules::RULES}; +use oxc_linter::{Config, RuleCategory, rules::RULES}; use miette::JSONReportHandler; @@ -17,7 +17,7 @@ pub struct JsonOutputFormatter { } impl InternalFormatter for JsonOutputFormatter { - fn all_rules(&self) -> Option { + fn all_rules(&self, _config: Option<&Config>) -> Option { #[derive(Debug, serde::Serialize)] struct RuleInfoJson<'a> { scope: &'a str, diff --git a/apps/oxlint/src/output_formatter/mod.rs b/apps/oxlint/src/output_formatter/mod.rs index 39a922fae62ea..7b6a851a1ceff 100644 --- a/apps/oxlint/src/output_formatter/mod.rs +++ b/apps/oxlint/src/output_formatter/mod.rs @@ -19,6 +19,7 @@ use stylish::StylishOutputFormatter; use unix::UnixOutputFormatter; use oxc_diagnostics::reporter::DiagnosticReporter; +use oxc_linter::Config; use crate::output_formatter::{default::DefaultOutputFormatter, json::JsonOutputFormatter}; @@ -72,7 +73,7 @@ pub struct LintCommandInfo { /// The Formatter is then managed by [`OutputFormatter`]. trait InternalFormatter { /// Print all available rules by oxlint - fn all_rules(&self) -> Option { + fn all_rules(&self, _config: Option<&Config>) -> Option { None } @@ -110,8 +111,8 @@ impl OutputFormatter { /// Print all available rules by oxlint /// See [`InternalFormatter::all_rules`] for more details. - pub fn all_rules(&self) -> Option { - self.internal.all_rules() + pub fn all_rules(&self, config: Option<&Config>) -> Option { + self.internal.all_rules(config) } /// At the end of the Lint command we may output extra information. diff --git a/crates/oxc_linter/src/table.rs b/crates/oxc_linter/src/table.rs index 0bdc6fa0d4395..6e5e3894c922a 100644 --- a/crates/oxc_linter/src/table.rs +++ b/crates/oxc_linter/src/table.rs @@ -2,12 +2,13 @@ use std::{borrow::Cow, fmt::Write}; use rustc_hash::{FxHashMap, FxHashSet}; -use crate::{RuleCategory, RuleFixMeta, rules::RULES}; +use crate::{Config, RuleCategory, RuleFixMeta, rules::RULES}; pub struct RuleTable { pub sections: Vec, pub total: usize, pub turned_on_by_default_count: usize, + pub enabled_count: usize, } pub struct RuleTableSection { @@ -27,25 +28,32 @@ pub struct RuleTableRow { pub schema: Option, pub turned_on_by_default: bool, + pub enabled: bool, pub autofix: RuleFixMeta, } impl Default for RuleTable { fn default() -> Self { - Self::new(None) + Self::new(None, None) } } impl RuleTable { #[expect(clippy::allow_attributes)] #[allow(unused, unused_mut)] - pub fn new(mut generator: Option<&mut schemars::SchemaGenerator>) -> Self { + pub fn new( + mut generator: Option<&mut schemars::SchemaGenerator>, + config: Option<&Config>, + ) -> Self { let default_rules = RULES .iter() .filter(|rule| rule.category() == RuleCategory::Correctness) .map(super::rules::RuleEnum::name) .collect::>(); + let enabled_rules = + config.map(|c| c.rules().iter().map(|rule| rule.0.name()).collect::>()); + let mut rows = RULES .iter() .map(|rule| { @@ -58,6 +66,7 @@ impl RuleTable { schema: generator.as_mut().and_then(|g| rule.schema(g)), plugin: rule.plugin_name().to_string(), category: rule.category(), + enabled: enabled_rules.as_ref().is_some_and(|e| e.contains(name)), turned_on_by_default: default_rules.contains(name), autofix: rule.fix(), } @@ -94,7 +103,12 @@ impl RuleTable { }) .collect::>(); - RuleTable { total, sections, turned_on_by_default_count: 123 } + RuleTable { + total, + sections, + turned_on_by_default_count: 123, + enabled_count: enabled_rules.map_or(0, |rules| rules.len()), + } } } @@ -106,9 +120,11 @@ impl RuleTableSection { pub fn render_markdown_table(&self, link_prefix: Option<&str>) -> String { const FIX_EMOJI_COL_WIDTH: usize = 10; const DEFAULT_EMOJI_COL_WIDTH: usize = 9; + const ENABLED_COL_WIDTH: usize = 10; /// text width, leave 2 spaces for padding const FIX: usize = FIX_EMOJI_COL_WIDTH - 2; const DEFAULT: usize = DEFAULT_EMOJI_COL_WIDTH - 2; + const ENABLED: usize = ENABLED_COL_WIDTH - 2; let mut s = String::new(); let category = &self.category; @@ -122,17 +138,22 @@ impl RuleTableSection { let x = ""; writeln!( s, - "| {: FIX { (emoji, 0) } else { (emoji, FIX - len) } }); - writeln!(s, "| {rendered_name: