Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/sessions/services/workspace/browser/workspaceContextService.ts
13401 views
1
/*---------------------------------------------------------------------------------------------
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 { Emitter, Event } from '../../../../base/common/event.js';
7
import { Queue } from '../../../../base/common/async.js';
8
import { removeTrailingPathSeparator } from '../../../../base/common/resources.js';
9
import { URI } from '../../../../base/common/uri.js';
10
import { IUriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentity.js';
11
import { Workspace, WorkspaceFolder, IWorkspace, IWorkspaceContextService, IWorkspaceFoldersChangeEvent, IWorkspaceFoldersWillChangeEvent, IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, IWorkspaceFolder, WorkbenchState } from '../../../../platform/workspace/common/workspace.js';
12
import { IWorkspaceFolderCreationData } from '../../../../platform/workspaces/common/workspaces.js';
13
import { getWorkspaceIdentifier } from '../../../../workbench/services/workspaces/browser/workspaces.js';
14
import { IWorkspaceEditingService } from '../../../../workbench/services/workspaces/common/workspaceEditing.js';
15
import { Disposable } from '../../../../base/common/lifecycle.js';
16
export class SessionsWorkspaceContextService extends Disposable implements IWorkspaceContextService, IWorkspaceEditingService {
17
18
declare readonly _serviceBrand: undefined;
19
20
readonly onDidChangeWorkbenchState = Event.None;
21
readonly onDidChangeWorkspaceName = Event.None;
22
readonly onDidEnterWorkspace = Event.None;
23
24
private readonly _onWillChangeWorkspaceFolders = new Emitter<IWorkspaceFoldersWillChangeEvent>();
25
readonly onWillChangeWorkspaceFolders = this._onWillChangeWorkspaceFolders.event;
26
27
private readonly _onDidChangeWorkspaceFolders = this._register(new Emitter<IWorkspaceFoldersChangeEvent>());
28
readonly onDidChangeWorkspaceFolders = this._onDidChangeWorkspaceFolders.event;
29
30
private workspace: Workspace;
31
private readonly _updateFoldersQueue = this._register(new Queue<void>());
32
33
constructor(
34
workspaceIdentifier: IWorkspaceIdentifier,
35
private readonly uriIdentityService: IUriIdentityService,
36
) {
37
super();
38
this.workspace = new Workspace(workspaceIdentifier.id, [], false, workspaceIdentifier.configPath, uri => uriIdentityService.extUri.ignorePathCasing(uri));
39
}
40
41
getCompleteWorkspace(): Promise<IWorkspace> {
42
return Promise.resolve(this.workspace);
43
}
44
45
getWorkspace(): IWorkspace {
46
return this.workspace;
47
}
48
49
getWorkbenchState(): WorkbenchState {
50
return WorkbenchState.WORKSPACE;
51
}
52
53
hasWorkspaceData(): boolean {
54
return true;
55
}
56
57
getWorkspaceFolder(resource: URI): IWorkspaceFolder | null {
58
return this.workspace.getFolder(resource);
59
}
60
61
public isInsideWorkspace(resource: URI): boolean {
62
return !!this.getWorkspaceFolder(resource);
63
}
64
65
public isCurrentWorkspace(workspaceIdOrFolder: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI): boolean {
66
return false;
67
}
68
69
public addFolders(foldersToAdd: IWorkspaceFolderCreationData[]): Promise<void> {
70
return this.doUpdateFolders(foldersToAdd, []);
71
}
72
73
public removeFolders(foldersToRemove: URI[]): Promise<void> {
74
return this.doUpdateFolders([], foldersToRemove);
75
}
76
77
public async updateFolders(index: number, deleteCount?: number, foldersToAddCandidates?: IWorkspaceFolderCreationData[]): Promise<void> {
78
const folders = this.workspace.folders;
79
80
let foldersToDelete: URI[] = [];
81
if (typeof deleteCount === 'number') {
82
foldersToDelete = folders.slice(index, index + deleteCount).map(folder => folder.uri);
83
}
84
85
let foldersToAdd: IWorkspaceFolderCreationData[] = [];
86
if (Array.isArray(foldersToAddCandidates)) {
87
foldersToAdd = foldersToAddCandidates.map(folderToAdd => ({ uri: removeTrailingPathSeparator(folderToAdd.uri), name: folderToAdd.name }));
88
}
89
90
return this.doUpdateFolders(foldersToAdd, foldersToDelete, index);
91
}
92
93
async enterWorkspace(_path: URI): Promise<void> { }
94
95
async createAndEnterWorkspace(_folders: IWorkspaceFolderCreationData[], _path?: URI): Promise<void> { }
96
97
async saveAndEnterWorkspace(_path: URI): Promise<void> { }
98
99
async copyWorkspaceSettings(_toWorkspace: IWorkspaceIdentifier): Promise<void> { }
100
101
async pickNewWorkspacePath(): Promise<URI | undefined> { return undefined; }
102
103
private doUpdateFolders(foldersToAdd: IWorkspaceFolderCreationData[], foldersToRemove: URI[], index?: number): Promise<void> {
104
return this._updateFoldersQueue.queue(() => this._doUpdateFolders(foldersToAdd, foldersToRemove, index));
105
}
106
107
private async _doUpdateFolders(foldersToAdd: IWorkspaceFolderCreationData[], foldersToRemove: URI[], index?: number): Promise<void> {
108
if (foldersToAdd.length === 0 && foldersToRemove.length === 0) {
109
return;
110
}
111
112
const currentFolders = this.workspace.folders;
113
114
// Remove folders
115
let newFolders = currentFolders.filter(folder =>
116
!foldersToRemove.some(toRemove => this.uriIdentityService.extUri.isEqual(folder.uri, toRemove))
117
);
118
119
// Add folders
120
const foldersToAddWorkspaceFolders = foldersToAdd
121
.filter(folderToAdd => !newFolders.some(existing => this.uriIdentityService.extUri.isEqual(existing.uri, folderToAdd.uri)))
122
.map(folderToAdd => new WorkspaceFolder(
123
{ uri: folderToAdd.uri, name: folderToAdd.name || this.uriIdentityService.extUri.basenameOrAuthority(folderToAdd.uri), index: 0 },
124
{ uri: folderToAdd.uri.toString() }
125
));
126
127
if (foldersToAddWorkspaceFolders.length > 0) {
128
if (typeof index === 'number' && index >= 0 && index < newFolders.length) {
129
newFolders = [...newFolders.slice(0, index), ...foldersToAddWorkspaceFolders, ...newFolders.slice(index)];
130
} else {
131
newFolders = [...newFolders, ...foldersToAddWorkspaceFolders];
132
}
133
}
134
135
// Recompute indices
136
newFolders = newFolders.map((f, i) => new WorkspaceFolder({ uri: f.uri, name: f.name, index: i }, f.raw));
137
138
// Compute change event
139
const added = newFolders.filter(folder => !currentFolders.some(existing => this.uriIdentityService.extUri.isEqual(existing.uri, folder.uri)));
140
const removed = currentFolders.filter(folder => !newFolders.some(existing => this.uriIdentityService.extUri.isEqual(existing.uri, folder.uri)));
141
const changed: IWorkspaceFolder[] = [];
142
const changes: IWorkspaceFoldersChangeEvent = { added, removed, changed };
143
144
if (added.length === 0 && removed.length === 0) {
145
return;
146
}
147
148
// Fire will change event
149
const joinPromises: Promise<void>[] = [];
150
this._onWillChangeWorkspaceFolders.fire({
151
changes,
152
fromCache: false,
153
join(promise: Promise<void>) { joinPromises.push(promise); }
154
});
155
await Promise.allSettled(joinPromises);
156
157
// Update workspace
158
const workspaceIdentifier = getWorkspaceIdentifier(this.workspace.configuration!);
159
const workspace = new Workspace(workspaceIdentifier.id, newFolders, false, workspaceIdentifier.configPath, uri => this.uriIdentityService.extUri.ignorePathCasing(uri));
160
this.workspace.update(workspace);
161
162
// Fire did change event
163
this._onDidChangeWorkspaceFolders.fire(changes);
164
}
165
}
166
167