| # 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 |