Path: blob/main/src/vs/workbench/api/test/browser/mainThreadDocumentsAndEditors.test.ts
5243 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 assert from 'assert';6import { MainThreadDocumentsAndEditors } from '../../browser/mainThreadDocumentsAndEditors.js';7import { SingleProxyRPCProtocol } from '../common/testRPCProtocol.js';8import { TestConfigurationService } from '../../../../platform/configuration/test/common/testConfigurationService.js';9import { ModelService } from '../../../../editor/common/services/modelService.js';10import { TestCodeEditorService } from '../../../../editor/test/browser/editorTestServices.js';11import { ITextFileService } from '../../../services/textfile/common/textfiles.js';12import { IDocumentsAndEditorsDelta } from '../../common/extHost.protocol.js';13import { createTestCodeEditor, ITestCodeEditor } from '../../../../editor/test/browser/testCodeEditor.js';14import { mock } from '../../../../base/test/common/mock.js';15import { TestEditorService, TestEditorGroupsService, TestEnvironmentService, TestPathService } from '../../../test/browser/workbenchTestServices.js';16import { Event } from '../../../../base/common/event.js';17import { ITextModel } from '../../../../editor/common/model.js';18import { ServiceCollection } from '../../../../platform/instantiation/common/serviceCollection.js';19import { ICodeEditorService } from '../../../../editor/browser/services/codeEditorService.js';20import { IFileService } from '../../../../platform/files/common/files.js';21import { TestThemeService } from '../../../../platform/theme/test/common/testThemeService.js';22import { UndoRedoService } from '../../../../platform/undoRedo/common/undoRedoService.js';23import { TestDialogService } from '../../../../platform/dialogs/test/common/testDialogService.js';24import { TestNotificationService } from '../../../../platform/notification/test/common/testNotificationService.js';25import { TestTextResourcePropertiesService, TestWorkingCopyFileService } from '../../../test/common/workbenchTestServices.js';26import { UriIdentityService } from '../../../../platform/uriIdentity/common/uriIdentityService.js';27import { IClipboardService } from '../../../../platform/clipboard/common/clipboardService.js';28import { IPaneCompositePartService } from '../../../services/panecomposite/browser/panecomposite.js';29import { TextModel } from '../../../../editor/common/model/textModel.js';30import { DisposableStore } from '../../../../base/common/lifecycle.js';31import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../base/test/common/utils.js';32import { TestInstantiationService } from '../../../../platform/instantiation/test/common/instantiationServiceMock.js';33import { ILanguageService } from '../../../../editor/common/languages/language.js';34import { LanguageService } from '../../../../editor/common/services/languageService.js';35import { ILanguageConfigurationService } from '../../../../editor/common/languages/languageConfigurationRegistry.js';36import { TestLanguageConfigurationService } from '../../../../editor/test/common/modes/testLanguageConfigurationService.js';37import { IUndoRedoService } from '../../../../platform/undoRedo/common/undoRedo.js';38import { IQuickDiffModelService } from '../../../contrib/scm/browser/quickDiffModel.js';39import { ITextEditorDiffInformation } from '../../../../platform/editor/common/editor.js';40import { ITreeSitterLibraryService } from '../../../../editor/common/services/treeSitter/treeSitterLibraryService.js';41import { TestTreeSitterLibraryService } from '../../../../editor/test/common/services/testTreeSitterLibraryService.js';4243suite('MainThreadDocumentsAndEditors', () => {4445let disposables: DisposableStore;4647let modelService: ModelService;48let codeEditorService: TestCodeEditorService;49let textFileService: ITextFileService;50const deltas: IDocumentsAndEditorsDelta[] = [];5152function myCreateTestCodeEditor(model: ITextModel | undefined): ITestCodeEditor {53return createTestCodeEditor(model, {54hasTextFocus: false,55serviceCollection: new ServiceCollection(56[ICodeEditorService, codeEditorService]57)58});59}6061setup(() => {62disposables = new DisposableStore();6364deltas.length = 0;65const configService = new TestConfigurationService();66configService.setUserConfiguration('editor', { 'detectIndentation': false });67const dialogService = new TestDialogService();68const notificationService = new TestNotificationService();69const undoRedoService = new UndoRedoService(dialogService, notificationService);70const themeService = new TestThemeService();71const instantiationService = new TestInstantiationService();72instantiationService.set(ILanguageService, disposables.add(new LanguageService()));73instantiationService.set(ILanguageConfigurationService, new TestLanguageConfigurationService());74instantiationService.set(ITreeSitterLibraryService, new TestTreeSitterLibraryService());75instantiationService.set(IUndoRedoService, undoRedoService);76modelService = new ModelService(77configService,78new TestTextResourcePropertiesService(configService),79undoRedoService,80instantiationService81);82codeEditorService = new TestCodeEditorService(themeService);83textFileService = new class extends mock<ITextFileService>() {84override isDirty() { return false; }85// eslint-disable-next-line local/code-no-any-casts86override files = <any>{87onDidSave: Event.None,88onDidRevert: Event.None,89onDidChangeDirty: Event.None,90onDidChangeEncoding: Event.None91};92// eslint-disable-next-line local/code-no-any-casts93override untitled = <any>{94onDidChangeEncoding: Event.None95};96override getEncoding() { return 'utf8'; }97};98const workbenchEditorService = disposables.add(new TestEditorService());99const editorGroupService = new TestEditorGroupsService();100101const fileService = new class extends mock<IFileService>() {102override onDidRunOperation = Event.None;103override onDidChangeFileSystemProviderCapabilities = Event.None;104override onDidChangeFileSystemProviderRegistrations = Event.None;105};106107new MainThreadDocumentsAndEditors(108SingleProxyRPCProtocol({109$acceptDocumentsAndEditorsDelta: (delta: IDocumentsAndEditorsDelta) => { deltas.push(delta); },110$acceptEditorDiffInformation: (id: string, diffInformation: ITextEditorDiffInformation | undefined) => { }111}),112modelService,113textFileService,114workbenchEditorService,115codeEditorService,116fileService,117null!,118editorGroupService,119new class extends mock<IPaneCompositePartService>() implements IPaneCompositePartService {120override onDidPaneCompositeOpen = Event.None;121override onDidPaneCompositeClose = Event.None;122override getActivePaneComposite() {123return undefined;124}125},126TestEnvironmentService,127new TestWorkingCopyFileService(),128new UriIdentityService(fileService),129new class extends mock<IClipboardService>() {130override readText() {131return Promise.resolve('clipboard_contents');132}133},134new TestPathService(),135new TestConfigurationService(),136new class extends mock<IQuickDiffModelService>() {137override createQuickDiffModelReference() {138return undefined;139}140}141);142});143144teardown(() => {145disposables.dispose();146});147148ensureNoDisposablesAreLeakedInTestSuite();149150test('Model#add', () => {151deltas.length = 0;152153disposables.add(modelService.createModel('farboo', null));154155assert.strictEqual(deltas.length, 1);156const [delta] = deltas;157158assert.strictEqual(delta.addedDocuments!.length, 1);159assert.strictEqual(delta.removedDocuments, undefined);160assert.strictEqual(delta.addedEditors, undefined);161assert.strictEqual(delta.removedEditors, undefined);162assert.strictEqual(delta.newActiveEditor, undefined);163});164165test('ignore huge model', function () {166167const oldLimit = TextModel._MODEL_SYNC_LIMIT;168try {169const largeModelString = 'abc'.repeat(1024);170TextModel._MODEL_SYNC_LIMIT = largeModelString.length / 2;171172const model = modelService.createModel(largeModelString, null);173disposables.add(model);174assert.ok(model.isTooLargeForSyncing());175176assert.strictEqual(deltas.length, 1);177const [delta] = deltas;178assert.strictEqual(delta.newActiveEditor, null);179assert.strictEqual(delta.addedDocuments, undefined);180assert.strictEqual(delta.removedDocuments, undefined);181assert.strictEqual(delta.addedEditors, undefined);182assert.strictEqual(delta.removedEditors, undefined);183184} finally {185TextModel._MODEL_SYNC_LIMIT = oldLimit;186}187});188189test('ignore huge model from editor', function () {190191const oldLimit = TextModel._MODEL_SYNC_LIMIT;192try {193const largeModelString = 'abc'.repeat(1024);194TextModel._MODEL_SYNC_LIMIT = largeModelString.length / 2;195196const model = modelService.createModel(largeModelString, null);197const editor = myCreateTestCodeEditor(model);198199assert.strictEqual(deltas.length, 1);200deltas.length = 0;201assert.strictEqual(deltas.length, 0);202editor.dispose();203model.dispose();204205} finally {206TextModel._MODEL_SYNC_LIMIT = oldLimit;207}208});209210test('ignore simple widget model', function () {211this.timeout(1000 * 60); // increase timeout for this one test212213const model = modelService.createModel('test', null, undefined, true);214disposables.add(model);215assert.ok(model.isForSimpleWidget);216217assert.strictEqual(deltas.length, 1);218const [delta] = deltas;219assert.strictEqual(delta.newActiveEditor, null);220assert.strictEqual(delta.addedDocuments, undefined);221assert.strictEqual(delta.removedDocuments, undefined);222assert.strictEqual(delta.addedEditors, undefined);223assert.strictEqual(delta.removedEditors, undefined);224});225226test('ignore editor w/o model', () => {227const editor = myCreateTestCodeEditor(undefined);228assert.strictEqual(deltas.length, 1);229const [delta] = deltas;230assert.strictEqual(delta.newActiveEditor, null);231assert.strictEqual(delta.addedDocuments, undefined);232assert.strictEqual(delta.removedDocuments, undefined);233assert.strictEqual(delta.addedEditors, undefined);234assert.strictEqual(delta.removedEditors, undefined);235236editor.dispose();237});238239test('editor with model', () => {240deltas.length = 0;241242const model = modelService.createModel('farboo', null);243const editor = myCreateTestCodeEditor(model);244245assert.strictEqual(deltas.length, 2);246const [first, second] = deltas;247assert.strictEqual(first.addedDocuments!.length, 1);248assert.strictEqual(first.newActiveEditor, undefined);249assert.strictEqual(first.removedDocuments, undefined);250assert.strictEqual(first.addedEditors, undefined);251assert.strictEqual(first.removedEditors, undefined);252253assert.strictEqual(second.addedEditors!.length, 1);254assert.strictEqual(second.addedDocuments, undefined);255assert.strictEqual(second.removedDocuments, undefined);256assert.strictEqual(second.removedEditors, undefined);257assert.strictEqual(second.newActiveEditor, undefined);258259editor.dispose();260model.dispose();261});262263test('editor with dispos-ed/-ing model', () => {264const model = modelService.createModel('farboo', null);265const editor = myCreateTestCodeEditor(model);266267// ignore things until now268deltas.length = 0;269270modelService.destroyModel(model.uri);271assert.strictEqual(deltas.length, 1);272const [first] = deltas;273274assert.strictEqual(first.newActiveEditor, undefined);275assert.strictEqual(first.removedEditors!.length, 1);276assert.strictEqual(first.removedDocuments!.length, 1);277assert.strictEqual(first.addedDocuments, undefined);278assert.strictEqual(first.addedEditors, undefined);279280editor.dispose();281model.dispose();282});283});284285286