diff --git a/src/vs/editor/common/languages.ts b/src/vs/editor/common/languages.ts index 404c668286c..ff67a82364b 100644 --- a/src/vs/editor/common/languages.ts +++ b/src/vs/editor/common/languages.ts @@ -839,8 +839,14 @@ export interface InlineCompletionWarning { icon?: IconPath; } +export enum InlineCompletionDisplayLocationKind { + Code = 1, + Label = 2 +} + export interface InlineCompletionDisplayLocation { range: IRange; + kind: InlineCompletionDisplayLocationKind; label: string; } diff --git a/src/vs/editor/common/standalone/standaloneEnums.ts b/src/vs/editor/common/standalone/standaloneEnums.ts index 2ff1379faef..d718de32f08 100644 --- a/src/vs/editor/common/standalone/standaloneEnums.ts +++ b/src/vs/editor/common/standalone/standaloneEnums.ts @@ -436,6 +436,11 @@ export enum InlayHintKind { Parameter = 2 } +export enum InlineCompletionDisplayLocationKind { + Code = 1, + Label = 2 +} + export enum InlineCompletionEndOfLifeReasonKind { Accepted = 0, Rejected = 1, diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts index a1787166da0..c3ff6aa21aa 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts @@ -50,6 +50,7 @@ import { IInlineCompletionsService } from '../../../../browser/services/inlineCo import { TypingInterval } from './typingSpeed.js'; import { StringReplacement } from '../../../../common/core/edits/stringEdit.js'; import { OffsetRange } from '../../../../common/core/ranges/offsetRange.js'; +import { URI } from '../../../../../base/common/uri.js'; export class InlineCompletionsModel extends Disposable { private readonly _source; @@ -538,6 +539,7 @@ export class InlineCompletionsModel extends Disposable { inlineEdit: InlineEdit; inlineCompletion: InlineEditItem; cursorAtInlineEdit: IObservable; + nextEditUri: URI | undefined; } | undefined>({ owner: this, equalsFn: (a, b) => { @@ -571,8 +573,9 @@ export class InlineCompletionsModel extends Disposable { const edits = inlineEditResult.updatedEdit; const e = edits ? TextEdit.fromStringEdit(edits, new TextModelText(this.textModel)).replacements : [edit]; - - return { kind: 'inlineEdit', inlineEdit, inlineCompletion: inlineEditResult, edits: e, cursorAtInlineEdit }; + const nextEditUri = (item.inlineEdit?.command?.id === 'vscode.open' || item.inlineEdit?.command?.id === '_workbench.open') && + item.inlineEdit?.command.arguments?.length ? URI.from(item.inlineEdit?.command.arguments[0]) : undefined; + return { kind: 'inlineEdit', inlineEdit, inlineCompletion: inlineEditResult, edits: e, cursorAtInlineEdit, nextEditUri }; } const suggestItem = this._selectedSuggestItem.read(reader); @@ -819,7 +822,7 @@ export class InlineCompletionsModel extends Disposable { } let completion: InlineSuggestionItem; - + let isNextEditUri = false; const state = this.state.get(); if (state?.kind === 'ghostText') { if (!state || state.primaryGhostText.isEmpty() || !state.inlineCompletion) { @@ -828,6 +831,7 @@ export class InlineCompletionsModel extends Disposable { completion = state.inlineCompletion; } else if (state?.kind === 'inlineEdit') { completion = state.inlineCompletion; + isNextEditUri = !!state.nextEditUri; } else { return; } @@ -837,7 +841,9 @@ export class InlineCompletionsModel extends Disposable { try { editor.pushUndoStop(); - if (completion.snippetInfo) { + if (isNextEditUri) { + // Do nothing + } else if (completion.snippetInfo) { const mainEdit = TextReplacement.delete(completion.editRange); const additionalEdits = completion.additionalTextEdits.map(e => new TextReplacement(Range.lift(e.range), e.text ?? '')); const edit = TextEdit.fromParallelReplacementsUnsorted([mainEdit, ...additionalEdits]); diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts index 1f759277446..19c7779c1fd 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts @@ -18,7 +18,7 @@ import { TextReplacement, TextEdit } from '../../../../common/core/edits/textEdi import { StringText } from '../../../../common/core/text/abstractText.js'; import { TextLength } from '../../../../common/core/text/textLength.js'; import { linesDiffComputers } from '../../../../common/diff/linesDiffComputers.js'; -import { InlineCompletion, InlineCompletionTriggerKind, Command, InlineCompletionWarning, PartialAcceptInfo, InlineCompletionEndOfLifeReason } from '../../../../common/languages.js'; +import { InlineCompletion, InlineCompletionTriggerKind, Command, InlineCompletionWarning, PartialAcceptInfo, InlineCompletionEndOfLifeReason, InlineCompletionDisplayLocationKind } from '../../../../common/languages.js'; import { ITextModel, EndOfLinePreference } from '../../../../common/model.js'; import { TextModelText } from '../../../../common/model/textModelText.js'; import { IDisplayLocation, InlineSuggestData, InlineSuggestionList, PartialAcceptance, SnippetInfo } from './provideInlineCompletions.js'; @@ -160,12 +160,14 @@ class InlineSuggestDisplayLocation implements IDisplayLocation { return new InlineSuggestDisplayLocation( displayLocation.range, displayLocation.label, + displayLocation.kind ); } private constructor( public readonly range: Range, public readonly label: string, + public readonly kind: InlineCompletionDisplayLocationKind ) { } public withEdit(edit: StringEdit, positionOffsetTransformer: PositionOffsetTransformerBase): InlineSuggestDisplayLocation | undefined { @@ -181,7 +183,7 @@ class InlineSuggestDisplayLocation implements IDisplayLocation { const newRange = positionOffsetTransformer.getRange(newOffsetRange); - return new InlineSuggestDisplayLocation(newRange, this.label); + return new InlineSuggestDisplayLocation(newRange, this.label, this.kind); } } diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts index 97b3d5fed65..a107bc97549 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts @@ -16,7 +16,7 @@ import { OffsetRange } from '../../../../common/core/ranges/offsetRange.js'; import { Position } from '../../../../common/core/position.js'; import { Range } from '../../../../common/core/range.js'; import { TextReplacement } from '../../../../common/core/edits/textEdit.js'; -import { InlineCompletionEndOfLifeReason, InlineCompletionEndOfLifeReasonKind, InlineCompletion, InlineCompletionContext, InlineCompletions, InlineCompletionsProvider, PartialAcceptInfo, InlineCompletionsDisposeReason, LifetimeSummary } from '../../../../common/languages.js'; +import { InlineCompletionEndOfLifeReason, InlineCompletionEndOfLifeReasonKind, InlineCompletionDisplayLocationKind, InlineCompletion, InlineCompletionContext, InlineCompletions, InlineCompletionsProvider, PartialAcceptInfo, InlineCompletionsDisposeReason, LifetimeSummary } from '../../../../common/languages.js'; import { ILanguageConfigurationService } from '../../../../common/languages/languageConfigurationRegistry.js'; import { ITextModel } from '../../../../common/model.js'; import { fixBracketsInLine } from '../../../../common/model/bracketPairsTextModelPart/fixBrackets.js'; @@ -226,7 +226,8 @@ function toInlineSuggestData( const displayLocation = inlineCompletion.displayLocation ? { range: Range.lift(inlineCompletion.displayLocation.range), - label: inlineCompletion.displayLocation.label + label: inlineCompletion.displayLocation.label, + kind: inlineCompletion.displayLocation.kind } : undefined; return new InlineSuggestData( @@ -457,6 +458,7 @@ export interface SnippetInfo { export interface IDisplayLocation { range: Range; label: string; + kind: InlineCompletionDisplayLocationKind; } export enum InlineCompletionEditorType { diff --git a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsCustomView.ts b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsCustomView.ts index 919d7d33c9c..a3e33e326d5 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsCustomView.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsCustomView.ts @@ -16,7 +16,7 @@ import { LineSource, renderLines, RenderOptions } from '../../../../../../browse import { EditorOption } from '../../../../../../common/config/editorOptions.js'; import { Rect } from '../../../../../../common/core/2d/rect.js'; import { LineRange } from '../../../../../../common/core/ranges/lineRange.js'; -import { InlineCompletionDisplayLocation } from '../../../../../../common/languages.js'; +import { InlineCompletionDisplayLocation, InlineCompletionDisplayLocationKind } from '../../../../../../common/languages.js'; import { ILanguageService } from '../../../../../../common/languages/language.js'; import { LineTokens, TokenArray } from '../../../../../../common/tokens/lineTokens.js'; import { IInlineEditsView, InlineEditTabAction } from '../inlineEditsViewInterface.js'; @@ -127,7 +127,7 @@ export class InlineEditsCustomView extends Disposable implements IInlineEditsVie return maxOriginalContent + maxModifiedContent + padding < editorWidth - editorContentLeft - editorVerticalScrollbar - minimapWidth; } - private getState(displayLocation: InlineCompletionDisplayLocation): { rect: IObservable; label: string } { + private getState(displayLocation: InlineCompletionDisplayLocation): { rect: IObservable; label: string; kind: InlineCompletionDisplayLocationKind } { const contentState = derived((reader) => { const startLineNumber = displayLocation.range.startLineNumber; @@ -217,16 +217,17 @@ export class InlineEditsCustomView extends Disposable implements IInlineEditsVie return { rect, - label: displayLocation.label + label: displayLocation.label, + kind: displayLocation.kind }; } - private getRendering(state: { rect: IObservable; label: string }, styles: IObservable<{ background: string; border: string }>) { + private getRendering(state: { rect: IObservable; label: string; kind: InlineCompletionDisplayLocationKind }, styles: IObservable<{ background: string; border: string }>) { const line = document.createElement('div'); const t = this._editor.getModel()!.tokenization.tokenizeLinesAt(1, [state.label])?.[0]; let tokens: LineTokens; - if (t) { + if (t && state.kind === InlineCompletionDisplayLocationKind.Code) { tokens = TokenArray.fromLineTokens(t).toLineTokens(state.label, this._languageService.languageIdCodec); } else { tokens = LineTokens.createEmpty(state.label, this._languageService.languageIdCodec); diff --git a/src/vs/editor/standalone/browser/standaloneLanguages.ts b/src/vs/editor/standalone/browser/standaloneLanguages.ts index 98a30838515..c8d6168a566 100644 --- a/src/vs/editor/standalone/browser/standaloneLanguages.ts +++ b/src/vs/editor/standalone/browser/standaloneLanguages.ts @@ -806,6 +806,7 @@ export function createMonacoLanguagesAPI(): typeof monaco.languages { PartialAcceptTriggerKind: standaloneEnums.PartialAcceptTriggerKind, HoverVerbosityAction: standaloneEnums.HoverVerbosityAction, InlineCompletionEndOfLifeReasonKind: standaloneEnums.InlineCompletionEndOfLifeReasonKind, + InlineCompletionDisplayLocationKind: standaloneEnums.InlineCompletionDisplayLocationKind, // classes FoldingRangeKind: languages.FoldingRangeKind, diff --git a/src/vs/monaco.d.ts b/src/vs/monaco.d.ts index 1272985c0ba..622d73f9034 100644 --- a/src/vs/monaco.d.ts +++ b/src/vs/monaco.d.ts @@ -7534,8 +7534,14 @@ declare namespace monaco.languages { icon?: IconPath; } + export enum InlineCompletionDisplayLocationKind { + Code = 1, + Label = 2 + } + export interface InlineCompletionDisplayLocation { range: IRange; + kind: InlineCompletionDisplayLocationKind; label: string; } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 28ba34128d8..da6c716ab8f 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -1839,6 +1839,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I TextToSpeechStatus: extHostTypes.TextToSpeechStatus, PartialAcceptTriggerKind: extHostTypes.PartialAcceptTriggerKind, InlineCompletionEndOfLifeReasonKind: extHostTypes.InlineCompletionEndOfLifeReasonKind, + InlineCompletionDisplayLocationKind: extHostTypes.InlineCompletionDisplayLocationKind, KeywordRecognitionStatus: extHostTypes.KeywordRecognitionStatus, ChatImageMimeType: extHostTypes.ChatImageMimeType, ChatResponseMarkdownPart: extHostTypes.ChatResponseMarkdownPart, diff --git a/src/vs/workbench/api/common/extHostLanguageFeatures.ts b/src/vs/workbench/api/common/extHostLanguageFeatures.ts index 89e3235fbe0..3b7d8d34fa2 100644 --- a/src/vs/workbench/api/common/extHostLanguageFeatures.ts +++ b/src/vs/workbench/api/common/extHostLanguageFeatures.ts @@ -36,7 +36,7 @@ import { ExtHostDiagnostics } from './extHostDiagnostics.js'; import { ExtHostDocuments } from './extHostDocuments.js'; import { ExtHostTelemetry, IExtHostTelemetry } from './extHostTelemetry.js'; import * as typeConvert from './extHostTypeConverters.js'; -import { CodeAction, CodeActionKind, CompletionList, DataTransfer, Disposable, DocumentDropOrPasteEditKind, DocumentSymbol, InlineCompletionsDisposeReasonKind, InlineCompletionTriggerKind, InternalDataTransferItem, Location, NewSymbolNameTriggerKind, Range, SemanticTokens, SemanticTokensEdit, SemanticTokensEdits, SnippetString, SymbolInformation, SyntaxTokenType } from './extHostTypes.js'; +import { CodeAction, CodeActionKind, CompletionList, DataTransfer, Disposable, DocumentDropOrPasteEditKind, DocumentSymbol, InlineCompletionsDisposeReasonKind, InlineCompletionDisplayLocationKind, InlineCompletionTriggerKind, InternalDataTransferItem, Location, NewSymbolNameTriggerKind, Range, SemanticTokens, SemanticTokensEdit, SemanticTokensEdits, SnippetString, SymbolInformation, SyntaxTokenType } from './extHostTypes.js'; // --- adapter @@ -1431,6 +1431,7 @@ class InlineCompletionAdapter { displayLocation: (item.displayLocation && this._isAdditionsProposedApiEnabled) ? { range: typeConvert.Range.from(item.displayLocation.range), label: item.displayLocation.label, + kind: item.displayLocation.kind ? typeConvert.InlineCompletionDisplayLocationKind.from(item.displayLocation.kind) : InlineCompletionDisplayLocationKind.Code, } : undefined, warning: (item.warning && this._isAdditionsProposedApiEnabled) ? { message: typeConvert.MarkdownString.from(item.warning.message), diff --git a/src/vs/workbench/api/common/extHostTypeConverters.ts b/src/vs/workbench/api/common/extHostTypeConverters.ts index 78b66ea6f50..326ff5cd5d0 100644 --- a/src/vs/workbench/api/common/extHostTypeConverters.ts +++ b/src/vs/workbench/api/common/extHostTypeConverters.ts @@ -3435,6 +3435,25 @@ export namespace InlineCompletionEndOfLifeReason { } } +export namespace InlineCompletionDisplayLocationKind { + export function from(value: vscode.InlineCompletionDisplayLocationKind): types.InlineCompletionDisplayLocationKind { + if (value === types.InlineCompletionDisplayLocationKind.Label) { + return types.InlineCompletionDisplayLocationKind.Label; + } else { + return types.InlineCompletionDisplayLocationKind.Code; + } + } + + export function to(kind: languages.InlineCompletionDisplayLocationKind): types.InlineCompletionDisplayLocationKind { + switch (kind) { + case languages.InlineCompletionDisplayLocationKind.Label: + return types.InlineCompletionDisplayLocationKind.Label; + default: + return types.InlineCompletionDisplayLocationKind.Code; + } + } +} + export namespace DebugTreeItem { export function from(item: vscode.DebugTreeItem, id: number): IDebugVisualizationTreeItem { return { diff --git a/src/vs/workbench/api/common/extHostTypes.ts b/src/vs/workbench/api/common/extHostTypes.ts index cce0d4b72c9..5b8681cba9b 100644 --- a/src/vs/workbench/api/common/extHostTypes.ts +++ b/src/vs/workbench/api/common/extHostTypes.ts @@ -1872,6 +1872,11 @@ export enum InlineCompletionEndOfLifeReasonKind { Ignored = 2, } +export enum InlineCompletionDisplayLocationKind { + Code = 1, + Label = 2 +} + export enum ViewColumn { Active = -1, Beside = -2, diff --git a/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts b/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts index 88a7698a157..8c91e6850f0 100644 --- a/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts +++ b/src/vscode-dts/vscode.proposed.inlineCompletionsAdditions.d.ts @@ -48,8 +48,14 @@ declare module 'vscode' { displayLocation?: InlineCompletionDisplayLocation; } + export enum InlineCompletionDisplayLocationKind { + Code = 1, + Label = 2 + } + export interface InlineCompletionDisplayLocation { range: Range; + kind: InlineCompletionDisplayLocationKind; label: string; }