Change:
Type: <bFeature Request</bCC any file containing comment thread editor, move your cursor to any line having comment your cursor is on the line, press ctrl+K ctrl+I to see if the comment tolltip opens Screen reader users cannot open comment tooltip on the current line via ctrl+K ctrl+I ctrl+K ctrl+I needs to work for the comment tooltip just like other tooltips. VS Code version: Code - Insiders 1.93.0-insider (, 2024-08-20T08:04:15.567Z) OS version: Windows_NT x64 10.0. Modes: <!-- generated by issue reporter --
the comment widget is not a tooltip. We cannot reuse this keybinding to focus the comment widget because it's possible that line will have hover info. pls lmk if you disagree. I do wonder if we should have a focus closest comment widget command/keybinding.
Aw, I see. Please then consider adding a keybinding to focus the closest comment widget. Currently, alt+F9 and shift+alt+F9 go to the next and previous comment widget, but there is no action available to focus the comment on the current line.
It does make sense to have an "Expand and focus comment at current line" command.
The new command is "Focus Comment on Current Line" with no default keybinding.
To verify: Install an extension that provides comments GitHub Pull Requests can be used for this Sign in Open the Pull Requests view Open a file diff for a PR. If there aren't any comments in the file, add a comment on one of the changed lines and collapse the comment Put your cursor on a line in a file with a collapsed comment Open the command palette and run the command "Focus Comment on Current Line" Verify that the comment has focus
This should probably be to the comments and/or the editor accessibility help dialog for discoverability.

Discussion:
private _inProcessContinueOnComments: Map<string, languages.PendingCommentThread[]> = new Map(); private _editorDisposables: IDisposable[] = []; private _activeCursorHasCommentingRange: IContextKey<boolean>; <ins> private _activeCursorHasComment: IContextKey<boolean>; </ins> private _activeEditorHasCommentingRange: IContextKey<boolean>; private _hasRespondedToEditorChange: boolean = false;

this._pendingEditsCache = {}; this._computePromise = null; this._activeCursorHasCommentingRange = CommentContextKeys.activeCursorHasCommentingRange.bindTo(contextKeyService); <ins> this._activeCursorHasComment = CommentContextKeys.activeCursorHasComment.bindTo(contextKeyService); </ins> this._activeEditorHasCommentingRange = CommentContextKeys.activeEditorHasCommentingRange.bindTo(contextKeyService); if (editor instanceof EmbeddedCodeEditorWidget) {

} private onEditorChangeCursorPosition(e: Position | null) { <del> const decorations = e ? this.editor?.getDecorationsInRange(Range.fromPositions(e, { column: -1, lineNumber: e.lineNumber })) : undefined; </del> <ins> if (!e) { return; } const range = Range.fromPositions(e, { column: -1, lineNumber: e.lineNumber }); const decorations = this.editor?.getDecorationsInRange(range); </ins> let hasCommentingRange = false; if (decorations) { for (const decoration of decorations) {

} } this._activeCursorHasCommentingRange.set(hasCommentingRange); <ins> this._activeCursorHasComment.set(this.getCommentsAtLine(range).length > 0); </ins> } private isEditorInlineOriginal(testEditor: ICodeEditor): boolean {

} } <ins> public getCommentsAtLine(commentRange: Range | undefined): ReviewZoneWidget[] { return this._commentWidgets.filter(widget => widget.getGlyphPosition() === (commentRange ? commentRange.endLineNumber : 0)); } </ins> public async addOrToggleCommentAtLine(commentRange: Range | undefined, e: IEditorMouseEvent | undefined): Promise<void> { // If an add is already in progress, queue the next add and process it after the current one finishes to // prevent empty comment threads from being added to the same line. if (!this._addInProgress) { this._addInProgress = true; // The widget's position is undefined until the widget has been displayed, so rely on the glyph position instead <del> const existingCommentsAtLine = this._commentWidgets.filter(widget => widget.getGlyphPosition() === (commentRange ? commentRange.endLineNumber : 0)); </del> <ins> const existingCommentsAtLine = this.getCommentsAtLine(commentRange); </ins> if (existingCommentsAtLine.length) { const allExpanded = existingCommentsAtLine.every(widget => widget.expanded); existingCommentsAtLine.forEach(allExpanded ? widget => widget.collapse() : widget => widget.expand(true));

import { registerWorkbenchContribution2, WorkbenchPhase } from '../../../common/contributions.js'; import { CommentsInputContentProvider } from './commentsInputContentProvider.js'; import { AccessibleViewProviderId } from '../../../../platform/accessibility/browser/accessibleView.js'; <ins> import { CommentWidgetFocus } from './commentThreadZoneWidget.js'; </ins> registerEditorContribution(ID, CommentController, EditorContributionInstantiation.AfterFirstRender); registerWorkbenchContribution2(CommentsInputContentProvider.ID, CommentsInputContentProvider, WorkbenchPhase.BlockRestore);

when: CommentContextKeys.activeCursorHasCommentingRange }); <ins> registerAction2(class extends Action2 { constructor() { super({ id: CommentCommandId.FocusCommentOnCurrentLine, title: { value: nls.localize('comments.focusCommentOnCurrentLine', "Focus Comment on Current Line"), original: 'Focus Comment on Current Line' }, category: { value: nls.localize('commentsCategory', "Comments"), original: 'Comments' }, f1: true, precondition: CommentContextKeys.activeCursorHasComment, }); } override async run(accessor: ServicesAccessor, ...args: any[]): Promise<void> { const activeEditor = getActiveEditor(accessor); if (!activeEditor) { return; } const controller = CommentController.get(activeEditor); if (!controller) { return; } const position = activeEditor.getSelection(); const notificationService = accessor.get(INotificationService); let error = false; try { const commentAtLine = controller.getCommentsAtLine(position); if (commentAtLine.length === 0) { error = true; } else { await controller.revealCommentThread(commentAtLine[0].commentThread.threadId, undefined, false, CommentWidgetFocus.Widget); } } catch (e) { error = true; } if (error) { notificationService.error(nls.localize('comments.focusCommand.error', "The cursor must be on a line with a comment to focus the comment")); } } }); </ins> CommandsRegistry.registerCommand({ id: CommentCommandId.CollapseAll, handler: (accessor) => {

export const enum CommentCommandId { Add = 'workbench.action.addComment', <ins> FocusCommentOnCurrentLine = 'workbench.action.focusCommentOnCurrentLine', </ins> NextThread = 'editor.action.nextCommentThreadAction', PreviousThread = 'editor.action.previousCommentThreadAction', NextCommentedRange = 'editor.action.nextCommentedRangeAction',

}); /** <ins> * A context key that is set when the active cursor is in the range of an existing comment. */ export const activeCursorHasComment = new RawContextKey<boolean>('activeCursorHasComment', false, { description: nls.localize('hasComment', "Whether the position at the active cursor has a comment"), type: 'boolean' }); /** </ins> * A context key that is set when the active editor has commenting ranges. */ export const activeEditorHasCommentingRange = new RawContextKey<boolean>('activeEditorHasCommentingRange', false, {