From a1d4cfa3d8dca89fbd2d4d510941d0853e44bdd8 Mon Sep 17 00:00:00 2001 From: Ladislau Szomoru <3372902+lszomoru@users.noreply.github.com> Date: Wed, 15 Oct 2025 16:22:12 +0200 Subject: [PATCH] SCM - graph hover provided by extension (#271519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Git - 💄 consolidate git blame and timeline hover code * Git - Delete code that was commented out * SCM - graph hover provided by extension * Apply suggestion from @Copilot Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * More fixes * More fixes --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- extensions/git/src/historyProvider.ts | 41 +++++----- extensions/github/package.json | 7 -- src/vs/platform/actions/common/actions.ts | 1 - .../workbench/api/common/extHost.protocol.ts | 1 + src/vs/workbench/api/common/extHostSCM.ts | 4 +- .../chat/browser/chatAttachmentWidgets.ts | 17 ++++- .../contrib/scm/browser/scmHistoryViewPane.ts | 45 ++--------- src/vs/workbench/contrib/scm/browser/util.ts | 75 ------------------- .../workbench/contrib/scm/common/history.ts | 2 + .../actions/common/menusExtensionPoint.ts | 6 -- .../vscode.proposed.scmHistoryProvider.d.ts | 1 + 11 files changed, 52 insertions(+), 148 deletions(-) diff --git a/extensions/git/src/historyProvider.ts b/extensions/git/src/historyProvider.ts index 77512ecb465..cf4fd96f749 100644 --- a/extensions/git/src/historyProvider.ts +++ b/extensions/git/src/historyProvider.ts @@ -12,7 +12,7 @@ import { AvatarQuery, AvatarQueryCommit, Branch, LogOptions, Ref, RefType } from import { emojify, ensureEmojis } from './emoji'; import { Commit, CommitShortStat } from './git'; import { OperationKind, OperationResult } from './operation'; -import { ISourceControlHistoryItemDetailsProviderRegistry, provideSourceControlHistoryItemAvatar, provideSourceControlHistoryItemMessageLinks } from './historyItemDetailsProvider'; +import { ISourceControlHistoryItemDetailsProviderRegistry, provideSourceControlHistoryItemAvatar, provideSourceControlHistoryItemHoverCommands, provideSourceControlHistoryItemMessageLinks } from './historyItemDetailsProvider'; import { throttle } from './decorators'; function compareSourceControlHistoryItemRef(ref1: SourceControlHistoryItemRef, ref2: SourceControlHistoryItemRef): number { @@ -282,6 +282,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec const commitAvatars = await provideSourceControlHistoryItemAvatar( this.historyItemDetailProviderRegistry, this.repository, avatarQuery); + const remoteHoverCommands = await provideSourceControlHistoryItemHoverCommands(this.historyItemDetailProviderRegistry, this.repository) ?? []; + await ensureEmojis(); const historyItems: SourceControlHistoryItem[] = []; @@ -293,6 +295,13 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec const avatarUrl = commitAvatars?.get(commit.hash); const references = this._resolveHistoryItemRefs(commit); + const commands: Command[][] = [ + getHistoryItemHoverCommitHashCommands(Uri.file(this.repository.root), commit.hash), + processHistoryItemRemoteHoverCommands(remoteHoverCommands, commit.hash) + ]; + + const tooltip = getHistoryItemHover(avatarUrl, commit.authorName, commit.authorEmail, commit.authorDate ?? commit.commitDate, messageWithLinks, commit.shortStat, commands); + historyItems.push({ id: commit.hash, parentIds: commit.parents, @@ -304,7 +313,8 @@ export class GitHistoryProvider implements SourceControlHistoryProvider, FileDec displayId: truncate(commit.hash, this.commitShortHashLength, false), timestamp: commit.authorDate?.getTime(), statistics: commit.shortStat ?? { files: 0, insertions: 0, deletions: 0 }, - references: references.length !== 0 ? references : undefined + references: references.length !== 0 ? references : undefined, + tooltip } satisfies SourceControlHistoryItem); } @@ -663,6 +673,17 @@ export function getHistoryItemHover(authorAvatar: string | undefined, authorName markdownString.appendMarkdown(`\n\n---\n\n`); } + // References + // TODO@lszomoru - move these to core + // if (references && references.length > 0) { + // markdownString.appendMarkdown((references ?? []).map(ref => { + // console.log(ref); + // const labelIconId = ref.icon instanceof ThemeIcon ? ref.icon.id : ''; + // return ` $(${labelIconId}) ${ref.name}  `; + // }).join('  ')); + // markdownString.appendMarkdown(`\n\n---\n\n`); + // } + // Commands if (commands && commands.length > 0) { for (let index = 0; index < commands.length; index++) { @@ -676,21 +697,5 @@ export function getHistoryItemHover(authorAvatar: string | undefined, authorName } } - // markdownString.appendMarkdown(`[\`$(git-commit) ${getCommitShortHash(documentUri, hash)} \`](command:git.viewCommit?${encodeURIComponent(JSON.stringify([documentUri, hash, documentUri]))} "${l10n.t('Open Commit')}")`); - // markdownString.appendMarkdown(' '); - // markdownString.appendMarkdown(`[$(copy)](command:git.copyContentToClipboard?${encodeURIComponent(JSON.stringify(hash))} "${l10n.t('Copy Commit Hash')}")`); - - // // Remote hover commands - // if (commands && commands.length > 0) { - // markdownString.appendMarkdown('  |  '); - - // const remoteCommandsMarkdown = commands - // .map(command => `[${command.title}](command:${command.command}?${encodeURIComponent(JSON.stringify([...command.arguments ?? [], hash]))} "${command.tooltip}")`); - // markdownString.appendMarkdown(remoteCommandsMarkdown.join(' ')); - // } - - // markdownString.appendMarkdown('  |  '); - // markdownString.appendMarkdown(`[$(gear)](command:workbench.action.openSettings?%5B%22git.blame%22%5D "${l10n.t('Open Settings')}")`); - return markdownString; } diff --git a/extensions/github/package.json b/extensions/github/package.json index 726a882ebc3..cd70cfea26b 100644 --- a/extensions/github/package.json +++ b/extensions/github/package.json @@ -157,13 +157,6 @@ "group": "0_view@2" } ], - "scm/historyItem/hover": [ - { - "command": "github.graph.openOnGitHub", - "when": "github.hasGitHubRepo", - "group": "1_open@1" - } - ], "timeline/item/context": [ { "command": "github.timeline.openOnGitHub", diff --git a/src/vs/platform/actions/common/actions.ts b/src/vs/platform/actions/common/actions.ts index 604bd28c3e1..77343d49aea 100644 --- a/src/vs/platform/actions/common/actions.ts +++ b/src/vs/platform/actions/common/actions.ts @@ -145,7 +145,6 @@ export class MenuId { static readonly SCMHistoryTitle = new MenuId('SCMHistoryTitle'); static readonly SCMHistoryItemContext = new MenuId('SCMHistoryItemContext'); static readonly SCMHistoryItemChangeContext = new MenuId('SCMHistoryItemChangeContext'); - static readonly SCMHistoryItemHover = new MenuId('SCMHistoryItemHover'); static readonly SCMHistoryItemRefContext = new MenuId('SCMHistoryItemRefContext'); static readonly SCMQuickDiffDecorations = new MenuId('SCMQuickDiffDecorations'); static readonly SCMTitle = new MenuId('SCMTitle'); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index e567cff832a..195117012b7 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -1661,6 +1661,7 @@ export interface SCMHistoryItemDto { readonly deletions: number; }; readonly references?: SCMHistoryItemRefDto[]; + readonly tooltip?: string | IMarkdownString | undefined; } export interface SCMHistoryItemChangeDto { diff --git a/src/vs/workbench/api/common/extHostSCM.ts b/src/vs/workbench/api/common/extHostSCM.ts index 43850a724c6..01eb10ff0ba 100644 --- a/src/vs/workbench/api/common/extHostSCM.ts +++ b/src/vs/workbench/api/common/extHostSCM.ts @@ -75,11 +75,13 @@ function getHistoryItemIconDto(icon: vscode.Uri | { light: vscode.Uri; dark: vsc function toSCMHistoryItemDto(historyItem: vscode.SourceControlHistoryItem): SCMHistoryItemDto { const authorIcon = getHistoryItemIconDto(historyItem.authorIcon); + const tooltip = MarkdownString.fromStrict(historyItem.tooltip); + const references = historyItem.references?.map(r => ({ ...r, icon: getHistoryItemIconDto(r.icon) })); - return { ...historyItem, authorIcon, references }; + return { ...historyItem, authorIcon, references, tooltip }; } function toSCMHistoryItemRefDto(historyItemRef?: vscode.SourceControlHistoryItemRef): SCMHistoryItemRefDto | undefined { diff --git a/src/vs/workbench/contrib/chat/browser/chatAttachmentWidgets.ts b/src/vs/workbench/contrib/chat/browser/chatAttachmentWidgets.ts index 313b5e9bf19..9624b1bf3be 100644 --- a/src/vs/workbench/contrib/chat/browser/chatAttachmentWidgets.ts +++ b/src/vs/workbench/contrib/chat/browser/chatAttachmentWidgets.ts @@ -49,7 +49,7 @@ import { IPreferencesService } from '../../../services/preferences/common/prefer import { revealInSideBarCommand } from '../../files/browser/fileActions.contribution.js'; import { CellUri } from '../../notebook/common/notebookCommon.js'; import { INotebookService } from '../../notebook/common/notebookService.js'; -import { getHistoryItemEditorTitle, getHistoryItemHoverContent } from '../../scm/browser/util.js'; +import { getHistoryItemEditorTitle } from '../../scm/browser/util.js'; import { IChatContentReference } from '../common/chatService.js'; import { IChatRequestPasteVariableEntry, IChatRequestVariableEntry, IElementVariableEntry, INotebookOutputVariableEntry, IPromptFileVariableEntry, IPromptTextVariableEntry, ISCMHistoryItemVariableEntry, OmittedState, PromptFileVariableKind, ChatRequestToolReferenceEntry, ISCMHistoryItemChangeVariableEntry, ISCMHistoryItemChangeRangeVariableEntry } from '../common/chatVariableEntries.js'; import { ILanguageModelChatMetadataAndIdentifier, ILanguageModelsService } from '../common/languageModels.js'; @@ -790,7 +790,12 @@ export class SCMHistoryItemAttachmentWidget extends AbstractChatAttachmentWidget this.element.style.cursor = 'pointer'; this.element.ariaLabel = localize('chat.attachment', "Attached context, {0}", attachment.name); - this._store.add(hoverService.setupManagedHover(hoverDelegate, this.element, () => getHistoryItemHoverContent(themeService, attachment.historyItem), { trapFocus: true })); + const historyItem = attachment.historyItem; + const hoverContent = { + markdown: historyItem.tooltip ?? historyItem.message, + markdownNotSupportedFallback: historyItem.message + } satisfies IManagedHoverTooltipMarkdownString; + this._store.add(hoverService.setupManagedHover(hoverDelegate, this.element, hoverContent, { trapFocus: true })); this._store.add(dom.addDisposableListener(this.element, dom.EventType.CLICK, (e: MouseEvent) => { dom.EventHelper.stop(e, true); @@ -835,7 +840,13 @@ export class SCMHistoryItemChangeAttachmentWidget extends AbstractChatAttachment this.label.setFile(attachment.value, { fileKind: FileKind.FILE, hidePath: true, nameSuffix }); this.element.ariaLabel = localize('chat.attachment', "Attached context, {0}", attachment.name); - this._store.add(hoverService.setupManagedHover(hoverDelegate, this.element, () => getHistoryItemHoverContent(themeService, attachment.historyItem), { trapFocus: true })); + + const historyItem = attachment.historyItem; + const hoverContent = { + markdown: historyItem.tooltip ?? historyItem.message, + markdownNotSupportedFallback: historyItem.message + } satisfies IManagedHoverTooltipMarkdownString; + this._store.add(hoverService.setupManagedHover(hoverDelegate, this.element, hoverContent, { trapFocus: true })); this.addResourceOpenHandlers(attachment.value, undefined); this.attachClearButton(); diff --git a/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts b/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts index d67712de4c6..8a36faae018 100644 --- a/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts +++ b/src/vs/workbench/contrib/scm/browser/scmHistoryViewPane.ts @@ -5,7 +5,7 @@ import './media/scm.css'; import { $, append, h, reset } from '../../../../base/browser/dom.js'; -import { IHoverAction, IHoverOptions } from '../../../../base/browser/ui/hover/hover.js'; +import { IHoverOptions, IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js'; import { IHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegate.js'; import { IconLabel } from '../../../../base/browser/ui/iconLabel/iconLabel.js'; import { IIdentityProvider, IListVirtualDelegate } from '../../../../base/browser/ui/list/list.js'; @@ -29,7 +29,7 @@ import { IFileIconTheme, IThemeService } from '../../../../platform/theme/common import { IViewPaneOptions, ViewAction, ViewPane, ViewPaneShowActions } from '../../../browser/parts/views/viewPane.js'; import { IViewDescriptorService, ViewContainerLocation } from '../../../common/views.js'; import { renderSCMHistoryItemGraph, toISCMHistoryItemViewModelArray, SWIMLANE_WIDTH, renderSCMHistoryGraphPlaceholder, historyItemHoverLabelForeground, historyItemHoverDefaultLabelBackground, getHistoryItemIndex } from './scmHistory.js'; -import { getHistoryItemEditorTitle, getHistoryItemHoverContent, getProviderKey, isSCMHistoryItemChangeNode, isSCMHistoryItemChangeViewModelTreeElement, isSCMHistoryItemLoadMoreTreeElement, isSCMHistoryItemViewModelTreeElement, isSCMRepository } from './util.js'; +import { getHistoryItemEditorTitle, getProviderKey, isSCMHistoryItemChangeNode, isSCMHistoryItemChangeViewModelTreeElement, isSCMHistoryItemLoadMoreTreeElement, isSCMHistoryItemViewModelTreeElement, isSCMRepository } from './util.js'; import { ISCMHistoryItem, ISCMHistoryItemChange, ISCMHistoryItemGraphNode, ISCMHistoryItemRef, ISCMHistoryItemViewModel, ISCMHistoryProvider, SCMHistoryItemChangeViewModelTreeElement, SCMHistoryItemLoadMoreTreeElement, SCMHistoryItemViewModelTreeElement } from '../common/history.js'; import { HISTORY_VIEW_PANE_ID, ISCMProvider, ISCMRepository, ISCMService, ISCMViewService, ViewMode } from '../common/scm.js'; import { IListAccessibilityProvider } from '../../../../base/browser/ui/list/listWidget.js'; @@ -53,7 +53,6 @@ import { Iterable } from '../../../../base/common/iterator.js'; import { clamp } from '../../../../base/common/numbers.js'; import { observableConfigValue } from '../../../../platform/observable/common/platformObservableUtils.js'; import { compare } from '../../../../base/common/strings.js'; -import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js'; import { getDefaultHoverDelegate } from '../../../../base/browser/ui/hover/hoverDelegateFactory.js'; import { IStorageService, StorageScope, StorageTarget } from '../../../../platform/storage/common/storage.js'; import { IExtensionService } from '../../../services/extensions/common/extensions.js'; @@ -408,7 +407,6 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer('scm.graph.badges', 'filter', this._configurationService); } @@ -445,9 +442,11 @@ class HistoryItemRenderer implements ICompressibleTreeRenderer item[1]); - - return [ - { - commandId: 'workbench.scm.action.graph.copyHistoryItemId', - iconClass: 'codicon.codicon-copy', - label: historyItem.displayId ?? historyItem.id, - run: () => this._clipboardService.writeText(historyItem.id) - }, - ...actions.map(action => { - const iconClass = ThemeIcon.isThemeIcon(action.item.icon) - ? ThemeIcon.asClassNameArray(action.item.icon).join('.') - : undefined; - - return { - commandId: action.id, - label: action.label, - iconClass, - run: () => action.run(historyItem) - }; - }) satisfies IHoverAction[] - ]; - } - private _processMatches(historyItemViewModel: ISCMHistoryItemViewModel, filterData: LabelFuzzyScore | undefined): [IMatch[] | undefined, IMatch[] | undefined] { if (!filterData) { return [undefined, undefined]; diff --git a/src/vs/workbench/contrib/scm/browser/util.ts b/src/vs/workbench/contrib/scm/browser/util.ts index 784f81ec934..e982ea2ac36 100644 --- a/src/vs/workbench/contrib/scm/browser/util.ts +++ b/src/vs/workbench/contrib/scm/browser/util.ts @@ -3,8 +3,6 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { localize } from '../../../../nls.js'; -import * as platform from '../../../../base/common/platform.js'; import { ISCMHistoryItem, SCMHistoryItemChangeViewModelTreeElement, SCMHistoryItemLoadMoreTreeElement, SCMHistoryItemViewModelTreeElement } from '../common/history.js'; import { ISCMResource, ISCMRepository, ISCMResourceGroup, ISCMInput, ISCMActionButton, ISCMViewService, ISCMProvider } from '../common/scm.js'; import { IMenu, MenuItemAction } from '../../../../platform/actions/common/actions.js'; @@ -20,14 +18,6 @@ import { Command } from '../../../../editor/common/languages.js'; import { reset } from '../../../../base/browser/dom.js'; import { IInstantiationService } from '../../../../platform/instantiation/common/instantiation.js'; import { IResourceNode, ResourceTree } from '../../../../base/common/resourceTree.js'; -import { IThemeService } from '../../../../platform/theme/common/themeService.js'; -import { IManagedHoverTooltipMarkdownString } from '../../../../base/browser/ui/hover/hover.js'; -import { MarkdownString } from '../../../../base/common/htmlContent.js'; -import { URI } from '../../../../base/common/uri.js'; -import { ThemeIcon } from '../../../../base/common/themables.js'; -import { fromNow, safeIntl } from '../../../../base/common/date.js'; -import { historyItemHoverAdditionsForeground, historyItemHoverDefaultLabelBackground, historyItemHoverDefaultLabelForeground, historyItemHoverDeletionsForeground, historyItemHoverLabelForeground } from './scmHistory.js'; -import { asCssVariable } from '../../../../platform/theme/common/colorUtils.js'; export function isSCMViewService(element: any): element is ISCMViewService { return Array.isArray((element as ISCMViewService).repositories) && Array.isArray((element as ISCMViewService).visibleRepositories); @@ -156,68 +146,3 @@ export function getRepositoryResourceCount(provider: ISCMProvider): number { export function getHistoryItemEditorTitle(historyItem: ISCMHistoryItem): string { return `${historyItem.displayId ?? historyItem.id} - ${historyItem.subject}`; } - -export function getHistoryItemHoverContent(themeService: IThemeService, historyItem: ISCMHistoryItem): IManagedHoverTooltipMarkdownString { - const colorTheme = themeService.getColorTheme(); - const markdown = new MarkdownString('', { isTrusted: true, supportThemeIcons: true }); - - if (historyItem.author) { - const icon = URI.isUri(historyItem.authorIcon) - ? `![${historyItem.author}](${historyItem.authorIcon.toString()}|width=20,height=20)` - : ThemeIcon.isThemeIcon(historyItem.authorIcon) - ? `$(${historyItem.authorIcon.id})` - : '$(account)'; - - if (historyItem.authorEmail) { - const emailTitle = localize('emailLinkTitle', "Email"); - markdown.appendMarkdown(`${icon} [**${historyItem.author}**](mailto:${historyItem.authorEmail} "${emailTitle} ${historyItem.author}")`); - } else { - markdown.appendMarkdown(`${icon} **${historyItem.author}**`); - } - - if (historyItem.timestamp) { - const dateFormatter = safeIntl.DateTimeFormat(platform.language, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' }).value; - markdown.appendMarkdown(`, $(history) ${fromNow(historyItem.timestamp, true, true)} (${dateFormatter.format(historyItem.timestamp)})`); - } - - markdown.appendMarkdown('\n\n'); - } - - markdown.appendMarkdown(`${historyItem.message.replace(/\r\n|\r|\n/g, '\n\n')}\n\n`); - - if (historyItem.statistics) { - markdown.appendMarkdown(`---\n\n`); - - markdown.appendMarkdown(`${historyItem.statistics.files === 1 ? - localize('fileChanged', "{0} file changed", historyItem.statistics.files) : - localize('filesChanged', "{0} files changed", historyItem.statistics.files)}`); - - if (historyItem.statistics.insertions) { - const additionsForegroundColor = colorTheme.getColor(historyItemHoverAdditionsForeground); - markdown.appendMarkdown(`, ${historyItem.statistics.insertions === 1 ? - localize('insertion', "{0} insertion{1}", historyItem.statistics.insertions, '(+)') : - localize('insertions', "{0} insertions{1}", historyItem.statistics.insertions, '(+)')}`); - } - - if (historyItem.statistics.deletions) { - const deletionsForegroundColor = colorTheme.getColor(historyItemHoverDeletionsForeground); - markdown.appendMarkdown(`, ${historyItem.statistics.deletions === 1 ? - localize('deletion', "{0} deletion{1}", historyItem.statistics.deletions, '(-)') : - localize('deletions', "{0} deletions{1}", historyItem.statistics.deletions, '(-)')}`); - } - } - - if ((historyItem.references ?? []).length > 0) { - markdown.appendMarkdown(`\n\n---\n\n`); - markdown.appendMarkdown((historyItem.references ?? []).map(ref => { - const labelIconId = ThemeIcon.isThemeIcon(ref.icon) ? ref.icon.id : ''; - - const labelBackgroundColor = ref.color ? asCssVariable(ref.color) : asCssVariable(historyItemHoverDefaultLabelBackground); - const labelForegroundColor = ref.color ? asCssVariable(historyItemHoverLabelForeground) : asCssVariable(historyItemHoverDefaultLabelForeground); - - return ` $(${labelIconId}) ${ref.name}  `; - }).join('  ')); - } - - return { markdown, markdownNotSupportedFallback: historyItem.message }; -} diff --git a/src/vs/workbench/contrib/scm/common/history.ts b/src/vs/workbench/contrib/scm/common/history.ts index 77e8b714319..def84c84214 100644 --- a/src/vs/workbench/contrib/scm/common/history.ts +++ b/src/vs/workbench/contrib/scm/common/history.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { CancellationToken } from '../../../../base/common/cancellation.js'; +import { IMarkdownString } from '../../../../base/common/htmlContent.js'; import { IObservable } from '../../../../base/common/observable.js'; import { ThemeIcon } from '../../../../base/common/themables.js'; import { URI } from '../../../../base/common/uri.js'; @@ -73,6 +74,7 @@ export interface ISCMHistoryItem { readonly timestamp?: number; readonly statistics?: ISCMHistoryItemStatistics; readonly references?: ISCMHistoryItemRef[]; + readonly tooltip?: string | IMarkdownString | undefined; } export interface ISCMHistoryItemGraphNode { diff --git a/src/vs/workbench/services/actions/common/menusExtensionPoint.ts b/src/vs/workbench/services/actions/common/menusExtensionPoint.ts index 2d4a20c1070..d8ae0d506ff 100644 --- a/src/vs/workbench/services/actions/common/menusExtensionPoint.ts +++ b/src/vs/workbench/services/actions/common/menusExtensionPoint.ts @@ -192,12 +192,6 @@ const apiMenus: IAPIMenu[] = [ description: localize('menus.historyItemContext', "The Source Control history item context menu"), proposed: 'contribSourceControlHistoryItemMenu' }, - { - key: 'scm/historyItem/hover', - id: MenuId.SCMHistoryItemHover, - description: localize('menus.historyItemHover', "The Source Control history item hover menu"), - proposed: 'contribSourceControlHistoryItemMenu' - }, { key: 'scm/historyItemRef/context', id: MenuId.SCMHistoryItemRefContext, diff --git a/src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts b/src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts index cf5f3c8e326..5f0a8eb257c 100644 --- a/src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts +++ b/src/vscode-dts/vscode.proposed.scmHistoryProvider.d.ts @@ -61,6 +61,7 @@ declare module 'vscode' { readonly timestamp?: number; readonly statistics?: SourceControlHistoryItemStatistics; readonly references?: SourceControlHistoryItemRef[]; + readonly tooltip?: string | MarkdownString | undefined; } export interface SourceControlHistoryItemRef {