From 6af5ca3f8036b937e9d84bdf2283e89986caca67 Mon Sep 17 00:00:00 2001 From: Smit Chaudhary Date: Sat, 11 Apr 2026 18:52:27 +0200 Subject: [PATCH] editor: Fix breadcrumb syntax colors not updating when theme changes (#53185) --- crates/editor/src/document_symbols.rs | 132 +++++++++++++++++++++++++- crates/editor/src/editor.rs | 1 + 2 files changed, 132 insertions(+), 1 deletion(-) diff --git a/crates/editor/src/document_symbols.rs b/crates/editor/src/document_symbols.rs index ef9159788a7a5c2b2c317015219090fdae6a4944..074e5a5ed27b104946ab7537c2e772cf0c9c5572 100644 --- a/crates/editor/src/document_symbols.rs +++ b/crates/editor/src/document_symbols.rs @@ -331,7 +331,7 @@ mod tests { use futures::StreamExt as _; use gpui::TestAppContext; - use settings::DocumentSymbols; + use settings::{DocumentSymbols, SettingsStore}; use util::path; use zed_actions::editor::{MoveDown, MoveUp}; @@ -875,4 +875,134 @@ mod tests { "Should not have made any LSP document symbol requests when setting is off" ); } + + #[gpui::test] + async fn test_breadcrumb_highlights_update_on_theme_change(cx: &mut TestAppContext) { + use collections::IndexMap; + use gpui::{Hsla, Rgba, UpdateGlobal as _}; + use theme_settings::{HighlightStyleContent, ThemeStyleContent}; + use ui::ActiveTheme as _; + + init_test(cx, |_| {}); + + let mut cx = EditorLspTestContext::new_rust(lsp::ServerCapabilities::default(), cx).await; + + // Set the initial theme with a red keyword color and sync it to the + // language registry so tree-sitter highlight maps are up to date. + let red_color: Hsla = Rgba { + r: 1.0, + g: 0.0, + b: 0.0, + a: 1.0, + } + .into(); + cx.update(|_, cx| { + SettingsStore::update_global(cx, |store, cx| { + store.update_user_settings(cx, |settings| { + settings.theme.experimental_theme_overrides = Some(ThemeStyleContent { + syntax: IndexMap::from_iter([( + "keyword".to_string(), + HighlightStyleContent { + color: Some("#ff0000".to_string()), + background_color: None, + font_style: None, + font_weight: None, + }, + )]), + ..ThemeStyleContent::default() + }); + }); + }); + }); + cx.update_editor(|editor, _window, cx| { + editor + .project + .as_ref() + .expect("editor should have a project") + .read(cx) + .languages() + .set_theme(cx.theme().clone()); + }); + cx.set_state("fn maˇin() {}"); + cx.run_until_parked(); + + cx.update_editor(|editor, _window, cx| { + let breadcrumbs = editor + .breadcrumbs_inner(cx) + .expect("Should have breadcrumbs"); + let symbol_segment = breadcrumbs + .iter() + .find(|b| b.text.as_ref() == "fn main") + .expect("Should have 'fn main' breadcrumb"); + let keyword_highlight = symbol_segment + .highlights + .iter() + .find(|(range, _)| &symbol_segment.text[range.clone()] == "fn") + .expect("Should have a highlight for the 'fn' keyword"); + assert_eq!( + keyword_highlight.1.color, + Some(red_color), + "The 'fn' keyword should have red color" + ); + }); + + // Change the theme to use a blue keyword color. This simulates a user + // switching themes. The language registry set_theme call mirrors what + // the application does in main.rs on theme change. + let blue_color: Hsla = Rgba { + r: 0.0, + g: 0.0, + b: 1.0, + a: 1.0, + } + .into(); + cx.update(|_, cx| { + SettingsStore::update_global(cx, |store, cx| { + store.update_user_settings(cx, |settings| { + settings.theme.experimental_theme_overrides = Some(ThemeStyleContent { + syntax: IndexMap::from_iter([( + "keyword".to_string(), + HighlightStyleContent { + color: Some("#0000ff".to_string()), + background_color: None, + font_style: None, + font_weight: None, + }, + )]), + ..ThemeStyleContent::default() + }); + }); + }); + }); + cx.update_editor(|editor, _window, cx| { + editor + .project + .as_ref() + .expect("editor should have a project") + .read(cx) + .languages() + .set_theme(cx.theme().clone()); + }); + cx.run_until_parked(); + + cx.update_editor(|editor, _window, cx| { + let breadcrumbs = editor + .breadcrumbs_inner(cx) + .expect("Should have breadcrumbs after theme change"); + let symbol_segment = breadcrumbs + .iter() + .find(|b| b.text.as_ref() == "fn main") + .expect("Should have 'fn main' breadcrumb after theme change"); + let keyword_highlight = symbol_segment + .highlights + .iter() + .find(|(range, _)| &symbol_segment.text[range.clone()] == "fn") + .expect("Should have a highlight for the 'fn' keyword after theme change"); + assert_eq!( + keyword_highlight.1.color, + Some(blue_color), + "The 'fn' keyword should have blue color after theme change" + ); + }); + } } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index 09fc8ece435c8aff22bbf380709669282bd28dcd..77ddd5e95d159d20ac627ec1d0406823d201ff4c 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -24815,6 +24815,7 @@ impl Editor { self.invalidate_semantic_tokens(None); self.refresh_semantic_tokens(None, None, cx); + self.refresh_outline_symbols_at_cursor(cx); } pub fn set_searchable(&mut self, searchable: bool) {