| # Document highlight | |
| LSP: [textDocument/documentHighlight][] requests | |
| Legacy: `analysis.occurrences` notification | |
| Document highlight is used to highlight both local declarations of and | |
| references to the element declared or referenced at the location of the | |
| insertion cursor. | |
| ## Symmetry | |
| In most cases the operation should be symmetric. That is, the same set of | |
| locations should be highlighted no matter which of those locations contains the | |
| insertion cursor. For example, if the user clicks on the declaration of a local | |
| variable, then all references to that variable should be highlighted, and if the | |
| user clicks on any of the highlighted references the set of highlights should | |
| stay the same. | |
| There are a few cases where symmetry is violated. In particular, symmetry is | |
| violated at declaration sites where a single declaration introduces multiple | |
| elements. In those cases, the set of references to all of the introduced | |
| elements are highlighted, clicking on one of the highlighted references will | |
| remove the highlights related to other elements. | |
| Declarations are the only place where this can occur. Any other references are, | |
| by the semantics of the language, a reference to a single element, so only | |
| references to that element should be highlighted. This is in keeping with the | |
| [principle of language fidelity][languageFidelity]. | |
| Below is a list of the places where symmetry is intentionally broken. | |
| - The declaration of a field introduces both the field (a storage location in an | |
| object), a getter, and optionally a setter (unless the field is either `final' | |
| or `const`). Selecting the field should highlight references to all three | |
| elements; selecting a reference to one of those three elements should only | |
| highlight references to the same element. | |
| - The declaration of a top-level variable similarly introduces both the variable | |
| (a storage location), a getter, and optionally a setter (unless the variable | |
| is either `final` or `const`). | |
| - The declaration of a declaring parameter introduces both the parameter and a | |
| field, which in turn introduces a getter and a possible setter. | |
| - In an object or record pattern, the names of a getter can be omitted if the | |
| matching pattern is a variable declaration pattern whose name matches the name | |
| of the getter. If the getter isn't specified, then the variable declaration | |
| introduces both a local variable declaration and a reference to the getter. | |
| There are a couple of other places where one declaration introduces other | |
| elements where we don't break symmetry. There isn't a principled reason for | |
| this, but it seems like breaking symmetry in these cases would be more | |
| surprising to users than the inconsistency is. | |
| - The declaration of a class or enum, when that declaration doesn't have an | |
| explicit declaration of a constructor, introduces the declaration of a default | |
| constructor (an unnamed constructor with no parameters). | |
| - The declaration of an enum introduces the static getter `values` and the | |
| instance getters `index` and `name`. | |
| ## Kinds | |
| Each document highlight has an associated `kind` which allows clients to | |
| highlight reads and writes differently. The LSP spec says: | |
| > Symbol matches usually have a `DocumentHighlightKind` of `Read` or `Write` | |
| > whereas fuzzy or textual matches use `Text` as the kind. | |
| TypeScript (which we often try to be consistent with when expected behaviour | |
| isn't obvious, since the VS Code, LSP and TypeScript teams working closely | |
| together) uses `Read` and `Write` even for names of types, so we have followed | |
| that pattern. | |
| - `Write` - assignments (setters, variables, initializers), declarations, argument names | |
| - `Read` - getters, variable reads, references to types and parameters | |
| - `Text` - keywords like `for`, `break`, `return` | |
| [languageFidelity]: ../principles/language_fidelity.md | |
| [textDocument/documentHighlight]: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_documentHighlight |