settings: Improve performance for internal editorconfig resolution (#48243)
Replaces O(N) iteration over all internal configs with O(D × log N) direct ancestor lookups, where D is path depth and N is total config count. Release Notes: - N/A
This commit is contained in:
1 parent
3c4368a076
commit
5ff32226cf
2 files changed
+71
-19
No files matched your search
@@ -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);
|
||||
|
||||
@@ -323,12 +323,13 @@ impl EditorconfigStore {
|
||||
) -> Option<EditorconfigProperties> {
|
||||
let mut properties = EditorconfigProperties::new();
|
||||
let state = self.worktree_state.get(&for_worktree);
|
||||
let empty_path: Arc<RelPath> = 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 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
if !for_path.starts_with(directory_with_config) {
|
||||
continue;
|
||||
}
|
||||
let parsed_editorconfig = parsed_editorconfig?;
|
||||
if parsed_editorconfig.is_root {
|
||||
properties = EditorconfigProperties::new();
|
||||
}
|
||||
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()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user