diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts index a8614f12966..6cf3220fbf1 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.ts @@ -51,6 +51,7 @@ import { StringReplacement } from '../../../../common/core/edits/stringEdit.js'; import { OffsetRange } from '../../../../common/core/ranges/offsetRange.js'; import { URI } from '../../../../../base/common/uri.js'; import { IDefaultAccountService } from '../../../../../platform/defaultAccount/common/defaultAccount.js'; +import { ModifierKeyEmitter } from '../../../../../base/browser/dom.js'; export class InlineCompletionsModel extends Disposable { private readonly _source; @@ -630,7 +631,7 @@ export class InlineCompletionsModel extends Disposable { return undefined; } const cursorAtInlineEdit = this.primaryPosition.map(cursorPos => LineRange.fromRangeInclusive(inlineEditResult.targetRange).addMargin(1, 1).contains(cursorPos.lineNumber)); - const stringEdit = inlineEditResult.action?.kind === 'edit' ? inlineEditResult.action.stringEdit : undefined; + const stringEdit = inlineEditResult.action?.kind === 'edit' || inlineEditResult.action?.kind === 'rename' ? inlineEditResult.action.stringEdit : undefined; const replacements = stringEdit ? TextEdit.fromStringEdit(stringEdit, new TextModelText(this.textModel)).replacements : []; const nextEditUri = (item.inlineEdit?.command?.id === 'vscode.open' || item.inlineEdit?.command?.id === '_workbench.open') && @@ -904,9 +905,13 @@ export class InlineCompletionsModel extends Disposable { editor.pushUndoStop(); if (isNextEditUri) { // Do nothing - } else if (completion.action?.kind === 'edit') { + } else if (completion.action?.kind === 'edit' || completion.action?.kind === 'rename') { const action = completion.action; - if (action.snippetInfo) { + if (action.kind === 'rename' && !ModifierKeyEmitter.getInstance().keyStatus.altKey) { + await this._commandService + .executeCommand(action.command.id, ...(action.command.arguments || [])) + .then(undefined, onUnexpectedExternalError); + } else if (action.kind === 'edit' && action.snippetInfo) { const mainEdit = TextReplacement.delete(action.textReplacement.range); const additionalEdits = completion.additionalTextEdits.map(e => new TextReplacement(Range.lift(e.range), e.text ?? '')); const edit = TextEdit.fromParallelReplacementsUnsorted([mainEdit, ...additionalEdits]); @@ -950,12 +955,6 @@ export class InlineCompletionsModel extends Disposable { // Reset before invoking the command, as the command might cause a follow up trigger (which we don't want to reset). this.stop(); - if (completion.renameCommand) { - await this._commandService - .executeCommand(completion.renameCommand.id, ...(completion.renameCommand.arguments || [])) - .then(undefined, onUnexpectedExternalError); - } - if (completion.command) { await this._commandService .executeCommand(completion.command.id, ...(completion.command.arguments || [])) diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsSource.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsSource.ts index 95b533d200c..b4623b4bc04 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsSource.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsSource.ts @@ -273,7 +273,7 @@ export class InlineCompletionsSource extends Disposable { return this._renameProcessor.proposeRenameRefactoring(this._textModel, s); })); - providerSuggestions.forEach(s => s.addPerformanceMarker('renameProcessed')); + suggestions.forEach(s => s.addPerformanceMarker('renameProcessed')); providerResult.cancelAndDispose({ kind: 'lostRace' }); diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts index 492084eacb3..9dec9667b15 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/inlineSuggestionItem.ts @@ -25,7 +25,7 @@ import { EndOfLinePreference, ITextModel } from '../../../../common/model.js'; import { TextModelText } from '../../../../common/model/textModelText.js'; import { InlineCompletionViewData, InlineCompletionViewKind } from '../view/inlineEdits/inlineEditsViewInterface.js'; import { computeEditKind, InlineSuggestionEditKind } from './editKind.js'; -import { IInlineSuggestDataActionEdit, InlineSuggestData, InlineSuggestionList, PartialAcceptance, RenameInfo, SnippetInfo } from './provideInlineCompletions.js'; +import { IInlineSuggestDataActionEdit, IInlineSuggestDataActionRename, InlineSuggestData, InlineSuggestionList, PartialAcceptance, RenameInfo, SnippetInfo } from './provideInlineCompletions.js'; import { singleTextRemoveCommonPrefix } from './singleTextEditHelpers.js'; export type InlineSuggestionItem = InlineEditItem | InlineCompletionItem; @@ -43,7 +43,7 @@ export namespace InlineSuggestionItem { } } -export type InlineSuggestionAction = IInlineSuggestionActionEdit | IInlineSuggestionActionJumpTo; +export type InlineSuggestionAction = IInlineSuggestionActionEdit | IInlineSuggestionActionJumpTo | IInlineSuggestionActionRename; export interface IInlineSuggestionActionEdit { kind: 'edit'; @@ -60,6 +60,19 @@ export interface IInlineSuggestionActionJumpTo { uri: URI | undefined; } +export interface IInlineSuggestionActionRename { + kind: 'rename'; + textReplacement: TextReplacement; + stringEdit: StringEdit; + uri: URI | undefined; + command: Command; +} + +function hashInlineSuggestionAction(action: InlineSuggestionAction | undefined): string { + const obj = action?.kind === 'rename' ? { ...action, command: action.command.id } : action; + return JSON.stringify(obj); +} + abstract class InlineSuggestionItemBase { constructor( protected readonly _data: InlineSuggestData, @@ -83,7 +96,7 @@ abstract class InlineSuggestionItemBase { if (this.hint) { return this.hint.range; } - if (this.action?.kind === 'edit') { + if (this.action?.kind === 'edit' || this.action?.kind === 'rename') { return this.action.textReplacement.range; } else if (this.action?.kind === 'jumpTo') { return Range.fromPositions(this.action.position); @@ -95,11 +108,10 @@ abstract class InlineSuggestionItemBase { public get gutterMenuLinkAction(): Command | undefined { return this._sourceInlineCompletion.gutterMenuLinkAction; } public get command(): Command | undefined { return this._sourceInlineCompletion.command; } public get supportsRename(): boolean { return this._data.supportsRename; } - public get renameCommand(): Command | undefined { return this._data.renameCommand; } public get warning(): InlineCompletionWarning | undefined { return this._sourceInlineCompletion.warning; } public get showInlineEditMenu(): boolean { return !!this._sourceInlineCompletion.showInlineEditMenu; } public get hash(): string { - return JSON.stringify(this.action); + return hashInlineSuggestionAction(this.action); } /** @deprecated */ public get shownCommand(): Command | undefined { return this._sourceInlineCompletion.shownCommand; } @@ -133,7 +145,7 @@ abstract class InlineSuggestionItemBase { } public reportInlineEditShown(commandService: ICommandService, viewKind: InlineCompletionViewKind, viewData: InlineCompletionViewData, model: ITextModel) { - const insertText = this.action?.kind === 'edit' ? this.action.textReplacement.text : ''; // TODO@hediet support insertText === undefined + const insertText = this.action?.kind === 'edit' || this.action?.kind === 'rename' ? this.action.textReplacement.text : ''; // TODO@hediet support insertText === undefined this._data.reportInlineEditShown(commandService, insertText, viewKind, viewData, this.computeEditKind(model)); } @@ -168,8 +180,8 @@ abstract class InlineSuggestionItemBase { this._data.setRenameProcessingInfo(info); } - public withRename(command: Command, hint: InlineSuggestHint): InlineSuggestData { - return this._data.withRename(command, hint); + public withRename(renameAction: IInlineSuggestDataActionRename): InlineSuggestData { + return this._data.withRename(renameAction); } public addPerformanceMarker(marker: string): void { @@ -434,6 +446,8 @@ export class InlineEditItem extends InlineSuggestionItemBase { offset: textModel.getOffsetAt(data.action.position), uri: data.action.uri, }; + } else if (data.action?.kind === 'rename') { + action = data.action; } else { action = undefined; if (!data.hint) { @@ -501,7 +515,7 @@ export class InlineEditItem extends InlineSuggestionItemBase { let inlineEditModelVersion = this._inlineEditModelVersion; let newAction: InlineSuggestionAction | undefined; - if (this.action?.kind === 'edit') { + if (this.action?.kind === 'edit') { // TODO What about rename? edits = edits.map(innerEdit => innerEdit.applyTextModelChanges(textModelChanges)); if (edits.some(edit => edit.edit === undefined)) { @@ -573,7 +587,7 @@ export class InlineEditItem extends InlineSuggestionItemBase { } override computeEditKind(model: ITextModel): InlineSuggestionEditKind | undefined { - const edit = this.action?.kind === 'edit' ? this.action.stringEdit : undefined; + const edit = this.action?.kind === 'edit' || this.action?.kind === 'rename' ? this.action.stringEdit : undefined; if (!edit) { return undefined; } diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts index fcd6119537a..1ec663c714e 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/provideInlineCompletions.ts @@ -11,7 +11,7 @@ import { Disposable, IDisposable } from '../../../../../base/common/lifecycle.js import { prefixedUuid } from '../../../../../base/common/uuid.js'; import { ICommandService } from '../../../../../platform/commands/common/commands.js'; import { ISingleEditOperation } from '../../../../common/core/editOperation.js'; -import { StringReplacement } from '../../../../common/core/edits/stringEdit.js'; +import { StringEdit, StringReplacement } from '../../../../common/core/edits/stringEdit.js'; import { OffsetRange } from '../../../../common/core/ranges/offsetRange.js'; import { Position } from '../../../../common/core/position.js'; import { Range } from '../../../../common/core/range.js'; @@ -270,7 +270,6 @@ function toInlineSuggestData( context, inlineCompletion.isInlineEdit ?? false, inlineCompletion.supportsRename ?? false, - undefined, requestInfo, providerRequestInfo, inlineCompletion.correlationId, @@ -311,7 +310,7 @@ export type InlineSuggestViewData = { viewKind?: InlineCompletionViewKind; }; -export type IInlineSuggestDataAction = IInlineSuggestDataActionEdit | IInlineSuggestDataActionJumpTo; +export type IInlineSuggestDataAction = IInlineSuggestDataActionEdit | IInlineSuggestDataActionJumpTo | IInlineSuggestDataActionRename; export interface IInlineSuggestDataActionEdit { kind: 'edit'; @@ -327,6 +326,14 @@ export interface IInlineSuggestDataActionJumpTo { uri: URI | undefined; } +export interface IInlineSuggestDataActionRename { + kind: 'rename'; + textReplacement: TextReplacement; + stringEdit: StringEdit; + uri: URI | undefined; + command: Command; +} + export class InlineSuggestData { private _didShow = false; private _timeUntilShown: number | undefined = undefined; @@ -354,7 +361,6 @@ export class InlineSuggestData { public readonly context: InlineCompletionContext, public readonly isInlineEdit: boolean, public readonly supportsRename: boolean, - public readonly renameCommand: Command | undefined, private readonly _requestInfo: InlineSuggestRequestInfo, private readonly _providerRequestInfo: InlineSuggestProviderRequestInfo, private readonly _correlationId: string | undefined, @@ -517,17 +523,16 @@ export class InlineSuggestData { this._renameInfo = info; } - public withRename(command: Command, hint: IInlineCompletionHint): InlineSuggestData { + public withRename(renameAction: IInlineSuggestDataActionRename): InlineSuggestData { return new InlineSuggestData( - undefined, - hint, + renameAction, + this.hint, this.additionalTextEdits, this.sourceInlineCompletion, this.source, this.context, this.isInlineEdit, this.supportsRename, - command, this._requestInfo, this._providerRequestInfo, this._correlationId, diff --git a/src/vs/editor/contrib/inlineCompletions/browser/model/renameSymbolProcessor.ts b/src/vs/editor/contrib/inlineCompletions/browser/model/renameSymbolProcessor.ts index 36cc3abf531..367d2e22efd 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/model/renameSymbolProcessor.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/model/renameSymbolProcessor.ts @@ -14,14 +14,15 @@ import { TextEdit } from '../../../../common/core/edits/textEdit.js'; import { Position } from '../../../../common/core/position.js'; import { Range } from '../../../../common/core/range.js'; import { StandardTokenType } from '../../../../common/encodedTokenAttributes.js'; -import { Command, InlineCompletionHintStyle } from '../../../../common/languages.js'; +import { Command } from '../../../../common/languages.js'; import { ILanguageConfigurationService } from '../../../../common/languages/languageConfigurationRegistry.js'; import { ITextModel } from '../../../../common/model.js'; import { ILanguageFeaturesService } from '../../../../common/services/languageFeatures.js'; import { EditSources, TextModelEditSource } from '../../../../common/textModelEditSource.js'; import { hasProvider, prepareRename, rename } from '../../../rename/browser/rename.js'; import { renameSymbolCommandId } from '../controller/commandIds.js'; -import { InlineSuggestHint, InlineSuggestionItem } from './inlineSuggestionItem.js'; +import { InlineSuggestionItem } from './inlineSuggestionItem.js'; +import { IInlineSuggestDataActionRename } from './provideInlineCompletions.js'; export type RenameEdits = { renames: { edits: TextEdit[]; position: Position; oldName: string; newName: string }; @@ -258,14 +259,19 @@ export class RenameSymbolProcessor extends Disposable { providerId: suggestItem.source.provider.providerId, languageId: textModel.getLanguageId(), }); - const hintRange = edits.renames.edits[0].replacements[0].range; const label = localize('renameSymbol', "Rename '{0}' to '{1}'", oldName, newName); const command: Command = { id: renameSymbolCommandId, title: label, arguments: [textModel, position, newName, source], }; - const hint = InlineSuggestHint.create({ range: hintRange, content: label, style: InlineCompletionHintStyle.Code }); - return InlineSuggestionItem.create(suggestItem.withRename(command, hint), textModel); + const renameAction: IInlineSuggestDataActionRename = { + kind: 'rename', + textReplacement: edit, + stringEdit: suggestItem.action.stringEdit, + command, + uri: textModel.uri + }; + return InlineSuggestionItem.create(suggestItem.withRename(renameAction), textModel); } } diff --git a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditWithChanges.ts b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditWithChanges.ts index f806c1633a4..0faf3aa26cc 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditWithChanges.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditWithChanges.ts @@ -16,7 +16,7 @@ export class InlineEditWithChanges { public get lineEdit(): LineReplacement { if (this.action?.kind === 'jumpTo') { return new LineReplacement(LineRange.ofLength(this.action.position.lineNumber, 0), []); - } else if (this.action?.kind === 'edit') { + } else if (this.action?.kind === 'edit' || this.action?.kind === 'rename') { return LineReplacement.fromSingleTextEdit(this.edit!.toReplacement(this.originalText), this.originalText); } diff --git a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.ts b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.ts index bbed6cd1893..e1e93db6f11 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsView.ts @@ -109,11 +109,11 @@ export class InlineEditsView extends Disposable { this._inlineCollapsedView = this._register(this._instantiationService.createInstance(InlineEditsCollapsedView, this._editor, - this._model.map((m, reader) => this._uiState.read(reader)?.state?.kind === 'collapsed' ? m?.inlineEdit : undefined) + this._model.map((m, reader) => this._uiState.read(reader)?.state?.kind === InlineCompletionViewKind.Collapsed ? m?.inlineEdit : undefined) )); this._customView = this._register(this._instantiationService.createInstance(InlineEditsCustomView, this._editor, - this._model.map((m, reader) => this._uiState.read(reader)?.state?.kind === 'custom' ? m?.displayLocation : undefined), + this._model.map((m, reader) => this._uiState.read(reader)?.state?.kind === InlineCompletionViewKind.Custom ? m?.displayLocation : undefined), this._tabAction, )); @@ -164,10 +164,10 @@ export class InlineEditsView extends Disposable { equalsFn: itemsEquals(itemEquals()) }, reader => { const s = this._uiState.read(reader); - return s?.state?.kind === 'wordReplacements' ? s.state.replacements : []; + return s?.state?.kind === InlineCompletionViewKind.WordReplacements ? s.state.replacements : []; }); this._wordReplacementViews = mapObservableArrayCached(this, wordReplacements, (e, store) => { - return store.add(this._instantiationService.createInstance(InlineEditsWordReplacementView, this._editorObs, e, this._tabAction)); + return store.add(this._instantiationService.createInstance(InlineEditsWordReplacementView, this._editorObs, e, this._model.get()?.inlineEdit.inlineCompletion.action?.kind === 'rename', this._tabAction)); }); this._lineReplacementView = this._register(this._instantiationService.createInstance(InlineEditsLineReplacementView, this._editorObs, @@ -426,6 +426,10 @@ export class InlineEditsView extends Disposable { return this._previousView!.view; } + if (model.inlineEdit.inlineCompletion.action?.kind === 'rename') { + return InlineCompletionViewKind.WordReplacements; + } + const uri = model.inlineEdit.inlineCompletion.action?.kind === 'edit' ? model.inlineEdit.inlineCompletion.action.uri : undefined; if (uri !== undefined) { return InlineCompletionViewKind.Custom; diff --git a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViewProducer.ts b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViewProducer.ts index 19c1b58ae42..cc62b979e83 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViewProducer.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViewProducer.ts @@ -35,7 +35,7 @@ export class InlineEditsViewAndDiffProducer extends Disposable { // TODO: This c let diffEdits: TextEdit | undefined; - if (action?.kind === 'edit') { + if (action?.kind === 'edit' || action?.kind === 'rename') { const editOffset = action.stringEdit; const edits = editOffset.replacements.map(e => { diff --git a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordReplacementView.ts b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordReplacementView.ts index aa176618e16..aeb78537d10 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordReplacementView.ts +++ b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/inlineEditsViews/inlineEditsWordReplacementView.ts @@ -3,12 +3,14 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { getWindow, n, ObserverNodeWithElement } from '../../../../../../../base/browser/dom.js'; +import { getWindow, ModifierKeyEmitter, n, ObserverNodeWithElement } from '../../../../../../../base/browser/dom.js'; import { IMouseEvent, StandardMouseEvent } from '../../../../../../../base/browser/mouseEvent.js'; +import { renderIcon } from '../../../../../../../base/browser/ui/iconLabel/iconLabels.js'; +import { Codicon } from '../../../../../../../base/common/codicons.js'; import { Emitter } from '../../../../../../../base/common/event.js'; import { Disposable } from '../../../../../../../base/common/lifecycle.js'; -import { constObservable, derived, IObservable, observableValue } from '../../../../../../../base/common/observable.js'; -import { editorBackground, editorHoverForeground } from '../../../../../../../platform/theme/common/colorRegistry.js'; +import { constObservable, derived, IObservable, observableFromEvent, observableValue } from '../../../../../../../base/common/observable.js'; +import { editorBackground, editorHoverBorder, editorHoverForeground } from '../../../../../../../platform/theme/common/colorRegistry.js'; import { asCssVariable } from '../../../../../../../platform/theme/common/colorUtils.js'; import { ObservableCodeEditor } from '../../../../../../browser/observableCodeEditor.js'; import { LineSource, renderLines, RenderOptions } from '../../../../../../browser/widget/diffEditor/components/diffEditorViewZones/renderLines.js'; @@ -48,6 +50,7 @@ export class InlineEditsWordReplacementView extends Disposable implements IInlin private readonly _editor: ObservableCodeEditor, /** Must be single-line in both sides */ private readonly _edit: TextReplacement, + private readonly _rename: boolean, protected readonly _tabAction: IObservable, @ILanguageService private readonly _languageService: ILanguageService, ) { @@ -76,6 +79,7 @@ export class InlineEditsWordReplacementView extends Disposable implements IInlin this._line.style.width = `${res.minWidthInPx}px`; }); const modifiedLineHeight = this._editor.observeLineHeightForPosition(this._edit.range.getStartPosition()); + const altPressed = observableFromEvent(this, ModifierKeyEmitter.getInstance().event, keyStatus => keyStatus?.altKey ?? ModifierKeyEmitter.getInstance().keyStatus.altKey); this._layout = derived(this, reader => { this._renderTextEffect.read(reader); const widgetStart = this._start.read(reader); @@ -94,15 +98,26 @@ export class InlineEditsWordReplacementView extends Disposable implements IInlin const modifiedTopOffset = 4; const modifiedOffset = new Point(modifiedLeftOffset, modifiedTopOffset); - const originalLine = Rect.fromPoints(widgetStart, widgetEnd).withHeight(lineHeight).translateX(-scrollLeft); - const modifiedLine = Rect.fromPointSize(originalLine.getLeftBottom().add(modifiedOffset), new Point(this._edit.text.length * w, originalLine.height)); + let label = undefined; + if (this._rename) { // TODO: make this customizable and not rename specific + if (altPressed.read(reader)) { + label = { content: 'Edit', icon: Codicon.edit }; + } else { + label = { content: 'Rename', icon: Codicon.replaceAll }; + } + } + const originalLine = Rect.fromPoints(widgetStart, widgetEnd).withHeight(lineHeight).translateX(-scrollLeft); + const codeLine = Rect.fromPointSize(originalLine.getLeftBottom().add(modifiedOffset), new Point(this._edit.text.length * w, originalLine.height)); + const modifiedLine = codeLine.withWidth(codeLine.width + (label ? label.content.length * w + 8 + 4 + 12 : 0)); const lowerBackground = modifiedLine.withLeft(originalLine.left); // debugView(debugLogRects({ lowerBackground }, this._editor.editor.getContainerDomNode()), reader); return { + label, originalLine, + codeLine, modifiedLine, lowerBackground, lineHeight, @@ -157,23 +172,56 @@ export class InlineEditsWordReplacementView extends Disposable implements IInlin style: { position: 'absolute', ...rectToProps(reader => layout.read(reader).modifiedLine.withMargin(BORDER_WIDTH, 2 * BORDER_WIDTH)), - fontFamily: this._editor.getOption(EditorOption.fontFamily), - fontSize: this._editor.getOption(EditorOption.fontSize), - fontWeight: this._editor.getOption(EditorOption.fontWeight), - + width: undefined, pointerEvents: 'none', boxSizing: 'border-box', borderRadius: '4px', - border: `${BORDER_WIDTH}px solid ${modifiedBorderColor}`, - background: asCssVariable(modifiedChangedTextOverlayColor), + background: asCssVariable(editorBackground), display: 'flex', - justifyContent: 'center', - alignItems: 'center', + justifyContent: 'left', outline: `2px solid ${asCssVariable(editorBackground)}`, } - }, [this._line]), + }, [ + n.div({ + style: { + fontFamily: this._editor.getOption(EditorOption.fontFamily), + fontSize: this._editor.getOption(EditorOption.fontSize), + fontWeight: this._editor.getOption(EditorOption.fontWeight), + width: rectToProps(reader => layout.read(reader).codeLine.withMargin(BORDER_WIDTH, 2 * BORDER_WIDTH)).width, + borderRadius: layout.map(l => l.label ? '4px 0 0 4px' : '4px'), + border: `${BORDER_WIDTH}px solid ${modifiedBorderColor}`, + boxSizing: 'border-box', + padding: `${BORDER_WIDTH}px`, + + background: asCssVariable(modifiedChangedTextOverlayColor), + display: 'flex', + justifyContent: 'left', + alignItems: 'center', + } + }, [this._line]), + derived(this, reader => { + const label = layout.read(reader).label; + if (!label) { + return undefined; + } + return n.div({ + style: { + fontFamily: this._editor.getOption(EditorOption.fontFamily), + fontSize: this._editor.getOption(EditorOption.fontSize), + fontWeight: this._editor.getOption(EditorOption.fontWeight), + borderRadius: '0 4px 4px 0', + border: `${BORDER_WIDTH}px solid ${asCssVariable(editorHoverBorder)}`, + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + padding: '0 4px', + }, + class: 'inline-edit-rename-label', + }, [renderIcon(label.icon), label.content]); + }) + ]), n.div({ style: { position: 'absolute', diff --git a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/view.css b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/view.css index 070a19ad4ee..254211721cd 100644 --- a/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/view.css +++ b/src/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/view.css @@ -243,7 +243,7 @@ } } -.go-to-label::before { +.inline-edits-long-distance-hint-widget .go-to-label::before { content: ''; position: absolute; left: -12px; @@ -252,3 +252,8 @@ height: 100%; background: linear-gradient(to left, var(--vscode-editorWidget-background) 0, transparent 12px); } + +.inline-edit-rename-label .codicon { + font-size: 12px !important; + padding-right: 4px; +}