From 85e7090710c8403fe01be482c0c0450bb3dfd256 Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Tue, 11 Mar 2025 19:13:38 +0100 Subject: [PATCH] Fixes #228033 (#243234) --- .../controller/inlineCompletionsController.ts | 12 ++++++--- .../inlineCompletionsAccessibleView.ts | 27 +++++++++++++------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.ts b/src/vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.ts index bc5d723722f..1658944cc6d 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/controller/inlineCompletionsController.ts @@ -243,7 +243,7 @@ export class InlineCompletionsController extends Disposable { const currentInlineCompletionBySemanticId = derivedObservableWithCache(this, (reader, last) => { const model = this.model.read(reader); - const state = model?.inlineCompletionState.read(reader); + const state = model?.state.read(reader); if (this._suggestWidgetAdapter.selectedItem.get()) { return last; } @@ -256,16 +256,20 @@ export class InlineCompletionsController extends Disposable { }), async (_value, _, _deltas, store) => { /** @description InlineCompletionsController.playAccessibilitySignalAndReadSuggestion */ const model = this.model.get(); - const state = model?.inlineCompletionState.get(); + const state = model?.state.get(); if (!state || !model) { return; } - const lineText = model.textModel.getLineContent(state.primaryGhostText.lineNumber); + const lineText = state.kind === 'ghostText' ? model.textModel.getLineContent(state.primaryGhostText.lineNumber) : ''; await timeout(50, cancelOnDispose(store)); await waitForState(this._suggestWidgetAdapter.selectedItem, isUndefined, () => false, cancelOnDispose(store)); await this._accessibilitySignalService.playSignal(AccessibilitySignal.inlineSuggestion); if (this.editor.getOption(EditorOption.screenReaderAnnounceInlineSuggestion)) { - this._provideScreenReaderUpdate(state.primaryGhostText.renderForScreenReader(lineText)); + if (state.kind === 'ghostText') { + this._provideScreenReaderUpdate(state.primaryGhostText.renderForScreenReader(lineText)); + } else { + this._provideScreenReaderUpdate(''); // Only announce Alt+F2 + } } })); diff --git a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsAccessibleView.ts b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsAccessibleView.ts index 0a4e864d2c6..959a99ea366 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsAccessibleView.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/inlineCompletionsAccessibleView.ts @@ -14,12 +14,16 @@ import { ContextKeyExpr } from '../../../../platform/contextkey/common/contextke import { ServicesAccessor } from '../../../../platform/instantiation/common/instantiation.js'; import { Disposable } from '../../../../base/common/lifecycle.js'; import { InlineCompletionsModel } from './model/inlineCompletionsModel.js'; +import { TextEdit } from '../../../common/core/textEdit.js'; +import { LineEdit } from '../../../common/core/lineEdit.js'; +import { TextModelText } from '../../../common/model/textModelText.js'; +import { localize } from '../../../../nls.js'; export class InlineCompletionsAccessibleView implements IAccessibleViewImplementation { readonly type = AccessibleViewType.View; readonly priority = 95; readonly name = 'inline-completions'; - readonly when = ContextKeyExpr.and(InlineCompletionContextKeys.inlineSuggestionVisible); + readonly when = ContextKeyExpr.or(InlineCompletionContextKeys.inlineSuggestionVisible, InlineCompletionContextKeys.inlineEditVisible); getProvider(accessor: ServicesAccessor) { const codeEditorService = accessor.get(ICodeEditorService); const editor = codeEditorService.getActiveCodeEditor() || codeEditorService.getFocusedCodeEditor(); @@ -28,7 +32,7 @@ export class InlineCompletionsAccessibleView implements IAccessibleViewImplement } const model = InlineCompletionsController.get(editor)?.model.get(); - if (!model?.inlineCompletionState.get()) { + if (!model?.state.get()) { return; } @@ -51,16 +55,23 @@ class InlineCompletionsAccessibleViewContentProvider extends Disposable implemen public readonly options = { language: this._editor.getModel()?.getLanguageId() ?? undefined, type: AccessibleViewType.View }; public provideContent(): string { - const state = this._model.inlineCompletionState.get(); + const state = this._model.state.get(); if (!state) { throw new Error('Inline completion is visible but state is not available'); } - const lineText = this._model.textModel.getLineContent(state.primaryGhostText.lineNumber); - const ghostText = state.primaryGhostText.renderForScreenReader(lineText); - if (!ghostText) { - throw new Error('Inline completion is visible but ghost text is not available'); + if (state.kind === 'ghostText') { + + const lineText = this._model.textModel.getLineContent(state.primaryGhostText.lineNumber); + const ghostText = state.primaryGhostText.renderForScreenReader(lineText); + if (!ghostText) { + throw new Error('Inline completion is visible but ghost text is not available'); + } + return lineText + ghostText; + } else { + const text = new TextModelText(this._model.textModel); + const lineEdit = LineEdit.fromTextEdit(new TextEdit(state.edits), text); + return localize('inlineEditAvailable', 'There is an inline edit available:') + '\n' + lineEdit.humanReadablePatch(text.getLines()); } - return lineText + ghostText; } public provideNextContent(): string | undefined { // asynchronously update the model and fire the event