SIGN IN SIGN UP

text_view: Fix code block highlighting after theme changes (#2622)

Closes #2618

## Description

This PR fixes Markdown code blocks keeping syntax colors from the theme
that was
active when the Markdown was parsed.

The root cause was that `CodeBlock` captured the active `HighlightTheme`
during
Markdown parsing and cached only the computed syntax styles.
Re-rendering the
same `TextViewState` after a theme change therefore kept returning that
theme-independent cache entry, even though the rest of the view used the
new
active theme.

This change:

- removes the highlight theme from the Markdown parsing and background
update
  pipeline
- resolves the current `ActiveTheme` when a code block is rendered
- stores the theme alongside cached code-block styles and recomputes
them when
  that theme changes
- keeps the normal render path inexpensive with an `Arc` identity fast
path,
while treating separately allocated but equivalent themes as the same
cache
  key and adopting the current `Arc` after an equivalent-value match
- adds a focused syntax-color regression test and a GPUI render-level
  regression test

The render-level test keeps the same parsed `CodeBlock` alive, changes
the
global theme from light to dark, redraws the window, and verifies that
the
existing block's highlight cache is updated without reparsing the
Markdown.

This preserves the existing behavior in which Markdown code blocks
follow the
current `ActiveTheme`. It does not introduce new per-view override
semantics for
the public `TextViewStyle::highlight_theme` field.

## Review Follow-up

During a second review of the fix, I found an efficiency edge case in
the
initial cache implementation. When an equivalent `HighlightTheme`
arrived in a
separately allocated `Arc`, the cache correctly reused the computed
syntax
styles but retained the previous `Arc`. Every later render would
therefore miss
the pointer-identity fast path and repeat a full `HighlightTheme` value
comparison. This did not affect rendered colors, but it made the
steady-state
render path unnecessarily expensive after an equivalent theme reload.

The cache now adopts the current `Arc` when the theme values are equal,
while
preserving the already computed syntax styles. Subsequent renders then
return
to the O(1) pointer-identity check without re-highlighting. The focused
regression test verifies that an equivalent replacement becomes the
cached
identity before testing a genuinely different theme.

The new cache-identity assertion was also run against the initial
implementation
and failed because the cache still pointed to the previous `Arc`. It
passes
after the follow-up change.

## Branch Synchronization

After contributor review, this branch was synchronized with
`upstream/main@de5859b2` through merge commits `fcb4a97a` and
`0554ed16`. The
upstream changes touched only `crates/ui/src/input/state.rs` and
`crates/ui/src/input/element.rs`, did not overlap this PR, and merged
without
conflict. The proposed diff relative to the current base remains limited
to the
three text files listed in this PR, and the relevant local validation
was rerun
after synchronization.

## Screenshot

Both screenshots show the same persistent `TextViewState` after
switching the
global theme from light to dark. The Markdown source is unchanged and is
not
reparsed. They compare the buggy and fixed builds; both screenshots are
taken
in the final dark-theme state.

Before the fix, the view background changed to dark, but the code block
kept
syntax styles cached under the light theme, producing stale and
low-contrast
token colors. After the fix, the existing code block detects the active
theme
change during rendering and refreshes its syntax styles with the dark
highlighting palette.

| Before | After |
| ------ | ----- |
| <img width="1360" height="816" alt="before-active"
src="https://github.com/user-attachments/assets/e4ee16ec-d051-4ca2-8567-ae2c2ac91183"
/> | <img width="1360" height="816" alt="after-active"
src="https://github.com/user-attachments/assets/5dec0f5b-9904-4e19-a6ae-b4cf2e052df8"
/> |

## Break Changes

None.

## How to Test

The regression test was first run against the old cache behavior and
failed
because the dark-theme render returned the light-theme number color. It
passes
after this change.

Focused regression and render-level tests:

```bash
cargo test --locked --offline -p gpui-component \
  --features tree-sitter-languages theme -- --nocapture --test-threads=1
```

Full component and workspace tests:

```bash
cargo test --locked --offline -p gpui-component \
  --features tree-sitter-languages -- --test-threads=1
cargo test --locked --offline -p gpui-component \
  --no-default-features -- --test-threads=1
cargo test --locked --offline --all -- --test-threads=1
```

Lint and cross-target checks:

```bash
cargo clippy --locked --offline -- --deny warnings
cargo clippy --locked --offline -p gpui-component --tests \
  --features tree-sitter-languages -- --deny warnings
cargo check --locked --offline -p gpui-component --no-default-features
cargo check --locked --offline --target wasm32-unknown-unknown \
  -p gpui-component --no-default-features
rustfmt --edition 2024 --check \
  crates/ui/src/text/node.rs \
  crates/ui/src/text/format/markdown.rs \
  crates/ui/src/text/state.rs
git diff --check
```

Results:

- `gpui-component` with tree-sitter languages: 358 passed
- `gpui-component` without default features: 340 passed
- full workspace tests: passed
- both Clippy invocations with warnings denied: passed
- native and WASM no-default checks: passed
- GitHub CI on macOS, Linux, and Windows for the synchronized head:
passed

Manual visual verification was performed on Linux with a dedicated local
story
reproduction. It changed only `Theme::change(...)` after the initial
parse and
produced the before/after screenshots above.

## AI Assistance

Codex assisted with root-cause analysis, implementation, regression
tests,
validation, screenshots, and drafting this PR description. The automated
and
manual checks listed above were run locally. The contributor reviewed
the final
diff, including follow-up commit `bf1483f3`, and confirmed that the
AI-assisted
changes are accurate.

## Checklist

- [x] I have read the [CONTRIBUTING](../CONTRIBUTING.md) document and
followed the guidelines.
- [x] Reviewed the changes in this PR and confirmed AI generated code
(If any) is accurate.
- [x] Passed `cargo run` for story tests related to the changes. A
dedicated local reproduction was run before and after the fix.
- [x] Tested macOS, Windows and Linux platforms performance (if the
change is platform-specific). Not platform-specific; the synchronized
head passed CI on all three platforms, the visual behavior was manually
verified on Linux, and the crate was compiled for WASM.
L
luren committed
be3c8413766cafc736a0c1c80306ff0f293e04f3
Parent: 98af891
Committed by GitHub <noreply@github.com> on 7/30/2026, 10:27:37 AM