diff --git a/crates/project/tests/integration/project_tests.rs b/crates/project/tests/integration/project_tests.rs index c2656c7885e4bfa73c4ea51b3a1929d96125e426..95163ca863330afdda645647dc5dfe30f3d7141e 100644 --- a/crates/project/tests/integration/project_tests.rs +++ b/crates/project/tests/integration/project_tests.rs @@ -349,6 +349,54 @@ async fn test_external_editorconfig_support(cx: &mut gpui::TestAppContext) { }); } +#[gpui::test] +async fn test_internal_editorconfig_root_stops_traversal(cx: &mut gpui::TestAppContext) { + init_test(cx); + + let fs = FakeFs::new(cx.executor()); + fs.insert_tree( + path!("/worktree"), + json!({ + ".editorconfig": "[*]\nindent_size = 99\n", + "src": { + ".editorconfig": "root = true\n[*]\nindent_size = 2\n", + "file.rs": "fn main() {}", + } + }), + ) + .await; + + let project = Project::test(fs, [path!("/worktree").as_ref()], cx).await; + + let language_registry = project.read_with(cx, |project, _| project.languages().clone()); + language_registry.add(rust_lang()); + + let worktree = project.update(cx, |project, cx| project.worktrees(cx).next().unwrap()); + + cx.executor().run_until_parked(); + + cx.update(|cx| { + let tree = worktree.read(cx); + let file_entry = tree + .entry_for_path(rel_path("src/file.rs")) + .unwrap() + .clone(); + let file = File::for_entry(file_entry, worktree.clone()); + let file_language = project + .read(cx) + .languages() + .load_language_for_file_path(file.path.as_std_path()); + let file_language = cx + .foreground_executor() + .block_on(file_language) + .expect("Failed to get file language"); + let file = file as _; + let settings = language_settings(Some(file_language.name()), Some(&file), cx).into_owned(); + + assert_eq!(Some(settings.tab_size), NonZeroU32::new(2)); + }); +} + #[gpui::test] async fn test_external_editorconfig_root_stops_traversal(cx: &mut gpui::TestAppContext) { init_test(cx); diff --git a/crates/settings/src/editorconfig_store.rs b/crates/settings/src/editorconfig_store.rs index 216cebebbe244f0bf8b90ccd62804d61e88478c4..b309c6892c9686da754c2d97b18ad8d362576c3e 100644 --- a/crates/settings/src/editorconfig_store.rs +++ b/crates/settings/src/editorconfig_store.rs @@ -323,12 +323,13 @@ impl EditorconfigStore { ) -> Option { let mut properties = EditorconfigProperties::new(); let state = self.worktree_state.get(&for_worktree); - let empty_path: Arc = RelPath::empty().into(); let internal_root_config_is_root = state - .and_then(|state| state.internal_configs.get(&empty_path)) + .and_then(|state| state.internal_configs.get(RelPath::empty())) .and_then(|data| data.1.as_ref()) .is_some_and(|ec| ec.is_root); + let std_path = for_path.as_std_path(); + if !internal_root_config_is_root { for (_, _, parsed_editorconfig) in self.external_configs(for_worktree) { if let Some(parsed_editorconfig) = parsed_editorconfig { @@ -336,29 +337,32 @@ impl EditorconfigStore { properties = EditorconfigProperties::new(); } for section in &parsed_editorconfig.sections { - section - .apply_to(&mut properties, for_path.as_std_path()) - .log_err()?; + section.apply_to(&mut properties, std_path).log_err()?; } } } } - 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) { - continue; - } - let parsed_editorconfig = parsed_editorconfig?; - if parsed_editorconfig.is_root { - properties = EditorconfigProperties::new(); + if let Some(state) = state { + let mut internal_configs: SmallVec<[&Editorconfig; 8]> = SmallVec::new(); + + for ancestor in for_path.ancestors() { + if let Some((_, parsed)) = state.internal_configs.get(ancestor) { + let config = parsed.as_ref()?; + internal_configs.push(config); + if config.is_root { + break; + } + } } - for section in &parsed_editorconfig.sections { - section - .apply_to(&mut properties, for_path.as_std_path()) - .log_err()?; + + for config in internal_configs.into_iter().rev() { + if config.is_root { + properties = EditorconfigProperties::new(); + } + for section in &config.sections { + section.apply_to(&mut properties, std_path).log_err()?; + } } }