extHostSCM.ts ×86

Frontier kind: Joint frontier

unlabeled · c_a9b675daa92f

1 test · 74506 LOC · 255 files · introduces 1 test · 432 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
87 ranges432 lines · 2 files
Tests
1 test

Contains — complete concept membership

All code (extent)
4998 ranges74506 lines · 255 files · Browse complete extent
All tests (intent)
1 testBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

1 test introduced at this concept.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 432 introduced LOC across 87 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/workbench/api/common/extHostSCM.ts 430 introduced LOC · 86 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- extHostSCM.ts
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import { URI, UriComponents } from '../../../base/common/uri.js';
7 > import { Event, Emitter } from '../../../base/common/event.js';
8 > import { debounce } from '../../../base/common/decorators.js';
9 > import { DisposableMap, DisposableStore, IDisposable, MutableDisposable } from '../../../base/common/lifecycle.js';
10 > import { asPromise } from '../../../base/common/async.js';
11 > import { ExtHostCommands } from './extHostCommands.js';
12 > import { MainContext, MainThreadSCMShape, SCMRawResource, SCMRawResourceSplice, SCMRawResourceSplices, IMainContext, ExtHostSCMShape, ICommandDto, MainThreadTelemetryShape, SCMGroupFeatures, SCMHistoryItemDto, SCMHistoryItemChangeDto, SCMHistoryItemRefDto, SCMActionButtonDto, SCMArtifactGroupDto, SCMArtifactDto } from './extHost.protocol.js';
13 > import { sortedDiff, equals } from '../../../base/common/arrays.js';
14 > import { comparePaths } from '../../../base/common/comparers.js';
15 > import type * as vscode from 'vscode';
16 > import { ISplice } from '../../../base/common/sequence.js';
17 > import { ILogService } from '../../../platform/log/common/log.js';
18 > import { CancellationToken } from '../../../base/common/cancellation.js';
19 > import { ExtensionIdentifierMap, IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
20 > import { MarshalledId } from '../../../base/common/marshallingIds.js';
21 > import { ThemeIcon } from '../../../base/common/themables.js';
22 > import { IMarkdownString } from '../../../base/common/htmlContent.js';
23 > import { MarkdownString, SourceControlInputBoxValidationType } from './extHostTypeConverters.js';
24 > import { checkProposedApiEnabled, isProposedApiEnabled } from '../../services/extensions/common/extensions.js';
25 > import { ExtHostDocuments } from './extHostDocuments.js';
26 > import { Schemas } from '../../../base/common/network.js';
27 > import { isLinux } from '../../../base/common/platform.js';
28 > import { structuralEquals } from '../../../base/common/equals.js';
29 > import { Iterable } from '../../../base/common/iterator.js';
30 >
31 > type ProviderHandle = number;
32 > type GroupHandle = number;
33 > type ResourceStateHandle = number;
34 >
35 function isUri(thing: any): thing is vscode.Uri {
36 return thing instanceof URI;
37 }
39 function uriEquals(a: vscode.Uri, b: vscode.Uri): boolean {
40 if (a.scheme === Schemas.file && b.scheme === Schemas.file && isLinux) {
44 return a.toString().toLowerCase() === b.toString().toLowerCase();
45 }
47 function getIconResource(decorations?: vscode.SourceControlResourceThemableDecorations): UriComponents | ThemeIcon | undefined {
48 if (!decorations) {
58 }
59 }
61 > function getHistoryItemIconDto(icon: vscode.Uri | { light: vscode.Uri; dark: vscode.Uri } | vscode.ThemeIcon | undefined): UriComponents | { light: UriComponents; dark: UriComponents } | ThemeIcon | undefined {
62 > if (!icon) {
63 > return undefined;
64 > } else if (URI.isUri(icon)) {
65 return icon;
66 } else if (ThemeIcon.isThemeIcon(icon)) {
70 return { light: iconDto.light, dark: iconDto.dark };
71 }
72 > } extHostSCM.ts
73 >
74 function toSCMHistoryItemDto(historyItem: vscode.SourceControlHistoryItem): SCMHistoryItemDto {
75 const authorIcon = getHistoryItemIconDto(historyItem.authorIcon);
84 return { ...historyItem, authorIcon, references, tooltip };
85 }
87 function toSCMHistoryItemRefDto(historyItemRef?: vscode.SourceControlHistoryItemRef): SCMHistoryItemRefDto | undefined {
88 return historyItemRef ? { ...historyItemRef, icon: getHistoryItemIconDto(historyItemRef.icon) } : undefined;
89 }
91 function compareResourceThemableDecorations(a: vscode.SourceControlResourceThemableDecorations, b: vscode.SourceControlResourceThemableDecorations): number {
92 if (!a.iconPath && !b.iconPath) {
102 return comparePaths(aPath, bPath);
103 }
105 function compareResourceStatesDecorations(a: vscode.SourceControlResourceDecorations, b: vscode.SourceControlResourceDecorations): number {
106 let result = 0;
146 return result;
147 }
149 function compareCommands(a: vscode.Command, b: vscode.Command): number {
150 if (a.command !== b.command) {
193 return 0;
194 }
196 function compareResourceStates(a: vscode.SourceControlResourceState, b: vscode.SourceControlResourceState): number {
197 let result = comparePaths(a.resourceUri.fsPath, b.resourceUri.fsPath, true);
247 return result;
248 }
250 function compareArgs(a: any[], b: any[]): boolean {
251 for (let i = 0; i < a.length; i++) {
257 return true;
258 }
260 function commandEquals(a: vscode.Command, b: vscode.Command): boolean {
261 return a.command === b.command
264 && (a.arguments && b.arguments ? compareArgs(a.arguments, b.arguments) : a.arguments === b.arguments);
265 }
267 function commandListEquals(a: readonly vscode.Command[], b: readonly vscode.Command[]): boolean {
268 return equals(a, b, commandEquals);
269 }
271 > export interface IValidateInput {
272 > (value: string, cursorPosition: number): vscode.ProviderResult<vscode.SourceControlInputBoxValidation | undefined | null>;
273 > }
274 >
275 > export class ExtHostSCMInputBox implements vscode.SourceControlInputBox {
276 >
277 > #proxy: MainThreadSCMShape;
278 > #extHostDocuments: ExtHostDocuments;
279 >
280 > private _value: string = '';
281 >
282 > get value(): string {
283 return this._value;
284 }
286 > set value(value: string) {
287 value = value ?? '';
288 this.#proxy.$setInputBoxValue(this._sourceControlHandle, value);
289 this.updateValue(value);
290 }
292 > private readonly _onDidChange = new Emitter<string>();
293 >
294 > get onDidChange(): Event<string> {
295 return this._onDidChange.event;
296 }
298 > private _placeholder: string = '';
299 >
300 > get placeholder(): string {
301 return this._placeholder;
302 }
304 > set placeholder(placeholder: string) {
305 this.#proxy.$setInputBoxPlaceholder(this._sourceControlHandle, placeholder);
306 this._placeholder = placeholder;
307 }
309 > private _validateInput: IValidateInput | undefined;
310 >
311 > get validateInput(): IValidateInput | undefined {
312 checkProposedApiEnabled(this._extension, 'scmValidation');
313
314 return this._validateInput;
315 }
317 > set validateInput(fn: IValidateInput | undefined) {
318 checkProposedApiEnabled(this._extension, 'scmValidation');
319
325 this.#proxy.$setValidationProviderIsEnabled(this._sourceControlHandle, !!fn);
326 }
328 > private _enabled: boolean = true;
329 >
330 > get enabled(): boolean {
331 return this._enabled;
332 }
334 > set enabled(enabled: boolean) {
335 enabled = !!enabled;
336
342 this.#proxy.$setInputBoxEnablement(this._sourceControlHandle, enabled);
343 }
345 > private _visible: boolean = true;
346 >
347 > get visible(): boolean {
348 return this._visible;
349 }
351 > set visible(visible: boolean) {
352 visible = !!visible;
353
359 this.#proxy.$setInputBoxVisibility(this._sourceControlHandle, visible);
360 }
362 > get document(): vscode.TextDocument {
363 checkProposedApiEnabled(this._extension, 'scmTextDocument');
364
365 return this.#extHostDocuments.getDocument(this._documentUri);
366 }
368 > constructor(private _extension: IExtensionDescription, _extHostDocuments: ExtHostDocuments, proxy: MainThreadSCMShape, private _sourceControlHandle: number, private _documentUri: URI) {
369 > this.#extHostDocuments = _extHostDocuments;
370 > this.#proxy = proxy;
371 > }
372 >
373 > showValidationMessage(message: string | vscode.MarkdownString, type: vscode.SourceControlInputBoxValidationType) {
374 checkProposedApiEnabled(this._extension, 'scmValidation');
375 this.#proxy.$showValidationMessage(this._sourceControlHandle, message, SourceControlInputBoxValidationType.from(type));
376 }
378 > $onInputBoxValueChange(value: string): void {
379 this.updateValue(value);
380 }
382 > private updateValue(value: string): void {
383 this._value = value;
384 this._onDidChange.fire(value);
385 }
386 > } extHostSCM.ts
387 >
388 > class ExtHostSourceControlResourceGroup implements vscode.SourceControlResourceGroup {
389 >
390 > private static _handlePool: number = 0;
391 > private _resourceHandlePool: number = 0;
392 > private _resourceStates: vscode.SourceControlResourceState[] = [];
393 >
394 > private _resourceStatesMap = new Map<ResourceStateHandle, vscode.SourceControlResourceState>();
395 > private _resourceStatesCommandsMap = new Map<ResourceStateHandle, vscode.Command>();
396 > private _resourceStatesDisposablesMap = new Map<ResourceStateHandle, IDisposable>();
397 >
398 > private readonly _onDidUpdateResourceStates = new Emitter<void>();
399 > readonly onDidUpdateResourceStates = this._onDidUpdateResourceStates.event;
400 >
401 > private _disposed = false;
402 > get disposed(): boolean { return this._disposed; }
403 > private readonly _onDidDispose = new Emitter<void>();
404 > readonly onDidDispose = this._onDidDispose.event;
405 >
406 > private _handlesSnapshot: number[] = [];
407 > private _resourceSnapshot: vscode.SourceControlResourceState[] = [];
408 >
409 > get id(): string { return this._id; }
410 >
411 > get label(): string { return this._label; }
412 > set label(label: string) {
413 this._label = label;
414 this._proxy.$updateGroupLabel(this._sourceControlHandle, this.handle, label);
415 }
417 > private _contextValue: string | undefined = undefined;
418 > get contextValue(): string | undefined {
419 return this._contextValue;
420 }
421 > set contextValue(contextValue: string | undefined) { extHostSCM.ts
422 this._contextValue = contextValue;
423 this._proxy.$updateGroup(this._sourceControlHandle, this.handle, this.features);
424 }
426 > private _hideWhenEmpty: boolean | undefined = undefined;
427 > get hideWhenEmpty(): boolean | undefined { return this._hideWhenEmpty; }
428 > set hideWhenEmpty(hideWhenEmpty: boolean | undefined) {
429 this._hideWhenEmpty = hideWhenEmpty;
430 this._proxy.$updateGroup(this._sourceControlHandle, this.handle, this.features);
431 }
433 > get features(): SCMGroupFeatures {
434 return {
435 contextValue: this.contextValue,
437 };
438 }
440 > get resourceStates(): vscode.SourceControlResourceState[] { return [...this._resourceStates]; }
441 > set resourceStates(resources: vscode.SourceControlResourceState[]) {
442 this._resourceStates = [...resources];
443 this._onDidUpdateResourceStates.fire();
444 }
446 > readonly handle = ExtHostSourceControlResourceGroup._handlePool++;
447 >
448 > constructor(
449 private _proxy: MainThreadSCMShape,
450 private _commands: ExtHostCommands,
455 private readonly _extension: IExtensionDescription,
456 ) { }
458 > getResourceState(handle: number): vscode.SourceControlResourceState | undefined {
459 return this._resourceStatesMap.get(handle);
460 }
462 > $executeResourceCommand(handle: number, preserveFocus: boolean): Promise<void> {
463 const command = this._resourceStatesCommandsMap.get(handle);
464
469 return asPromise(() => this._commands.executeCommand(command.command, ...(command.arguments || []), preserveFocus));
470 }
472 > _takeResourceStateSnapshot(): SCMRawResourceSplice[] {
473 const snapshot = [...this._resourceStates].sort(compareResourceStates);
474 const diffs = sortedDiff(this._resourceSnapshot, snapshot, compareResourceStates);
534 return rawResourceSplices;
535 }
537 > dispose(): void {
538 this._disposed = true;
539 this._onDidDispose.fire();
541 this._onDidDispose.dispose();
542 }
543 > } extHostSCM.ts
544 >
545 > class ExtHostSourceControl implements vscode.SourceControl {
546 >
547 > private static _handlePool: number = 0;
548 >
549 > readonly onDidDisposeParent: Event<void>;
550 >
551 > private readonly _onDidDispose = new Emitter<void>();
552 > readonly onDidDispose = this._onDidDispose.event;
553 >
554 >
555 > #proxy: MainThreadSCMShape;
556 >
557 > private _groups: Map<GroupHandle, ExtHostSourceControlResourceGroup> = new Map<GroupHandle, ExtHostSourceControlResourceGroup>();
558 >
559 > get id(): string {
560 return this._id;
561 }
563 > get label(): string {
564 return this._label;
565 }
567 > get rootUri(): vscode.Uri | undefined {
568 return this._rootUri;
569 }
571 > private _contextValue: string | undefined = undefined;
572 >
573 > get contextValue(): string | undefined {
574 checkProposedApiEnabled(this._extension, 'scmProviderOptions');
575 return this._contextValue;
576 }
578 > set contextValue(contextValue: string | undefined) {
579 checkProposedApiEnabled(this._extension, 'scmProviderOptions');
580
586 this.#proxy.$updateSourceControl(this.handle, { contextValue });
587 }
589 > private _inputBox: ExtHostSCMInputBox;
590 > get inputBox(): ExtHostSCMInputBox { return this._inputBox; }
591 >
592 > private _count: number | undefined = undefined;
593 >
594 > get count(): number | undefined {
595 return this._count;
596 }
598 > set count(count: number | undefined) {
599 if (this._count === count) {
600 return;
604 this.#proxy.$updateSourceControl(this.handle, { count });
605 }
607 > private _quickDiffProvider: vscode.QuickDiffProvider | undefined = undefined;
608 >
609 > get quickDiffProvider(): vscode.QuickDiffProvider | undefined {
610 return this._quickDiffProvider;
611 }
613 > set quickDiffProvider(quickDiffProvider: vscode.QuickDiffProvider | undefined) {
614 this._quickDiffProvider = quickDiffProvider;
615 let quickDiffLabel = undefined;
619 this.#proxy.$updateSourceControl(this.handle, { hasQuickDiffProvider: !!quickDiffProvider, quickDiffLabel });
620 }
622 > private _secondaryQuickDiffProvider: vscode.QuickDiffProvider | undefined = undefined;
623 >
624 > get secondaryQuickDiffProvider(): vscode.QuickDiffProvider | undefined {
625 checkProposedApiEnabled(this._extension, 'quickDiffProvider');
626 return this._secondaryQuickDiffProvider;
627 }
629 > set secondaryQuickDiffProvider(secondaryQuickDiffProvider: vscode.QuickDiffProvider | undefined) {
630 checkProposedApiEnabled(this._extension, 'quickDiffProvider');
631
634 this.#proxy.$updateSourceControl(this.handle, { hasSecondaryQuickDiffProvider: !!secondaryQuickDiffProvider, secondaryQuickDiffLabel });
635 }
637 > private _historyProvider: vscode.SourceControlHistoryProvider | undefined;
638 > private readonly _historyProviderDisposable = new MutableDisposable<DisposableStore>();
639 >
640 > get historyProvider(): vscode.SourceControlHistoryProvider | undefined {
641 checkProposedApiEnabled(this._extension, 'scmHistoryProvider');
642 return this._historyProvider;
643 }
645 > set historyProvider(historyProvider: vscode.SourceControlHistoryProvider | undefined) {
646 checkProposedApiEnabled(this._extension, 'scmHistoryProvider');
647
672 }
673 }
675 > private _artifactProvider: vscode.SourceControlArtifactProvider | undefined;
676 > private readonly _artifactProviderDisposable = new MutableDisposable<DisposableStore>();
677 >
678 > get artifactProvider(): vscode.SourceControlArtifactProvider | undefined {
679 checkProposedApiEnabled(this._extension, 'scmArtifactProvider');
680 return this._artifactProvider;
681 }
683 > set artifactProvider(artifactProvider: vscode.SourceControlArtifactProvider | undefined) {
684 checkProposedApiEnabled(this._extension, 'scmArtifactProvider');
685
697 }
698 }
700 > private _commitTemplate: string | undefined = undefined;
701 >
702 > get commitTemplate(): string | undefined {
703 return this._commitTemplate;
704 }
706 > set commitTemplate(commitTemplate: string | undefined) {
707 if (commitTemplate === this._commitTemplate) {
708 return;
712 this.#proxy.$updateSourceControl(this.handle, { commitTemplate });
713 }
715 > private readonly _acceptInputDisposables = new MutableDisposable<DisposableStore>();
716 > private _acceptInputCommand: vscode.Command | undefined = undefined;
717 >
718 > get acceptInputCommand(): vscode.Command | undefined {
719 return this._acceptInputCommand;
720 }
722 > set acceptInputCommand(acceptInputCommand: vscode.Command | undefined) {
723 this._acceptInputDisposables.value = new DisposableStore();
724
728 this.#proxy.$updateSourceControl(this.handle, { acceptInputCommand: internal });
729 }
731 > // We know what we're doing here:
732 > // eslint-disable-next-line local/code-no-potentially-unsafe-disposables
733 > private _actionButtonDisposables = new DisposableStore();
734 > private _actionButton: vscode.SourceControlActionButton | undefined;
735 > get actionButton(): vscode.SourceControlActionButton | undefined {
736 checkProposedApiEnabled(this._extension, 'scmActionButton');
737 return this._actionButton;
738 }
740 > set actionButton(actionButton: vscode.SourceControlActionButton | undefined) {
741 checkProposedApiEnabled(this._extension, 'scmActionButton');
742
770 .finally(() => oldActionButtonDisposables.dispose());
771 }
773 > // We know what we're doing here:
774 > // eslint-disable-next-line local/code-no-potentially-unsafe-disposables
775 > private _statusBarDisposables = new DisposableStore();
776 > private _statusBarCommands: vscode.Command[] | undefined = undefined;
777 >
778 > get statusBarCommands(): vscode.Command[] | undefined {
779 return this._statusBarCommands;
780 }
782 > set statusBarCommands(statusBarCommands: vscode.Command[] | undefined) {
783 if (this._statusBarCommands && statusBarCommands && commandListEquals(this._statusBarCommands, statusBarCommands)) {
784 return;
797 .finally(() => oldStatusBarDisposables.dispose());
798 }
800 > private _selected: boolean = false;
801 >
802 > get selected(): boolean {
803 return this._selected;
804 }
806 > private readonly _onDidChangeSelection = new Emitter<boolean>();
807 > readonly onDidChangeSelection = this._onDidChangeSelection.event;
808 >
809 > private readonly _artifactCommandsDisposables = new DisposableMap<string /* artifact group */, DisposableStore>();
810 >
811 > readonly handle: number = ExtHostSourceControl._handlePool++;
812 >
813 > constructor(
814 > private readonly _extension: IExtensionDescription,
815 > _extHostDocuments: ExtHostDocuments,
816 > proxy: MainThreadSCMShape,
817 > private _commands: ExtHostCommands,
818 > private _id: string,
819 > private _label: string,
820 > private _rootUri?: vscode.Uri,
821 > _iconPath?: vscode.IconPath,
822 > _isHidden?: boolean,
823 > _parent?: ExtHostSourceControl
824 > ) {
825 > this.#proxy = proxy;
826 >
827 > const inputBoxDocumentUri = URI.from({
828 > scheme: Schemas.vscodeSourceControl,
829 > path: `${_id}/scm${this.handle}/input`,
830 > query: _rootUri ? `rootUri=${encodeURIComponent(_rootUri.toString())}` : undefined
831 > });
832 >
833 > this._inputBox = new ExtHostSCMInputBox(_extension, _extHostDocuments, this.#proxy, this.handle, inputBoxDocumentUri);
834 > this.#proxy.$registerSourceControl(this.handle, _parent?.handle, _id, _label, _rootUri, getHistoryItemIconDto(_iconPath), _isHidden, inputBoxDocumentUri);
835 >
836 > this.onDidDisposeParent = _parent ? _parent.onDidDispose : Event.None;
837 > }
838 >
839 > private createdResourceGroups = new Map<ExtHostSourceControlResourceGroup, IDisposable>();
840 > private updatedResourceGroups = new Set<ExtHostSourceControlResourceGroup>();
841 >
842 > createResourceGroup(id: string, label: string, options?: { multiDiffEditorEnableViewChanges?: boolean }): ExtHostSourceControlResourceGroup {
843 const multiDiffEditorEnableViewChanges = isProposedApiEnabled(this._extension, 'scmMultiDiffEditor') && options?.multiDiffEditorEnableViewChanges === true;
844 const group = new ExtHostSourceControlResourceGroup(this.#proxy, this._commands, this.handle, id, label, multiDiffEditorEnableViewChanges, this._extension);
848 return group;
849 }
851 > @debounce(100)
852 > eventuallyAddResourceGroups(): void {
853 const groups: [number /*handle*/, string /*id*/, string /*label*/, SCMGroupFeatures, /*multiDiffEditorEnableViewChanges*/ boolean][] = [];
854 const splices: SCMRawResourceSplices[] = [];
883 this.createdResourceGroups.clear();
884 }
886 > @debounce(100)
887 > eventuallyUpdateResourceStates(): void {
888 const splices: SCMRawResourceSplices[] = [];
889
904 this.updatedResourceGroups.clear();
905 }
907 > getResourceGroup(handle: GroupHandle): ExtHostSourceControlResourceGroup | undefined {
908 return this._groups.get(handle);
909 }
911 > setSelectionState(selected: boolean): void {
912 this._selected = selected;
913 this._onDidChangeSelection.fire(selected);
914 }
916 > async provideArtifacts(group: string, token: CancellationToken): Promise<SCMArtifactDto[] | undefined> {
917 const commandsDisposables = new DisposableStore();
918 const artifacts = await this.artifactProvider?.provideArtifacts(group, token);
928 return artifactsDto;
929 }
931 > dispose(): void {
932 > this._acceptInputDisposables.dispose();
933 > this._actionButtonDisposables.dispose();
934 > this._statusBarDisposables.dispose();
935 > this._historyProviderDisposable.dispose();
936 > this._artifactProviderDisposable.dispose();
937 > this._artifactCommandsDisposables.dispose();
938 >
939 > this._groups.forEach(group => group.dispose());
940 > this.#proxy.$unregisterSourceControl(this.handle);
941 >
942 > this._onDidChangeSelection.dispose();
943 > this._onDidDispose.fire();
944 > this._onDidDispose.dispose();
945 > }
946 > }
947 >
948 > export class ExtHostSCM implements ExtHostSCMShape {
949 >
950 > private _proxy: MainThreadSCMShape;
951 > private readonly _telemetry: MainThreadTelemetryShape;
952 > private _sourceControls: Map<ProviderHandle, ExtHostSourceControl> = new Map<ProviderHandle, ExtHostSourceControl>();
953 > private _sourceControlsByExtension: ExtensionIdentifierMap<ExtHostSourceControl[]> = new ExtensionIdentifierMap<ExtHostSourceControl[]>();
954 >
955 > private readonly _onDidChangeActiveProvider = new Emitter<vscode.SourceControl>();
956 > get onDidChangeActiveProvider(): Event<vscode.SourceControl> { return this._onDidChangeActiveProvider.event; }
957 >
958 > private _selectedSourceControlHandle: number | undefined;
959 >
960 > constructor(
961 > mainContext: IMainContext,
962 > private _commands: ExtHostCommands,
963 > private _extHostDocuments: ExtHostDocuments,
964 > @ILogService private readonly logService: ILogService
965 > ) {
966 > this._proxy = mainContext.getProxy(MainContext.MainThreadSCM);
967 > this._telemetry = mainContext.getProxy(MainContext.MainThreadTelemetry);
968 >
969 > _commands.registerArgumentProcessor({
970 > processArgument: arg => {
971 if (arg && arg.$mid === MarshalledId.ScmResource) {
972 const sourceControl = this._sourceControls.get(arg.sourceControlHandle);
1003 return arg;
1004 }
1005 > }); extHostSCM.ts
1006 > }
1007 >
1008 > createSourceControl(extension: IExtensionDescription, id: string, label: string, rootUri: vscode.Uri | undefined, iconPath: vscode.IconPath | undefined, isHidden: boolean | undefined, parent: vscode.SourceControl | undefined): vscode.SourceControl {
1009 > this.logService.trace('ExtHostSCM#createSourceControl', extension.identifier.value, id, label, rootUri);
1010 >
1011 > type TEvent = { extensionId: string };
1012 > type TMeta = {
1013 > owner: 'joaomoreno';
1014 > extensionId: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The ID of the extension contributing to the Source Control API.' };
1015 > comment: 'This is used to know what extensions contribute to the Source Control API.';
1016 > };
1017 > this._telemetry.$publicLog2<TEvent, TMeta>('api/scm/createSourceControl', {
1018 > extensionId: extension.identifier.value,
1019 > });
1020 >
1021 > const parentSourceControl = parent ? Iterable.find(this._sourceControls.values(), s => s === parent) : undefined;
1022 > const sourceControl = new ExtHostSourceControl(extension, this._extHostDocuments, this._proxy, this._commands, id, label, rootUri, iconPath, isHidden, parentSourceControl);
1023 > this._sourceControls.set(sourceControl.handle, sourceControl);
1024 >
1025 > const sourceControls = this._sourceControlsByExtension.get(extension.identifier) || [];
1026 > sourceControls.push(sourceControl);
1027 > this._sourceControlsByExtension.set(extension.identifier, sourceControls);
1028 >
1029 > Event.once(sourceControl.onDidDispose)(() => {
1030 > this.logService.trace('ExtHostSCM#disposeSourceControl', extension.identifier.value, id, label, rootUri);
1031 >
1032 > this._sourceControls.delete(sourceControl.handle);
1033 >
1034 > const sourceControls = this._sourceControlsByExtension.get(extension.identifier);
1035 > if (sourceControls) {
1036 > const index = sourceControls.indexOf(sourceControl);
1037 > if (index !== -1) {
1038 > sourceControls.splice(index, 1);
1039 > }
1040 >
1041 > if (sourceControls.length === 0) {
1042 > this._sourceControlsByExtension.delete(extension.identifier);
1043 > }
1044 > }
1045 > });
1046 >
1047 > return sourceControl;
1048 > }
1049 >
1050 > // Deprecated
1051 > getLastInputBox(extension: IExtensionDescription): ExtHostSCMInputBox | undefined {
1052 > this.logService.trace('ExtHostSCM#getLastInputBox', extension.identifier.value);
1053 >
1054 > const sourceControls = this._sourceControlsByExtension.get(extension.identifier);
1055 > const sourceControl = sourceControls && sourceControls[sourceControls.length - 1];
1056 > return sourceControl && sourceControl.inputBox;
1057 > }
1058 >
1059 > $provideOriginalResource(sourceControlHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<UriComponents | null> {
1060 const uri = URI.revive(uriComponents);
1061 this.logService.trace('ExtHostSCM#$provideOriginalResource', sourceControlHandle, uri.toString());
1070 .then<UriComponents | null>(r => r || null);
1071 }
1072 > extHostSCM.ts
1073 > $provideSecondaryOriginalResource(sourceControlHandle: number, uriComponents: UriComponents, token: CancellationToken): Promise<UriComponents | null> {
1074 const uri = URI.revive(uriComponents);
1075 this.logService.trace('ExtHostSCM#$provideSecondaryOriginalResource', sourceControlHandle, uri.toString());
1084 .then<UriComponents | null>(r => r || null);
1085 }
1086 > extHostSCM.ts
1087 > $onInputBoxValueChange(sourceControlHandle: number, value: string): Promise<void> {
1088 this.logService.trace('ExtHostSCM#$onInputBoxValueChange', sourceControlHandle);
1089
1097 return Promise.resolve(undefined);
1098 }
1099 > extHostSCM.ts
1100 > $executeResourceCommand(sourceControlHandle: number, groupHandle: number, handle: number, preserveFocus: boolean): Promise<void> {
1101 this.logService.trace('ExtHostSCM#$executeResourceCommand', sourceControlHandle, groupHandle, handle);
1102
1115 return group.$executeResourceCommand(handle, preserveFocus);
1116 }
1117 > extHostSCM.ts
1118 > $validateInput(sourceControlHandle: number, value: string, cursorPosition: number): Promise<[string | IMarkdownString, number] | undefined> {
1119 this.logService.trace('ExtHostSCM#$validateInput', sourceControlHandle);
1120
1142 });
1143 }
1144 > extHostSCM.ts
1145 > $setSelectedSourceControl(selectedSourceControlHandle: number | undefined): Promise<void> {
1146 this.logService.trace('ExtHostSCM#$setSelectedSourceControl', selectedSourceControlHandle);
1147 if (this._selectedSourceControlHandle === selectedSourceControlHandle) {
1160 return Promise.resolve(undefined);
1161 }
1162 > extHostSCM.ts
1163 > async $resolveHistoryItem(sourceControlHandle: number, historyItemId: string, token: CancellationToken): Promise<SCMHistoryItemDto | undefined> {
1164 try {
1165 const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
1173 }
1174 }
1175 > extHostSCM.ts
1176 > async $resolveHistoryItemChatContext(sourceControlHandle: number, historyItemId: string, token: CancellationToken): Promise<string | undefined> {
1177 try {
1178 const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
1186 }
1187 }
1188 > extHostSCM.ts
1189 > async $resolveHistoryItemChangeRangeChatContext(sourceControlHandle: number, historyItemId: string, historyItemParentId: string, path: string, token: CancellationToken): Promise<string | undefined> {
1190 try {
1191 const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
1199 }
1200 }
1201 > extHostSCM.ts
1202 > async $resolveHistoryItemRefsCommonAncestor(sourceControlHandle: number, historyItemRefs: string[], token: CancellationToken): Promise<string | undefined> {
1203 try {
1204 const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
1212 }
1213 }
1214 > extHostSCM.ts
1215 > async $provideHistoryItemRefs(sourceControlHandle: number, historyItemRefs: string[] | undefined, token: CancellationToken): Promise<SCMHistoryItemRefDto[] | undefined> {
1216 try {
1217 const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
1225 }
1226 }
1227 > extHostSCM.ts
1228 > async $provideHistoryItems(sourceControlHandle: number, options: vscode.SourceControlHistoryOptions, token: CancellationToken): Promise<SCMHistoryItemDto[] | undefined> {
1229 try {
1230 const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
1238 }
1239 }
1240 > extHostSCM.ts
1241 > async $provideHistoryItemChanges(sourceControlHandle: number, historyItemId: string, historyItemParentId: string | undefined, token: CancellationToken): Promise<SCMHistoryItemChangeDto[] | undefined> {
1242 try {
1243 const historyProvider = this._sourceControls.get(sourceControlHandle)?.historyProvider;
1251 }
1252 }
1253 > extHostSCM.ts
1254 > async $provideArtifactGroups(sourceControlHandle: number, token: CancellationToken): Promise<SCMArtifactGroupDto[] | undefined> {
1255 try {
1256 const artifactProvider = this._sourceControls.get(sourceControlHandle)?.artifactProvider;
1267 }
1268 }
1269 > extHostSCM.ts
1270 > async $provideArtifacts(sourceControlHandle: number, group: string, token: CancellationToken): Promise<SCMArtifactDto[] | undefined> {
1271 try {
1272 const sourceControl = this._sourceControls.get(sourceControlHandle);
src/vs/platform/extensions/common/extensions.ts 2 introduced LOC · 1 range

Open complete file

476
477 public delete(id: ExtensionIdentifier | string): void {
478 > this._map.delete(ExtensionIdentifier.toKey(id)); extensions.ts
479 > }
480
481 public get(id: ExtensionIdentifier | string): T | undefined {