diff --git a/.changeset/fix-formatter-override-inheritance.md b/.changeset/fix-formatter-override-inheritance.md new file mode 100644 index 000000000000..ed693e20719a --- /dev/null +++ b/.changeset/fix-formatter-override-inheritance.md @@ -0,0 +1,20 @@ +--- +"@biomejs/biome": patch +--- + +Fixed [#8429](https://github.com/biomejs/biome/issues/8429). Formatter, linter, and assist settings now correctly inherit from global configuration when not explicitly specified in overrides. + +Before this fix, when an override specified only one feature (e.g., only `linter`), other features would be incorrectly disabled instead of inheriting from global settings. + +Example configuration that now works correctly: +```json +{ + "formatter": { "enabled": true }, + "overrides": [{ + "includes": ["*.vue"], + "linter": { "enabled": false } + }] +} +``` + +After this fix, `.vue` files will have the linter disabled (as specified in the override) but the formatter enabled (inherited from global settings). diff --git a/crates/biome_service/src/settings.rs b/crates/biome_service/src/settings.rs index 2460d43dbb46..932930a8d7fc 100644 --- a/crates/biome_service/src/settings.rs +++ b/crates/biome_service/src/settings.rs @@ -1750,7 +1750,7 @@ pub fn to_override_settings( let formatter = pattern .formatter .map(|formatter| OverrideFormatSettings { - enabled: formatter.enabled, + enabled: formatter.enabled.or(current_settings.formatter.enabled), format_with_errors: formatter .format_with_errors .or(current_settings.formatter.format_with_errors), @@ -1767,7 +1767,7 @@ pub fn to_override_settings( let linter = pattern .linter .map(|linter| OverrideLinterSettings { - enabled: linter.enabled, + enabled: linter.enabled.or(current_settings.linter.enabled), rules: linter.rules, domains: linter.domains, }) @@ -1775,7 +1775,7 @@ pub fn to_override_settings( let assist = pattern .assist .map(|assist| OverrideAssistSettings { - enabled: assist.enabled, + enabled: assist.enabled.or(current_settings.assist.enabled), actions: assist.actions, }) .unwrap_or_default(); diff --git a/crates/biome_service/src/settings.tests.rs b/crates/biome_service/src/settings.tests.rs index 05e9a2f88f90..0b9da0103e7d 100644 --- a/crates/biome_service/src/settings.tests.rs +++ b/crates/biome_service/src/settings.tests.rs @@ -6,7 +6,7 @@ use biome_configuration::javascript::JsxRuntime; use biome_configuration::json::{JsonAssistConfiguration, JsonLinterConfiguration}; use biome_configuration::max_size::MaxSize; use biome_configuration::{ - Configuration, JsConfiguration, JsonConfiguration, LinterConfiguration, + Configuration, FormatterConfiguration, JsConfiguration, JsonConfiguration, LinterConfiguration, OverrideFilesConfiguration, OverrideGlobs, OverrideLinterConfiguration, OverridePattern, Overrides, RuleConfiguration, RulePlainConfiguration, Rules, }; @@ -174,3 +174,60 @@ fn json_to_settings_includes_linter_and_assist() { assert_eq!(settings.linter.enabled, Some(true.into())); assert_eq!(settings.assist.enabled, Some(true.into())); } + +#[test] +fn override_inherits_global_formatter_when_not_specified() { + // the formatter should inherit from global settings instead of being disabled + let configuration = Configuration { + formatter: Some(FormatterConfiguration { + enabled: Some(true.into()), + ..FormatterConfiguration::default() + }), + linter: Some(LinterConfiguration { + enabled: Some(true.into()), + ..LinterConfiguration::default() + }), + overrides: Some(Overrides(vec![OverridePattern { + includes: Some(OverrideGlobs::Globs(Box::new([ + biome_glob::NormalizedGlob::from_str("*.vue").unwrap(), + ]))), + // Override only specifies linter, not formatter + linter: Some(OverrideLinterConfiguration { + enabled: Some(false.into()), + ..OverrideLinterConfiguration::default() + }), + ..OverridePattern::default() + }])), + ..Default::default() + }; + + let mut settings = Settings::default(); + settings + .merge_with_configuration(configuration, None, vec![]) + .expect("valid configuration"); + + // For .vue files, linter should be disabled (from override) + let linter_enabled = + JsLanguage::linter_enabled_for_file_path(&settings, Utf8Path::new("test.vue")); + assert!(!linter_enabled, "Linter should be disabled for .vue files"); + + // For .vue files, formatter should be enabled (inherited from global) + let formatter_enabled = + JsLanguage::formatter_enabled_for_file_path(&settings, Utf8Path::new("test.vue")); + assert!( + formatter_enabled, + "Formatter should be enabled for .vue files (inherited from global)" + ); + + // For non .vue files, both should be enabled (from global) + let linter_enabled_js = + JsLanguage::linter_enabled_for_file_path(&settings, Utf8Path::new("test.js")); + assert!(linter_enabled_js, "Linter should be enabled for .js files"); + + let formatter_enabled_js = + JsLanguage::formatter_enabled_for_file_path(&settings, Utf8Path::new("test.js")); + assert!( + formatter_enabled_js, + "Formatter should be enabled for .js files" + ); +}