src/vs/workbench/test/common/workbenchTestServices.ts

908 LOC · 667 covered · 241 uncovered · 135 ranges · 1601 concepts · 32 introducers · 859 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

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 related-file, concept, and source links on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- workbenchTestServices.ts ×76
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 { DeferredPromise, timeout } from '../../../base/common/async.js';
7 > import { bufferToStream, readableToBuffer, VSBuffer, VSBufferReadable } from '../../../base/common/buffer.js';
8 > import { CancellationToken } from '../../../base/common/cancellation.js';
9 > import { Emitter, Event } from '../../../base/common/event.js';
10 > import { Iterable } from '../../../base/common/iterator.js';
11 > import { Disposable, IDisposable, toDisposable } from '../../../base/common/lifecycle.js';
12 > import { ResourceMap, ResourceSet } from '../../../base/common/map.js';
13 > import { Schemas } from '../../../base/common/network.js';
14 > import { observableValue } from '../../../base/common/observable.js';
15 > import { join } from '../../../base/common/path.js';
16 > import { isLinux, isMacintosh } from '../../../base/common/platform.js';
17 > import { basename, isEqual, isEqualOrParent } from '../../../base/common/resources.js';
18 > import { URI } from '../../../base/common/uri.js';
19 > import { ITextResourcePropertiesService } from '../../../editor/common/services/textResourceConfiguration.js';
20 > import { IConfigurationService } from '../../../platform/configuration/common/configuration.js';
21 > import { IResourceEditorInput } from '../../../platform/editor/common/editor.js';
22 > import { FileChangesEvent, FileOperationEvent, FileSystemProviderCapabilities, IBaseFileStat, ICreateFileOptions, IFileContent, IFileService, IFileStat, IFileStatResult, IFileStatWithMetadata, IFileStatWithPartialMetadata, IFileStreamContent, IFileSystemProvider, IFileSystemProviderActivationEvent, IFileSystemProviderCapabilitiesChangeEvent, IFileSystemWatcher, IReadFileOptions, IReadFileStreamOptions, IResolveFileOptions, IResolveMetadataFileOptions, IWatchOptions, IWatchOptionsWithCorrelation, IWriteFileOptions } from '../../../platform/files/common/files.js';
23 > import { AbstractLoggerService, ILogger, LogLevel, NullLogger } from '../../../platform/log/common/log.js';
24 > import { IMarker, IMarkerData, IMarkerService, IResourceMarker, MarkerStatistics } from '../../../platform/markers/common/markers.js';
25 > import product from '../../../platform/product/common/product.js';
26 > import { IProgress, IProgressStep } from '../../../platform/progress/common/progress.js';
27 > import { InMemoryStorageService, WillSaveStateReason } from '../../../platform/storage/common/storage.js';
28 > import { toUserDataProfile } from '../../../platform/userDataProfile/common/userDataProfile.js';
29 > import { ISingleFolderWorkspaceIdentifier, IWorkspace, IWorkspaceContextService, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, IWorkspaceFoldersWillChangeEvent, IWorkspaceIdentifier, WorkbenchState, Workspace } from '../../../platform/workspace/common/workspace.js';
30 > import { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService, IWorkspaceTrustRequestService, IWorkspaceTrustTransitionParticipant, IWorkspaceTrustUriInfo, ResourceTrustRequestOptions, WorkspaceTrustRequestOptions, WorkspaceTrustUriResponse } from '../../../platform/workspace/common/workspaceTrust.js';
31 > import { TestWorkspace } from '../../../platform/workspace/test/common/testWorkspace.js';
32 > import { GroupIdentifier, IRevertOptions, ISaveOptions, SaveReason } from '../../common/editor.js';
33 > import { EditorInput } from '../../common/editor/editorInput.js';
34 > import { IActivity, IActivityService } from '../../services/activity/common/activity.js';
35 > import { ChatEntitlement, ChatEntitlementContext, IChatEntitlementService } from '../../services/chat/common/chatEntitlementService.js';
36 > import { Lazy } from '../../../base/common/lazy.js';
37 > import { NullExtensionService } from '../../services/extensions/common/extensions.js';
38 > import { IAutoSaveConfiguration, IAutoSaveMode, IFilesConfigurationService } from '../../services/filesConfiguration/common/filesConfigurationService.js';
39 > import { IHistoryService } from '../../services/history/common/history.js';
40 > import { BeforeShutdownErrorEvent, ILifecycleService, InternalBeforeShutdownEvent, LifecyclePhase, ShutdownReason, StartupKind, WillShutdownEvent } from '../../services/lifecycle/common/lifecycle.js';
41 > import { IResourceEncoding } from '../../services/textfile/common/textfiles.js';
42 > import { IUserDataProfileService } from '../../services/userDataProfile/common/userDataProfile.js';
43 > import { IStoredFileWorkingCopySaveEvent } from '../../services/workingCopy/common/storedFileWorkingCopy.js';
44 > import { IWorkingCopy, IWorkingCopyBackup, WorkingCopyCapabilities } from '../../services/workingCopy/common/workingCopy.js';
45 > import { ICopyOperation, ICreateFileOperation, ICreateOperation, IDeleteOperation, IFileOperationUndoRedoInfo, IMoveOperation, IStoredFileWorkingCopySaveParticipant, IStoredFileWorkingCopySaveParticipantContext, IWorkingCopyFileOperationParticipant, IWorkingCopyFileService, WorkingCopyFileEvent } from '../../services/workingCopy/common/workingCopyFileService.js';
46 >
47 > export class TestLoggerService extends AbstractLoggerService {
48 > constructor(logsHome?: URI) {
49 > super(LogLevel.Info, logsHome ?? URI.file('tests').with({ scheme: 'vscode-tests' })); mcpServerRequestHandler.ts ×42
50 > }
51 > protected doCreateLogger(): ILogger { return new NullLogger(); } workbenchTestServices.ts ×76
52 > }
53 >
54 > export class TestTextResourcePropertiesService implements ITextResourcePropertiesService {
55 >
56 > declare readonly _serviceBrand: undefined;
57 >
58 > constructor(
59 @IConfigurationService private readonly configurationService: IConfigurationService,
60 ) {
61 }
63 > getEOL(resource: URI, language?: string): string {
64 const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource });
65 if (eol && typeof eol === 'string' && eol !== 'auto') {
66 return eol;
67 }
68 return (isLinux || isMacintosh) ? '\n' : '\r\n';
69 }
71 >
72 > export class TestUserDataProfileService implements IUserDataProfileService {
74 > readonly _serviceBrand: undefined;
75 > readonly onDidChangeCurrentProfile = Event.None;
76 > readonly currentProfile = toUserDataProfile('test', 'test', URI.file('tests').with({ scheme: 'vscode-tests' }), URI.file('tests').with({ scheme: 'vscode-tests' }));
77 > async updateCurrentProfile(): Promise<void> { } workbenchTestServices.ts ×76
78 > }
79 >
80 > export class TestContextService implements IWorkspaceContextService {
81 >
82 > declare readonly _serviceBrand: undefined;
83 >
84 > private workspace: Workspace;
85 > private options: object;
86 >
87 > private readonly _onDidChangeWorkspaceName: Emitter<void>;
88 > get onDidChangeWorkspaceName(): Event<void> { return this._onDidChangeWorkspaceName.event; }
89 >
90 > private readonly _onWillChangeWorkspaceFolders: Emitter<IWorkspaceFoldersWillChangeEvent>;
91 > get onWillChangeWorkspaceFolders(): Event<IWorkspaceFoldersWillChangeEvent> { return this._onWillChangeWorkspaceFolders.event; }
92 >
93 > private readonly _onDidChangeWorkspaceFolders: Emitter<IWorkspaceFoldersChangeEvent>;
94 > get onDidChangeWorkspaceFolders(): Event<IWorkspaceFoldersChangeEvent> { return this._onDidChangeWorkspaceFolders.event; }
95 >
96 > private readonly _onDidChangeWorkbenchState: Emitter<WorkbenchState>;
97 > get onDidChangeWorkbenchState(): Event<WorkbenchState> { return this._onDidChangeWorkbenchState.event; }
98 >
99 > constructor(workspace = TestWorkspace, options = null) {
100 > this.workspace = workspace; workbenchTestServices.ts ×1
101 > this.options = options || Object.create(null);
102 > this._onDidChangeWorkspaceName = new Emitter<void>();
103 > this._onWillChangeWorkspaceFolders = new Emitter<IWorkspaceFoldersWillChangeEvent>();
104 > this._onDidChangeWorkspaceFolders = new Emitter<IWorkspaceFoldersChangeEvent>();
105 > this._onDidChangeWorkbenchState = new Emitter<WorkbenchState>();
106 > }
108 > getFolders(): IWorkspaceFolder[] {
109 return this.workspace ? this.workspace.folders : [];
110 }
112 > getWorkbenchState(): WorkbenchState {
113 > if (this.workspace.configuration) { workbenchTestServices.ts ×3
114 return WorkbenchState.WORKSPACE;
115 }
117 > if (this.workspace.folders.length) {
118 > return WorkbenchState.FOLDER; queryBuilder.ts ×2
119 > }
121 > return WorkbenchState.EMPTY;
124 > hasWorkspaceData(): boolean {
125 return this.getWorkbenchState() !== WorkbenchState.EMPTY;
126 }
128 > getCompleteWorkspace(): Promise<IWorkspace> {
129 return Promise.resolve(this.getWorkspace());
130 }
132 > getWorkspace(): IWorkspace {
133 > return this.workspace; workbenchTestServices.ts ×1
134 > }
136 > getWorkspaceFolder(resource: URI): IWorkspaceFolder | null {
137 > return this.workspace.getFolder(resource); workbenchTestServices.ts ×1
138 > }
140 > setWorkspace(workspace: any): void {
141 > this.workspace = workspace; workbenchTestServices.ts ×1
142 > }
144 > getOptions() {
145 return this.options;
146 }
148 > updateOptions() { }
149 >
150 > isInsideWorkspace(resource: URI): boolean {
151 if (resource && this.workspace) {
152 return isEqualOrParent(resource, this.workspace.folders[0].uri);
153 }
154
155 return false;
156 }
158 > toResource(workspaceRelativePath: string): URI {
159 return URI.file(join('C:\\', workspaceRelativePath));
160 }
162 > isCurrentWorkspace(workspaceIdOrFolder: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI): boolean {
163 return URI.isUri(workspaceIdOrFolder) && isEqual(this.workspace.folders[0].uri, workspaceIdOrFolder);
164 }
166 >
167 > export class TestStorageService extends InMemoryStorageService {
168 >
169 > testEmitWillSaveState(reason: WillSaveStateReason): void {
170 > super.emitWillSaveState(reason); chatServiceImpl.ts ×3
171 > }
173 >
174 > export class TestHistoryService implements IHistoryService {
175 >
176 > declare readonly _serviceBrand: undefined;
177 >
178 > constructor(private root?: URI) { }
179 >
180 > async reopenLastClosedEditor(): Promise<void> { }
181 > async goForward(): Promise<void> { }
182 > async goBack(): Promise<void> { }
183 > async goPrevious(): Promise<void> { }
184 > async goLast(): Promise<void> { }
185 > removeFromHistory(_input: EditorInput | IResourceEditorInput): void { }
186 > clear(): void { }
187 > clearRecentlyOpened(): void { }
188 > getHistory(): readonly (EditorInput | IResourceEditorInput)[] { return []; }
189 > async openNextRecentlyUsedEditor(group?: GroupIdentifier): Promise<void> { }
190 > async openPreviouslyUsedEditor(group?: GroupIdentifier): Promise<void> { }
191 > getLastActiveWorkspaceRoot(_schemeFilter: string): URI | undefined { return this.root; }
192 > getLastActiveFile(_schemeFilter: string): URI | undefined { return undefined; }
193 > }
194 >
195 > export class TestWorkingCopy extends Disposable implements IWorkingCopy {
196 >
197 > private readonly _onDidChangeDirty = this._register(new Emitter<void>());
198 > readonly onDidChangeDirty = this._onDidChangeDirty.event;
199 >
200 > private readonly _onDidChangeContent = this._register(new Emitter<void>());
201 > readonly onDidChangeContent = this._onDidChangeContent.event;
202 >
203 > private readonly _onDidSave = this._register(new Emitter<IStoredFileWorkingCopySaveEvent>());
204 > readonly onDidSave = this._onDidSave.event;
205 >
206 > readonly capabilities = WorkingCopyCapabilities.None;
207 >
208 > readonly name;
209 >
210 > private dirty = false;
211 >
212 > constructor(readonly resource: URI, isDirty = false, readonly typeId = 'testWorkingCopyType') {
214 >
215 > this.name = basename(this.resource);
216 > this.dirty = isDirty;
217 > }
219 > setDirty(dirty: boolean): void {
220 > if (this.dirty !== dirty) { workingCopyService.ts ×5
221 > this.dirty = dirty;
222 > this._onDidChangeDirty.fire();
223 > }
224 > }
226 > setContent(content: string): void {
227 > this._onDidChangeContent.fire(); workingCopyService.ts ×9
228 > }
230 > isDirty(): boolean {
231 > return this.dirty; workingCopyService.ts ×18
232 > }
234 > isModified(): boolean {
235 > return this.isDirty(); workingCopyService.ts ×9
236 > }
238 > async save(options?: ISaveOptions, stat?: IFileStatWithMetadata): Promise<boolean> {
239 > this._onDidSave.fire({ reason: options?.reason ?? SaveReason.EXPLICIT, stat: stat ?? createFileStat(this.resource), source: options?.source }); workingCopyService.ts ×9
240 >
241 > return true;
242 > }
244 > async revert(options?: IRevertOptions): Promise<void> {
245 this.setDirty(false);
246 }
248 > async backup(token: CancellationToken): Promise<IWorkingCopyBackup> {
249 return {};
250 }
252 >
253 > export function createFileStat(resource: URI, readonly = false, isFile?: boolean, isDirectory?: boolean, isSymbolicLink?: boolean, children?: { resource: URI; isFile?: boolean; isDirectory?: boolean; isSymbolicLink?: boolean; executable?: boolean }[] | undefined, executable?: boolean): IFileStatWithMetadata {
255 > resource,
256 > etag: Date.now().toString(),
257 > mtime: Date.now(),
258 > ctime: Date.now(),
259 > size: 42,
260 > isFile: isFile ?? true,
261 > isDirectory: isDirectory ?? false,
262 > isSymbolicLink: isSymbolicLink ?? false,
263 > readonly,
264 > locked: false,
265 > executable: executable ?? false,
266 > name: basename(resource),
267 > children: children?.map(c => createFileStat(c.resource, false, c.isFile, c.isDirectory, c.isSymbolicLink, undefined, c.executable)),
268 > };
269 > }
271 > export class TestWorkingCopyFileService implements IWorkingCopyFileService {
272
273 declare readonly _serviceBrand: undefined;
274
275 readonly onWillRunWorkingCopyFileOperation: Event<WorkingCopyFileEvent> = Event.None;
276 readonly onDidFailWorkingCopyFileOperation: Event<WorkingCopyFileEvent> = Event.None;
277 readonly onDidRunWorkingCopyFileOperation: Event<WorkingCopyFileEvent> = Event.None;
278
279 addFileOperationParticipant(participant: IWorkingCopyFileOperationParticipant): IDisposable { return Disposable.None; }
280
281 readonly hasSaveParticipants = false;
282 > addSaveParticipant(participant: IStoredFileWorkingCopySaveParticipant): IDisposable { return Disposable.None; } workbenchTestServices.ts ×76
283 > async runSaveParticipants(workingCopy: IWorkingCopy, context: IStoredFileWorkingCopySaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> { }
284 >
285 > async delete(operations: IDeleteOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<void> { }
286 >
287 > registerWorkingCopyProvider(provider: (resourceOrFolder: URI) => IWorkingCopy[]): IDisposable { return Disposable.None; }
288 >
289 > getDirty(resource: URI): IWorkingCopy[] { return []; }
290 >
291 > create(operations: ICreateFileOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }
292 > createFolder(operations: ICreateOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }
293 >
294 > move(operations: IMoveOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }
295 >
296 > copy(operations: ICopyOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }
297 > }
298 >
299 > export function mock<T>(): Ctor<T> {
300 > // eslint-disable-next-line local/code-no-any-casts workbenchTestServices.ts ×1
301 > return function () { } as any;
302 > }
304 > export interface Ctor<T> {
305 > new(): T;
306 > }
307 >
308 > export class TestExtensionService extends NullExtensionService { }
309 >
310 > export const TestProductService = { _serviceBrand: undefined, ...product };
311 >
312 > export class TestActivityService implements IActivityService {
313 _serviceBrand: undefined;
314 onDidChangeActivity = Event.None;
315 > getViewContainerActivities(viewContainerId: string): IActivity[] { workbenchTestServices.ts ×76
316 return [];
317 }
318 > getActivity(id: string): IActivity[] { workbenchTestServices.ts ×76
319 return [];
320 }
321 > showViewContainerActivity(viewContainerId: string, badge: IActivity): IDisposable { workbenchTestServices.ts ×76
322 return this;
323 }
324 > showViewActivity(viewId: string, badge: IActivity): IDisposable { workbenchTestServices.ts ×76
325 return this;
326 }
327 > showAccountsActivity(activity: IActivity): IDisposable { workbenchTestServices.ts ×76
328 return this;
329 }
330 > showGlobalActivity(activity: IActivity): IDisposable { workbenchTestServices.ts ×76
331 return this;
332 }
334 > dispose() { }
335 > }
336 >
337 > export const NullFilesConfigurationService = new class implements IFilesConfigurationService {
338 >
339 > _serviceBrand: undefined;
340 >
341 > readonly onDidChangeAutoSaveConfiguration = Event.None;
342 > readonly onDidChangeAutoSaveDisabled = Event.None;
343 > readonly onDidChangeReadonly = Event.None;
344 > readonly onDidChangeFilesAssociation = Event.None;
345 >
346 > readonly isHotExitEnabled = false;
347 > readonly hotExitConfiguration = undefined;
348 >
349 > getAutoSaveConfiguration(): IAutoSaveConfiguration { throw new Error('Method not implemented.'); }
350 > getAutoSaveMode(): IAutoSaveMode { throw new Error('Method not implemented.'); }
351 > hasShortAutoSaveDelay(): boolean { throw new Error('Method not implemented.'); }
352 > toggleAutoSave(): Promise<void> { throw new Error('Method not implemented.'); }
353 > enableAutoSaveAfterShortDelay(resourceOrEditor: URI | EditorInput): IDisposable { throw new Error('Method not implemented.'); }
354 > disableAutoSave(resourceOrEditor: URI | EditorInput): IDisposable { throw new Error('Method not implemented.'); }
355 > isReadonly(resource: URI, stat?: IBaseFileStat | undefined): boolean { return false; }
356 > async updateReadonly(_resource: URI | URI[], _readonly: boolean | 'toggle' | 'reset'): Promise<void> { }
357 > preventSaveConflicts(resource: URI, language?: string | undefined): boolean { throw new Error('Method not implemented.'); }
358 > };
359 >
360 > export class TestWorkspaceTrustEnablementService implements IWorkspaceTrustEnablementService {
361 > _serviceBrand: undefined;
362 >
363 > constructor(private isEnabled: boolean = true) { }
364 >
365 > isWorkspaceTrustEnabled(): boolean {
366 > return this.isEnabled; workbenchTestServices.ts ×1
367 > }
369 >
370 > export class TestWorkspaceTrustManagementService extends Disposable implements IWorkspaceTrustManagementService {
371 > _serviceBrand: undefined;
372 >
373 > private _onDidChangeTrust = this._register(new Emitter<boolean>());
374 > onDidChangeTrust = this._onDidChangeTrust.event;
375 >
376 > private _onDidChangeTrustedFolders = this._register(new Emitter<void>());
377 > onDidChangeTrustedFolders = this._onDidChangeTrustedFolders.event;
378 >
379 > private _onDidInitiateWorkspaceTrustRequestOnStartup = this._register(new Emitter<void>());
380 > onDidInitiateWorkspaceTrustRequestOnStartup = this._onDidInitiateWorkspaceTrustRequestOnStartup.event;
381 >
382 >
383 > constructor(
384 > private trusted: boolean = true, workbenchTestServices.ts ×2
385 > private trustedUris: ResourceSet = new ResourceSet()
386 > ) {
387 > super();
388 > }
390 > get acceptsOutOfWorkspaceFiles(): boolean {
391 throw new Error('Method not implemented.');
392 }
394 > set acceptsOutOfWorkspaceFiles(value: boolean) {
395 throw new Error('Method not implemented.');
396 }
398 > addWorkspaceTrustTransitionParticipant(participant: IWorkspaceTrustTransitionParticipant): IDisposable {
399 throw new Error('Method not implemented.');
400 }
402 > getTrustedUris(): URI[] {
403 throw new Error('Method not implemented.');
404 }
406 > setParentFolderTrust(trusted: boolean): Promise<void> {
407 throw new Error('Method not implemented.');
408 }
410 > getUriTrustInfo(uri: URI): Promise<IWorkspaceTrustUriInfo> {
411 > return Promise.resolve({ trusted: this.trustedUris.has(uri), uri }); workbenchTestServices.ts ×1
412 > }
414 > async setTrustedUris(folders: URI[]): Promise<void> {
415 > this.trustedUris = new ResourceSet(folders); workbenchTestServices.ts ×1
416 > }
418 > async setUrisTrust(uris: URI[], trusted: boolean): Promise<void> {
419 throw new Error('Method not implemented.');
420 }
422 > canSetParentFolderTrust(): boolean {
423 throw new Error('Method not implemented.');
424 }
426 > canSetWorkspaceTrust(): boolean {
427 throw new Error('Method not implemented.');
428 }
430 > isWorkspaceTrusted(): boolean {
431 > return this.trusted; workbenchTestServices.ts ×1
432 > }
434 > isWorkspaceTrustForced(): boolean {
435 return false;
436 }
438 > get workspaceTrustInitialized(): Promise<void> {
439 return Promise.resolve();
440 }
442 > get workspaceResolved(): Promise<void> {
443 return Promise.resolve();
444 }
446 > async setWorkspaceTrust(trusted: boolean): Promise<void> {
447 > if (this.trusted !== trusted) { promptsServiceImpl.ts ×1
448 > this.trusted = trusted;
449 > this._onDidChangeTrust.fire(this.trusted);
450 > }
451 > }
453 >
454 > export class TestWorkspaceTrustRequestService extends Disposable implements IWorkspaceTrustRequestService {
455 > _serviceBrand: any;
456 >
457 > private readonly _onDidInitiateOpenFilesTrustRequest = this._register(new Emitter<void>());
458 > readonly onDidInitiateOpenFilesTrustRequest = this._onDidInitiateOpenFilesTrustRequest.event;
459 >
460 > private readonly _onDidInitiateResourcesTrustRequest = this._register(new Emitter<ResourceTrustRequestOptions>());
461 > readonly onDidInitiateResourcesTrustRequest = this._onDidInitiateResourcesTrustRequest.event;
462 >
463 > private readonly _onDidInitiateWorkspaceTrustRequest = this._register(new Emitter<WorkspaceTrustRequestOptions>());
464 > readonly onDidInitiateWorkspaceTrustRequest = this._onDidInitiateWorkspaceTrustRequest.event;
465 >
466 > private readonly _onDidInitiateWorkspaceTrustRequestOnStartup = this._register(new Emitter<void>());
467 > readonly onDidInitiateWorkspaceTrustRequestOnStartup = this._onDidInitiateWorkspaceTrustRequestOnStartup.event;
468 >
469 > constructor(private readonly _trusted: boolean) {
470 super();
471 }
472
473 requestOpenUrisHandler = async (uris: URI[]) => {
474 return WorkspaceTrustUriResponse.Open;
475 };
477 > requestOpenFilesTrust(uris: URI[]): Promise<WorkspaceTrustUriResponse> {
478 return this.requestOpenUrisHandler(uris);
479 }
481 > async completeOpenFilesTrustRequest(result: WorkspaceTrustUriResponse, saveResponse: boolean): Promise<void> {
482 throw new Error('Method not implemented.');
483 }
485 > async completeResourcesTrustRequest(uri: URI, result: WorkspaceTrustUriResponse): Promise<void> {
486 throw new Error('Method not implemented.');
487 }
489 > async requestResourcesTrust(options: ResourceTrustRequestOptions): Promise<boolean | undefined> {
490 return this._trusted;
491 }
493 > cancelWorkspaceTrustRequest(): void {
494 throw new Error('Method not implemented.');
495 }
497 > async completeWorkspaceTrustRequest(trusted?: boolean): Promise<void> {
498 throw new Error('Method not implemented.');
499 }
501 > async requestWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<boolean> {
502 return this._trusted;
503 }
505 > requestWorkspaceTrustOnStartup(): void {
506 throw new Error('Method not implemented.');
507 }
509 >
510 > export class TestMarkerService implements IMarkerService {
511
512 _serviceBrand: undefined;
513
514 onMarkerChanged = Event.None;
516 > getStatistics(): MarkerStatistics { throw new Error('Method not implemented.'); }
517 > changeOne(owner: string, resource: URI, markers: IMarkerData[]): void { }
518 > changeAll(owner: string, data: IResourceMarker[]): void { }
519 > remove(owner: string, resources: URI[]): void { }
520 > read(filter?: { owner?: string | undefined; resource?: URI | undefined; severities?: number | undefined; take?: number | undefined } | undefined): IMarker[] { return []; }
521 > installResourceFilter(resource: URI, reason: string): IDisposable {
522 return { dispose: () => { /* TODO: Implement cleanup logic */ } };
523 }
525 >
526 > export class TestFileService implements IFileService {
528 > declare readonly _serviceBrand: undefined;
529 >
530 > private readonly _onDidFilesChange = new Emitter<FileChangesEvent>();
531 > get onDidFilesChange(): Event<FileChangesEvent> { return this._onDidFilesChange.event; }
532 > fireFileChanges(event: FileChangesEvent): void { this._onDidFilesChange.fire(event); }
533 >
534 > private readonly _onDidRunOperation = new Emitter<FileOperationEvent>();
535 > get onDidRunOperation(): Event<FileOperationEvent> { return this._onDidRunOperation.event; }
536 > fireAfterOperation(event: FileOperationEvent): void { this._onDidRunOperation.fire(event); }
537 >
538 > private readonly _onDidChangeFileSystemProviderCapabilities = new Emitter<IFileSystemProviderCapabilitiesChangeEvent>();
539 > get onDidChangeFileSystemProviderCapabilities(): Event<IFileSystemProviderCapabilitiesChangeEvent> { return this._onDidChangeFileSystemProviderCapabilities.event; }
540 > fireFileSystemProviderCapabilitiesChangeEvent(event: IFileSystemProviderCapabilitiesChangeEvent): void { this._onDidChangeFileSystemProviderCapabilities.fire(event); }
541 >
542 > private _onWillActivateFileSystemProvider = new Emitter<IFileSystemProviderActivationEvent>();
543 > readonly onWillActivateFileSystemProvider = this._onWillActivateFileSystemProvider.event;
544 > readonly onDidWatchError = Event.None;
545 >
546 > protected content = 'Hello Html';
547 > protected lastReadFileUri!: URI;
548 >
549 > readonly = false;
550 >
551 > // Tracking functionality for tests
552 > readonly writeOperations: Array<{ resource: URI; content: string }> = [];
553 > readonly readOperations: Array<{ resource: URI }> = [];
554 >
555 > setContent(content: string): void { this.content = content; }
556 > getContent(): string { return this.content; }
557 > getLastReadFileUri(): URI { return this.lastReadFileUri; }
558 >
559 > // Clear tracking data for tests
560 > clearTracking(): void {
561 this.writeOperations.length = 0;
562 this.readOperations.length = 0;
563 }
565 > resolve(resource: URI, _options: IResolveMetadataFileOptions): Promise<IFileStatWithMetadata>;
566 > resolve(resource: URI, _options?: IResolveFileOptions): Promise<IFileStat>;
567 > async resolve(resource: URI, _options?: IResolveFileOptions): Promise<IFileStat> {
568 > return createFileStat(resource, this.readonly); chatSessionStore.ts ×7
569 > }
571 > stat(resource: URI): Promise<IFileStatWithPartialMetadata> {
572 return this.resolve(resource, { resolveMetadata: true });
573 }
575 > async realpath(resource: URI): Promise<URI> {
576 return resource;
577 }
579 > async resolveAll(toResolve: { resource: URI; options?: IResolveFileOptions }[]): Promise<IFileStatResult[]> {
580 const stats = await Promise.all(toResolve.map(resourceAndOption => this.resolve(resourceAndOption.resource, resourceAndOption.options)));
581
582 return stats.map(stat => ({ stat, success: true }));
583 }
585 > readonly notExistsSet = new ResourceMap<boolean>();
586 >
587 > async exists(_resource: URI): Promise<boolean> { return !this.notExistsSet.has(_resource); }
588 >
589 > readShouldThrowError: Error | undefined = undefined;
590 >
591 > async readFile(resource: URI, options?: IReadFileOptions | undefined): Promise<IFileContent> {
592 if (this.readShouldThrowError) {
593 throw this.readShouldThrowError;
594 }
595
596 this.lastReadFileUri = resource;
597 this.readOperations.push({ resource });
598
599 return {
600 ...createFileStat(resource, this.readonly),
601 value: VSBuffer.fromString(this.content)
602 };
603 }
605 > async readFileStream(resource: URI, options?: IReadFileStreamOptions | undefined): Promise<IFileStreamContent> {
606 if (this.readShouldThrowError) {
607 throw this.readShouldThrowError;
608 }
609
610 this.lastReadFileUri = resource;
611
612 return {
613 ...createFileStat(resource, this.readonly),
614 value: bufferToStream(VSBuffer.fromString(this.content))
615 };
616 }
618 > writeShouldThrowError: Error | undefined = undefined;
619 >
620 > async writeFile(resource: URI, bufferOrReadable: VSBuffer | VSBufferReadable, options?: IWriteFileOptions): Promise<IFileStatWithMetadata> {
621 await timeout(0);
622
623 if (this.writeShouldThrowError) {
624 throw this.writeShouldThrowError;
625 }
626
627 let content: VSBuffer | undefined;
628 if (bufferOrReadable instanceof VSBuffer) {
629 content = bufferOrReadable;
630 } else {
631 try {
632 content = readableToBuffer(bufferOrReadable);
633 } catch {
634 // Some preexisting tests are writing with invalid objects
635 }
636 }
637
638 if (content) {
639 this.writeOperations.push({ resource, content: content.toString() });
640 }
641
642 return createFileStat(resource, this.readonly);
643 }
645 > move(_source: URI, _target: URI, _overwrite?: boolean): Promise<IFileStatWithMetadata> { return Promise.resolve(null!); }
646 > copy(_source: URI, _target: URI, _overwrite?: boolean): Promise<IFileStatWithMetadata> { return Promise.resolve(null!); }
647 > async cloneFile(_source: URI, _target: URI): Promise<void> { }
648 > createFile(_resource: URI, _content?: VSBuffer | VSBufferReadable, _options?: ICreateFileOptions): Promise<IFileStatWithMetadata> { return Promise.resolve(null!); }
649 > createFolder(_resource: URI): Promise<IFileStatWithMetadata> { return Promise.resolve(null!); }
650 >
651 > onDidChangeFileSystemProviderRegistrations = Event.None;
652 >
653 > private providers = new Map<string, IFileSystemProvider>();
654 >
655 > registerProvider(scheme: string, provider: IFileSystemProvider) {
656 this.providers.set(scheme, provider);
657
658 return toDisposable(() => this.providers.delete(scheme));
659 }
661 > getProvider(scheme: string) {
662 return this.providers.get(scheme);
663 }
665 > async activateProvider(_scheme: string): Promise<void> {
666 this._onWillActivateFileSystemProvider.fire({ scheme: _scheme, join: () => { } });
667 }
668 > async canHandleResource(resource: URI): Promise<boolean> { return this.hasProvider(resource); } workbenchTestServices.ts ×16
669 > hasProvider(resource: URI): boolean { return resource.scheme === Schemas.file || this.providers.has(resource.scheme); }
670 > listCapabilities() {
671 return [
672 { scheme: Schemas.file, capabilities: FileSystemProviderCapabilities.FileOpenReadWriteClose },
673 ...Iterable.map(this.providers, ([scheme, p]) => { return { scheme, capabilities: p.capabilities }; })
674 ];
675 }
676 > hasCapability(resource: URI, capability: FileSystemProviderCapabilities): boolean { workbenchTestServices.ts ×16
677 if (capability === FileSystemProviderCapabilities.PathCaseSensitive && isLinux) {
678 return true;
679 }
680
681 const provider = this.getProvider(resource.scheme);
682
683 return !!(provider && (provider.capabilities & capability));
684 }
686 > async del(_resource: URI, _options?: { useTrash?: boolean; recursive?: boolean }): Promise<void> { }
687 >
688 > createWatcher(resource: URI, options: IWatchOptions): IFileSystemWatcher {
689 return {
690 onDidChange: Event.None,
691 dispose: () => { }
692 };
693 }
695 >
696 > readonly watches: URI[] = [];
697 > watch(_resource: URI, options: IWatchOptionsWithCorrelation): IFileSystemWatcher; workbenchTestServices.ts ×76
698 > watch(_resource: URI): IDisposable;
699 > watch(_resource: URI): IDisposable {
700 this.watches.push(_resource);
701
702 return toDisposable(() => this.watches.splice(this.watches.indexOf(_resource), 1));
703 }
705 > getWriteEncoding(_resource: URI): IResourceEncoding { return { encoding: 'utf8', hasBOM: false }; }
706 > dispose(): void { }
707 >
708 > async canCreateFile(source: URI, options?: ICreateFileOptions): Promise<Error | true> { return true; }
709 > async canMove(source: URI, target: URI, overwrite?: boolean | undefined): Promise<Error | true> { return true; }
710 > async canCopy(source: URI, target: URI, overwrite?: boolean | undefined): Promise<Error | true> { return true; }
711 > async canDelete(resource: URI, options?: { useTrash?: boolean | undefined; recursive?: boolean | undefined } | undefined): Promise<Error | true> { return true; }
712 > }
713 >
714 > /**
715 > * TestFileService with in-memory file storage.
716 > * Use this when your test needs to write files and read them back.
717 > */
718 > export class InMemoryTestFileService extends TestFileService {
720 > private files = new ResourceMap<VSBuffer>();
722 > override clearTracking(): void {
723 super.clearTracking();
724 this.files.clear();
725 }
727 > override async readFile(resource: URI, options?: IReadFileOptions | undefined): Promise<IFileContent> {
728 > if (this.readShouldThrowError) { chatSessionStore.ts ×7
729 throw this.readShouldThrowError;
730 }
732 > this.lastReadFileUri = resource;
733 > this.readOperations.push({ resource });
734 >
735 > // Check if we have content in our in-memory store
736 > const content = this.files.get(resource);
737 > if (content) {
738 > return { chatSessionStore.ts ×2
739 > ...createFileStat(resource, this.readonly),
740 > value: content
741 > };
742 > }
744 > return {
745 > ...createFileStat(resource, this.readonly),
746 > value: VSBuffer.fromString(this.content)
747 > };
750 > override async writeFile(resource: URI, bufferOrReadable: VSBuffer | VSBufferReadable, options?: IWriteFileOptions): Promise<IFileStatWithMetadata> {
751 > await timeout(0); workbenchTestServices.ts ×3
752 >
753 > if (this.writeShouldThrowError) {
754 throw this.writeShouldThrowError;
755 }
757 > let content: VSBuffer;
758 > if (bufferOrReadable instanceof VSBuffer) {
759 > content = bufferOrReadable;
760 > } else {
761 content = readableToBuffer(bufferOrReadable);
762 }
764 > // Store in memory and track
765 > this.files.set(resource, content);
766 > this.writeOperations.push({ resource, content: content.toString() });
767 >
768 > return createFileStat(resource, this.readonly);
769 > }
771 > override async del(resource: URI, _options?: { useTrash?: boolean; recursive?: boolean }): Promise<void> {
772 > this.files.delete(resource); workbenchTestServices.ts ×1
773 > this.notExistsSet.set(resource, true);
774 > }
776 > override async exists(resource: URI): Promise<boolean> {
777 > const inMemory = this.files.has(resource); workbenchTestServices.ts ×2
778 > if (inMemory) {
779 > return true; chatSessionStore.ts ×2
780 > }
782 > return super.exists(resource);
783 > }
785 >
786 > export class TestChatEntitlementService implements IChatEntitlementService {
788 > _serviceBrand: undefined;
789 >
790 > context: Lazy<ChatEntitlementContext> | undefined;
791 >
792 > readonly organisations: undefined;
793 > readonly isInternal = false;
794 > readonly sku = undefined;
795 > readonly copilotTrackingId = undefined;
796 >
797 > readonly onDidChangeQuotaExceeded = Event.None;
798 > readonly onDidChangeQuotaRemaining = Event.None;
799 > readonly onDidChangeUsageBasedBilling = Event.None;
800 > readonly quotas = {};
801 >
802 > update(token: CancellationToken): Promise<void> {
803 > throw new Error('Method not implemented.');
804 > }
805 >
806 > readonly onDidChangeSentiment = Event.None;
807 > readonly sentimentObs = observableValue({}, {});
808 > readonly sentiment = {};
809 >
810 > readonly onDidChangeEntitlement = Event.None;
811 > entitlement: ChatEntitlement = ChatEntitlement.Unknown;
812 > readonly entitlementObs = observableValue({}, ChatEntitlement.Unknown);
813 >
814 > readonly anonymous = false;
815 > onDidChangeAnonymous = Event.None;
816 > readonly anonymousObs = observableValue({}, false);
817 >
818 > acceptQuotas(): void { }
819 > clearQuotas(): void { }
820 > markAnonymousRateLimited(): void { }
821 > markSetupCompleted(): void { }
822 > setForceHidden(_hidden: boolean): void { }
823 >
824 > readonly clientByokEnabled = false;
825 > readonly hasByokModels = false;
827 >
828 > export class TestLifecycleService extends Disposable implements ILifecycleService {
830 > declare readonly _serviceBrand: undefined;
831 >
832 > usePhases = false;
833 > _phase!: LifecyclePhase;
834 > get phase(): LifecyclePhase { return this._phase; }
835 > set phase(value: LifecyclePhase) {
836 this._phase = value;
837 if (value === LifecyclePhase.Starting) {
838 this.whenStarted.complete();
839 } else if (value === LifecyclePhase.Ready) {
840 this.whenReady.complete();
841 } else if (value === LifecyclePhase.Restored) {
842 this.whenRestored.complete();
843 } else if (value === LifecyclePhase.Eventually) {
844 this.whenEventually.complete();
845 }
846 }
848 > private readonly whenStarted = new DeferredPromise<void>();
849 > private readonly whenReady = new DeferredPromise<void>();
850 > private readonly whenRestored = new DeferredPromise<void>();
851 > private readonly whenEventually = new DeferredPromise<void>();
852 > async when(phase: LifecyclePhase): Promise<void> {
853 if (!this.usePhases) {
854 return;
855 }
856 if (phase === LifecyclePhase.Starting) {
857 await this.whenStarted.p;
858 } else if (phase === LifecyclePhase.Ready) {
859 await this.whenReady.p;
860 } else if (phase === LifecyclePhase.Restored) {
861 await this.whenRestored.p;
862 } else if (phase === LifecyclePhase.Eventually) {
863 await this.whenEventually.p;
864 }
865 }
867 > startupKind!: StartupKind;
868 > willShutdown = false;
869 >
870 > private readonly _onBeforeShutdown = this._register(new Emitter<InternalBeforeShutdownEvent>());
871 > get onBeforeShutdown(): Event<InternalBeforeShutdownEvent> { return this._onBeforeShutdown.event; }
872 >
873 > private readonly _onBeforeShutdownError = this._register(new Emitter<BeforeShutdownErrorEvent>());
874 > get onBeforeShutdownError(): Event<BeforeShutdownErrorEvent> { return this._onBeforeShutdownError.event; }
875 >
876 > private readonly _onShutdownVeto = this._register(new Emitter<void>());
877 > get onShutdownVeto(): Event<void> { return this._onShutdownVeto.event; }
878 >
879 > private readonly _onWillShutdown = this._register(new Emitter<WillShutdownEvent>());
880 > get onWillShutdown(): Event<WillShutdownEvent> { return this._onWillShutdown.event; }
881 >
882 > private readonly _onDidShutdown = this._register(new Emitter<void>());
883 > get onDidShutdown(): Event<void> { return this._onDidShutdown.event; }
884 >
885 > shutdownJoiners: Promise<void>[] = [];
887 > fireShutdown(reason = ShutdownReason.QUIT): void {
888 this.shutdownJoiners = [];
889
890 this._onWillShutdown.fire({
891 join: p => {
892 this.shutdownJoiners.push(typeof p === 'function' ? p() : p);
893 },
894 joiners: () => [],
895 force: () => { /* No-Op in tests */ },
896 token: CancellationToken.None,
897 reason
898 });
899 }
901 > fireBeforeShutdown(event: InternalBeforeShutdownEvent): void { this._onBeforeShutdown.fire(event); }
902 >
903 > fireWillShutdown(event: WillShutdownEvent): void { this._onWillShutdown.fire(event); }
904 >
905 > async shutdown(): Promise<void> {
906 this.fireShutdown();
907 }