Collect document highlights for the symbol under the cursor. Returns `None` when the cursor is not on a navigable symbol.
(
&self,
uri: &str,
content: &str,
position: Position,
)
| 28 | /// |
| 29 | /// Returns `None` when the cursor is not on a navigable symbol. |
| 30 | pub fn handle_document_highlight( |
| 31 | &self, |
| 32 | uri: &str, |
| 33 | content: &str, |
| 34 | position: Position, |
| 35 | ) -> Option<Vec<DocumentHighlight>> { |
| 36 | // Look up the symbol span at the cursor (retries one byte |
| 37 | // earlier for end-of-token edge cases). |
| 38 | let span = self.lookup_symbol_at_position(uri, content, position)?; |
| 39 | |
| 40 | let maps = self.symbol_maps.read(); |
| 41 | let symbol_map = maps.get(uri)?; |
| 42 | |
| 43 | let highlights = match &span.kind { |
| 44 | SymbolKind::Variable { name } => { |
| 45 | // Check if this is actually a property declaration — if |
| 46 | // so, highlight member accesses instead of local vars. |
| 47 | if let Some(VarDefKind::Property) = symbol_map.var_def_kind_at(name, span.start) { |
| 48 | self.highlight_member_name(symbol_map, content, name) |
| 49 | } else { |
| 50 | self.highlight_variable(symbol_map, content, name, span.start) |
| 51 | } |
| 52 | } |
| 53 | SymbolKind::ClassReference { name, is_fqn, .. } => { |
| 54 | let ctx = self.file_context(uri); |
| 55 | let fqn = if *is_fqn { |
| 56 | name.clone() |
| 57 | } else { |
| 58 | ctx.resolve_name_at(name, span.start) |
| 59 | }; |
| 60 | self.highlight_class(symbol_map, content, &fqn, &ctx.use_map, &ctx.namespace) |
| 61 | } |
| 62 | SymbolKind::ClassDeclaration { name } => { |
| 63 | let ctx = self.file_context(uri); |
| 64 | let fqn = build_fqn(name, ctx.namespace.as_deref()); |
| 65 | self.highlight_class(symbol_map, content, &fqn, &ctx.use_map, &ctx.namespace) |
| 66 | } |
| 67 | SymbolKind::MemberAccess { member_name, .. } => { |
| 68 | self.highlight_member_name(symbol_map, content, member_name) |
| 69 | } |
| 70 | SymbolKind::MemberDeclaration { name, .. } => { |
| 71 | self.highlight_member_name(symbol_map, content, name) |
| 72 | } |
| 73 | SymbolKind::FunctionCall { name, .. } => { |
| 74 | self.highlight_function(symbol_map, content, name) |
| 75 | } |
| 76 | SymbolKind::ConstantReference { name } => { |
| 77 | self.highlight_constant(symbol_map, content, name) |
| 78 | } |
| 79 | SymbolKind::SelfStaticParent(ssp_kind) => { |
| 80 | if *ssp_kind == SelfStaticParentKind::This { |
| 81 | self.highlight_this(symbol_map, content, span.start, uri) |
| 82 | } else { |
| 83 | self.highlight_keyword(symbol_map, content, *ssp_kind, span.start, uri) |
| 84 | } |
| 85 | } |
| 86 | SymbolKind::NamespaceDeclaration { .. } |
| 87 | | SymbolKind::LaravelStringKey { .. } |