From b951bd3d6fb4d12c98ef86e5c1b2828ca9753c15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=80=E1=B4=8D=E1=B4=9B=E1=B4=8F=E1=B4=80=E1=B4=87?= =?UTF-8?q?=CA=80?= Date: Tue, 3 Feb 2026 12:51:41 +0800 Subject: [PATCH] Fix subdirectory `.editorconfig` files being ignored in certain directory structures (#48203) Closes #48187 The bug occurred when iterating internal_configs (a BTreeMap sorted by path): the code would `break` on the first non-matching path, causing configs with lexicographically later paths to be skipped. For example, when querying "d/d.rs" with configs ["", "b", "d"], iteration would break at "b" (since "d/d.rs" doesn't start with "b"), preventing "d"'s config from being applied. This PR replaces `break` with `continue` to skip non-ancestors, and adds a minor early-exit optimization when `config_path > for_path` since later paths can't be ancestors. Release Notes: - Fixed subdirectory `.editorconfig` files being ignored in certain directory structures --- crates/project/tests/integration/project_tests.rs | 11 ++++++++++- crates/settings/src/editorconfig_store.rs | 6 ++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/crates/project/tests/integration/project_tests.rs b/crates/project/tests/integration/project_tests.rs index dabd4282dee96a5952bb3e903bdfb54bf54d36f8..c2656c7885e4bfa73c4ea51b3a1929d96125e426 100644 --- a/crates/project/tests/integration/project_tests.rs +++ b/crates/project/tests/integration/project_tests.rs @@ -215,6 +215,13 @@ async fn test_editorconfig_support(cx: &mut gpui::TestAppContext) { "b.rs": "fn b() {\n B\n}", }, "c.js": "def c\n C\nend", + "d": { + ".editorconfig": r#" + [*.rs] + indent_size = 1 + "#, + "d.rs": "fn d() {\n D\n}", + }, "README.json": "tabs are better\n", })); @@ -252,6 +259,7 @@ async fn test_editorconfig_support(cx: &mut gpui::TestAppContext) { let settings_a = settings_for("a.rs"); let settings_b = settings_for("b/b.rs"); let settings_c = settings_for("c.js"); + let settings_d = settings_for("d/d.rs"); let settings_readme = settings_for("README.json"); // .editorconfig overrides .zed/settings @@ -261,8 +269,9 @@ async fn test_editorconfig_support(cx: &mut gpui::TestAppContext) { assert_eq!(settings_a.remove_trailing_whitespace_on_save, true); assert_eq!(settings_a.preferred_line_length, 120); - // .editorconfig in b/ overrides .editorconfig in root + // .editorconfig in subdirectory overrides .editorconfig in root assert_eq!(Some(settings_b.tab_size), NonZeroU32::new(2)); + assert_eq!(Some(settings_d.tab_size), NonZeroU32::new(1)); // "indent_size" is not set, so "tab_width" is used assert_eq!(Some(settings_c.tab_size), NonZeroU32::new(10)); diff --git a/crates/settings/src/editorconfig_store.rs b/crates/settings/src/editorconfig_store.rs index fdca88fcf5ca19b1be800940630b856a44d2fad2..216cebebbe244f0bf8b90ccd62804d61e88478c4 100644 --- a/crates/settings/src/editorconfig_store.rs +++ b/crates/settings/src/editorconfig_store.rs @@ -345,9 +345,11 @@ impl EditorconfigStore { } for (directory_with_config, _, parsed_editorconfig) in self.internal_configs(for_worktree) { + if directory_with_config > for_path { + break; + } if !for_path.starts_with(directory_with_config) { - properties.use_fallbacks(); - return Some(properties); + continue; } let parsed_editorconfig = parsed_editorconfig?; if parsed_editorconfig.is_root {