mirror of
https://github.com/Microsoft/vscode
synced 2024-09-13 13:46:13 +00:00
Separate quick diff API from SCM (#170544)
* Separate quick diff API from SCM Part 1: split up the API. upcoming in part 2: In editor UX for multiple quick diffs. Fixes #169012 * Respond to review feedback Co-authored-by: João Moreno <joao.moreno@microsoft.com>
This commit is contained in:
parent
6d40104789
commit
04f0fb46ff
|
@ -45,6 +45,7 @@ import './mainThreadLogService';
|
||||||
import './mainThreadMessageService';
|
import './mainThreadMessageService';
|
||||||
import './mainThreadOutputService';
|
import './mainThreadOutputService';
|
||||||
import './mainThreadProgress';
|
import './mainThreadProgress';
|
||||||
|
import './mainThreadQuickDiff';
|
||||||
import './mainThreadQuickOpen';
|
import './mainThreadQuickOpen';
|
||||||
import './mainThreadRemoteConnectionData';
|
import './mainThreadRemoteConnectionData';
|
||||||
import './mainThreadSaveParticipant';
|
import './mainThreadSaveParticipant';
|
||||||
|
|
54
src/vs/workbench/api/browser/mainThreadQuickDiff.ts
Normal file
54
src/vs/workbench/api/browser/mainThreadQuickDiff.ts
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { CancellationTokenSource } from 'vs/base/common/cancellation';
|
||||||
|
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||||
|
import { ExtHostContext, ExtHostQuickDiffShape, MainContext, MainThreadQuickDiffShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||||
|
import { IQuickDiffService, QuickDiffProvider } from 'vs/workbench/contrib/scm/common/quickDiff';
|
||||||
|
import { extHostNamedCustomer, IExtHostContext } from 'vs/workbench/services/extensions/common/extHostCustomers';
|
||||||
|
|
||||||
|
@extHostNamedCustomer(MainContext.MainThreadQuickDiff)
|
||||||
|
export class MainThreadQuickDiff implements MainThreadQuickDiffShape {
|
||||||
|
|
||||||
|
private readonly proxy: ExtHostQuickDiffShape;
|
||||||
|
private providers = new Map<number, QuickDiffProvider>();
|
||||||
|
private providerDisposables = new Map<number, IDisposable>();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
extHostContext: IExtHostContext,
|
||||||
|
@IQuickDiffService private readonly quickDiffService: IQuickDiffService
|
||||||
|
) {
|
||||||
|
this.proxy = extHostContext.getProxy(ExtHostContext.ExtHostQuickDiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
async $registerQuickDiffProvider(handle: number, label: string, rootUri: UriComponents | undefined): Promise<void> {
|
||||||
|
const provider: QuickDiffProvider = {
|
||||||
|
label,
|
||||||
|
rootUri: URI.revive(rootUri),
|
||||||
|
getOriginalResource: async (uri: URI) => {
|
||||||
|
return URI.revive(await this.proxy.$provideOriginalResource(handle, uri, new CancellationTokenSource().token));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
this.providers.set(handle, provider);
|
||||||
|
const disposable = this.quickDiffService.addQuickDiffProvider(provider);
|
||||||
|
this.providerDisposables.set(handle, disposable);
|
||||||
|
}
|
||||||
|
|
||||||
|
async $unregisterQuickDiffProvider(handle: number): Promise<void> {
|
||||||
|
if (this.providers.has(handle)) {
|
||||||
|
this.providers.delete(handle);
|
||||||
|
}
|
||||||
|
if (this.providerDisposables.has(handle)) {
|
||||||
|
this.providerDisposables.delete(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dispose(): void {
|
||||||
|
this.providers.clear();
|
||||||
|
dispose(this.providerDisposables.values());
|
||||||
|
this.providerDisposables.clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
import { MarshalledId } from 'vs/base/common/marshallingIds';
|
import { MarshalledId } from 'vs/base/common/marshallingIds';
|
||||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||||
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
import { IMarkdownString } from 'vs/base/common/htmlContent';
|
||||||
|
import { IQuickDiffService, QuickDiffProvider } from 'vs/workbench/contrib/scm/common/quickDiff';
|
||||||
|
|
||||||
class MainThreadSCMResourceGroup implements ISCMResourceGroup {
|
class MainThreadSCMResourceGroup implements ISCMResourceGroup {
|
||||||
|
|
||||||
|
@ -89,7 +90,7 @@ class MainThreadSCMResource implements ISCMResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MainThreadSCMProvider implements ISCMProvider {
|
class MainThreadSCMProvider implements ISCMProvider, QuickDiffProvider {
|
||||||
|
|
||||||
private static ID_HANDLE = 0;
|
private static ID_HANDLE = 0;
|
||||||
private _id = `scm${MainThreadSCMProvider.ID_HANDLE++}`;
|
private _id = `scm${MainThreadSCMProvider.ID_HANDLE++}`;
|
||||||
|
@ -133,12 +134,15 @@ class MainThreadSCMProvider implements ISCMProvider {
|
||||||
private readonly _onDidChange = new Emitter<void>();
|
private readonly _onDidChange = new Emitter<void>();
|
||||||
readonly onDidChange: Event<void> = this._onDidChange.event;
|
readonly onDidChange: Event<void> = this._onDidChange.event;
|
||||||
|
|
||||||
|
private _quickDiff: IDisposable | undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly proxy: ExtHostSCMShape,
|
private readonly proxy: ExtHostSCMShape,
|
||||||
private readonly _handle: number,
|
private readonly _handle: number,
|
||||||
private readonly _contextValue: string,
|
private readonly _contextValue: string,
|
||||||
private readonly _label: string,
|
private readonly _label: string,
|
||||||
private readonly _rootUri: URI | undefined
|
private readonly _rootUri: URI | undefined,
|
||||||
|
private readonly _quickDiffService: IQuickDiffService
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
$updateSourceControl(features: SCMProviderFeatures): void {
|
$updateSourceControl(features: SCMProviderFeatures): void {
|
||||||
|
@ -152,6 +156,13 @@ class MainThreadSCMProvider implements ISCMProvider {
|
||||||
if (typeof features.statusBarCommands !== 'undefined') {
|
if (typeof features.statusBarCommands !== 'undefined') {
|
||||||
this._onDidChangeStatusBarCommands.fire(this.statusBarCommands!);
|
this._onDidChangeStatusBarCommands.fire(this.statusBarCommands!);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (features.hasQuickDiffProvider && !this._quickDiff) {
|
||||||
|
this._quickDiff = this._quickDiffService.addQuickDiffProvider(this);
|
||||||
|
} else if (features.hasQuickDiffProvider === false && this._quickDiff) {
|
||||||
|
this._quickDiff.dispose();
|
||||||
|
this._quickDiff = undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$registerGroups(_groups: [number /*handle*/, string /*id*/, string /*label*/, SCMGroupFeatures][]): void {
|
$registerGroups(_groups: [number /*handle*/, string /*id*/, string /*label*/, SCMGroupFeatures][]): void {
|
||||||
|
@ -284,7 +295,8 @@ export class MainThreadSCM implements MainThreadSCMShape {
|
||||||
constructor(
|
constructor(
|
||||||
extHostContext: IExtHostContext,
|
extHostContext: IExtHostContext,
|
||||||
@ISCMService private readonly scmService: ISCMService,
|
@ISCMService private readonly scmService: ISCMService,
|
||||||
@ISCMViewService private readonly scmViewService: ISCMViewService
|
@ISCMViewService private readonly scmViewService: ISCMViewService,
|
||||||
|
@IQuickDiffService private readonly quickDiffService: IQuickDiffService
|
||||||
) {
|
) {
|
||||||
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSCM);
|
this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostSCM);
|
||||||
}
|
}
|
||||||
|
@ -300,7 +312,7 @@ export class MainThreadSCM implements MainThreadSCMShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
$registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined): void {
|
$registerSourceControl(handle: number, id: string, label: string, rootUri: UriComponents | undefined): void {
|
||||||
const provider = new MainThreadSCMProvider(this._proxy, handle, id, label, rootUri ? URI.revive(rootUri) : undefined);
|
const provider = new MainThreadSCMProvider(this._proxy, handle, id, label, rootUri ? URI.revive(rootUri) : undefined, this.quickDiffService);
|
||||||
const repository = this.scmService.registerSCMProvider(provider);
|
const repository = this.scmService.registerSCMProvider(provider);
|
||||||
this._repositories.set(handle, repository);
|
this._repositories.set(handle, repository);
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ import { DebugConfigurationProviderTriggerKind } from 'vs/workbench/contrib/debu
|
||||||
import { IExtHostLocalizationService } from 'vs/workbench/api/common/extHostLocalizationService';
|
import { IExtHostLocalizationService } from 'vs/workbench/api/common/extHostLocalizationService';
|
||||||
import { EditSessionIdentityMatch } from 'vs/platform/workspace/common/editSessions';
|
import { EditSessionIdentityMatch } from 'vs/platform/workspace/common/editSessions';
|
||||||
import { ExtHostProfileContentHandlers } from 'vs/workbench/api/common/extHostProfileContentHandler';
|
import { ExtHostProfileContentHandlers } from 'vs/workbench/api/common/extHostProfileContentHandler';
|
||||||
|
import { ExtHostQuickDiff } from 'vs/workbench/api/common/extHostQuickDiff';
|
||||||
|
|
||||||
export interface IExtensionRegistries {
|
export interface IExtensionRegistries {
|
||||||
mine: ExtensionDescriptionRegistry;
|
mine: ExtensionDescriptionRegistry;
|
||||||
|
@ -175,6 +176,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||||
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpcProtocol, extHostLogService, extHostDocumentsAndEditors));
|
const extHostFileSystemEvent = rpcProtocol.set(ExtHostContext.ExtHostFileSystemEventService, new ExtHostFileSystemEventService(rpcProtocol, extHostLogService, extHostDocumentsAndEditors));
|
||||||
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, createExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
|
const extHostQuickOpen = rpcProtocol.set(ExtHostContext.ExtHostQuickOpen, createExtHostQuickOpen(rpcProtocol, extHostWorkspace, extHostCommands));
|
||||||
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
const extHostSCM = rpcProtocol.set(ExtHostContext.ExtHostSCM, new ExtHostSCM(rpcProtocol, extHostCommands, extHostLogService));
|
||||||
|
const extHostQuickDiff = rpcProtocol.set(ExtHostContext.ExtHostQuickDiff, new ExtHostQuickDiff(rpcProtocol));
|
||||||
const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, createExtHostComments(rpcProtocol, extHostCommands, extHostDocuments));
|
const extHostComment = rpcProtocol.set(ExtHostContext.ExtHostComments, createExtHostComments(rpcProtocol, extHostCommands, extHostDocuments));
|
||||||
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
const extHostProgress = rpcProtocol.set(ExtHostContext.ExtHostProgress, new ExtHostProgress(rpcProtocol.getProxy(MainContext.MainThreadProgress)));
|
||||||
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
|
const extHostLabelService = rpcProtocol.set(ExtHostContext.ExtHosLabelService, new ExtHostLabelService(rpcProtocol));
|
||||||
|
@ -802,6 +804,10 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||||
checkProposedApiEnabled(extension, 'profileContentHandlers');
|
checkProposedApiEnabled(extension, 'profileContentHandlers');
|
||||||
return extHostProfileContentHandlers.registrProfileContentHandler(extension, id, handler);
|
return extHostProfileContentHandlers.registrProfileContentHandler(extension, id, handler);
|
||||||
},
|
},
|
||||||
|
async registerQuickDiffProvider(quickDiffProvider: vscode.QuickDiffProvider, label: string, rootUri?: vscode.Uri): Promise<vscode.Disposable> {
|
||||||
|
checkProposedApiEnabled(extension, 'quickDiffProvider');
|
||||||
|
return extHostQuickDiff.registerQuickDiffProvider(quickDiffProvider, label, rootUri);
|
||||||
|
},
|
||||||
get tabGroups(): vscode.TabGroups {
|
get tabGroups(): vscode.TabGroups {
|
||||||
return extHostEditorTabs.tabGroups;
|
return extHostEditorTabs.tabGroups;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1237,6 +1237,11 @@ export interface MainThreadSCMShape extends IDisposable {
|
||||||
$setValidationProviderIsEnabled(sourceControlHandle: number, enabled: boolean): void;
|
$setValidationProviderIsEnabled(sourceControlHandle: number, enabled: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface MainThreadQuickDiffShape extends IDisposable {
|
||||||
|
$registerQuickDiffProvider(handle: number, label: string, rootUri: UriComponents | undefined): Promise<void>;
|
||||||
|
$unregisterQuickDiffProvider(handle: number): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
export type DebugSessionUUID = string;
|
export type DebugSessionUUID = string;
|
||||||
|
|
||||||
export interface IDebugConfiguration {
|
export interface IDebugConfiguration {
|
||||||
|
@ -1869,6 +1874,10 @@ export interface ExtHostSCMShape {
|
||||||
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void>;
|
$setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ExtHostQuickDiffShape {
|
||||||
|
$provideOriginalResource(sourceControlHandle: number, uri: UriComponents, token: CancellationToken): Promise<UriComponents | null>;
|
||||||
|
}
|
||||||
|
|
||||||
export interface ExtHostTaskShape {
|
export interface ExtHostTaskShape {
|
||||||
$provideTasks(handle: number, validTypes: { [key: string]: boolean }): Promise<tasks.ITaskSetDTO>;
|
$provideTasks(handle: number, validTypes: { [key: string]: boolean }): Promise<tasks.ITaskSetDTO>;
|
||||||
$resolveTask(handle: number, taskDTO: tasks.ITaskDTO): Promise<tasks.ITaskDTO | undefined>;
|
$resolveTask(handle: number, taskDTO: tasks.ITaskDTO): Promise<tasks.ITaskDTO | undefined>;
|
||||||
|
@ -2333,6 +2342,7 @@ export const MainContext = {
|
||||||
MainThreadMessageService: createProxyIdentifier<MainThreadMessageServiceShape>('MainThreadMessageService'),
|
MainThreadMessageService: createProxyIdentifier<MainThreadMessageServiceShape>('MainThreadMessageService'),
|
||||||
MainThreadOutputService: createProxyIdentifier<MainThreadOutputServiceShape>('MainThreadOutputService'),
|
MainThreadOutputService: createProxyIdentifier<MainThreadOutputServiceShape>('MainThreadOutputService'),
|
||||||
MainThreadProgress: createProxyIdentifier<MainThreadProgressShape>('MainThreadProgress'),
|
MainThreadProgress: createProxyIdentifier<MainThreadProgressShape>('MainThreadProgress'),
|
||||||
|
MainThreadQuickDiff: createProxyIdentifier<MainThreadQuickDiffShape>('MainThreadQuickDiff'),
|
||||||
MainThreadQuickOpen: createProxyIdentifier<MainThreadQuickOpenShape>('MainThreadQuickOpen'),
|
MainThreadQuickOpen: createProxyIdentifier<MainThreadQuickOpenShape>('MainThreadQuickOpen'),
|
||||||
MainThreadStatusBar: createProxyIdentifier<MainThreadStatusBarShape>('MainThreadStatusBar'),
|
MainThreadStatusBar: createProxyIdentifier<MainThreadStatusBarShape>('MainThreadStatusBar'),
|
||||||
MainThreadSecretState: createProxyIdentifier<MainThreadSecretStateShape>('MainThreadSecretState'),
|
MainThreadSecretState: createProxyIdentifier<MainThreadSecretStateShape>('MainThreadSecretState'),
|
||||||
|
@ -2385,6 +2395,7 @@ export const ExtHostContext = {
|
||||||
ExtHostLanguages: createProxyIdentifier<ExtHostLanguagesShape>('ExtHostLanguages'),
|
ExtHostLanguages: createProxyIdentifier<ExtHostLanguagesShape>('ExtHostLanguages'),
|
||||||
ExtHostLanguageFeatures: createProxyIdentifier<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
|
ExtHostLanguageFeatures: createProxyIdentifier<ExtHostLanguageFeaturesShape>('ExtHostLanguageFeatures'),
|
||||||
ExtHostQuickOpen: createProxyIdentifier<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
|
ExtHostQuickOpen: createProxyIdentifier<ExtHostQuickOpenShape>('ExtHostQuickOpen'),
|
||||||
|
ExtHostQuickDiff: createProxyIdentifier<ExtHostQuickDiffShape>('ExtHostQuickDiff'),
|
||||||
ExtHostExtensionService: createProxyIdentifier<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
|
ExtHostExtensionService: createProxyIdentifier<ExtHostExtensionServiceShape>('ExtHostExtensionService'),
|
||||||
ExtHostLogLevelServiceShape: createProxyIdentifier<ExtHostLogLevelServiceShape>('ExtHostLogLevelServiceShape'),
|
ExtHostLogLevelServiceShape: createProxyIdentifier<ExtHostLogLevelServiceShape>('ExtHostLogLevelServiceShape'),
|
||||||
ExtHostTerminalService: createProxyIdentifier<ExtHostTerminalServiceShape>('ExtHostTerminalService'),
|
ExtHostTerminalService: createProxyIdentifier<ExtHostTerminalServiceShape>('ExtHostTerminalService'),
|
||||||
|
|
44
src/vs/workbench/api/common/extHostQuickDiff.ts
Normal file
44
src/vs/workbench/api/common/extHostQuickDiff.ts
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import type * as vscode from 'vscode';
|
||||||
|
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||||
|
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||||
|
import { ExtHostQuickDiffShape, IMainContext, MainContext, MainThreadQuickDiffShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||||
|
import { asPromise } from 'vs/base/common/async';
|
||||||
|
|
||||||
|
export class ExtHostQuickDiff implements ExtHostQuickDiffShape {
|
||||||
|
private static handlePool: number = 0;
|
||||||
|
|
||||||
|
private proxy: MainThreadQuickDiffShape;
|
||||||
|
private providers: Map<number, vscode.QuickDiffProvider> = new Map();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
mainContext: IMainContext
|
||||||
|
) {
|
||||||
|
this.proxy = mainContext.getProxy(MainContext.MainThreadQuickDiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
$provideOriginalResource(handle: number, uriComponents: UriComponents, token: CancellationToken): Promise<UriComponents | null> {
|
||||||
|
const uri = URI.revive(uriComponents);
|
||||||
|
const provider = this.providers.get(handle);
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
return Promise.resolve(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return asPromise(() => provider.provideOriginalResource!(uri, token))
|
||||||
|
.then<UriComponents | null>(r => r || null);
|
||||||
|
}
|
||||||
|
|
||||||
|
async registerQuickDiffProvider(quickDiffProvider: vscode.QuickDiffProvider, label: string, rootUri?: vscode.Uri): Promise<vscode.Disposable> {
|
||||||
|
const handle = ExtHostQuickDiff.handlePool++;
|
||||||
|
this.providers.set(handle, quickDiffProvider);
|
||||||
|
await this.proxy.$registerQuickDiffProvider(handle, label, rootUri);
|
||||||
|
return {
|
||||||
|
dispose: () => this.providers.delete(handle)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,7 +18,7 @@ import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { Progress } from 'vs/platform/progress/common/progress';
|
import { Progress } from 'vs/platform/progress/common/progress';
|
||||||
import { getOriginalResource } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator';
|
import { getOriginalResource } from 'vs/workbench/contrib/scm/browser/dirtydiffDecorator';
|
||||||
import { ISCMService } from 'vs/workbench/contrib/scm/common/scm';
|
import { IQuickDiffService } from 'vs/workbench/contrib/scm/common/quickDiff';
|
||||||
|
|
||||||
registerEditorAction(class FormatModifiedAction extends EditorAction {
|
registerEditorAction(class FormatModifiedAction extends EditorAction {
|
||||||
|
|
||||||
|
@ -50,11 +50,11 @@ registerEditorAction(class FormatModifiedAction extends EditorAction {
|
||||||
|
|
||||||
|
|
||||||
export async function getModifiedRanges(accessor: ServicesAccessor, modified: ITextModel): Promise<Range[] | undefined | null> {
|
export async function getModifiedRanges(accessor: ServicesAccessor, modified: ITextModel): Promise<Range[] | undefined | null> {
|
||||||
const scmService = accessor.get(ISCMService);
|
const quickDiffService = accessor.get(IQuickDiffService);
|
||||||
const workerService = accessor.get(IEditorWorkerService);
|
const workerService = accessor.get(IEditorWorkerService);
|
||||||
const modelService = accessor.get(ITextModelService);
|
const modelService = accessor.get(ITextModelService);
|
||||||
|
|
||||||
const original = await getOriginalResource(scmService, modified.uri);
|
const original = await getOriginalResource(quickDiffService, modified.uri);
|
||||||
if (!original) {
|
if (!original) {
|
||||||
return null; // let undefined signify no changes, null represents no source control (there's probably a better way, but I can't think of one rn)
|
return null; // let undefined signify no changes, null represents no source control (there's probably a better way, but I can't think of one rn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
import * as nls from 'vs/nls';
|
import * as nls from 'vs/nls';
|
||||||
|
|
||||||
import 'vs/css!./media/dirtydiffDecorator';
|
import 'vs/css!./media/dirtydiffDecorator';
|
||||||
import { ThrottledDelayer, first } from 'vs/base/common/async';
|
import { ThrottledDelayer } from 'vs/base/common/async';
|
||||||
import { IDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
import { IDisposable, dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
|
||||||
import { Event, Emitter } from 'vs/base/common/event';
|
import { Event, Emitter } from 'vs/base/common/event';
|
||||||
import * as ext from 'vs/workbench/common/contributions';
|
import * as ext from 'vs/workbench/common/contributions';
|
||||||
|
@ -15,7 +15,7 @@ import { IResolvedTextEditorModel, ITextModelService } from 'vs/editor/common/se
|
||||||
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker';
|
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorker';
|
||||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||||
import { URI } from 'vs/base/common/uri';
|
import { URI } from 'vs/base/common/uri';
|
||||||
import { ISCMService, ISCMRepository, ISCMProvider } from 'vs/workbench/contrib/scm/common/scm';
|
import { ISCMService, ISCMRepository } from 'vs/workbench/contrib/scm/common/scm';
|
||||||
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
|
||||||
import { IColorTheme, themeColorFromId, IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
import { IColorTheme, themeColorFromId, IThemeService, ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||||
import { editorErrorForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry';
|
import { editorErrorForeground, registerColor, transparent } from 'vs/platform/theme/common/colorRegistry';
|
||||||
|
@ -34,7 +34,7 @@ import { IDiffEditorOptions, EditorOption } from 'vs/editor/common/config/editor
|
||||||
import { Action, IAction, ActionRunner } from 'vs/base/common/actions';
|
import { Action, IAction, ActionRunner } from 'vs/base/common/actions';
|
||||||
import { IActionBarOptions } from 'vs/base/browser/ui/actionbar/actionbar';
|
import { IActionBarOptions } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||||
import { basename, isEqualOrParent } from 'vs/base/common/resources';
|
import { basename } from 'vs/base/common/resources';
|
||||||
import { MenuId, IMenuService, IMenu, MenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions';
|
import { MenuId, IMenuService, IMenu, MenuItemAction, MenuRegistry } from 'vs/platform/actions/common/actions';
|
||||||
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
import { createAndFillInActionBarActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||||
import { IEditorModel, ScrollType, IEditorContribution, IDiffEditorModel } from 'vs/editor/common/editorCommon';
|
import { IEditorModel, ScrollType, IEditorContribution, IDiffEditorModel } from 'vs/editor/common/editorCommon';
|
||||||
|
@ -51,13 +51,13 @@ import { TextCompareEditorActiveContext } from 'vs/workbench/common/contextkeys'
|
||||||
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
|
||||||
import { IChange } from 'vs/editor/common/diff/smartLinesDiffComputer';
|
import { IChange } from 'vs/editor/common/diff/smartLinesDiffComputer';
|
||||||
import { Color } from 'vs/base/common/color';
|
import { Color } from 'vs/base/common/color';
|
||||||
import { Iterable } from 'vs/base/common/iterator';
|
|
||||||
import { ResourceMap } from 'vs/base/common/map';
|
import { ResourceMap } from 'vs/base/common/map';
|
||||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||||
import { DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
|
import { DEFAULT_EDITOR_ASSOCIATION } from 'vs/workbench/common/editor';
|
||||||
import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files';
|
import { FILE_EDITOR_INPUT_ID } from 'vs/workbench/contrib/files/common/files';
|
||||||
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
import { AudioCue, IAudioCueService } from 'vs/platform/audioCues/browser/audioCueService';
|
||||||
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility';
|
||||||
|
import { IQuickDiffService } from 'vs/workbench/contrib/scm/common/quickDiff';
|
||||||
|
|
||||||
class DiffActionRunner extends ActionRunner {
|
class DiffActionRunner extends ActionRunner {
|
||||||
|
|
||||||
|
@ -1095,37 +1095,10 @@ function compareChanges(a: IChange, b: IChange): number {
|
||||||
return a.originalEndLineNumber - b.originalEndLineNumber;
|
return a.originalEndLineNumber - b.originalEndLineNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createProviderComparer(uri: URI): (a: ISCMProvider, b: ISCMProvider) => number {
|
|
||||||
return (a, b) => {
|
|
||||||
const aIsParent = isEqualOrParent(uri, a.rootUri!);
|
|
||||||
const bIsParent = isEqualOrParent(uri, b.rootUri!);
|
|
||||||
|
|
||||||
if (aIsParent && bIsParent) {
|
export async function getOriginalResource(quickDiffService: IQuickDiffService, uri: URI): Promise<URI | null> {
|
||||||
return a.rootUri!.fsPath.length - b.rootUri!.fsPath.length;
|
const quickDiffs = await quickDiffService.getQuickDiffs(uri);
|
||||||
} else if (aIsParent) {
|
return quickDiffs.length > 0 ? quickDiffs[0].originalResource : null;
|
||||||
return -1;
|
|
||||||
} else if (bIsParent) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function getOriginalResource(scmService: ISCMService, uri: URI): Promise<URI | null> {
|
|
||||||
const providers = Iterable.map(scmService.repositories, r => r.provider);
|
|
||||||
const rootedProviders = Array.from(Iterable.filter(providers, p => !!p.rootUri));
|
|
||||||
|
|
||||||
rootedProviders.sort(createProviderComparer(uri));
|
|
||||||
|
|
||||||
const result = await first(rootedProviders.map(p => () => p.getOriginalResource(uri)));
|
|
||||||
|
|
||||||
if (result) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
const nonRootedProviders = Iterable.filter(providers, p => !p.rootUri);
|
|
||||||
return first(Array.from(nonRootedProviders, p => () => p.getOriginalResource(uri)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DirtyDiffModel extends Disposable {
|
export class DirtyDiffModel extends Disposable {
|
||||||
|
@ -1151,6 +1124,7 @@ export class DirtyDiffModel extends Disposable {
|
||||||
constructor(
|
constructor(
|
||||||
textFileModel: IResolvedTextFileEditorModel,
|
textFileModel: IResolvedTextFileEditorModel,
|
||||||
@ISCMService private readonly scmService: ISCMService,
|
@ISCMService private readonly scmService: ISCMService,
|
||||||
|
@IQuickDiffService private readonly quickDiffService: IQuickDiffService,
|
||||||
@IEditorWorkerService private readonly editorWorkerService: IEditorWorkerService,
|
@IEditorWorkerService private readonly editorWorkerService: IEditorWorkerService,
|
||||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||||
@ITextModelService private readonly textModelResolverService: ITextModelService,
|
@ITextModelService private readonly textModelResolverService: ITextModelService,
|
||||||
|
@ -1306,7 +1280,7 @@ export class DirtyDiffModel extends Disposable {
|
||||||
}
|
}
|
||||||
|
|
||||||
const uri = this._model.resource;
|
const uri = this._model.resource;
|
||||||
return getOriginalResource(this.scmService, uri);
|
return getOriginalResource(this.quickDiffService, uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
findNextClosestChange(lineNumber: number, inclusive = true): number {
|
findNextClosestChange(lineNumber: number, inclusive = true): number {
|
||||||
|
|
|
@ -30,6 +30,8 @@ import { SCMRepositoriesViewPane } from 'vs/workbench/contrib/scm/browser/scmRep
|
||||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||||
import { Context as SuggestContext } from 'vs/editor/contrib/suggest/browser/suggest';
|
import { Context as SuggestContext } from 'vs/editor/contrib/suggest/browser/suggest';
|
||||||
import { MANAGE_TRUST_COMMAND_ID, WorkspaceTrustContext } from 'vs/workbench/contrib/workspace/common/workspace';
|
import { MANAGE_TRUST_COMMAND_ID, WorkspaceTrustContext } from 'vs/workbench/contrib/workspace/common/workspace';
|
||||||
|
import { IQuickDiffService } from 'vs/workbench/contrib/scm/common/quickDiff';
|
||||||
|
import { QuickDiffService } from 'vs/workbench/contrib/scm/common/quickDiffService';
|
||||||
|
|
||||||
ModesRegistry.registerLanguage({
|
ModesRegistry.registerLanguage({
|
||||||
id: 'scminput',
|
id: 'scminput',
|
||||||
|
@ -385,3 +387,4 @@ MenuRegistry.appendMenuItem(MenuId.SCMSourceControl, {
|
||||||
|
|
||||||
registerSingleton(ISCMService, SCMService, InstantiationType.Delayed);
|
registerSingleton(ISCMService, SCMService, InstantiationType.Delayed);
|
||||||
registerSingleton(ISCMViewService, SCMViewService, InstantiationType.Delayed);
|
registerSingleton(ISCMViewService, SCMViewService, InstantiationType.Delayed);
|
||||||
|
registerSingleton(IQuickDiffService, QuickDiffService, InstantiationType.Delayed);
|
||||||
|
|
28
src/vs/workbench/contrib/scm/common/quickDiff.ts
Normal file
28
src/vs/workbench/contrib/scm/common/quickDiff.ts
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||||
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
|
||||||
|
export const IQuickDiffService = createDecorator<IQuickDiffService>('quickDiff');
|
||||||
|
|
||||||
|
export interface QuickDiffProvider {
|
||||||
|
label: string;
|
||||||
|
rootUri: URI | undefined;
|
||||||
|
getOriginalResource(uri: URI): Promise<URI | null>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface QuickDiff {
|
||||||
|
label: string;
|
||||||
|
originalResource: URI;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IQuickDiffService {
|
||||||
|
readonly _serviceBrand: undefined;
|
||||||
|
|
||||||
|
addQuickDiffProvider(quickDiff: QuickDiffProvider): IDisposable;
|
||||||
|
getQuickDiffs(uri: URI): Promise<QuickDiff[]>;
|
||||||
|
}
|
66
src/vs/workbench/contrib/scm/common/quickDiffService.ts
Normal file
66
src/vs/workbench/contrib/scm/common/quickDiffService.ts
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { URI } from 'vs/base/common/uri';
|
||||||
|
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { IQuickDiffService, QuickDiff, QuickDiffProvider } from 'vs/workbench/contrib/scm/common/quickDiff';
|
||||||
|
import { isEqualOrParent } from 'vs/base/common/resources';
|
||||||
|
|
||||||
|
function createProviderComparer(uri: URI): (a: QuickDiffProvider, b: QuickDiffProvider) => number {
|
||||||
|
return (a, b) => {
|
||||||
|
if (a.rootUri && !b.rootUri) {
|
||||||
|
return -1;
|
||||||
|
} else if (!a.rootUri && b.rootUri) {
|
||||||
|
return 1;
|
||||||
|
} else if (!a.rootUri && !b.rootUri) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const aIsParent = isEqualOrParent(uri, a.rootUri!);
|
||||||
|
const bIsParent = isEqualOrParent(uri, b.rootUri!);
|
||||||
|
|
||||||
|
if (aIsParent && bIsParent) {
|
||||||
|
return a.rootUri!.fsPath.length - b.rootUri!.fsPath.length;
|
||||||
|
} else if (aIsParent) {
|
||||||
|
return -1;
|
||||||
|
} else if (bIsParent) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class QuickDiffService implements IQuickDiffService {
|
||||||
|
declare readonly _serviceBrand: undefined;
|
||||||
|
|
||||||
|
private quickDiffProviders: Set<QuickDiffProvider> = new Set();
|
||||||
|
|
||||||
|
addQuickDiffProvider(quickDiff: QuickDiffProvider): IDisposable {
|
||||||
|
this.quickDiffProviders.add(quickDiff);
|
||||||
|
return {
|
||||||
|
dispose: () => {
|
||||||
|
this.quickDiffProviders.delete(quickDiff);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private isQuickDiff(diff: { originalResource: URI | null; label: string }): diff is QuickDiff {
|
||||||
|
return !!diff.originalResource;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getQuickDiffs(uri: URI): Promise<QuickDiff[]> {
|
||||||
|
const sorted = Array.from(this.quickDiffProviders).sort(createProviderComparer(uri));
|
||||||
|
|
||||||
|
const diffs = await Promise.all(Array.from(sorted.values()).map(async (provider) => {
|
||||||
|
const diff = {
|
||||||
|
originalResource: await provider.getOriginalResource(uri),
|
||||||
|
label: provider.label
|
||||||
|
};
|
||||||
|
return diff;
|
||||||
|
}));
|
||||||
|
return diffs.filter<QuickDiff>(this.isQuickDiff);
|
||||||
|
}
|
||||||
|
}
|
|
@ -50,6 +50,7 @@ export const allApiProposals = Object.freeze({
|
||||||
notebookMime: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookMime.d.ts',
|
notebookMime: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.notebookMime.d.ts',
|
||||||
portsAttributes: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.portsAttributes.d.ts',
|
portsAttributes: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.portsAttributes.d.ts',
|
||||||
profileContentHandlers: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.profileContentHandlers.d.ts',
|
profileContentHandlers: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.profileContentHandlers.d.ts',
|
||||||
|
quickDiffProvider: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.quickDiffProvider.d.ts',
|
||||||
quickPickSortByLabel: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.quickPickSortByLabel.d.ts',
|
quickPickSortByLabel: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.quickPickSortByLabel.d.ts',
|
||||||
resolvers: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.resolvers.d.ts',
|
resolvers: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.resolvers.d.ts',
|
||||||
scmActionButton: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.scmActionButton.d.ts',
|
scmActionButton: 'https://raw.githubusercontent.com/microsoft/vscode/main/src/vscode-dts/vscode.proposed.scmActionButton.d.ts',
|
||||||
|
|
13
src/vscode-dts/vscode.proposed.quickDiffProvider.d.ts
vendored
Normal file
13
src/vscode-dts/vscode.proposed.quickDiffProvider.d.ts
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
declare module 'vscode' {
|
||||||
|
|
||||||
|
// https://github.com/microsoft/vscode/issues/169012
|
||||||
|
|
||||||
|
export namespace window {
|
||||||
|
export function registerQuickDiffProvider(quickDiffProvider: QuickDiffProvider, label: string, rootUri?: Uri): Thenable<Disposable>;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue