semantic-tokens.md

  1# Semantic Tokens
  2
  3Semantic tokens provide richer syntax highlighting by using information from language servers. Unlike tree-sitter highlighting, which is based purely on syntax, semantic tokens understand the meaning of your code—distinguishing between local variables and parameters, or between a class definition and a class reference.
  4
  5## Enabling Semantic Tokens
  6
  7Semantic tokens are controlled by the `semantic_tokens` setting. By default, semantic tokens are disabled.
  8
  9```json [settings]
 10{
 11  "semantic_tokens": "combined"
 12}
 13```
 14
 15This setting accepts three values:
 16
 17| Value        | Description                                                                                                                                                 |
 18| ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
 19| `"off"`      | Do not request semantic tokens from language servers. Uses tree-sitter highlighting only. (Default)                                                         |
 20| `"combined"` | Use LSP semantic tokens together with tree-sitter highlighting. Tree-sitter provides base highlighting, and semantic tokens overlay additional information. |
 21| `"full"`     | Use LSP semantic tokens exclusively. Tree-sitter highlighting is disabled entirely for buffers with semantic token support.                                 |
 22
 23You can configure this globally or per-language:
 24
 25```json [settings]
 26{
 27  "semantic_tokens": "off",
 28  "languages": {
 29    "Rust": {
 30      "semantic_tokens": "combined"
 31    },
 32    "TypeScript": {
 33      "semantic_tokens": "full"
 34    }
 35  }
 36}
 37```
 38
 39> **Note:** Changing the `semantic_tokens` mode may require a language server restart to take effect. Use the `lsp: restart language servers` command from the command palette if highlighting doesn't update immediately.
 40
 41## Customizing Token Colors
 42
 43Semantic tokens are styled using rules that map LSP token types and modifiers to theme styles or custom colors. Zed provides sensible defaults, but you can customize these in your settings.json: add rules under `global_lsp_settings.semantic_token_rules` key.
 44
 45Rules are matched in order, and the first matching rule wins.
 46User-defined rules take precedence over defaults.
 47
 48### Rule Structure
 49
 50Each rule can specify:
 51
 52| Property           | Description                                                                                                        |
 53| ------------------ | ------------------------------------------------------------------------------------------------------------------ |
 54| `token_type`       | The LSP semantic token type to match (e.g., `"variable"`, `"function"`, `"class"`). If omitted, matches all types. |
 55| `token_modifiers`  | A list of modifiers that must all be present (e.g., `["declaration"]`, `["readonly", "static"]`).                  |
 56| `style`            | A list of theme style names to try. The first one found in the current theme is used.                              |
 57| `foreground_color` | Override foreground color in hex format (e.g., `"#ff0000"`).                                                       |
 58| `background_color` | Override background color in hex format.                                                                           |
 59| `underline`        | Boolean or hex color. If `true`, underlines with the text color.                                                   |
 60| `strikethrough`    | Boolean or hex color. If `true`, strikes through with the text color.                                              |
 61| `font_weight`      | `"normal"` or `"bold"`.                                                                                            |
 62| `font_style`       | `"normal"` or `"italic"`.                                                                                          |
 63
 64### Example: Highlighting Unresolved References
 65
 66To make unresolved references stand out:
 67
 68```json [settings]
 69{
 70  "global_lsp_settings": {
 71    "semantic_token_rules": [
 72      {
 73        "token_type": "unresolvedReference",
 74        "foreground_color": "#c93f3f",
 75        "font_weight": "bold"
 76      }
 77    ]
 78  }
 79}
 80```
 81
 82### Example: Highlighting Unsafe Code
 83
 84To highlight unsafe operations in Rust:
 85
 86```json [settings]
 87{
 88  "global_lsp_settings": {
 89    "semantic_token_rules": [
 90      {
 91        "token_type": "punctuation",
 92        "token_modifiers": ["unsafe"],
 93        "foreground_color": "#AA1111",
 94        "font_weight": "bold"
 95      }
 96    ]
 97  }
 98}
 99```
100
101### Example: Using Theme Styles
102
103Instead of hardcoding colors, reference styles from your theme:
104
105```json [settings]
106{
107  "global_lsp_settings": {
108    "semantic_token_rules": [
109      {
110        "token_type": "variable",
111        "token_modifiers": ["mutable"],
112        "style": ["variable.mutable", "variable"]
113      }
114    ]
115  }
116}
117```
118
119The first style found in the current theme is used, providing fallback options.
120
121### Example: Disabling a Token Type
122
123To disable highlighting for a specific token type, add an empty rule that matches it:
124
125```json [settings]
126{
127  "global_lsp_settings": {
128    "semantic_token_rules": [
129      {
130        "token_type": "comment"
131      }
132    ]
133  }
134}
135```
136
137Since user rules are prepended to defaults and the first match wins, this empty rule prevents any styling from being applied to comment tokens.
138
139## Default Rules
140
141Zed's default semantic token rules map standard LSP token types to common theme styles. For example:
142
143- `function` → `function` style
144- `variable` with `constant` modifier → `constant` style
145- `class` → `type.class`, `class`, or `type` style (first found)
146- `comment` with `documentation` modifier → `comment.documentation` or `comment.doc` style
147
148The full default configuration can be shown in Zed with the `zed: show default semantic token rules` command.
149
150## Standard Token Types
151
152Language servers report tokens using standardized types. Common types include:
153
154| Type            | Description                        |
155| --------------- | ---------------------------------- |
156| `namespace`     | Namespace or module names          |
157| `type`          | Type names                         |
158| `class`         | Class names                        |
159| `enum`          | Enum type names                    |
160| `interface`     | Interface names                    |
161| `struct`        | Struct names                       |
162| `typeParameter` | Generic type parameters            |
163| `parameter`     | Function/method parameters         |
164| `variable`      | Variable names                     |
165| `property`      | Object properties or struct fields |
166| `enumMember`    | Enum variants                      |
167| `function`      | Function names                     |
168| `method`        | Method names                       |
169| `macro`         | Macro names                        |
170| `keyword`       | Language keywords                  |
171| `comment`       | Comments                           |
172| `string`        | String literals                    |
173| `number`        | Numeric literals                   |
174| `operator`      | Operators                          |
175
176Common modifiers include: `declaration`, `definition`, `readonly`, `static`, `deprecated`, `async`, `documentation`, `defaultLibrary`, and language-specific modifiers like `unsafe` (Rust) or `abstract` (TypeScript).
177
178For the complete specification, see the [LSP Semantic Tokens documentation](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#semanticTokenTypes).
179
180## Inspecting Semantic Tokens
181
182To see semantic tokens applied to your code in real-time, use the `dev: open highlights tree view` command from the command palette. This opens a panel showing all highlights (including semantic tokens) for the current buffer, making it easier to understand which tokens are being applied and debug your custom rules.
183
184## Troubleshooting
185
186### Semantic highlighting not appearing
187
1881. Ensure `semantic_tokens` is set to `"combined"` or `"full"` for the language
1892. Verify the language server supports semantic tokens (not all do)
1903. Try restarting the language server with `lsp: restart language servers`
1914. Check the LSP logs (`workspace: open lsp log`) for errors
192
193### Colors not updating after changing settings
194
195Changes to `semantic_tokens` mode may require a language server restart. Use `lsp: restart language servers` from the command palette.
196
197### Theme styles not being applied
198
199Ensure the style names in your rules match styles defined in your theme. The `style` array provides fallback options—if the first style isn't found, Zed tries the next one.