Path: blob/main/src/vs/sessions/services/workspace/browser/workspaceContextService.ts
13401 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { Emitter, Event } from '../../../../base/common/event.js';6import { Queue } from '../../../../base/common/async.js';7import { removeTrailingPathSeparator } from '../../../../base/common/resources.js';8import { URI } from '../../../../base/common/uri.js';9import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';10import { Workspace, WorkspaceFolder, IWorkspace, IWorkspaceContextService, IWorkspaceFoldersChangeEvent, IWorkspaceFoldersWillChangeEvent, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceFolder, WorkbenchState } from '../../../../platform/workspace/common/workspace.js';11import { IWorkspaceFolderCreationData } from '../../../../platform/workspaces/common/workspaces.js';12import { getWorkspaceIdentifier } from '../../../../workbench/services/workspaces/browser/workspaces.js';13import { IWorkspaceEditingService } from '../../../../workbench/services/workspaces/common/workspaceEditing.js';14import { Disposable } from '../../../../base/common/lifecycle.js';15export class SessionsWorkspaceContextService extends Disposable implements IWorkspaceContextService, IWorkspaceEditingService {1617declare readonly _serviceBrand: undefined;1819readonly onDidChangeWorkbenchState = Event.None;20readonly onDidChangeWorkspaceName = Event.None;21readonly onDidEnterWorkspace = Event.None;2223private readonly _onWillChangeWorkspaceFolders = new Emitter<IWorkspaceFoldersWillChangeEvent>();24readonly onWillChangeWorkspaceFolders = this._onWillChangeWorkspaceFolders.event;2526private readonly _onDidChangeWorkspaceFolders = this._register(new Emitter<IWorkspaceFoldersChangeEvent>());27readonly onDidChangeWorkspaceFolders = this._onDidChangeWorkspaceFolders.event;2829private workspace: Workspace;30private readonly _updateFoldersQueue = this._register(new Queue<void>());3132constructor(33workspaceIdentifier: IWorkspaceIdentifier,34private readonly uriIdentityService: IUriIdentityService,35) {36super();37this.workspace = new Workspace(workspaceIdentifier.id, [], false, workspaceIdentifier.configPath, uri => uriIdentityService.extUri.ignorePathCasing(uri));38}3940getCompleteWorkspace(): Promise<IWorkspace> {41return Promise.resolve(this.workspace);42}4344getWorkspace(): IWorkspace {45return this.workspace;46}4748getWorkbenchState(): WorkbenchState {49return WorkbenchState.WORKSPACE;50}5152hasWorkspaceData(): boolean {53return true;54}5556getWorkspaceFolder(resource: URI): IWorkspaceFolder | null {57return this.workspace.getFolder(resource);58}5960public isInsideWorkspace(resource: URI): boolean {61return !!this.getWorkspaceFolder(resource);62}6364public isCurrentWorkspace(workspaceIdOrFolder: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI): boolean {65return false;66}6768public addFolders(foldersToAdd: IWorkspaceFolderCreationData[]): Promise<void> {69return this.doUpdateFolders(foldersToAdd, []);70}7172public removeFolders(foldersToRemove: URI[]): Promise<void> {73return this.doUpdateFolders([], foldersToRemove);74}7576public async updateFolders(index: number, deleteCount?: number, foldersToAddCandidates?: IWorkspaceFolderCreationData[]): Promise<void> {77const folders = this.workspace.folders;7879let foldersToDelete: URI[] = [];80if (typeof deleteCount === 'number') {81foldersToDelete = folders.slice(index, index + deleteCount).map(folder => folder.uri);82}8384let foldersToAdd: IWorkspaceFolderCreationData[] = [];85if (Array.isArray(foldersToAddCandidates)) {86foldersToAdd = foldersToAddCandidates.map(folderToAdd => ({ uri: removeTrailingPathSeparator(folderToAdd.uri), name: folderToAdd.name }));87}8889return this.doUpdateFolders(foldersToAdd, foldersToDelete, index);90}9192async enterWorkspace(_path: URI): Promise<void> { }9394async createAndEnterWorkspace(_folders: IWorkspaceFolderCreationData[], _path?: URI): Promise<void> { }9596async saveAndEnterWorkspace(_path: URI): Promise<void> { }9798async copyWorkspaceSettings(_toWorkspace: IWorkspaceIdentifier): Promise<void> { }99100async pickNewWorkspacePath(): Promise<URI | undefined> { return undefined; }101102private doUpdateFolders(foldersToAdd: IWorkspaceFolderCreationData[], foldersToRemove: URI[], index?: number): Promise<void> {103return this._updateFoldersQueue.queue(() => this._doUpdateFolders(foldersToAdd, foldersToRemove, index));104}105106private async _doUpdateFolders(foldersToAdd: IWorkspaceFolderCreationData[], foldersToRemove: URI[], index?: number): Promise<void> {107if (foldersToAdd.length === 0 && foldersToRemove.length === 0) {108return;109}110111const currentFolders = this.workspace.folders;112113// Remove folders114let newFolders = currentFolders.filter(folder =>115!foldersToRemove.some(toRemove => this.uriIdentityService.extUri.isEqual(folder.uri, toRemove))116);117118// Add folders119const foldersToAddWorkspaceFolders = foldersToAdd120.filter(folderToAdd => !newFolders.some(existing => this.uriIdentityService.extUri.isEqual(existing.uri, folderToAdd.uri)))121.map(folderToAdd => new WorkspaceFolder(122{ uri: folderToAdd.uri, name: folderToAdd.name || this.uriIdentityService.extUri.basenameOrAuthority(folderToAdd.uri), index: 0 },123{ uri: folderToAdd.uri.toString() }124));125126if (foldersToAddWorkspaceFolders.length > 0) {127if (typeof index === 'number' && index >= 0 && index < newFolders.length) {128newFolders = [...newFolders.slice(0, index), ...foldersToAddWorkspaceFolders, ...newFolders.slice(index)];129} else {130newFolders = [...newFolders, ...foldersToAddWorkspaceFolders];131}132}133134// Recompute indices135newFolders = newFolders.map((f, i) => new WorkspaceFolder({ uri: f.uri, name: f.name, index: i }, f.raw));136137// Compute change event138const added = newFolders.filter(folder => !currentFolders.some(existing => this.uriIdentityService.extUri.isEqual(existing.uri, folder.uri)));139const removed = currentFolders.filter(folder => !newFolders.some(existing => this.uriIdentityService.extUri.isEqual(existing.uri, folder.uri)));140const changed: IWorkspaceFolder[] = [];141const changes: IWorkspaceFoldersChangeEvent = { added, removed, changed };142143if (added.length === 0 && removed.length === 0) {144return;145}146147// Fire will change event148const joinPromises: Promise<void>[] = [];149this._onWillChangeWorkspaceFolders.fire({150changes,151fromCache: false,152join(promise: Promise<void>) { joinPromises.push(promise); }153});154await Promise.allSettled(joinPromises);155156// Update workspace157const workspaceIdentifier = getWorkspaceIdentifier(this.workspace.configuration!);158const workspace = new Workspace(workspaceIdentifier.id, newFolders, false, workspaceIdentifier.configPath, uri => this.uriIdentityService.extUri.ignorePathCasing(uri));159this.workspace.update(workspace);160161// Fire did change event162this._onDidChangeWorkspaceFolders.fire(changes);163}164}165166167