Path: blob/main/src/vs/workbench/test/common/workbenchTestServices.ts
3296 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 { join } from '../../../base/common/path.js';6import { basename, isEqual, isEqualOrParent } from '../../../base/common/resources.js';7import { URI } from '../../../base/common/uri.js';8import { Event, Emitter } from '../../../base/common/event.js';9import { IConfigurationService } from '../../../platform/configuration/common/configuration.js';10import { IWorkspaceContextService, IWorkspace, WorkbenchState, IWorkspaceFolder, IWorkspaceFoldersChangeEvent, Workspace, IWorkspaceFoldersWillChangeEvent, ISingleFolderWorkspaceIdentifier, IWorkspaceIdentifier } from '../../../platform/workspace/common/workspace.js';11import { TestWorkspace } from '../../../platform/workspace/test/common/testWorkspace.js';12import { ITextResourcePropertiesService } from '../../../editor/common/services/textResourceConfiguration.js';13import { isLinux, isMacintosh } from '../../../base/common/platform.js';14import { InMemoryStorageService, WillSaveStateReason } from '../../../platform/storage/common/storage.js';15import { IWorkingCopy, IWorkingCopyBackup, WorkingCopyCapabilities } from '../../services/workingCopy/common/workingCopy.js';16import { NullExtensionService } from '../../services/extensions/common/extensions.js';17import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent, IDeleteOperation, ICopyOperation, IMoveOperation, IFileOperationUndoRedoInfo, ICreateFileOperation, ICreateOperation, IStoredFileWorkingCopySaveParticipant, IStoredFileWorkingCopySaveParticipantContext } from '../../services/workingCopy/common/workingCopyFileService.js';18import { IDisposable, Disposable } from '../../../base/common/lifecycle.js';19import { IBaseFileStat, IFileStatWithMetadata } from '../../../platform/files/common/files.js';20import { ISaveOptions, IRevertOptions, SaveReason, GroupIdentifier } from '../../common/editor.js';21import { CancellationToken } from '../../../base/common/cancellation.js';22import product from '../../../platform/product/common/product.js';23import { IActivity, IActivityService } from '../../services/activity/common/activity.js';24import { IStoredFileWorkingCopySaveEvent } from '../../services/workingCopy/common/storedFileWorkingCopy.js';25import { AbstractLoggerService, ILogger, LogLevel, NullLogger } from '../../../platform/log/common/log.js';26import { IResourceEditorInput } from '../../../platform/editor/common/editor.js';27import { EditorInput } from '../../common/editor/editorInput.js';28import { IHistoryService } from '../../services/history/common/history.js';29import { IAutoSaveConfiguration, IAutoSaveMode, IFilesConfigurationService } from '../../services/filesConfiguration/common/filesConfigurationService.js';30import { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService, IWorkspaceTrustRequestService, IWorkspaceTrustTransitionParticipant, IWorkspaceTrustUriInfo, WorkspaceTrustRequestOptions, WorkspaceTrustUriResponse } from '../../../platform/workspace/common/workspaceTrust.js';31import { IMarker, IMarkerData, IMarkerService, IResourceMarker, MarkerStatistics } from '../../../platform/markers/common/markers.js';32import { IProgress, IProgressStep } from '../../../platform/progress/common/progress.js';33import { IUserDataProfileService } from '../../services/userDataProfile/common/userDataProfile.js';34import { toUserDataProfile } from '../../../platform/userDataProfile/common/userDataProfile.js';3536export class TestLoggerService extends AbstractLoggerService {37constructor(logsHome?: URI) {38super(LogLevel.Info, logsHome ?? URI.file('tests').with({ scheme: 'vscode-tests' }));39}40protected doCreateLogger(): ILogger { return new NullLogger(); }41}4243export class TestTextResourcePropertiesService implements ITextResourcePropertiesService {4445declare readonly _serviceBrand: undefined;4647constructor(48@IConfigurationService private readonly configurationService: IConfigurationService,49) {50}5152getEOL(resource: URI, language?: string): string {53const eol = this.configurationService.getValue('files.eol', { overrideIdentifier: language, resource });54if (eol && typeof eol === 'string' && eol !== 'auto') {55return eol;56}57return (isLinux || isMacintosh) ? '\n' : '\r\n';58}59}6061export class TestUserDataProfileService implements IUserDataProfileService {6263readonly _serviceBrand: undefined;64readonly onDidChangeCurrentProfile = Event.None;65readonly currentProfile = toUserDataProfile('test', 'test', URI.file('tests').with({ scheme: 'vscode-tests' }), URI.file('tests').with({ scheme: 'vscode-tests' }));66async updateCurrentProfile(): Promise<void> { }67}6869export class TestContextService implements IWorkspaceContextService {7071declare readonly _serviceBrand: undefined;7273private workspace: Workspace;74private options: object;7576private readonly _onDidChangeWorkspaceName: Emitter<void>;77get onDidChangeWorkspaceName(): Event<void> { return this._onDidChangeWorkspaceName.event; }7879private readonly _onWillChangeWorkspaceFolders: Emitter<IWorkspaceFoldersWillChangeEvent>;80get onWillChangeWorkspaceFolders(): Event<IWorkspaceFoldersWillChangeEvent> { return this._onWillChangeWorkspaceFolders.event; }8182private readonly _onDidChangeWorkspaceFolders: Emitter<IWorkspaceFoldersChangeEvent>;83get onDidChangeWorkspaceFolders(): Event<IWorkspaceFoldersChangeEvent> { return this._onDidChangeWorkspaceFolders.event; }8485private readonly _onDidChangeWorkbenchState: Emitter<WorkbenchState>;86get onDidChangeWorkbenchState(): Event<WorkbenchState> { return this._onDidChangeWorkbenchState.event; }8788constructor(workspace = TestWorkspace, options = null) {89this.workspace = workspace;90this.options = options || Object.create(null);91this._onDidChangeWorkspaceName = new Emitter<void>();92this._onWillChangeWorkspaceFolders = new Emitter<IWorkspaceFoldersWillChangeEvent>();93this._onDidChangeWorkspaceFolders = new Emitter<IWorkspaceFoldersChangeEvent>();94this._onDidChangeWorkbenchState = new Emitter<WorkbenchState>();95}9697getFolders(): IWorkspaceFolder[] {98return this.workspace ? this.workspace.folders : [];99}100101getWorkbenchState(): WorkbenchState {102if (this.workspace.configuration) {103return WorkbenchState.WORKSPACE;104}105106if (this.workspace.folders.length) {107return WorkbenchState.FOLDER;108}109110return WorkbenchState.EMPTY;111}112113getCompleteWorkspace(): Promise<IWorkspace> {114return Promise.resolve(this.getWorkspace());115}116117getWorkspace(): IWorkspace {118return this.workspace;119}120121getWorkspaceFolder(resource: URI): IWorkspaceFolder | null {122return this.workspace.getFolder(resource);123}124125setWorkspace(workspace: any): void {126this.workspace = workspace;127}128129getOptions() {130return this.options;131}132133updateOptions() { }134135isInsideWorkspace(resource: URI): boolean {136if (resource && this.workspace) {137return isEqualOrParent(resource, this.workspace.folders[0].uri);138}139140return false;141}142143toResource(workspaceRelativePath: string): URI {144return URI.file(join('C:\\', workspaceRelativePath));145}146147isCurrentWorkspace(workspaceIdOrFolder: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | URI): boolean {148return URI.isUri(workspaceIdOrFolder) && isEqual(this.workspace.folders[0].uri, workspaceIdOrFolder);149}150}151152export class TestStorageService extends InMemoryStorageService {153154testEmitWillSaveState(reason: WillSaveStateReason): void {155super.emitWillSaveState(reason);156}157}158159export class TestHistoryService implements IHistoryService {160161declare readonly _serviceBrand: undefined;162163constructor(private root?: URI) { }164165async reopenLastClosedEditor(): Promise<void> { }166async goForward(): Promise<void> { }167async goBack(): Promise<void> { }168async goPrevious(): Promise<void> { }169async goLast(): Promise<void> { }170removeFromHistory(_input: EditorInput | IResourceEditorInput): void { }171clear(): void { }172clearRecentlyOpened(): void { }173getHistory(): readonly (EditorInput | IResourceEditorInput)[] { return []; }174async openNextRecentlyUsedEditor(group?: GroupIdentifier): Promise<void> { }175async openPreviouslyUsedEditor(group?: GroupIdentifier): Promise<void> { }176getLastActiveWorkspaceRoot(_schemeFilter: string): URI | undefined { return this.root; }177getLastActiveFile(_schemeFilter: string): URI | undefined { return undefined; }178}179180export class TestWorkingCopy extends Disposable implements IWorkingCopy {181182private readonly _onDidChangeDirty = this._register(new Emitter<void>());183readonly onDidChangeDirty = this._onDidChangeDirty.event;184185private readonly _onDidChangeContent = this._register(new Emitter<void>());186readonly onDidChangeContent = this._onDidChangeContent.event;187188private readonly _onDidSave = this._register(new Emitter<IStoredFileWorkingCopySaveEvent>());189readonly onDidSave = this._onDidSave.event;190191readonly capabilities = WorkingCopyCapabilities.None;192193readonly name;194195private dirty = false;196197constructor(readonly resource: URI, isDirty = false, readonly typeId = 'testWorkingCopyType') {198super();199200this.name = basename(this.resource);201this.dirty = isDirty;202}203204setDirty(dirty: boolean): void {205if (this.dirty !== dirty) {206this.dirty = dirty;207this._onDidChangeDirty.fire();208}209}210211setContent(content: string): void {212this._onDidChangeContent.fire();213}214215isDirty(): boolean {216return this.dirty;217}218219isModified(): boolean {220return this.isDirty();221}222223async save(options?: ISaveOptions, stat?: IFileStatWithMetadata): Promise<boolean> {224this._onDidSave.fire({ reason: options?.reason ?? SaveReason.EXPLICIT, stat: stat ?? createFileStat(this.resource), source: options?.source });225226return true;227}228229async revert(options?: IRevertOptions): Promise<void> {230this.setDirty(false);231}232233async backup(token: CancellationToken): Promise<IWorkingCopyBackup> {234return {};235}236}237238export function createFileStat(resource: URI, readonly = false, isFile?: boolean, isDirectory?: boolean, isSymbolicLink?: boolean, children?: { resource: URI; isFile?: boolean; isDirectory?: boolean; isSymbolicLink?: boolean }[] | undefined): IFileStatWithMetadata {239return {240resource,241etag: Date.now().toString(),242mtime: Date.now(),243ctime: Date.now(),244size: 42,245isFile: isFile ?? true,246isDirectory: isDirectory ?? false,247isSymbolicLink: isSymbolicLink ?? false,248readonly,249locked: false,250name: basename(resource),251children: children?.map(c => createFileStat(c.resource, false, c.isFile, c.isDirectory, c.isSymbolicLink)),252};253}254255export class TestWorkingCopyFileService implements IWorkingCopyFileService {256257declare readonly _serviceBrand: undefined;258259onWillRunWorkingCopyFileOperation: Event<WorkingCopyFileEvent> = Event.None;260onDidFailWorkingCopyFileOperation: Event<WorkingCopyFileEvent> = Event.None;261onDidRunWorkingCopyFileOperation: Event<WorkingCopyFileEvent> = Event.None;262263addFileOperationParticipant(participant: IWorkingCopyFileOperationParticipant): IDisposable { return Disposable.None; }264265readonly hasSaveParticipants = false;266addSaveParticipant(participant: IStoredFileWorkingCopySaveParticipant): IDisposable { return Disposable.None; }267async runSaveParticipants(workingCopy: IWorkingCopy, context: IStoredFileWorkingCopySaveParticipantContext, progress: IProgress<IProgressStep>, token: CancellationToken): Promise<void> { }268269async delete(operations: IDeleteOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<void> { }270271registerWorkingCopyProvider(provider: (resourceOrFolder: URI) => IWorkingCopy[]): IDisposable { return Disposable.None; }272273getDirty(resource: URI): IWorkingCopy[] { return []; }274275create(operations: ICreateFileOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }276createFolder(operations: ICreateOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }277278move(operations: IMoveOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }279280copy(operations: ICopyOperation[], token: CancellationToken, undoInfo?: IFileOperationUndoRedoInfo): Promise<IFileStatWithMetadata[]> { throw new Error('Method not implemented.'); }281}282283export function mock<T>(): Ctor<T> {284return function () { } as any;285}286287export interface Ctor<T> {288new(): T;289}290291export class TestExtensionService extends NullExtensionService { }292293export const TestProductService = { _serviceBrand: undefined, ...product };294295export class TestActivityService implements IActivityService {296_serviceBrand: undefined;297onDidChangeActivity = Event.None;298getViewContainerActivities(viewContainerId: string): IActivity[] {299return [];300}301getActivity(id: string): IActivity[] {302return [];303}304showViewContainerActivity(viewContainerId: string, badge: IActivity): IDisposable {305return this;306}307showViewActivity(viewId: string, badge: IActivity): IDisposable {308return this;309}310showAccountsActivity(activity: IActivity): IDisposable {311return this;312}313showGlobalActivity(activity: IActivity): IDisposable {314return this;315}316317dispose() { }318}319320export const NullFilesConfigurationService = new class implements IFilesConfigurationService {321322_serviceBrand: undefined;323324readonly onDidChangeAutoSaveConfiguration = Event.None;325readonly onDidChangeAutoSaveDisabled = Event.None;326readonly onDidChangeReadonly = Event.None;327readonly onDidChangeFilesAssociation = Event.None;328329readonly isHotExitEnabled = false;330readonly hotExitConfiguration = undefined;331332getAutoSaveConfiguration(): IAutoSaveConfiguration { throw new Error('Method not implemented.'); }333getAutoSaveMode(): IAutoSaveMode { throw new Error('Method not implemented.'); }334hasShortAutoSaveDelay(): boolean { throw new Error('Method not implemented.'); }335toggleAutoSave(): Promise<void> { throw new Error('Method not implemented.'); }336enableAutoSaveAfterShortDelay(resourceOrEditor: URI | EditorInput): IDisposable { throw new Error('Method not implemented.'); }337disableAutoSave(resourceOrEditor: URI | EditorInput): IDisposable { throw new Error('Method not implemented.'); }338isReadonly(resource: URI, stat?: IBaseFileStat | undefined): boolean { return false; }339async updateReadonly(resource: URI, readonly: boolean | 'toggle' | 'reset'): Promise<void> { }340preventSaveConflicts(resource: URI, language?: string | undefined): boolean { throw new Error('Method not implemented.'); }341};342343export class TestWorkspaceTrustEnablementService implements IWorkspaceTrustEnablementService {344_serviceBrand: undefined;345346constructor(private isEnabled: boolean = true) { }347348isWorkspaceTrustEnabled(): boolean {349return this.isEnabled;350}351}352353export class TestWorkspaceTrustManagementService extends Disposable implements IWorkspaceTrustManagementService {354_serviceBrand: undefined;355356private _onDidChangeTrust = this._register(new Emitter<boolean>());357onDidChangeTrust = this._onDidChangeTrust.event;358359private _onDidChangeTrustedFolders = this._register(new Emitter<void>());360onDidChangeTrustedFolders = this._onDidChangeTrustedFolders.event;361362private _onDidInitiateWorkspaceTrustRequestOnStartup = this._register(new Emitter<void>());363onDidInitiateWorkspaceTrustRequestOnStartup = this._onDidInitiateWorkspaceTrustRequestOnStartup.event;364365366constructor(367private trusted: boolean = true368) {369super();370}371372get acceptsOutOfWorkspaceFiles(): boolean {373throw new Error('Method not implemented.');374}375376set acceptsOutOfWorkspaceFiles(value: boolean) {377throw new Error('Method not implemented.');378}379380addWorkspaceTrustTransitionParticipant(participant: IWorkspaceTrustTransitionParticipant): IDisposable {381throw new Error('Method not implemented.');382}383384getTrustedUris(): URI[] {385throw new Error('Method not implemented.');386}387388setParentFolderTrust(trusted: boolean): Promise<void> {389throw new Error('Method not implemented.');390}391392getUriTrustInfo(uri: URI): Promise<IWorkspaceTrustUriInfo> {393throw new Error('Method not implemented.');394}395396async setTrustedUris(folders: URI[]): Promise<void> {397throw new Error('Method not implemented.');398}399400async setUrisTrust(uris: URI[], trusted: boolean): Promise<void> {401throw new Error('Method not implemented.');402}403404canSetParentFolderTrust(): boolean {405throw new Error('Method not implemented.');406}407408canSetWorkspaceTrust(): boolean {409throw new Error('Method not implemented.');410}411412isWorkspaceTrusted(): boolean {413return this.trusted;414}415416isWorkspaceTrustForced(): boolean {417return false;418}419420get workspaceTrustInitialized(): Promise<void> {421return Promise.resolve();422}423424get workspaceResolved(): Promise<void> {425return Promise.resolve();426}427428async setWorkspaceTrust(trusted: boolean): Promise<void> {429if (this.trusted !== trusted) {430this.trusted = trusted;431this._onDidChangeTrust.fire(this.trusted);432}433}434}435436export class TestWorkspaceTrustRequestService extends Disposable implements IWorkspaceTrustRequestService {437_serviceBrand: any;438439private readonly _onDidInitiateOpenFilesTrustRequest = this._register(new Emitter<void>());440readonly onDidInitiateOpenFilesTrustRequest = this._onDidInitiateOpenFilesTrustRequest.event;441442private readonly _onDidInitiateWorkspaceTrustRequest = this._register(new Emitter<WorkspaceTrustRequestOptions>());443readonly onDidInitiateWorkspaceTrustRequest = this._onDidInitiateWorkspaceTrustRequest.event;444445private readonly _onDidInitiateWorkspaceTrustRequestOnStartup = this._register(new Emitter<void>());446readonly onDidInitiateWorkspaceTrustRequestOnStartup = this._onDidInitiateWorkspaceTrustRequestOnStartup.event;447448constructor(private readonly _trusted: boolean) {449super();450}451452requestOpenUrisHandler = async (uris: URI[]) => {453return WorkspaceTrustUriResponse.Open;454};455456requestOpenFilesTrust(uris: URI[]): Promise<WorkspaceTrustUriResponse> {457return this.requestOpenUrisHandler(uris);458}459460async completeOpenFilesTrustRequest(result: WorkspaceTrustUriResponse, saveResponse: boolean): Promise<void> {461throw new Error('Method not implemented.');462}463464cancelWorkspaceTrustRequest(): void {465throw new Error('Method not implemented.');466}467468async completeWorkspaceTrustRequest(trusted?: boolean): Promise<void> {469throw new Error('Method not implemented.');470}471472async requestWorkspaceTrust(options?: WorkspaceTrustRequestOptions): Promise<boolean> {473return this._trusted;474}475476requestWorkspaceTrustOnStartup(): void {477throw new Error('Method not implemented.');478}479}480481export class TestMarkerService implements IMarkerService {482483_serviceBrand: undefined;484485onMarkerChanged = Event.None;486487getStatistics(): MarkerStatistics { throw new Error('Method not implemented.'); }488changeOne(owner: string, resource: URI, markers: IMarkerData[]): void { }489changeAll(owner: string, data: IResourceMarker[]): void { }490remove(owner: string, resources: URI[]): void { }491read(filter?: { owner?: string | undefined; resource?: URI | undefined; severities?: number | undefined; take?: number | undefined } | undefined): IMarker[] { return []; }492installResourceFilter(resource: URI, reason: string): IDisposable {493return { dispose: () => { /* TODO: Implement cleanup logic */ } };494}495}496497498