java-topology/defects/zed/patch/zed-0002-extension-manifest-dedup.patch

56 lines
2.8 KiB
Diff

# UNDF: UNDF-2026-000000812
# UNDF: (leave blank)
# zed-0002: extension_builder manifest entry dedup Vec::contains O(N²)
#
# File: crates/extension/src/extension_builder.rs
# Function: compile_extension_manifest (lines 585-632)
#
# Defect: Three while-loops accumulate entries into manifest.languages,
# manifest.themes, and manifest.icon_themes (all Vec), each
# checking Vec::contains before push — O(N²) per category where
# N = number of language dirs / theme files / icon theme files.
#
# Fix: Use a HashSet<PathBuf> as a seen-set for each category.
# Severity: LOW (N = extension assets, typically 1-20; only at build time)
# Speedup: 20x at N=20
#
--- a/crates/extension/src/extension_builder.rs
+++ b/crates/extension/src/extension_builder.rs
@@ -580,6 +580,7 @@
+ let existing_languages: HashSet<_> = manifest.languages.iter().cloned().collect();
while let Some(language_dir) = language_dir_entries.next().await {
let language_dir = language_dir?;
let config_path = language_dir.join(LanguageConfig::FILE_NAME);
if fs.is_file(config_path.as_path()).await {
let relative_language_dir =
language_dir.strip_prefix(extension_path)?.to_path_buf();
- if !manifest.languages.contains(&relative_language_dir) {
+ if !existing_languages.contains(&relative_language_dir) {
manifest.languages.push(relative_language_dir);
}
}
@@ -598,6 +600,7 @@
+ let existing_themes: HashSet<_> = manifest.themes.iter().cloned().collect();
while let Some(theme_path) = theme_dir_entries.next().await {
let theme_path = theme_path?;
if theme_path.extension() == Some("json".as_ref()) {
let relative_theme_path = theme_path.strip_prefix(extension_path)?.to_path_buf();
- if !manifest.themes.contains(&relative_theme_path) {
+ if !existing_themes.contains(&relative_theme_path) {
manifest.themes.push(relative_theme_path);
}
}
@@ -616,6 +620,7 @@
+ let existing_icon_themes: HashSet<_> = manifest.icon_themes.iter().cloned().collect();
while let Some(icon_theme_path) = icon_theme_dir_entries.next().await {
let icon_theme_path = icon_theme_path?;
if icon_theme_path.extension() == Some("json".as_ref()) {
let relative_icon_theme_path =
icon_theme_path.strip_prefix(extension_path)?.to_path_buf();
- if !manifest.icon_themes.contains(&relative_icon_theme_path) {
+ if !existing_icon_themes.contains(&relative_icon_theme_path) {
manifest.icon_themes.push(relative_icon_theme_path);
}
}