diff --git a/crates/biome_analyze/src/lib.rs b/crates/biome_analyze/src/lib.rs index 743b11412e50..5a981ff74d3e 100644 --- a/crates/biome_analyze/src/lib.rs +++ b/crates/biome_analyze/src/lib.rs @@ -815,6 +815,19 @@ impl<'a> Display for RuleFilter<'a> { } } +impl<'a> biome_console::fmt::Display for RuleFilter<'a> { + fn fmt(&self, fmt: &mut biome_console::fmt::Formatter) -> std::io::Result<()> { + match self { + RuleFilter::Group(group) => { + write!(fmt, "{group}") + } + RuleFilter::Rule(group, rule) => { + write!(fmt, "{group}/{rule}") + } + } + } +} + /// Allows filtering the list of rules that will be executed in a run of the analyzer, /// and at what source code range signals (diagnostics or actions) may be raised #[derive(Debug, Default, Clone, Copy)] diff --git a/crates/biome_cli/src/commands/rage.rs b/crates/biome_cli/src/commands/rage.rs index 410c1704710b..36587530898e 100644 --- a/crates/biome_cli/src/commands/rage.rs +++ b/crates/biome_cli/src/commands/rage.rs @@ -1,21 +1,18 @@ -use biome_configuration::ConfigurationPathHint; +use biome_configuration::{ConfigurationPathHint, Rules}; use biome_console::fmt::{Display, Formatter}; -use biome_console::{fmt, markup, ConsoleExt, HorizontalLine, Markup}; +use biome_console::{fmt, markup, ConsoleExt, HorizontalLine, Markup, Padding, SOFT_LINE}; use biome_diagnostics::termcolor::{ColorChoice, WriteColor}; use biome_diagnostics::{termcolor, PrintDescription}; use biome_fs::FileSystem; use biome_service::configuration::{load_configuration, LoadedConfiguration}; use biome_service::workspace::{client, RageEntry, RageParams}; use biome_service::{DynRef, Workspace}; -use serde_json::Value; -use std::collections::HashMap; use std::{env, io, ops::Deref}; use tokio::runtime::Runtime; use crate::commands::daemon::read_most_recent_log_file; use crate::service::enumerate_pipes; use crate::{service, CliDiagnostic, CliSession, VERSION}; -use serde::Serialize; /// Handler for the `rage` command pub(crate) fn rage( @@ -273,11 +270,18 @@ impl Display for RageConfiguration<'_, '_> { // Print linter configuration if --linter option is true if self.linter { let linter_configuration = configuration.get_linter_rules(); + + let javascript_linter = configuration.get_javascript_linter_configuration(); + let json_linter = configuration.get_json_linter_configuration(); + let css_linter = configuration.get_css_linter_configuration(); markup! ( {Section("Linter")} + {KeyValuePair("JavaScript enabled", markup!({DebugDisplay(javascript_linter.enabled)}))} + {KeyValuePair("JSON enabled", markup!({DebugDisplay(json_linter.enabled)}))} + {KeyValuePair("CSS enabled", markup!({DebugDisplay(css_linter.enabled)}))} {KeyValuePair("Recommended", markup!({DebugDisplay(linter_configuration.recommended.unwrap_or_default())}))} {KeyValuePair("All", markup!({DebugDisplay(linter_configuration.all.unwrap_or_default())}))} - {RageConfigurationLintRules("Rules",linter_configuration)} + {RageConfigurationLintRules("Enabled rules",linter_configuration)} ).fmt(fmt)?; } } @@ -293,48 +297,18 @@ impl Display for RageConfiguration<'_, '_> { } } -struct RageConfigurationLintRules<'a, T>(&'a str, T); +struct RageConfigurationLintRules<'a>(&'a str, Rules); -impl Display for RageConfigurationLintRules<'_, T> -where - T: Serialize, -{ - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> io::Result<()> { +impl Display for RageConfigurationLintRules<'_> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> io::Result<()> { let rules_str = self.0; - write!(fmt, " {rules_str}:")?; - - let rule_json_str = serde_json::to_string(&self.1) - .map_err(|_| io::Error::new(io::ErrorKind::Other, "Failed to serialize"))?; - let group_to_rules: HashMap = serde_json::from_str(rule_json_str.as_str()) - .map_err(|_| { - io::Error::new(io::ErrorKind::Other, "Failed to convert to HashMap") - })?; - - let mut groups: Vec<&String> = group_to_rules.keys().collect(); - groups.sort(); - - let first_padding_width = 30usize.saturating_sub(rules_str.len() + 1); - let mut padding_width = first_padding_width; - - if groups.is_empty() { - for _ in 0..padding_width { - fmt.write_str(" ")?; - } - markup!("unset\n").fmt(fmt)?; - } else { - for group in groups { - if let Some(rules) = group_to_rules.get(group).and_then(Value::as_object) { - for (rule_name, rule_config) in rules { - for _ in 0..padding_width { - fmt.write_str(" ")?; - } - fmt.write_str(&format!("{}/{} = {}\n", group, rule_name, rule_config))?; - if padding_width == first_padding_width { - padding_width = 30usize.saturating_sub(0) + 2; - } - } - } - } + let padding = Padding::new(2); + fmt.write_markup(markup! {{padding}{rules_str}":"})?; + fmt.write_markup(markup! {{SOFT_LINE}})?; + let rules = self.1.as_enabled_rules(); + for rule in rules { + fmt.write_markup(markup! {{padding}{rule}})?; + fmt.write_markup(markup! {{SOFT_LINE}})?; } Ok(()) diff --git a/crates/biome_cli/tests/commands/rage.rs b/crates/biome_cli/tests/commands/rage.rs index 08faf4fb42a3..a230f51d41e5 100644 --- a/crates/biome_cli/tests/commands/rage.rs +++ b/crates/biome_cli/tests/commands/rage.rs @@ -289,7 +289,7 @@ fn with_linter_configuration() { "linter": { "enabled": true, "rules": { - "recommended": true, + "recommended": false, "a11y": { "noAccessKey": "off", "noAutofocus": "off" @@ -297,17 +297,6 @@ fn with_linter_configuration() { "complexity": { "recommended": true }, - "correctness": { - "all": true - }, - "nursery": { - "useConsistentArrayType": { - "level": "warn", - "options": { - "syntax": "shorthand" - } - } - }, "suspicious": { "noCommentText": { "level": "warn" diff --git a/crates/biome_cli/tests/snapshots/main_commands_rage/with_linter_configuration.snap b/crates/biome_cli/tests/snapshots/main_commands_rage/with_linter_configuration.snap index 76b1c174d68d..a6c91d215d7a 100644 --- a/crates/biome_cli/tests/snapshots/main_commands_rage/with_linter_configuration.snap +++ b/crates/biome_cli/tests/snapshots/main_commands_rage/with_linter_configuration.snap @@ -9,7 +9,7 @@ expression: content "linter": { "enabled": true, "rules": { - "recommended": true, + "recommended": false, "a11y": { "noAccessKey": "off", "noAutofocus": "off" @@ -17,17 +17,6 @@ expression: content "complexity": { "recommended": true }, - "correctness": { - "all": true - }, - "nursery": { - "useConsistentArrayType": { - "level": "warn", - "options": { - "syntax": "shorthand" - } - } - }, "suspicious": { "noCommentText": { "level": "warn" @@ -61,22 +50,46 @@ Environment: NODE_PACKAGE_MANAGER: unset Biome Configuration: - Error: Found an unknown key `useConsistentArrayType`. - Status: Loaded with errors + Status: Loaded successfully Formatter disabled: false Linter disabled: false Organize imports disabled: false VCS disabled: true Linter: - Recommended: true + JavaScript enabled: true + JSON enabled: true + CSS enabled: false + Recommended: false All: false - Rules: a11y/noAccessKey = "off" - a11y/noAutofocus = "off" - complexity/recommended = true - correctness/all = true - style/noNonNullAssertion = "off" - suspicious/noCommentText = {"level":"warn","options":null} + Enabled rules: + complexity/noBannedTypes + complexity/noThisInStatic + complexity/noUselessConstructor + complexity/useLiteralKeys + complexity/useOptionalChain + complexity/noMultipleSpacesInRegularExpressionLiterals + complexity/noUselessLoneBlockStatements + complexity/noUselessEmptyExport + complexity/noUselessSwitchCase + complexity/noStaticOnlyClass + complexity/noUselessTypeConstraint + complexity/noWith + complexity/useRegexLiterals + complexity/useArrowFunction + complexity/noExtraBooleanCast + complexity/noEmptyTypeParameters + complexity/useSimpleNumberKeys + suspicious/noCommentText + complexity/noExcessiveNestedTestSuites + complexity/noUselessLabel + complexity/noUselessCatch + complexity/noUselessFragments + complexity/noUselessTernary + complexity/noForEach + complexity/useFlatMap + complexity/noUselessRename + complexity/noUselessThisAlias Server: Version: 0.0.0 @@ -87,5 +100,3 @@ Server: Workspace: Open Documents: 0 ``` - - diff --git a/crates/biome_configuration/src/css.rs b/crates/biome_configuration/src/css.rs index bfb790119e4d..f7f8fdd1509a 100644 --- a/crates/biome_configuration/src/css.rs +++ b/crates/biome_configuration/src/css.rs @@ -92,3 +92,11 @@ pub struct CssLinter { #[partial(bpaf(long("css-linter-enabled"), argument("true|false"), optional))] pub enabled: bool, } + +impl PartialCssLinter { + pub fn get_linter_configuration(&self) -> CssLinter { + CssLinter { + enabled: self.enabled.unwrap_or_default(), + } + } +} diff --git a/crates/biome_configuration/src/javascript/formatter.rs b/crates/biome_configuration/src/javascript/formatter.rs index 24d76dd38367..1cdd5991089a 100644 --- a/crates/biome_configuration/src/javascript/formatter.rs +++ b/crates/biome_configuration/src/javascript/formatter.rs @@ -146,28 +146,3 @@ impl Default for JavascriptFormatter { } } } - -/// Linter options specific to the JavaScript linter -#[derive(Clone, Debug, Deserialize, Eq, Partial, PartialEq, Serialize)] -#[partial(derive(Bpaf, Clone, Deserializable, Eq, Merge, PartialEq))] -#[partial(cfg_attr(feature = "schema", derive(schemars::JsonSchema)))] -#[partial(serde(rename_all = "camelCase", default, deny_unknown_fields))] -pub struct JavascriptLinter { - /// Control the linter for JavaScript (and its super languages) files. - #[partial(bpaf(long("javascript-linter-enabled"), argument("true|false"), optional))] - pub enabled: bool, -} - -impl Default for JavascriptLinter { - fn default() -> Self { - Self { enabled: true } - } -} - -impl PartialJavascriptLinter { - pub fn get_formatter_configuration(&self) -> JavascriptLinter { - JavascriptLinter { - enabled: self.enabled.unwrap_or_default(), - } - } -} diff --git a/crates/biome_configuration/src/javascript/mod.rs b/crates/biome_configuration/src/javascript/mod.rs index 132833bc54f8..87c5307c88ca 100644 --- a/crates/biome_configuration/src/javascript/mod.rs +++ b/crates/biome_configuration/src/javascript/mod.rs @@ -2,13 +2,11 @@ mod formatter; use std::str::FromStr; -use crate::javascript::formatter::JavascriptLinter; use biome_deserialize::StringSet; use biome_deserialize_macros::{Deserializable, Merge, Partial}; use bpaf::Bpaf; pub use formatter::{ - partial_javascript_formatter, partial_javascript_linter, JavascriptFormatter, - PartialJavascriptFormatter, PartialJavascriptLinter, + partial_javascript_formatter, JavascriptFormatter, PartialJavascriptFormatter, }; use serde::{Deserialize, Serialize}; @@ -97,3 +95,28 @@ impl FromStr for JsxRuntime { } } } + +/// Linter options specific to the JavaScript linter +#[derive(Clone, Debug, Deserialize, Eq, Partial, PartialEq, Serialize)] +#[partial(derive(Bpaf, Clone, Deserializable, Eq, Merge, PartialEq))] +#[partial(cfg_attr(feature = "schema", derive(schemars::JsonSchema)))] +#[partial(serde(rename_all = "camelCase", default, deny_unknown_fields))] +pub struct JavascriptLinter { + /// Control the linter for JavaScript (and its super languages) files. + #[partial(bpaf(long("javascript-linter-enabled"), argument("true|false"), optional))] + pub enabled: bool, +} + +impl Default for JavascriptLinter { + fn default() -> Self { + Self { enabled: true } + } +} + +impl PartialJavascriptLinter { + pub fn get_linter_configuration(&self) -> JavascriptLinter { + JavascriptLinter { + enabled: self.enabled.unwrap_or_default(), + } + } +} diff --git a/crates/biome_configuration/src/json.rs b/crates/biome_configuration/src/json.rs index 9cc3a21220fd..1dd7378a74c9 100644 --- a/crates/biome_configuration/src/json.rs +++ b/crates/biome_configuration/src/json.rs @@ -126,3 +126,11 @@ impl Default for JsonLinter { Self { enabled: true } } } + +impl PartialJsonLinter { + pub fn get_linter_configuration(&self) -> JsonLinter { + JsonLinter { + enabled: self.enabled.unwrap_or_default(), + } + } +} diff --git a/crates/biome_configuration/src/lib.rs b/crates/biome_configuration/src/lib.rs index 462167764210..d39023285b5d 100644 --- a/crates/biome_configuration/src/lib.rs +++ b/crates/biome_configuration/src/lib.rs @@ -14,9 +14,12 @@ pub mod organize_imports; mod overrides; pub mod vcs; +use crate::css::CssLinter; pub use crate::diagnostics::BiomeDiagnostic; pub use crate::diagnostics::CantLoadExtendFile; pub use crate::generated::push_to_analyzer_rules; +use crate::javascript::JavascriptLinter; +use crate::json::JsonLinter; use crate::organize_imports::{partial_organize_imports, OrganizeImports, PartialOrganizeImports}; use crate::vcs::{partial_vcs_configuration, PartialVcsConfiguration, VcsConfiguration}; use biome_deserialize::{Deserialized, StringSet}; @@ -155,6 +158,18 @@ impl PartialConfiguration { .unwrap_or_default() } + pub fn get_javascript_linter_configuration(&self) -> JavascriptLinter { + self.javascript + .as_ref() + .map(|f| { + f.linter + .as_ref() + .map(|f| f.get_linter_configuration()) + .unwrap_or_default() + }) + .unwrap_or_default() + } + pub fn get_json_formatter_configuration(&self) -> JsonFormatter { self.json .as_ref() @@ -167,6 +182,18 @@ impl PartialConfiguration { .unwrap_or_default() } + pub fn get_json_linter_configuration(&self) -> JsonLinter { + self.json + .as_ref() + .map(|f| { + f.linter + .as_ref() + .map(|f| f.get_linter_configuration()) + .unwrap_or_default() + }) + .unwrap_or_default() + } + pub fn get_css_formatter_configuration(&self) -> CssFormatter { self.css .as_ref() @@ -179,6 +206,18 @@ impl PartialConfiguration { .unwrap_or_default() } + pub fn get_css_linter_configuration(&self) -> CssLinter { + self.css + .as_ref() + .map(|f| { + f.linter + .as_ref() + .map(|f| f.get_linter_configuration()) + .unwrap_or_default() + }) + .unwrap_or_default() + } + pub fn is_linter_disabled(&self) -> bool { self.linter.as_ref().map_or(false, |f| f.is_disabled()) }