editor: Resolve semantic token overlaps by configured server order (#61735)
`RawSemanticTokens` says tokens later in the list override earlier ones
on overlap, but there's no list to be later in — the tokens are stored
in a `HashMap<LanguageServerId, _>` and the sort that flattens them keys
only on `range.start`:
https://github.com/zed-industries/zed/blob/9dcc3c29099724321c34797d18573d28a2c9df25/crates/project/src/lsp_store/semantic_tokens.rs#L702-L709
https://github.com/zed-industries/zed/blob/9dcc3c29099724321c34797d18573d28a2c9df25/crates/editor/src/semantic_tokens.rs#L312-L314
`sort_by` is stable, so two servers' tokens at the same position keep
whatever order the map iteration gave them, and which one wins changes
between sessions.
You hit this any time two servers tokenize the same range. In my case a
server that highlights an embedded query inside a string literal renders
fine, then loses the range to svelte-language-server once that
refreshes. Setting `languages.Svelte.language_servers` doesn't help,
since that isn't what decides it.
Breaking ties by `server_id` makes it deterministic.
`SemanticTokenHighlight` already carries the id and `LanguageServerId`
is `Ord`, so it's just the tiebreak.
Worth noting the servers do arrive as an ordered `Vec` from
`language_server_ids_for_buffer` and that order is dropped when they go
into the `HashMap`. Sorting by id gets determinism but not that original
order; if preserving it is what was intended I'm happy to submit a PR
for that functionality instead.
Release Notes:
- Fixed semantic token highlighting being applied unpredictably when
more than one language server provides tokens for the same range.
bbd198f57bDrew Ridley committed on 8/4/2026, 2:05:46 PM· committed by GitHubparentc6e0868