From 23057d8a051c2b3c11c76aed82366f546798fa7e Mon Sep 17 00:00:00 2001 From: bkellam Date: Sun, 30 Nov 2025 16:35:24 -0800 Subject: [PATCH] highlight the selected reference --- .../components/symbolHoverPopup/index.tsx | 27 ++++------ .../useHoveredOverSymbolInfo.ts | 50 ++++++++++++++++++- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/packages/web/src/ee/features/codeNav/components/symbolHoverPopup/index.tsx b/packages/web/src/ee/features/codeNav/components/symbolHoverPopup/index.tsx index 9399a2ed..a786f600 100644 --- a/packages/web/src/ee/features/codeNav/components/symbolHoverPopup/index.tsx +++ b/packages/web/src/ee/features/codeNav/components/symbolHoverPopup/index.tsx @@ -163,7 +163,11 @@ export const SymbolHoverPopup: React.FC = ({ symbolInfo ]); - const onFindReferences = useCallback((symbolName: string) => { + const onFindReferences = useCallback(() => { + if (!symbolInfo) { + return; + } + captureEvent('wa_find_references_pressed', { source, }); @@ -171,7 +175,7 @@ export const SymbolHoverPopup: React.FC = ({ createAuditAction({ action: "user.performed_find_references", metadata: { - message: symbolName, + message: symbolInfo.symbolName, }, }) @@ -180,9 +184,10 @@ export const SymbolHoverPopup: React.FC = ({ revisionName, path: fileName, pathType: 'blob', + highlightRange: symbolInfo.range, setBrowseState: { selectedSymbolInfo: { - symbolName, + symbolName: symbolInfo.symbolName, repoName, revisionName, language, @@ -191,15 +196,7 @@ export const SymbolHoverPopup: React.FC = ({ isBottomPanelCollapsed: false, } }) - }, [ - captureEvent, - fileName, - language, - navigateToPath, - repoName, - revisionName, - source - ]); + }, [captureEvent, fileName, language, navigateToPath, repoName, revisionName, source, symbolInfo]); // @todo: We should probably make the behaviour s.t., the ctrl / cmd key needs to be held // down to navigate to the definition. We should also only show the underline when the key @@ -216,9 +213,7 @@ export const SymbolHoverPopup: React.FC = ({ }, [symbolInfo, onGotoDefinition]); useHotkeys('alt+shift+f12', () => { - if (symbolInfo?.symbolName) { - onFindReferences(symbolInfo.symbolName); - } + onFindReferences(); }, { enableOnFormTags: true, enableOnContentEditable: true, @@ -302,7 +297,7 @@ export const SymbolHoverPopup: React.FC = ({ diff --git a/packages/web/src/ee/features/codeNav/components/symbolHoverPopup/useHoveredOverSymbolInfo.ts b/packages/web/src/ee/features/codeNav/components/symbolHoverPopup/useHoveredOverSymbolInfo.ts index a537fe53..44b5d804 100644 --- a/packages/web/src/ee/features/codeNav/components/symbolHoverPopup/useHoveredOverSymbolInfo.ts +++ b/packages/web/src/ee/features/codeNav/components/symbolHoverPopup/useHoveredOverSymbolInfo.ts @@ -27,6 +27,7 @@ export type SymbolDefinition = { interface HoveredOverSymbolInfo { element: HTMLElement; symbolName: string; + range: SourceRange; isSymbolDefinitionsLoading: boolean; symbolDefinitions?: SymbolDefinition[]; } @@ -127,17 +128,64 @@ export const useHoveredOverSymbolInfo = ({ }; }, [editorRef, domain, clearTimers]); + // Extract the highlight range of the symbolElement from the editor view. + const highlightRange = useMemo((): SourceRange | undefined => { + if (!symbolElement || !editorRef.view) { + return undefined; + } + + const view = editorRef.view; + const rect = symbolElement.getBoundingClientRect(); + + // Get the start position (left edge, middle vertically) + const startPos = view.posAtCoords({ + x: rect.left, + y: rect.top + rect.height / 2, + }); + + // Get the end position (right edge, middle vertically) + const endPos = view.posAtCoords({ + x: rect.right, + y: rect.top + rect.height / 2, + }); + + if (startPos === null || endPos === null) { + return undefined; + } + + // Convert CodeMirror positions to SourceRange format + const startLine = view.state.doc.lineAt(startPos); + const endLine = view.state.doc.lineAt(endPos); + + const startColumn = startPos - startLine.from + 1; // 1-based column + const endColumn = endPos - endLine.from + 1; // 1-based column + + return { + start: { + byteOffset: startPos, // 0-based byte offset + lineNumber: startLine.number, // 1-based line number + column: startColumn, // 1-based column + }, + end: { + byteOffset: endPos, // 0-based byte offset + lineNumber: endLine.number, // 1-based line number + column: endColumn, // 1-based column + }, + }; + }, [symbolElement, editorRef.view]); + if (!isVisible && !isSticky) { return undefined; } - if (!symbolElement || !symbolName) { + if (!symbolElement || !symbolName || !highlightRange) { return undefined; } return { element: symbolElement, symbolName, + range: highlightRange, isSymbolDefinitionsLoading: isSymbolDefinitionsLoading, symbolDefinitions, };