Merge from vscode 8a997f7321ae6612fc0e6eb3eac4f358a6233bfb

This commit is contained in:
ADS Merger
2020-02-11 07:08:19 +00:00
parent 0f934081e1
commit 085752f111
217 changed files with 2561 additions and 2063 deletions

View File

@@ -12,6 +12,7 @@ import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers'
import { mock } from 'vs/workbench/test/browser/api/mock';
import { Emitter, Event } from 'vs/base/common/event';
import { NullLogService } from 'vs/platform/log/common/log';
import type * as vscode from 'vscode';
suite('ExtHostDiagnostics', () => {
@@ -96,7 +97,7 @@ suite('ExtHostDiagnostics', () => {
assert.throws(() => array.pop());
assert.throws(() => array[0] = new Diagnostic(new Range(0, 0, 0, 0), 'evil'));
collection.forEach((uri, array: readonly Diagnostic[]) => {
collection.forEach((uri: URI, array: readonly vscode.Diagnostic[]): any => {
assert.throws(() => (array as Diagnostic[]).length = 0);
assert.throws(() => (array as Diagnostic[]).pop());
assert.throws(() => (array as Diagnostic[])[0] = new Diagnostic(new Range(0, 0, 0, 0), 'evil'));

View File

@@ -79,12 +79,13 @@ export class TestRPCProtocol implements IExtHostContext, IExtHostRpcService {
private _createProxy<T>(proxyId: string): T {
let handler = {
get: (target: any, name: string) => {
if (!target[name] && name.charCodeAt(0) === CharCode.DollarSign) {
get: (target: any, name: PropertyKey) => {
if (typeof name === 'string' && !target[name] && name.charCodeAt(0) === CharCode.DollarSign) {
target[name] = (...myArgs: any[]) => {
return this._remoteCall(proxyId, name, myArgs);
};
}
return target[name];
}
};

View File

@@ -1,496 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import * as assert from 'assert';
import { join } from 'vs/base/common/path';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IUntitledTextEditorService, UntitledTextEditorService } from 'vs/workbench/services/untitled/common/untitledTextEditorService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { workbenchInstantiationService, TestEditorService } from 'vs/workbench/test/browser/workbenchTestServices';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ModeServiceImpl } from 'vs/editor/common/services/modeServiceImpl';
import { snapshotToString } from 'vs/workbench/services/textfile/common/textfiles';
import { ModesRegistry, PLAINTEXT_MODE_ID } from 'vs/editor/common/modes/modesRegistry';
import { IWorkingCopyService, IWorkingCopy } from 'vs/workbench/services/workingCopy/common/workingCopyService';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IIdentifiedSingleEditOperation } from 'vs/editor/common/model';
import { Range } from 'vs/editor/common/core/range';
class ServiceAccessor {
constructor(
@IUntitledTextEditorService public readonly untitledTextEditorService: IUntitledTextEditorService,
@IEditorService public readonly editorService: TestEditorService,
@IWorkingCopyService public readonly workingCopyService: IWorkingCopyService,
@IModeService public readonly modeService: ModeServiceImpl,
@IConfigurationService public readonly testConfigurationService: TestConfigurationService
) { }
}
suite('Untitled text editors', () => {
let instantiationService: IInstantiationService;
let accessor: ServiceAccessor;
setup(() => {
instantiationService = workbenchInstantiationService();
accessor = instantiationService.createInstance(ServiceAccessor);
});
teardown(() => {
(accessor.untitledTextEditorService as UntitledTextEditorService).dispose();
});
test('basics', async () => {
const service = accessor.untitledTextEditorService;
const workingCopyService = accessor.workingCopyService;
const input1 = service.create();
await input1.resolve();
assert.equal(input1, service.create({ untitledResource: input1.getResource() }));
assert.equal(service.get(input1.getResource()), input1);
assert.ok(service.exists(input1.getResource()));
assert.ok(!service.exists(URI.file('testing')));
const input2 = service.create();
assert.equal(service.get(input2.getResource()), input2);
// get()
assert.equal(service.get(input1.getResource()), input1);
assert.equal(service.get(input2.getResource()), input2);
// revert()
await input1.revert(0);
assert.ok(input1.isDisposed());
assert.ok(!service.get(input1.getResource()));
// dirty
const model = await input2.resolve();
assert.equal(await service.resolve({ untitledResource: input2.getResource() }), model);
assert.ok(service.exists(model.resource));
assert.ok(!input2.isDirty());
const resourcePromise = awaitDidChangeDirty(accessor.untitledTextEditorService);
model.textEditorModel.setValue('foo bar');
const resource = await resourcePromise;
assert.equal(resource.toString(), input2.getResource().toString());
assert.ok(input2.isDirty());
assert.ok(workingCopyService.isDirty(input2.getResource()));
assert.equal(workingCopyService.dirtyCount, 1);
await input1.revert(0);
await input2.revert(0);
assert.ok(!service.get(input1.getResource()));
assert.ok(!service.get(input2.getResource()));
assert.ok(!input2.isDirty());
assert.ok(!model.isDirty());
assert.ok(!workingCopyService.isDirty(input2.getResource()));
assert.equal(workingCopyService.dirtyCount, 0);
assert.equal(await input1.revert(0), false);
assert.ok(input1.isDisposed());
assert.ok(!service.exists(input1.getResource()));
input2.dispose();
assert.ok(!service.exists(input2.getResource()));
});
function awaitDidChangeDirty(service: IUntitledTextEditorService): Promise<URI> {
return new Promise(c => {
const listener = service.onDidChangeDirty(async resource => {
listener.dispose();
c(resource);
});
});
}
test('associated resource is dirty', () => {
const service = accessor.untitledTextEditorService;
const file = URI.file(join('C:\\', '/foo/file.txt'));
const untitled = service.create({ associatedResource: file });
assert.ok(service.hasAssociatedFilePath(untitled.getResource()));
assert.equal(untitled.isDirty(), true);
untitled.dispose();
});
test('no longer dirty when content gets empty (not with associated resource)', async () => {
const service = accessor.untitledTextEditorService;
const workingCopyService = accessor.workingCopyService;
const input = service.create();
// dirty
const model = await input.resolve();
model.textEditorModel.setValue('foo bar');
assert.ok(model.isDirty());
assert.ok(workingCopyService.isDirty(model.resource));
model.textEditorModel.setValue('');
assert.ok(!model.isDirty());
assert.ok(!workingCopyService.isDirty(model.resource));
input.dispose();
model.dispose();
});
test('via create options', async () => {
const service = accessor.untitledTextEditorService;
const model1 = await service.create().resolve();
model1.textEditorModel!.setValue('foo bar');
assert.ok(model1.isDirty());
model1.textEditorModel!.setValue('');
assert.ok(!model1.isDirty());
const model2 = await service.create({ initialValue: 'Hello World' }).resolve();
assert.equal(snapshotToString(model2.createSnapshot()!), 'Hello World');
const input = service.create();
const model3 = await service.create({ untitledResource: input.getResource() }).resolve();
assert.equal(model3.resource.toString(), input.getResource().toString());
const file = URI.file(join('C:\\', '/foo/file44.txt'));
const model4 = await service.create({ associatedResource: file }).resolve();
assert.ok(service.hasAssociatedFilePath(model4.resource));
assert.ok(model4.isDirty());
model1.dispose();
model2.dispose();
model3.dispose();
model4.dispose();
input.dispose();
});
test('associated path remains dirty when content gets empty', async () => {
const service = accessor.untitledTextEditorService;
const file = URI.file(join('C:\\', '/foo/file.txt'));
const input = service.create({ associatedResource: file });
// dirty
const model = await input.resolve();
model.textEditorModel.setValue('foo bar');
assert.ok(model.isDirty());
model.textEditorModel.setValue('');
assert.ok(model.isDirty());
input.dispose();
model.dispose();
});
test('initial content is dirty', async () => {
const service = accessor.untitledTextEditorService;
const workingCopyService = accessor.workingCopyService;
const untitled = service.create({ initialValue: 'Hello World' });
assert.equal(untitled.isDirty(), true);
let onDidChangeDirty: IWorkingCopy | undefined = undefined;
const listener = workingCopyService.onDidChangeDirty(copy => {
onDidChangeDirty = copy;
});
// dirty
const model = await untitled.resolve();
assert.ok(model.isDirty());
assert.equal(workingCopyService.dirtyCount, 1);
assert.equal(onDidChangeDirty, model);
untitled.dispose();
listener.dispose();
model.dispose();
});
test('created with files.defaultLanguage setting', () => {
const defaultLanguage = 'javascript';
const config = accessor.testConfigurationService;
config.setUserConfiguration('files', { 'defaultLanguage': defaultLanguage });
const service = accessor.untitledTextEditorService;
const input = service.create();
assert.equal(input.getMode(), defaultLanguage);
config.setUserConfiguration('files', { 'defaultLanguage': undefined });
input.dispose();
});
test('created with files.defaultLanguage setting (${activeEditorLanguage})', () => {
const config = accessor.testConfigurationService;
config.setUserConfiguration('files', { 'defaultLanguage': '${activeEditorLanguage}' });
accessor.editorService.activeTextEditorMode = 'typescript';
const service = accessor.untitledTextEditorService;
const input = service.create();
assert.equal(input.getMode(), 'typescript');
config.setUserConfiguration('files', { 'defaultLanguage': undefined });
accessor.editorService.activeTextEditorMode = undefined;
input.dispose();
});
test('created with mode overrides files.defaultLanguage setting', () => {
const mode = 'typescript';
const defaultLanguage = 'javascript';
const config = accessor.testConfigurationService;
config.setUserConfiguration('files', { 'defaultLanguage': defaultLanguage });
const service = accessor.untitledTextEditorService;
const input = service.create({ mode });
assert.equal(input.getMode(), mode);
config.setUserConfiguration('files', { 'defaultLanguage': undefined });
input.dispose();
});
test('can change mode afterwards', async () => {
const mode = 'untitled-input-test';
ModesRegistry.registerLanguage({
id: mode,
});
const service = accessor.untitledTextEditorService;
const input = service.create({ mode });
assert.equal(input.getMode(), mode);
const model = await input.resolve();
assert.equal(model.getMode(), mode);
input.setMode('text');
assert.equal(input.getMode(), PLAINTEXT_MODE_ID);
input.dispose();
model.dispose();
});
test('service#onDidChangeEncoding', async () => {
const service = accessor.untitledTextEditorService;
const input = service.create();
let counter = 0;
service.onDidChangeEncoding(r => {
counter++;
assert.equal(r.toString(), input.getResource().toString());
});
// encoding
const model = await input.resolve();
model.setEncoding('utf16');
assert.equal(counter, 1);
input.dispose();
model.dispose();
});
test('service#onDidChangeLabel', async () => {
const service = accessor.untitledTextEditorService;
const input = service.create();
let counter = 0;
service.onDidChangeLabel(r => {
counter++;
assert.equal(r.toString(), input.getResource().toString());
});
// label
const model = await input.resolve();
model.textEditorModel.setValue('Foo Bar');
assert.equal(counter, 1);
input.dispose();
model.dispose();
});
test('service#onDidDisposeModel', async () => {
const service = accessor.untitledTextEditorService;
const input = service.create();
let counter = 0;
service.onDidDisposeModel(r => {
counter++;
assert.equal(r.toString(), input.getResource().toString());
});
const model = await input.resolve();
assert.equal(counter, 0);
input.dispose();
assert.equal(counter, 1);
model.dispose();
});
test('model#onDidChangeContent', async function () {
const service = accessor.untitledTextEditorService;
const input = service.create();
let counter = 0;
const model = await input.resolve();
model.onDidChangeContent(() => counter++);
model.textEditorModel.setValue('foo');
assert.equal(counter, 1, 'Dirty model should trigger event');
model.textEditorModel.setValue('bar');
assert.equal(counter, 2, 'Content change when dirty should trigger event');
model.textEditorModel.setValue('');
assert.equal(counter, 3, 'Manual revert should trigger event');
model.textEditorModel.setValue('foo');
assert.equal(counter, 4, 'Dirty model should trigger event');
input.dispose();
model.dispose();
});
test('model#onDispose when reverted', async function () {
const service = accessor.untitledTextEditorService;
const input = service.create();
let counter = 0;
const model = await input.resolve();
model.onDispose(() => counter++);
model.textEditorModel.setValue('foo');
await model.revert();
assert.ok(input.isDisposed());
assert.ok(counter > 1);
});
test('model#onDidChangeName and input name', async function () {
const service = accessor.untitledTextEditorService;
const input = service.create();
let counter = 0;
let model = await input.resolve();
model.onDidChangeName(() => counter++);
model.textEditorModel.setValue('foo');
assert.equal(input.getName(), 'foo');
assert.equal(model.name, 'foo');
assert.equal(counter, 1);
model.textEditorModel.setValue('bar');
assert.equal(input.getName(), 'bar');
assert.equal(model.name, 'bar');
assert.equal(counter, 2);
model.textEditorModel.setValue('');
assert.equal(input.getName(), 'Untitled-1');
assert.equal(model.name, 'Untitled-1');
model.textEditorModel.setValue(' ');
assert.equal(input.getName(), 'Untitled-1');
assert.equal(model.name, 'Untitled-1');
model.textEditorModel.setValue('([]}'); // require actual words
assert.equal(input.getName(), 'Untitled-1');
assert.equal(model.name, 'Untitled-1');
model.textEditorModel.setValue('([]}hello '); // require actual words
assert.equal(input.getName(), '([]}hello');
assert.equal(model.name, '([]}hello');
assert.equal(counter, 4);
model.textEditorModel.setValue('Hello\nWorld');
assert.equal(counter, 5);
function createSingleEditOp(text: string, positionLineNumber: number, positionColumn: number, selectionLineNumber: number = positionLineNumber, selectionColumn: number = positionColumn): IIdentifiedSingleEditOperation {
let range = new Range(
selectionLineNumber,
selectionColumn,
positionLineNumber,
positionColumn
);
return {
identifier: null,
range,
text,
forceMoveMarkers: false
};
}
model.textEditorModel.applyEdits([createSingleEditOp('hello', 2, 2)]);
assert.equal(counter, 5); // change was not on first line
input.dispose();
model.dispose();
const inputWithContents = service.create({ initialValue: 'Foo' });
model = await inputWithContents.resolve();
assert.equal(inputWithContents.getName(), 'Foo');
inputWithContents.dispose();
model.dispose();
});
test('model#onDidChangeDirty', async function () {
const service = accessor.untitledTextEditorService;
const input = service.create();
let counter = 0;
const model = await input.resolve();
model.onDidChangeDirty(() => counter++);
model.textEditorModel.setValue('foo');
assert.equal(counter, 1, 'Dirty model should trigger event');
model.textEditorModel.setValue('bar');
assert.equal(counter, 1, 'Another change does not fire event');
input.dispose();
model.dispose();
});
test('model#onDidChangeEncoding', async function () {
const service = accessor.untitledTextEditorService;
const input = service.create();
let counter = 0;
const model = await input.resolve();
model.onDidChangeEncoding(() => counter++);
model.setEncoding('utf16');
assert.equal(counter, 1, 'Dirty model should trigger event');
model.setEncoding('utf16');
assert.equal(counter, 1, 'Another change to same encoding does not fire event');
input.dispose();
model.dispose();
});
});

View File

@@ -93,6 +93,7 @@ export import TestContextService = CommonWorkbenchTestServices.TestContextServic
export import TestStorageService = CommonWorkbenchTestServices.TestStorageService;
export import TestWorkingCopyService = CommonWorkbenchTestServices.TestWorkingCopyService;
import { IRemotePathService } from 'vs/workbench/services/path/common/remotePathService';
import { Direction } from 'vs/base/browser/ui/grid/grid';
export function createFileInput(instantiationService: IInstantiationService, resource: URI): FileEditorInput {
return instantiationService.createInstance(FileEditorInput, resource, undefined, undefined);
@@ -225,6 +226,7 @@ export class TestAccessibilityService implements IAccessibilityService {
isScreenReaderOptimized(): boolean { return false; }
alwaysUnderlineAccessKeys(): Promise<boolean> { return Promise.resolve(false); }
setAccessibilitySupport(accessibilitySupport: AccessibilitySupport): void { }
getAccessibilitySupport(): AccessibilitySupport { return AccessibilitySupport.Unknown; }
}
export class TestDecorationsService implements IDecorationsService {
@@ -361,6 +363,7 @@ export class TestLayoutService implements IWorkbenchLayoutService {
registerPart(part: Part): void { }
isWindowMaximized() { return false; }
updateWindowMaximizedState(maximized: boolean): void { }
getVisibleNeighborPart(part: Parts, direction: Direction): Parts | undefined { return undefined; }
}
let activeViewlet: Viewlet = {} as any;