diff --git a/crates/biome_configuration/src/bool.rs b/crates/biome_configuration/src/bool.rs index 687fac8ad9a8..7f14de33f38e 100644 --- a/crates/biome_configuration/src/bool.rs +++ b/crates/biome_configuration/src/bool.rs @@ -6,10 +6,18 @@ use std::{ }; /// A `bool` type wrapper with a configurable default value (`true` or `false`) +/// +/// The const generic indicates the default bool value of this wrapper type #[derive( Clone, Copy, Eq, Merge, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema, )] -pub struct Bool(pub bool); +pub struct Bool(pub bool); + +impl Bool { + pub fn value(&self) -> bool { + self.0 + } +} impl Default for Bool { fn default() -> Self { @@ -42,7 +50,7 @@ impl Deserializable for Bool { impl fmt::Debug for Bool { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) + self.value().fmt(f) } } @@ -54,18 +62,18 @@ impl From for Bool { impl From> for bool { fn from(value: Bool) -> Self { - value.0 + value.value() } } impl From> for Bool { fn from(value: Bool) -> Self { - Self(value.0) + Self(value.value()) } } impl From> for Bool { fn from(value: Bool) -> Self { - Self(value.0) + Self(value.value()) } } diff --git a/crates/biome_configuration/src/css.rs b/crates/biome_configuration/src/css.rs index bf54bbea5a21..5ed3897ad1ff 100644 --- a/crates/biome_configuration/src/css.rs +++ b/crates/biome_configuration/src/css.rs @@ -1,4 +1,4 @@ -use crate::{bool::Bool, formatter::FormatterEnabled, linter::LinterEnabled, PlainIndentStyle}; +use crate::{bool::Bool, PlainIndentStyle}; use biome_deserialize_macros::{Deserializable, Merge}; use biome_formatter::{IndentWidth, LineEnding, LineWidth, QuoteStyle}; use bpaf::Bpaf; @@ -43,6 +43,8 @@ pub struct CssParserConfiguration { pub css_modules: Option, } +pub type CssFormatterEnabled = Bool; + /// Options that changes how the CSS formatter behaves #[derive( Bpaf, Clone, Debug, Default, Deserializable, Deserialize, Eq, Merge, PartialEq, Serialize, @@ -52,7 +54,7 @@ pub struct CssParserConfiguration { pub struct CssFormatterConfiguration { /// Control the formatter for CSS (and its super languages) files. #[bpaf(long("css-formatter-enabled"), argument("true|false"))] - pub enabled: Option, + pub enabled: Option, /// The indent style applied to CSS (and its super languages) files. #[bpaf(long("css-formatter-indent-style"), argument("tab|space"))] @@ -85,6 +87,7 @@ impl CssFormatterConfiguration { } } +pub type CssLinterEnabled = Bool; /// Options that changes how the CSS linter behaves #[derive( Bpaf, Clone, Debug, Default, Deserializable, Deserialize, Eq, Merge, PartialEq, Serialize, @@ -94,7 +97,7 @@ impl CssFormatterConfiguration { pub struct CssLinterConfiguration { /// Control the linter for CSS (and its super languages) files. #[bpaf(long("css-linter-enabled"), argument("true|false"))] - pub enabled: Option, + pub enabled: Option, } impl CssLinterConfiguration { diff --git a/crates/biome_configuration/src/graphql.rs b/crates/biome_configuration/src/graphql.rs index 86d5a93ab679..c14d68987827 100644 --- a/crates/biome_configuration/src/graphql.rs +++ b/crates/biome_configuration/src/graphql.rs @@ -1,4 +1,4 @@ -use crate::{formatter::FormatterEnabled, PlainIndentStyle}; +use crate::{bool::Bool, PlainIndentStyle}; use biome_deserialize_macros::{Deserializable, Merge}; use biome_formatter::{BracketSpacing, IndentWidth, LineEnding, LineWidth, QuoteStyle}; use bpaf::Bpaf; @@ -16,6 +16,8 @@ pub struct GraphqlConfiguration { pub formatter: Option, } +pub type GraphqlFormatterEnabled = Bool; + /// Options that changes how the GraphQL formatter behaves #[derive( Bpaf, Clone, Debug, Default, Deserializable, Deserialize, Eq, Merge, PartialEq, Serialize, @@ -25,7 +27,7 @@ pub struct GraphqlConfiguration { pub struct GraphqlFormatterConfiguration { /// Control the formatter for GraphQL files. #[bpaf(long("graphql-formatter-enabled"), argument("true|false"))] - pub enabled: Option, + pub enabled: Option, /// The indent style applied to GraphQL files. #[bpaf(long("graphql-formatter-indent-style"), argument("tab|space"))] diff --git a/crates/biome_configuration/src/javascript/formatter.rs b/crates/biome_configuration/src/javascript/formatter.rs index d68595cae004..c8486585686f 100644 --- a/crates/biome_configuration/src/javascript/formatter.rs +++ b/crates/biome_configuration/src/javascript/formatter.rs @@ -1,4 +1,4 @@ -use crate::{bool::Bool, formatter::FormatterEnabled, PlainIndentStyle}; +use crate::{bool::Bool, PlainIndentStyle}; use biome_deserialize_macros::{Deserializable, Merge}; use biome_formatter::{ AttributePosition, BracketSpacing, IndentWidth, LineEnding, LineWidth, QuoteStyle, @@ -9,6 +9,7 @@ use biome_js_formatter::context::{ use bpaf::Bpaf; use serde::{Deserialize, Serialize}; +pub type JsFormatterEnabled = Bool; pub type BracketSameLineEnabled = Bool; /// Formatting options specific to the JavaScript files @@ -20,7 +21,7 @@ pub type BracketSameLineEnabled = Bool; pub struct JsFormatterConfiguration { /// Control the formatter for JavaScript (and its super languages) files. #[bpaf(long("javascript-formatter-enabled"), argument("true|false"))] - pub enabled: Option, + pub enabled: Option, /// The type of quotes used in JSX. Defaults to double. #[bpaf(long("jsx-quote-style"), argument("double|single"))] diff --git a/crates/biome_configuration/src/javascript/mod.rs b/crates/biome_configuration/src/javascript/mod.rs index 37a4e9157367..8ed4d8006335 100644 --- a/crates/biome_configuration/src/javascript/mod.rs +++ b/crates/biome_configuration/src/javascript/mod.rs @@ -1,5 +1,5 @@ mod formatter; -use crate::{bool::Bool, linter::LinterEnabled}; +use crate::bool::Bool; use biome_deserialize::StringSet; use biome_deserialize_macros::{Deserializable, Merge}; use bpaf::Bpaf; @@ -99,6 +99,8 @@ impl FromStr for JsxRuntime { } } +pub type JsLinterEnabled = Bool; + /// Linter options specific to the JavaScript linter #[derive( Bpaf, Clone, Debug, Default, Deserializable, Deserialize, Eq, Merge, PartialEq, Serialize, @@ -108,7 +110,7 @@ impl FromStr for JsxRuntime { pub struct JsLinterConfiguration { /// Control the linter for JavaScript (and its super languages) files. #[bpaf(long("javascript-linter-enabled"), argument("true|false"))] - pub enabled: Option, + pub enabled: Option, } impl JsLinterConfiguration { diff --git a/crates/biome_configuration/src/json.rs b/crates/biome_configuration/src/json.rs index 1425b6f4de72..5e57d4f382a5 100644 --- a/crates/biome_configuration/src/json.rs +++ b/crates/biome_configuration/src/json.rs @@ -1,4 +1,4 @@ -use crate::{bool::Bool, formatter::FormatterEnabled, linter::LinterEnabled, PlainIndentStyle}; +use crate::{bool::Bool, PlainIndentStyle}; use biome_deserialize_macros::{Deserializable, Merge}; use biome_formatter::{IndentWidth, LineEnding, LineWidth}; use biome_json_formatter::context::TrailingCommas; @@ -44,6 +44,8 @@ pub struct JsonParserConfiguration { pub allow_trailing_commas: Option, } +pub type JsonFormatterEnabled = Bool; + #[derive( Bpaf, Clone, Debug, Default, Deserializable, Deserialize, Eq, Merge, PartialEq, Serialize, )] @@ -52,7 +54,7 @@ pub struct JsonParserConfiguration { pub struct JsonFormatterConfiguration { /// Control the formatter for JSON (and its super languages) files. #[bpaf(long("json-formatter-enabled"), argument("true|false"))] - pub enabled: Option, + pub enabled: Option, /// The indent style applied to JSON (and its super languages) files. #[bpaf(long("json-formatter-indent-style"), argument("tab|space"))] @@ -90,6 +92,8 @@ impl JsonFormatterConfiguration { } } +pub type JsonLinterEnabled = Bool; + /// Linter options specific to the JSON linter #[derive( Bpaf, Clone, Debug, Default, Deserializable, Deserialize, Eq, Merge, PartialEq, Serialize, @@ -99,7 +103,7 @@ impl JsonFormatterConfiguration { pub struct JsonLinterConfiguration { /// Control the linter for JSON (and its super languages) files. #[bpaf(long("json-linter-enabled"), argument("true|false"), optional)] - pub enabled: Option, + pub enabled: Option, } impl JsonLinterConfiguration { diff --git a/crates/biome_service/src/file_handlers/css.rs b/crates/biome_service/src/file_handlers/css.rs index 52d22e7cf8e7..4bb6501b0a64 100644 --- a/crates/biome_service/src/file_handlers/css.rs +++ b/crates/biome_service/src/file_handlers/css.rs @@ -21,10 +21,10 @@ use biome_analyze::{ AnalysisFilter, AnalyzerConfiguration, AnalyzerOptions, ControlFlow, Never, RuleCategoriesBuilder, RuleCategory, RuleError, }; -use biome_configuration::css::{AllowWrongLineCommentsEnabled, CssModulesEnabled}; -use biome_configuration::formatter::FormatterEnabled; -use biome_configuration::linter::LinterEnabled; -use biome_configuration::organize_imports::OrganizeImportsEnabled; +use biome_configuration::bool::Bool; +use biome_configuration::css::{ + AllowWrongLineCommentsEnabled, CssFormatterEnabled, CssLinterEnabled, CssModulesEnabled, +}; use biome_css_analyze::analyze; use biome_css_formatter::context::CssFormatOptions; use biome_css_formatter::format_node; @@ -56,7 +56,7 @@ pub struct CssFormatterSettings { pub indent_width: Option, pub indent_style: Option, pub quote_style: Option, - pub enabled: Option, + pub enabled: Option, } impl CssFormatterSettings { @@ -68,7 +68,7 @@ impl CssFormatterSettings { #[derive(Clone, Debug, Default, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct CssLinterSettings { - pub enabled: Option, + pub enabled: Option, } impl CssLinterSettings { @@ -77,10 +77,12 @@ impl CssLinterSettings { } } +pub type CssOrganizeImportsEnabled = Bool; + #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct CssOrganizeImportsSettings { - pub enabled: Option, + pub enabled: Option, } impl ServiceLanguage for CssLanguage { diff --git a/crates/biome_service/src/file_handlers/graphql.rs b/crates/biome_service/src/file_handlers/graphql.rs index f56788e99410..3dfd4181571a 100644 --- a/crates/biome_service/src/file_handlers/graphql.rs +++ b/crates/biome_service/src/file_handlers/graphql.rs @@ -18,7 +18,7 @@ use biome_analyze::{ AnalysisFilter, AnalyzerConfiguration, AnalyzerOptions, ControlFlow, Never, RuleCategoriesBuilder, RuleCategory, RuleError, }; -use biome_configuration::formatter::FormatterEnabled; +use biome_configuration::graphql::GraphqlFormatterEnabled; use biome_diagnostics::{category, Applicability, Diagnostic, DiagnosticExt, Severity}; use biome_formatter::{ BracketSpacing, FormatError, IndentStyle, IndentWidth, LineEnding, LineWidth, Printed, @@ -38,7 +38,7 @@ use tracing::{debug_span, error, info, trace, trace_span}; #[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct GraphqlFormatterSettings { - pub enabled: Option, + pub enabled: Option, pub line_ending: Option, pub line_width: Option, pub indent_width: Option, diff --git a/crates/biome_service/src/file_handlers/javascript.rs b/crates/biome_service/src/file_handlers/javascript.rs index bdb73a6df82b..c66f8aabf1b0 100644 --- a/crates/biome_service/src/file_handlers/javascript.rs +++ b/crates/biome_service/src/file_handlers/javascript.rs @@ -24,10 +24,10 @@ use biome_analyze::{ QueryMatch, Queryable, RegistryVisitor, RuleCategoriesBuilder, RuleCategory, RuleError, RuleFilter, RuleGroup, }; -use biome_configuration::formatter::FormatterEnabled; -use biome_configuration::javascript::{JsxRuntime, UnsafeParameterDecoratorsEnabled}; -use biome_configuration::linter::LinterEnabled; -use biome_configuration::organize_imports::OrganizeImportsEnabled; +use biome_configuration::bool::Bool; +use biome_configuration::javascript::{ + JsFormatterEnabled, JsLinterEnabled, JsxRuntime, UnsafeParameterDecoratorsEnabled, +}; use biome_diagnostics::{category, Applicability, Diagnostic, DiagnosticExt, Severity}; use biome_formatter::{ AttributePosition, BracketSpacing, FormatError, IndentStyle, IndentWidth, LineEnding, @@ -69,7 +69,7 @@ pub struct JsFormatterSettings { pub line_width: Option, pub indent_width: Option, pub indent_style: Option, - pub enabled: Option, + pub enabled: Option, pub attribute_position: Option, } @@ -88,7 +88,7 @@ pub struct JsParserSettings { #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct JsLinterSettings { - pub enabled: Option, + pub enabled: Option, } impl JsLinterSettings { @@ -97,10 +97,12 @@ impl JsLinterSettings { } } +pub type JsOrganizeImportsEnabled = Bool; + #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct JsOrganizeImportsSettings { - pub enabled: Option, + pub enabled: Option, } #[derive(Clone, Debug, Default, Deserialize, Serialize)] diff --git a/crates/biome_service/src/file_handlers/json.rs b/crates/biome_service/src/file_handlers/json.rs index e4578dfb02a8..7f36c3914c67 100644 --- a/crates/biome_service/src/file_handlers/json.rs +++ b/crates/biome_service/src/file_handlers/json.rs @@ -21,10 +21,10 @@ use biome_analyze::{ AnalysisFilter, AnalyzerConfiguration, AnalyzerOptions, ControlFlow, GroupCategory, Never, Queryable, RegistryVisitor, RuleCategoriesBuilder, RuleCategory, RuleFilter, RuleGroup, }; -use biome_configuration::formatter::FormatterEnabled; -use biome_configuration::json::{AllowCommentsEnabled, AllowTrailingCommasEnabled}; -use biome_configuration::linter::LinterEnabled; -use biome_configuration::organize_imports::OrganizeImportsEnabled; +use biome_configuration::bool::Bool; +use biome_configuration::json::{ + AllowCommentsEnabled, AllowTrailingCommasEnabled, JsonFormatterEnabled, JsonLinterEnabled, +}; use biome_configuration::Configuration; use biome_deserialize::json::deserialize_from_json_ast; use biome_diagnostics::{category, Diagnostic, DiagnosticExt, Severity}; @@ -49,7 +49,7 @@ pub struct JsonFormatterSettings { pub indent_width: Option, pub indent_style: Option, pub trailing_commas: Option, - pub enabled: Option, + pub enabled: Option, } impl JsonFormatterSettings { @@ -68,7 +68,7 @@ pub struct JsonParserSettings { #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct JsonLinterSettings { - pub enabled: Option, + pub enabled: Option, } impl JsonLinterSettings { @@ -77,10 +77,12 @@ impl JsonLinterSettings { } } +pub type JsonOrganizeImportsEnabled = Bool; + #[derive(Debug, Clone, Default, serde::Serialize, serde::Deserialize)] #[cfg_attr(feature = "schema", derive(schemars::JsonSchema))] pub struct JsonOrganizeImportsSettings { - pub enabled: Option, + pub enabled: Option, } impl ServiceLanguage for JsonLanguage { diff --git a/crates/biome_service/src/file_handlers/mod.rs b/crates/biome_service/src/file_handlers/mod.rs index 28747aeca2f7..2159141f9a67 100644 --- a/crates/biome_service/src/file_handlers/mod.rs +++ b/crates/biome_service/src/file_handlers/mod.rs @@ -33,6 +33,11 @@ pub use javascript::JsFormatterSettings; use std::ffi::OsStr; use std::path::Path; +pub use crate::file_handlers::{ + css::CssOrganizeImportsEnabled, javascript::JsOrganizeImportsEnabled, + json::JsonOrganizeImportsEnabled, +}; + mod astro; mod css; mod graphql; diff --git a/crates/biome_service/src/settings.rs b/crates/biome_service/src/settings.rs index f0e5c74503c3..e53616b7efc3 100644 --- a/crates/biome_service/src/settings.rs +++ b/crates/biome_service/src/settings.rs @@ -1,10 +1,16 @@ +use crate::file_handlers::{ + CssOrganizeImportsEnabled, JsOrganizeImportsEnabled, JsonOrganizeImportsEnabled, +}; use crate::workspace::{DocumentFileSource, ProjectKey, WorkspaceData}; use crate::{Matcher, WorkspaceError}; use biome_analyze::{AnalyzerOptions, AnalyzerRules}; +use biome_configuration::bool::Bool; +use biome_configuration::css::{CssFormatterEnabled, CssLinterEnabled}; use biome_configuration::diagnostics::InvalidIgnorePattern; use biome_configuration::file_size::FileSize; use biome_configuration::formatter::{FormatWithErrorsEnabled, FormatterEnabled}; -use biome_configuration::javascript::JsxRuntime; +use biome_configuration::javascript::{JsFormatterEnabled, JsLinterEnabled, JsxRuntime}; +use biome_configuration::json::{JsonFormatterEnabled, JsonLinterEnabled}; use biome_configuration::linter::LinterEnabled; use biome_configuration::organize_imports::{OrganizeImports, OrganizeImportsEnabled}; use biome_configuration::{ @@ -245,28 +251,28 @@ impl Settings { self.files.ignore_unknown.unwrap_or_default().into() } - /// Whether the formatter is enabled for this foreign file path - pub fn formatter_enabled_for_this_foreign_file_path(&self, path: &Path) -> bool { + /// Whether the formatter is enabled for this file path + pub fn formatter_enabled_for_this_file_path(&self, path: &Path) -> bool { self.override_settings - .formatter_enabled_for_this_foreign_file_path(path) + .formatter_enabled_for_this_file_path(path) .or(self.formatter.enabled) .unwrap_or_default() .into() } - /// Whether the linter is enabled for this foreign file path - pub fn linter_enabled_for_this_foreign_file_path(&self, path: &Path) -> bool { + /// Whether the linter is enabled for this file path + pub fn linter_enabled_for_this_file_path(&self, path: &Path) -> bool { self.override_settings - .linter_enabled_for_this_foreign_file_path(path) + .linter_enabled_for_this_file_path(path) .or(self.linter.enabled) .unwrap_or_default() .into() } - /// Whether the organize_imports is enabled for this foreign file path - pub fn organize_imports_enabled_for_this_foreign_file_path(&self, path: &Path) -> bool { + /// Whether the organize_imports is enabled for this file path + pub fn organize_imports_enabled_for_this_file_path(&self, path: &Path) -> bool { self.override_settings - .organize_imports_enabled_for_this_foreign_file_path(path) + .organize_imports_enabled_for_this_file_path(path) .or(self.linter.enabled) .unwrap_or_default() .into() @@ -276,8 +282,10 @@ impl Settings { pub fn formatter_enabled_for_this_js_file_path(&self, path: &Path) -> bool { self.override_settings .formatter_enabled_for_this_js_file_path(path) - .or(self.languages.javascript.formatter.enabled) - .or(self.formatter.enabled) + .or(calc_capability( + self.languages.javascript.formatter.enabled, + self.formatter.enabled, + )) .unwrap_or_default() .into() } @@ -286,8 +294,10 @@ impl Settings { pub fn linter_enabled_for_this_js_file_path(&self, path: &Path) -> bool { self.override_settings .linter_enabled_for_this_js_file_path(path) - .or(self.languages.javascript.linter.enabled) - .or(self.linter.enabled) + .or(calc_capability( + self.languages.javascript.linter.enabled, + self.linter.enabled, + )) .unwrap_or_default() .into() } @@ -296,8 +306,10 @@ impl Settings { pub fn organize_imports_enabled_for_this_js_file_path(&self, path: &Path) -> bool { self.override_settings .organize_imports_enabled_for_this_js_file_path(path) - .or(self.languages.javascript.organize_imports.enabled) - .or(self.organize_imports.enabled) + .or(calc_capability( + self.languages.javascript.organize_imports.enabled, + self.organize_imports.enabled, + )) .unwrap_or_default() .into() } @@ -306,8 +318,10 @@ impl Settings { pub fn formatter_enabled_for_this_json_file_path(&self, path: &Path) -> bool { self.override_settings .formatter_enabled_for_this_json_file_path(path) - .or(self.languages.json.formatter.enabled) - .or(self.formatter.enabled) + .or(calc_capability( + self.languages.json.formatter.enabled, + self.formatter.enabled, + )) .unwrap_or_default() .into() } @@ -316,8 +330,10 @@ impl Settings { pub fn linter_enabled_for_this_json_file_path(&self, path: &Path) -> bool { self.override_settings .linter_enabled_for_this_json_file_path(path) - .or(self.languages.json.linter.enabled) - .or(self.linter.enabled) + .or(calc_capability( + self.languages.json.linter.enabled, + self.linter.enabled, + )) .unwrap_or_default() .into() } @@ -326,8 +342,10 @@ impl Settings { pub fn organize_imports_enabled_for_this_json_file_path(&self, path: &Path) -> bool { self.override_settings .organize_imports_enabled_for_this_json_file_path(path) - .or(self.languages.json.organize_imports.enabled) - .or(self.organize_imports.enabled) + .or(calc_capability( + self.languages.json.organize_imports.enabled, + self.organize_imports.enabled, + )) .unwrap_or_default() .into() } @@ -336,8 +354,10 @@ impl Settings { pub fn formatter_enabled_for_this_css_file_path(&self, path: &Path) -> bool { self.override_settings .formatter_enabled_for_this_css_file_path(path) - .or(self.languages.css.formatter.enabled) - .or(self.formatter.enabled) + .or(calc_capability( + self.languages.css.formatter.enabled, + self.formatter.enabled, + )) .unwrap_or_default() .into() } @@ -346,8 +366,10 @@ impl Settings { pub fn linter_enabled_for_this_css_file_path(&self, path: &Path) -> bool { self.override_settings .linter_enabled_for_this_css_file_path(path) - .or(self.languages.css.linter.enabled) - .or(self.linter.enabled) + .or(calc_capability( + self.languages.css.linter.enabled, + self.linter.enabled, + )) .unwrap_or_default() .into() } @@ -356,8 +378,10 @@ impl Settings { pub fn organize_imports_enabled_for_this_css_file_path(&self, path: &Path) -> bool { self.override_settings .organize_imports_enabled_for_this_css_file_path(path) - .or(self.languages.css.organize_imports.enabled) - .or(self.organize_imports.enabled) + .or(calc_capability( + self.languages.css.organize_imports.enabled, + self.organize_imports.enabled, + )) .unwrap_or_default() .into() } @@ -864,8 +888,7 @@ impl From for LanguageSettings { } if let Some(formatter) = css.formatter { - // TODO: change RHS to `formatter.enabled` when css formatting is enabled by default - language_setting.formatter.enabled = Some(formatter.enabled.unwrap_or_default()); + language_setting.formatter.enabled = formatter.enabled; language_setting.formatter.indent_width = formatter.indent_width; language_setting.formatter.indent_style = formatter.indent_style.map(Into::into); language_setting.formatter.line_width = formatter.line_width; @@ -874,8 +897,7 @@ impl From for LanguageSettings { } if let Some(linter) = css.linter { - // TODO: change RHS to `linter.enabled` when css linting is enabled by default - language_setting.linter.enabled = Some(linter.enabled.unwrap_or_default()); + language_setting.linter.enabled = linter.enabled; } language_setting @@ -887,8 +909,7 @@ impl From for LanguageSettings { let mut language_setting: LanguageSettings = LanguageSettings::default(); if let Some(formatter) = graphql.formatter { - // TODO: change RHS to `formatter.enabled` when graphql formatting is enabled by default - language_setting.formatter.enabled = Some(formatter.enabled.unwrap_or_default()); + language_setting.formatter.enabled = formatter.enabled; language_setting.formatter.indent_width = formatter.indent_width; language_setting.formatter.indent_style = formatter.indent_style.map(Into::into); language_setting.formatter.line_width = formatter.line_width; @@ -1010,11 +1031,8 @@ impl OverrideSettings { /// Scans the overrides and checks if there's an override /// that sets the top-level formatter "enabled" option - /// explicitly for this foreign file path - pub fn formatter_enabled_for_this_foreign_file_path( - &self, - path: &Path, - ) -> Option { + /// explicitly for this file path + fn formatter_enabled_for_this_file_path(&self, path: &Path) -> Option { // Reverse the traversal as only the last override takes effect return self.patterns.iter().rev().find_map(|pattern| { // Check the top-level option @@ -1031,8 +1049,8 @@ impl OverrideSettings { /// Scans the overrides and checks if there's an override /// that sets the top-level linter "enabled" option - /// explicitly for this foreign file path - pub fn linter_enabled_for_this_foreign_file_path(&self, path: &Path) -> Option { + /// explicitly for this file path + fn linter_enabled_for_this_file_path(&self, path: &Path) -> Option { // Reverse the traversal as only the last override takes effect return self.patterns.iter().rev().find_map(|pattern| { // Check the top-level option @@ -1049,8 +1067,8 @@ impl OverrideSettings { /// Scans the overrides and checks if there's an override /// that sets the top-level organize_imports "enabled" option - /// explicitly for this foreign file path - pub fn organize_imports_enabled_for_this_foreign_file_path( + /// explicitly for this file path + fn organize_imports_enabled_for_this_file_path( &self, path: &Path, ) -> Option { @@ -1069,266 +1087,101 @@ impl OverrideSettings { } /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific formatter "enabled" option - /// explicitly for this JavaScript file path - pub fn formatter_enabled_for_this_js_file_path(&self, path: &Path) -> Option { - // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .javascript - .formatter - .enabled - // Then check the top-level option - .or(pattern.formatter.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); - } - - /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific linter "enabled" option - /// explicitly for this JavaScript file path - pub fn linter_enabled_for_this_js_file_path(&self, path: &Path) -> Option { - // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .javascript - .linter - .enabled - // Then check the top-level option - .or(pattern.linter.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); - } - - /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific organize_imports "enabled" option - /// explicitly for this JavaScript file path - pub fn organize_imports_enabled_for_this_js_file_path( - &self, - path: &Path, - ) -> Option { - // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .javascript - .organize_imports - .enabled - // Then check the top-level option - .or(pattern.organize_imports.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); - } - - /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific formatter "enabled" option - /// explicitly for this JSON file path - pub fn formatter_enabled_for_this_json_file_path( - &self, - path: &Path, - ) -> Option { - // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .json - .formatter - .enabled - // Then check the top-level option - .or(pattern.formatter.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); - } - - /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific linter "enabled" option - /// explicitly for this JSON file path - pub fn linter_enabled_for_this_json_file_path(&self, path: &Path) -> Option { - // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .json - .linter - .enabled - // Then check the top-level option - .or(pattern.linter.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); - } - - /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific organize_imports "enabled" option - /// explicitly for this JSON file path - pub fn organize_imports_enabled_for_this_json_file_path( + /// that sets the top-level formatter "format_with_errors" option + /// explicitly for this file path + fn format_with_errors_enabled_for_this_file_path( &self, path: &Path, - ) -> Option { + ) -> Option { // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .json - .organize_imports - .enabled - // Then check the top-level option - .or(pattern.organize_imports.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); + self.patterns.iter().rev().find_map(|pattern| { + if let Some(enabled) = pattern.formatter.format_with_errors { + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + return Some(enabled); + } + } + None + }) } + // endregion - /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific formatter "enabled" option - /// explicitly for this CSS file path - pub fn formatter_enabled_for_this_css_file_path( - &self, - path: &Path, - ) -> Option { - // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .css - .formatter - .enabled - // Then check the top-level option - .or(pattern.formatter.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); - } + // region: Javascript-specific methods /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific linter "enabled" option - /// explicitly for this CSS file path - pub fn linter_enabled_for_this_css_file_path(&self, path: &Path) -> Option { + /// that sets the language-specific formatter "enabled" option + /// explicitly for this JavaScript file path + /// + /// The function also takes the top-level formatter "enabled" + /// option into consideration + fn formatter_enabled_for_this_js_file_path(&self, path: &Path) -> Option { // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .css - .linter - .enabled - // Then check the top-level option - .or(pattern.linter.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); + self.patterns.iter().rev().find_map(|pattern| { + calc_capability( + pattern.languages.javascript.formatter.enabled, + pattern.formatter.enabled, + ) + .and_then(|enabled| { + // Then check whether the path satisfies + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + Some(enabled) + } else { + None + } + }) + }) } /// Scans the overrides and checks if there's an override - /// that sets the top-level or language-specific organize_imports "enabled" option - /// explicitly for this CSS file path - pub fn organize_imports_enabled_for_this_css_file_path( - &self, - path: &Path, - ) -> Option { + /// that sets the language-specific linter "enabled" option + /// explicitly for this JavaScript file path + /// + /// The function also takes the top-level linter "enabled" + /// option into consideration + fn linter_enabled_for_this_js_file_path(&self, path: &Path) -> Option { // Reverse the traversal as only the last override takes effect - return self.patterns.iter().rev().find_map(|pattern| { - // Check language-specific option first - pattern - .languages - .css - .organize_imports - .enabled - // Then check the top-level option - .or(pattern.organize_imports.enabled) - .and_then(|enabled| { - // Then check whether the path satisfies - if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - Some(enabled) - } else { - None - } - }) - }); + self.patterns.iter().rev().find_map(|pattern| { + calc_capability( + pattern.languages.javascript.linter.enabled, + pattern.linter.enabled, + ) + .and_then(|enabled| { + // Then check whether the path satisfies + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + Some(enabled) + } else { + None + } + }) + }) } /// Scans the overrides and checks if there's an override - /// that sets the formatter "format_with_errors" option explicitly - pub fn format_with_errors_enabled_for_this_file_path( + /// that sets the language-specific organize_imports "enabled" option + /// explicitly for this JavaScript file path + /// + /// The function also takes the top-level organize_imports "enabled" + /// option into consideration + fn organize_imports_enabled_for_this_js_file_path( &self, path: &Path, - ) -> Option { + ) -> Option { // Reverse the traversal as only the last override takes effect self.patterns.iter().rev().find_map(|pattern| { - if let Some(enabled) = pattern.formatter.format_with_errors { + calc_capability( + pattern.languages.javascript.organize_imports.enabled, + pattern.organize_imports.enabled, + ) + .and_then(|enabled| { + // Then check whether the path satisfies if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { - return Some(enabled); + Some(enabled) + } else { + None } - } - None + }) }) } - // endregion - - // region: Javascript-specific methods - /// Scans and aggregates all the overrides into a single `JsParseOptions` pub fn to_override_js_parse_options( &self, @@ -1405,6 +1258,84 @@ impl OverrideSettings { // region: JSON-specific methods + /// Scans the overrides and checks if there's an override + /// that sets the language-specific formatter "enabled" option + /// explicitly for this JSON file path + /// + /// The function also takes the top-level formatter "enabled" + /// option into consideration + fn formatter_enabled_for_this_json_file_path( + &self, + path: &Path, + ) -> Option { + // Reverse the traversal as only the last override takes effect + self.patterns.iter().rev().find_map(|pattern| { + calc_capability( + pattern.languages.json.formatter.enabled, + pattern.formatter.enabled, + ) + .and_then(|enabled| { + // Then check whether the path satisfies + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + Some(enabled) + } else { + None + } + }) + }) + } + + /// Scans the overrides and checks if there's an override + /// that sets the language-specific linter "enabled" option + /// explicitly for this JSON file path + /// + /// The function also takes the top-level linter "enabled" + /// option into consideration + fn linter_enabled_for_this_json_file_path(&self, path: &Path) -> Option { + // Reverse the traversal as only the last override takes effect + self.patterns.iter().rev().find_map(|pattern| { + calc_capability( + pattern.languages.json.linter.enabled, + pattern.linter.enabled, + ) + .and_then(|enabled| { + // Then check whether the path satisfies + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + Some(enabled) + } else { + None + } + }) + }) + } + + /// Scans the overrides and checks if there's an override + /// that sets the language-specific organize_imports "enabled" option + /// explicitly for this JSON file path + /// + /// The function also takes the top-level organize_imports "enabled" + /// option into consideration + fn organize_imports_enabled_for_this_json_file_path( + &self, + path: &Path, + ) -> Option { + // Reverse the traversal as only the last override takes effect + self.patterns.iter().rev().find_map(|pattern| { + calc_capability( + pattern.languages.json.organize_imports.enabled, + pattern.organize_imports.enabled, + ) + .and_then(|enabled| { + // Then check whether the path satisfies + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + Some(enabled) + } else { + None + } + }) + }) + } + /// Scans and aggregates all the overrides into a single `JsonParseOptions` pub fn to_override_json_parse_options( &self, @@ -1437,6 +1368,79 @@ impl OverrideSettings { // region: CSS-specific methods + /// Scans the overrides and checks if there's an override + /// that sets the language-specific formatter "enabled" option + /// explicitly for this CSS file path + /// + /// The function also takes the top-level formatter "enabled" + /// option into consideration + fn formatter_enabled_for_this_css_file_path(&self, path: &Path) -> Option { + // Reverse the traversal as only the last override takes effect + self.patterns.iter().rev().find_map(|pattern| { + calc_capability( + pattern.languages.css.formatter.enabled, + pattern.formatter.enabled, + ) + .and_then(|enabled| { + // Then check whether the path satisfies + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + Some(enabled) + } else { + None + } + }) + }) + } + + /// Scans the overrides and checks if there's an override + /// that sets the language-specific linter "enabled" option + /// explicitly for this CSS file path + /// + /// The function also takes the top-level linter "enabled" + /// option into consideration + fn linter_enabled_for_this_css_file_path(&self, path: &Path) -> Option { + // Reverse the traversal as only the last override takes effect + self.patterns.iter().rev().find_map(|pattern| { + calc_capability(pattern.languages.css.linter.enabled, pattern.linter.enabled).and_then( + |enabled| { + // Then check whether the path satisfies + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + Some(enabled) + } else { + None + } + }, + ) + }) + } + + /// Scans the overrides and checks if there's an override + /// that sets the language-specific organize_imports "enabled" option + /// explicitly for this CSS file path + /// + /// The function also takes the top-level organize_imports "enabled" + /// option into consideration + fn organize_imports_enabled_for_this_css_file_path( + &self, + path: &Path, + ) -> Option { + // Reverse the traversal as only the last override takes effect + self.patterns.iter().rev().find_map(|pattern| { + calc_capability( + pattern.languages.css.organize_imports.enabled, + pattern.organize_imports.enabled, + ) + .and_then(|enabled| { + // Then check whether the path satisfies + if pattern.include.matches_path(path) && !pattern.exclude.matches_path(path) { + Some(enabled) + } else { + None + } + }) + }) + } + /// Scans and aggregates all the overrides into a single `CssParseOptions` pub fn to_override_css_parse_options( &self, @@ -1788,3 +1792,37 @@ impl OverrideSettingPattern { } // endregion + +/// Calculates the capability given language-specific and top level +/// capabilities +/// +/// ```markdown +/// | Top \ Lang | Some(T) | Some(F) | N | +/// | :--------: | :-----: | :-----: | :-----: | +/// | Some(T) | Some(T) | Some(F) | N | <-- notice: not Some(T) +/// | Some(F) | Some(T) | Some(F) | Some(F) | +/// | N | Some(T) | Some(F) | N | +/// ``` +/// +/// The reason for the notice is that we don't want a global capability +/// to override the language-specific capability whose default +/// value is false but in an "unset" state (`None`). So that we can +/// still use `.unwrap_or_default()` to retrieve the correct +/// fallback value. This happens when we want to mark the capabilities +/// of some languages as opt-in. +/// +fn calc_capability( + language_specific_capability: Option>, + top_level_capability: Option>, +) -> Option> { + // Check language-specific capability first + language_specific_capability + // Then check the top level capability + .or(top_level_capability.and_then(|v| { + if v.into() { + None + } else { + Some(v.value().into()) + } + })) +} diff --git a/crates/biome_service/src/workspace.rs b/crates/biome_service/src/workspace.rs index af5d719c900e..54605a5cb454 100644 --- a/crates/biome_service/src/workspace.rs +++ b/crates/biome_service/src/workspace.rs @@ -164,7 +164,7 @@ impl FileFeaturesResult { } else if file_source.is_css_like() { settings.formatter_enabled_for_this_css_file_path(path) } else { - settings.formatter_enabled_for_this_foreign_file_path(path) + settings.formatter_enabled_for_this_file_path(path) }; if !formatter_enabled { self.features_supported @@ -179,7 +179,7 @@ impl FileFeaturesResult { } else if file_source.is_css_like() { settings.linter_enabled_for_this_css_file_path(path) } else { - settings.linter_enabled_for_this_foreign_file_path(path) + settings.linter_enabled_for_this_file_path(path) }; if !linter_enabled { self.features_supported @@ -194,7 +194,7 @@ impl FileFeaturesResult { } else if file_source.is_css_like() { settings.organize_imports_enabled_for_this_css_file_path(path) } else { - settings.organize_imports_enabled_for_this_foreign_file_path(path) + settings.organize_imports_enabled_for_this_file_path(path) }; if !organize_imports_enabled { self.features_supported