Merge branch 'master' into ben/electron-sandbox

This commit is contained in:
Benjamin Pasero 2020-05-26 09:39:17 +02:00
commit 76590a7764
36 changed files with 510 additions and 177 deletions

View File

@ -207,6 +207,7 @@
"vs/nls",
"**/vs/base/common/**",
"**/vs/base/parts/*/common/**",
"**/vs/base/test/common/**",
"**/vs/platform/*/common/**",
"**/vs/platform/*/test/common/**"
]

View File

@ -0,0 +1,211 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as assert from 'assert';
import { UndoRedoService } from 'vs/platform/undoRedo/common/undoRedoService';
import { TestDialogService } from 'vs/platform/dialogs/test/common/testDialogService';
import { TestNotificationService } from 'vs/platform/notification/test/common/testNotificationService';
import { UndoRedoElementType, IUndoRedoElement } from 'vs/platform/undoRedo/common/undoRedo';
import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/base/test/common/mock';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
suite('UndoRedoService', () => {
function createUndoRedoService(dialogService: IDialogService = new TestDialogService()): UndoRedoService {
const notificationService = new TestNotificationService();
return new UndoRedoService(dialogService, notificationService);
}
test('simple single resource elements', () => {
const resource = URI.file('test.txt');
const service = createUndoRedoService();
assert.equal(service.canUndo(resource), false);
assert.equal(service.canRedo(resource), false);
assert.equal(service.hasElements(resource), false);
assert.ok(service.getLastElement(resource) === null);
let undoCall1 = 0;
let redoCall1 = 0;
const element1: IUndoRedoElement = {
type: UndoRedoElementType.Resource,
resource: resource,
label: 'typing 1',
undo: () => { undoCall1++; },
redo: () => { redoCall1++; }
};
service.pushElement(element1);
assert.equal(undoCall1, 0);
assert.equal(redoCall1, 0);
assert.equal(service.canUndo(resource), true);
assert.equal(service.canRedo(resource), false);
assert.equal(service.hasElements(resource), true);
assert.ok(service.getLastElement(resource) === element1);
service.undo(resource);
assert.equal(undoCall1, 1);
assert.equal(redoCall1, 0);
assert.equal(service.canUndo(resource), false);
assert.equal(service.canRedo(resource), true);
assert.equal(service.hasElements(resource), true);
assert.ok(service.getLastElement(resource) === null);
service.redo(resource);
assert.equal(undoCall1, 1);
assert.equal(redoCall1, 1);
assert.equal(service.canUndo(resource), true);
assert.equal(service.canRedo(resource), false);
assert.equal(service.hasElements(resource), true);
assert.ok(service.getLastElement(resource) === element1);
let undoCall2 = 0;
let redoCall2 = 0;
const element2: IUndoRedoElement = {
type: UndoRedoElementType.Resource,
resource: resource,
label: 'typing 2',
undo: () => { undoCall2++; },
redo: () => { redoCall2++; }
};
service.pushElement(element2);
assert.equal(undoCall1, 1);
assert.equal(redoCall1, 1);
assert.equal(undoCall2, 0);
assert.equal(redoCall2, 0);
assert.equal(service.canUndo(resource), true);
assert.equal(service.canRedo(resource), false);
assert.equal(service.hasElements(resource), true);
assert.ok(service.getLastElement(resource) === element2);
service.undo(resource);
assert.equal(undoCall1, 1);
assert.equal(redoCall1, 1);
assert.equal(undoCall2, 1);
assert.equal(redoCall2, 0);
assert.equal(service.canUndo(resource), true);
assert.equal(service.canRedo(resource), true);
assert.equal(service.hasElements(resource), true);
assert.ok(service.getLastElement(resource) === null);
let undoCall3 = 0;
let redoCall3 = 0;
const element3: IUndoRedoElement = {
type: UndoRedoElementType.Resource,
resource: resource,
label: 'typing 2',
undo: () => { undoCall3++; },
redo: () => { redoCall3++; }
};
service.pushElement(element3);
assert.equal(undoCall1, 1);
assert.equal(redoCall1, 1);
assert.equal(undoCall2, 1);
assert.equal(redoCall2, 0);
assert.equal(undoCall3, 0);
assert.equal(redoCall3, 0);
assert.equal(service.canUndo(resource), true);
assert.equal(service.canRedo(resource), false);
assert.equal(service.hasElements(resource), true);
assert.ok(service.getLastElement(resource) === element3);
service.undo(resource);
assert.equal(undoCall1, 1);
assert.equal(redoCall1, 1);
assert.equal(undoCall2, 1);
assert.equal(redoCall2, 0);
assert.equal(undoCall3, 1);
assert.equal(redoCall3, 0);
assert.equal(service.canUndo(resource), true);
assert.equal(service.canRedo(resource), true);
assert.equal(service.hasElements(resource), true);
assert.ok(service.getLastElement(resource) === null);
});
test('multi resource elements', async () => {
const resource1 = URI.file('test1.txt');
const resource2 = URI.file('test2.txt');
const service = createUndoRedoService(new class extends mock<IDialogService>() {
async show() {
return {
choice: 0 // confirm!
};
}
});
let undoCall1 = 0, undoCall11 = 0, undoCall12 = 0;
let redoCall1 = 0, redoCall11 = 0, redoCall12 = 0;
const element1: IUndoRedoElement = {
type: UndoRedoElementType.Workspace,
resources: [resource1, resource2],
label: 'typing 1',
undo: () => { undoCall1++; },
redo: () => { redoCall1++; },
split: () => {
return [
{
type: UndoRedoElementType.Resource,
resource: resource1,
label: 'typing 1.1',
undo: () => { undoCall11++; },
redo: () => { redoCall11++; }
},
{
type: UndoRedoElementType.Resource,
resource: resource2,
label: 'typing 1.2',
undo: () => { undoCall12++; },
redo: () => { redoCall12++; }
}
];
}
};
service.pushElement(element1);
assert.equal(service.canUndo(resource1), true);
assert.equal(service.canRedo(resource1), false);
assert.equal(service.hasElements(resource1), true);
assert.ok(service.getLastElement(resource1) === element1);
assert.equal(service.canUndo(resource2), true);
assert.equal(service.canRedo(resource2), false);
assert.equal(service.hasElements(resource2), true);
assert.ok(service.getLastElement(resource2) === element1);
await service.undo(resource1);
assert.equal(undoCall1, 1);
assert.equal(redoCall1, 0);
assert.equal(service.canUndo(resource1), false);
assert.equal(service.canRedo(resource1), true);
assert.equal(service.hasElements(resource1), true);
assert.ok(service.getLastElement(resource1) === null);
assert.equal(service.canUndo(resource2), false);
assert.equal(service.canRedo(resource2), true);
assert.equal(service.hasElements(resource2), true);
assert.ok(service.getLastElement(resource2) === null);
await service.redo(resource2);
assert.equal(undoCall1, 1);
assert.equal(redoCall1, 1);
assert.equal(undoCall11, 0);
assert.equal(redoCall11, 0);
assert.equal(undoCall12, 0);
assert.equal(redoCall12, 0);
assert.equal(service.canUndo(resource1), true);
assert.equal(service.canRedo(resource1), false);
assert.equal(service.hasElements(resource1), true);
assert.ok(service.getLastElement(resource1) === element1);
assert.equal(service.canUndo(resource2), true);
assert.equal(service.canRedo(resource2), false);
assert.equal(service.hasElements(resource2), true);
assert.ok(service.getLastElement(resource2) === element1);
});
});

View File

@ -246,7 +246,7 @@ export abstract class AbstractSynchroniser extends Disposable {
} catch (e) {
if (e instanceof UserDataSyncError) {
switch (e.code) {
case UserDataSyncErrorCode.RemotePreconditionFailed:
case UserDataSyncErrorCode.PreconditionFailed:
// Rejected as there is a new remote version. Syncing again...
this.logService.info(`${this.syncResourceLogLabel}: Failed to synchronize as there is a new remote version available. Synchronizing again...`);

View File

@ -184,18 +184,19 @@ export interface IUserDataSyncBackupStoreService {
// #region User Data Sync Error
export enum UserDataSyncErrorCode {
// Server Errors
Unauthorized = 'Unauthorized',
Forbidden = 'Forbidden',
// Client Errors (>= 400 )
Unauthorized = 'Unauthorized', /* 401 */
PreconditionFailed = 'PreconditionFailed', /* 412 */
TooLarge = 'TooLarge', /* 413 */
UpgradeRequired = 'UpgradeRequired', /* 426 */
PreconditionRequired = 'PreconditionRequired', /* 428 */
TooManyRequests = 'RemoteTooManyRequests', /* 429 */
// Local Errors
ConnectionRefused = 'ConnectionRefused',
RemotePreconditionFailed = 'RemotePreconditionFailed',
TooManyRequests = 'RemoteTooManyRequests',
TooLarge = 'TooLarge',
NoRef = 'NoRef',
TurnedOff = 'TurnedOff',
SessionExpired = 'SessionExpired',
// Local Errors
LocalTooManyRequests = 'LocalTooManyRequests',
LocalPreconditionFailed = 'LocalPreconditionFailed',
LocalInvalidContent = 'LocalInvalidContent',

View File

@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { IUserDataSyncService, SyncStatus, IUserDataSyncStoreService, SyncResource, IUserDataSyncLogService, IUserDataSynchroniser, UserDataSyncStoreError, UserDataSyncErrorCode, UserDataSyncError, SyncResourceConflicts, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
import { IUserDataSyncService, SyncStatus, IUserDataSyncStoreService, SyncResource, IUserDataSyncLogService, IUserDataSynchroniser, UserDataSyncErrorCode, UserDataSyncError, SyncResourceConflicts, ISyncResourceHandle } from 'vs/platform/userDataSync/common/userDataSync';
import { Disposable } from 'vs/base/common/lifecycle';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Emitter, Event } from 'vs/base/common/event';
@ -26,7 +26,7 @@ import { platform, PlatformToString } from 'vs/base/common/platform';
import { escapeRegExpCharacters } from 'vs/base/common/strings';
type SyncClassification = {
source?: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
resource?: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
};
const SESSION_ID_KEY = 'sync.sessionId';
@ -96,26 +96,40 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
async pull(): Promise<void> {
await this.checkEnablement();
for (const synchroniser of this.synchronisers) {
try {
await synchroniser.pull();
} catch (e) {
this.handleSyncError(e, synchroniser.resource);
try {
for (const synchroniser of this.synchronisers) {
try {
await synchroniser.pull();
} catch (e) {
this.handleSynchronizerError(e, synchroniser.resource);
}
}
this.updateLastSyncTime();
} catch (error) {
if (error instanceof UserDataSyncError) {
this.telemetryService.publicLog2<{ resource?: string }, SyncClassification>(`sync/error/${UserDataSyncErrorCode.TooLarge}`, { resource: error.resource });
}
throw error;
}
this.updateLastSyncTime();
}
async push(): Promise<void> {
await this.checkEnablement();
for (const synchroniser of this.synchronisers) {
try {
await synchroniser.push();
} catch (e) {
this.handleSyncError(e, synchroniser.resource);
try {
for (const synchroniser of this.synchronisers) {
try {
await synchroniser.push();
} catch (e) {
this.handleSynchronizerError(e, synchroniser.resource);
}
}
this.updateLastSyncTime();
} catch (error) {
if (error instanceof UserDataSyncError) {
this.telemetryService.publicLog2<{ resource?: string }, SyncClassification>(`sync/error/${UserDataSyncErrorCode.TooLarge}`, { resource: error.resource });
}
throw error;
}
this.updateLastSyncTime();
}
private recoveredSettings: boolean = false;
@ -169,7 +183,7 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
try {
await synchroniser.sync(manifest);
} catch (e) {
this.handleSyncError(e, synchroniser.resource);
this.handleSynchronizerError(e, synchroniser.resource);
this._syncErrors.push([synchroniser.resource, UserDataSyncError.toUserDataSyncError(e)]);
}
}
@ -192,6 +206,11 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
this.logService.info(`Sync done. Took ${new Date().getTime() - startTime}ms`);
this.updateLastSyncTime();
} catch (error) {
if (error instanceof UserDataSyncError) {
this.telemetryService.publicLog2<{ resource?: string }, SyncClassification>(`sync/error/${UserDataSyncErrorCode.TooLarge}`, { resource: error.resource });
}
throw error;
} finally {
this.updateStatus();
this._onSyncErrors.fire(this._syncErrors);
@ -374,18 +393,16 @@ export class UserDataSyncService extends Disposable implements IUserDataSyncServ
}
}
private handleSyncError(e: Error, source: SyncResource): void {
if (e instanceof UserDataSyncStoreError) {
private handleSynchronizerError(e: Error, source: SyncResource): void {
if (e instanceof UserDataSyncError) {
switch (e.code) {
case UserDataSyncErrorCode.TooLarge:
this.telemetryService.publicLog2<{ source: string }, SyncClassification>(`sync/error/${UserDataSyncErrorCode.TooLarge}`, { source });
break;
case UserDataSyncErrorCode.TooManyRequests:
case UserDataSyncErrorCode.LocalTooManyRequests:
this.telemetryService.publicLog2(`sync/error/${e.code}`);
break;
case UserDataSyncErrorCode.UpgradeRequired:
case UserDataSyncErrorCode.Incompatible:
throw e;
}
throw e;
}
this.logService.error(e);
this.logService.error(`${source}: ${toErrorMessage(e)}`);

View File

@ -262,18 +262,18 @@ export class UserDataSyncStoreService extends Disposable implements IUserDataSyn
throw new UserDataSyncStoreError(`Request '${options.url?.toString()}' failed because of Unauthorized (401).`, UserDataSyncErrorCode.Unauthorized);
}
if (context.res.statusCode === 403) {
throw new UserDataSyncStoreError(`Request '${options.url?.toString()}' is Forbidden (403).`, UserDataSyncErrorCode.Forbidden);
}
if (context.res.statusCode === 412) {
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of Precondition Failed (412). There is new data exists for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.RemotePreconditionFailed);
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of Precondition Failed (412). There is new data exists for this resource. Make the request again with latest data.`, UserDataSyncErrorCode.PreconditionFailed);
}
if (context.res.statusCode === 413) {
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of too large payload (413).`, UserDataSyncErrorCode.TooLarge);
}
if (context.res.statusCode === 426) {
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed with status Upgrade Required (426). Please upgrade the client and try again.`, UserDataSyncErrorCode.UpgradeRequired);
}
if (context.res.statusCode === 429) {
throw new UserDataSyncStoreError(`${options.type} request '${options.url?.toString()}' failed because of too many requests (429).`, UserDataSyncErrorCode.TooManyRequests);
}

View File

@ -24,6 +24,11 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
import { dirname } from 'vs/base/common/resources';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
export interface WebviewIntialized {
__vscode_notebook_message: boolean;
type: 'initialized'
}
export interface IDimensionMessage {
__vscode_notebook_message: boolean;
type: 'dimension';
@ -107,6 +112,7 @@ export interface IScrollRequestMessage {
export interface IUpdatePreloadResourceMessage {
type: 'preload';
resources: string[];
source: string;
}
interface ICachedInset {
@ -124,7 +130,7 @@ function html(strings: TemplateStringsArray, ...values: any[]): string {
return str;
}
type IMessage = IDimensionMessage | IScrollAckMessage | IWheelMessage | IMouseEnterMessage | IMouseLeaveMessage | IBlurOutputMessage;
type IMessage = IDimensionMessage | IScrollAckMessage | IWheelMessage | IMouseEnterMessage | IMouseLeaveMessage | IBlurOutputMessage | WebviewIntialized;
let version = 0;
export class BackLayerWebView extends Disposable {
@ -134,12 +140,12 @@ export class BackLayerWebView extends Disposable {
hiddenInsetMapping: Set<IOutput> = new Set();
reversedInsetMapping: Map<string, IOutput> = new Map();
preloadsCache: Map<string, boolean> = new Map();
kernelPreloadsCache: Map<string, boolean> = new Map();
localResourceRootsCache: URI[] | undefined = undefined;
rendererRootsCache: URI[] = [];
kernelRootsCache: URI[] = [];
private readonly _onMessage = this._register(new Emitter<any>());
public readonly onMessage: Event<any> = this._onMessage.event;
private _loaded!: Promise<void>;
private _initalized: Promise<void>;
private _disposed = false;
@ -473,6 +479,11 @@ ${loaderJs}
}
}
});
vscode.postMessage({
__vscode_notebook_message: true,
type: 'initialized'
});
}());
</script>
@ -584,6 +595,19 @@ ${loaderJs}
allowScripts: true,
localResourceRoots: this.localResourceRootsCache
}, undefined);
let resolveFunc: () => void;
this._loaded = new Promise<void>((resolve, reject) => {
resolveFunc = resolve;
});
let dispose = webview.onMessage((data: IMessage) => {
if (data.__vscode_notebook_message && data.type === 'initialized') {
resolveFunc();
dispose.dispose();
}
});
webview.html = content;
return webview;
}
@ -744,11 +768,13 @@ ${loaderJs}
}, 50);
}
updateKernelPreloads(extensionLocations: URI[], preloads: URI[]) {
async updateKernelPreloads(extensionLocations: URI[], preloads: URI[]) {
if (this._disposed) {
return;
}
await this._loaded;
let resources: string[] = [];
preloads = preloads.map(preload => {
if (this.environmentService.isExtensionDevelopment && (preload.scheme === 'http' || preload.scheme === 'https')) {
@ -758,9 +784,9 @@ ${loaderJs}
});
preloads.forEach(e => {
if (!this.kernelPreloadsCache.has(e.toString())) {
if (!this.preloadsCache.has(e.toString())) {
resources.push(e.toString());
this.kernelPreloadsCache.set(e.toString(), true);
this.preloadsCache.set(e.toString(), true);
}
});
@ -769,14 +795,16 @@ ${loaderJs}
}
this.kernelRootsCache = [...extensionLocations, ...this.kernelRootsCache];
this._updatePreloads(resources);
this._updatePreloads(resources, 'kernel');
}
updateRendererPreloads(preloads: ReadonlySet<number>) {
async updateRendererPreloads(preloads: ReadonlySet<number>) {
if (this._disposed) {
return;
}
await this._loaded;
let resources: string[] = [];
let extensionLocations: URI[] = [];
preloads.forEach(preload => {
@ -799,23 +827,23 @@ ${loaderJs}
}
});
if (!resources.length) {
return;
}
this.rendererRootsCache = extensionLocations;
this._updatePreloads(resources);
this._updatePreloads(resources, 'renderer');
}
private _updatePreloads(resources: string[]) {
private _updatePreloads(resources: string[], source: string) {
const mixedResourceRoots = [...(this.localResourceRootsCache || []), ...this.rendererRootsCache, ...this.kernelRootsCache];
this.webview.contentOptions = {
allowMultipleAPIAcquire: true,
allowScripts: true,
enableCommandUris: true,
localResourceRoots: mixedResourceRoots
};
this.webview.localResourcesRoot = mixedResourceRoots;
let message: IUpdatePreloadResourceMessage = {
type: 'preload',
resources: resources
resources: resources,
source: source
};
this.webview.sendMessage(message);

View File

@ -28,7 +28,7 @@ const languageScopeSchemaId = 'vscode://schemas/snippets';
const snippetSchemaProperties: IJSONSchemaMap = {
prefix: {
description: nls.localize('snippetSchema.json.prefix', 'The prefix to used when selecting the snippet in intellisense'),
description: nls.localize('snippetSchema.json.prefix', 'The prefix to use when selecting the snippet in intellisense'),
type: ['string', 'array']
},
body: {

View File

@ -2515,38 +2515,58 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer
location: ProgressLocation.Window,
title: nls.localize('TaskService.fetchingBuildTasks', 'Fetching build tasks...')
};
let promise = this.getTasksForGroup(TaskGroup.Build).then((tasks) => {
if (tasks.length > 0) {
let { defaults, users } = this.splitPerGroupType(tasks);
if (defaults.length === 1) {
this.run(defaults[0]).then(undefined, reason => {
// eat the error, it has already been surfaced to the user and we don't care about it here
});
return;
} else if (defaults.length + users.length > 0) {
tasks = defaults.concat(users);
let promise = this.getWorkspaceTasks().then(tasks => {
const buildTasks: ConfiguringTask[] = [];
for (const taskSource of tasks) {
for (const task in taskSource[1].configurations?.byIdentifier) {
if ((taskSource[1].configurations?.byIdentifier[task].configurationProperties.group === TaskGroup.Build) &&
(taskSource[1].configurations?.byIdentifier[task].configurationProperties.groupType === GroupType.default)) {
buildTasks.push(taskSource[1].configurations.byIdentifier[task]);
}
}
}
this.showIgnoredFoldersMessage().then(() => {
this.showQuickPick(tasks,
nls.localize('TaskService.pickBuildTask', 'Select the build task to run'),
{
label: nls.localize('TaskService.noBuildTask', 'No build task to run found. Configure Build Task...'),
task: null
},
true).then((entry) => {
let task: Task | undefined | null = entry ? entry.task : undefined;
if (task === undefined) {
return;
}
if (task === null) {
this.runConfigureDefaultBuildTask();
return;
}
this.run(task, { attachProblemMatcher: true }).then(undefined, reason => {
if (buildTasks.length === 1) {
this.tryResolveTask(buildTasks[0]).then(resolvedTask => {
this.run(resolvedTask).then(undefined, reason => {
// eat the error, it has already been surfaced to the user and we don't care about it here
});
});
return;
}
return this.getTasksForGroup(TaskGroup.Build).then((tasks) => {
if (tasks.length > 0) {
let { defaults, users } = this.splitPerGroupType(tasks);
if (defaults.length === 1) {
this.run(defaults[0]).then(undefined, reason => {
// eat the error, it has already been surfaced to the user and we don't care about it here
});
});
return;
} else if (defaults.length + users.length > 0) {
tasks = defaults.concat(users);
}
}
this.showIgnoredFoldersMessage().then(() => {
this.showQuickPick(tasks,
nls.localize('TaskService.pickBuildTask', 'Select the build task to run'),
{
label: nls.localize('TaskService.noBuildTask', 'No build task to run found. Configure Build Task...'),
task: null
},
true).then((entry) => {
let task: Task | undefined | null = entry ? entry.task : undefined;
if (task === undefined) {
return;
}
if (task === null) {
this.runConfigureDefaultBuildTask();
return;
}
this.run(task, { attachProblemMatcher: true }).then(undefined, reason => {
// eat the error, it has already been surfaced to the user and we don't care about it here
});
});
});
});
});
this.progressService.withProgress(options, () => promise);

View File

@ -1276,9 +1276,6 @@ export class TerminalTaskSystem implements ITaskSystem {
}
}
if (basename === 'cmd' && platform === Platform.Platform.Windows && commandQuoted && argQuoted) {
commandLine = '"' + commandLine + '"';
}
return commandLine;
}

View File

@ -136,7 +136,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
this.userDataSyncWorkbenchService.onDidChangeAccountStatus
)(() => this.updateBadge()));
this._register(userDataSyncService.onDidChangeConflicts(() => this.onDidChangeConflicts(this.userDataSyncService.conflicts)));
this._register(userDataSyncService.onSyncErrors(errors => this.onSyncErrors(errors)));
this._register(userDataSyncService.onSyncErrors(errors => this.onSynchronizerErrors(errors)));
this._register(userDataAutoSyncService.onError(error => this.onAutoSyncError(error)));
this.registerActions();
@ -261,7 +261,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
}
private onAutoSyncError(error: UserDataSyncError): void {
private onAutoSyncError(error: UserDataSyncError): boolean {
switch (error.code) {
case UserDataSyncErrorCode.TurnedOff:
case UserDataSyncErrorCode.SessionExpired:
@ -272,7 +272,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
primary: [new Action('turn on sync', localize('turn on sync', "Turn on Preferences Sync..."), undefined, true, () => this.turnOn())]
}
});
return;
return true;
case UserDataSyncErrorCode.TooLarge:
if (error.resource === SyncResource.Keybindings || error.resource === SyncResource.Settings) {
this.disableSync(error.resource);
@ -286,19 +286,21 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
});
}
return;
return true;
case UserDataSyncErrorCode.Incompatible:
case UserDataSyncErrorCode.UpgradeRequired:
this.disableSync();
this.notificationService.notify({
severity: Severity.Error,
message: localize('error incompatible', "Turned off sync because local data is incompatible with the data in the cloud. Please update {0} and turn on sync to continue syncing.", this.productService.nameLong),
message: localize('error upgrade required', "Turned off sync because the current version ({0}) of {1} is not compatible with the Preferences Sync Service. Please update and turn on sync to continue syncing.", this.productService.version, this.productService.nameLong),
});
return;
return true;
}
return false;
}
private readonly invalidContentErrorDisposables = new Map<SyncResource, IDisposable>();
private onSyncErrors(errors: [SyncResource, UserDataSyncError][]): void {
private onSynchronizerErrors(errors: [SyncResource, UserDataSyncError][]): void {
if (errors.length) {
for (const [source, error] of errors) {
switch (error.code) {
@ -392,6 +394,14 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
}
await this.userDataSyncWorkbenchService.turnOn();
this.storageService.store('sync.donotAskPreviewConfirmation', true, StorageScope.GLOBAL);
} catch (e) {
if (isPromiseCanceledError(e)) {
return;
}
if (e instanceof UserDataSyncError && this.onAutoSyncError(e)) {
return;
}
this.notificationService.error(localize('turn on failed', "Error while starting Sync: {0}", toErrorMessage(e)));
} finally {
this.turningOnSync = false;
}
@ -616,15 +626,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
private registerTurnOnSyncAction(): void {
const turnOnSyncWhenContext = ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), CONTEXT_SYNC_ENABLEMENT.toNegated(), CONTEXT_ACCOUNT_STATE.notEqualsTo(AccountStatus.Uninitialized), CONTEXT_TURNING_ON_STATE.negate());
CommandsRegistry.registerCommand(turnOnSyncCommand.id, async () => {
try {
await this.turnOn();
} catch (e) {
if (!isPromiseCanceledError(e)) {
this.notificationService.error(localize('turn on failed', "Error while starting Sync: {0}", toErrorMessage(e)));
}
}
});
CommandsRegistry.registerCommand(turnOnSyncCommand.id, () => this.turnOn());
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '5_sync',
command: {

View File

@ -6,6 +6,7 @@
import { addClass } from 'vs/base/browser/dom';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@ -248,6 +249,10 @@ export abstract class BaseWebview<T extends HTMLElement> extends Disposable {
this.doUpdateContent();
}
public set localResourcesRoot(resources: URI[]) {
/** no op */
}
public set state(state: string | undefined) {
this.content = {
html: this.content.html,

View File

@ -7,6 +7,7 @@ import { Dimension } from 'vs/base/browser/dom';
import { IMouseWheelEvent } from 'vs/base/browser/mouseEvent';
import { memoize } from 'vs/base/common/decorators';
import { Emitter, Event } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { Disposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
@ -174,6 +175,10 @@ export class DynamicWebviewEditorOverlay extends Disposable implements WebviewOv
this.withWebview(webview => webview.contentOptions = value);
}
public set localResourcesRoot(resources: URI[]) {
this.withWebview(webview => webview.localResourcesRoot = resources);
}
private readonly _onDidFocus = this._register(new Emitter<void>());
public readonly onDidFocus: Event<void> = this._onDidFocus.event;

View File

@ -76,6 +76,7 @@ export interface WebviewExtensionDescription {
export interface Webview extends IDisposable {
html: string;
contentOptions: WebviewContentOptions;
localResourcesRoot: URI[];
extension: WebviewExtensionDescription | undefined;
initialScrollProgress: number;
state: string | undefined;

View File

@ -381,6 +381,11 @@ export class ElectronWebviewBasedWebview extends BaseWebview<WebviewTag> impleme
super.contentOptions = options;
}
public set localResourcesRoot(resources: URI[]) {
this._protocolProvider.update(resources || []);
super.localResourcesRoot = resources;
}
protected readonly extraContentOptions = {};
public set html(value: string) {

View File

@ -421,22 +421,6 @@ class KeybindingItemMatches {
return this.wordMatchesMetaModifier(word);
}
private wordMatchesMetaModifier(word: string): boolean {
if (matchesPrefix(this.modifierLabels.ui.metaKey, word)) {
return true;
}
if (matchesPrefix(this.modifierLabels.aria.metaKey, word)) {
return true;
}
if (matchesPrefix(this.modifierLabels.user.metaKey, word)) {
return true;
}
if (matchesPrefix(localize('meta', "meta"), word)) {
return true;
}
return false;
}
private matchesCtrlModifier(keybinding: ResolvedKeybindingPart | null, word: string): boolean {
if (!keybinding) {
return false;
@ -447,19 +431,6 @@ class KeybindingItemMatches {
return this.wordMatchesCtrlModifier(word);
}
private wordMatchesCtrlModifier(word: string): boolean {
if (matchesPrefix(this.modifierLabels.ui.ctrlKey, word)) {
return true;
}
if (matchesPrefix(this.modifierLabels.aria.ctrlKey, word)) {
return true;
}
if (matchesPrefix(this.modifierLabels.user.ctrlKey, word)) {
return true;
}
return false;
}
private matchesShiftModifier(keybinding: ResolvedKeybindingPart | null, word: string): boolean {
if (!keybinding) {
return false;
@ -470,19 +441,6 @@ class KeybindingItemMatches {
return this.wordMatchesShiftModifier(word);
}
private wordMatchesShiftModifier(word: string): boolean {
if (matchesPrefix(this.modifierLabels.ui.shiftKey, word)) {
return true;
}
if (matchesPrefix(this.modifierLabels.aria.shiftKey, word)) {
return true;
}
if (matchesPrefix(this.modifierLabels.user.shiftKey, word)) {
return true;
}
return false;
}
private matchesAltModifier(keybinding: ResolvedKeybindingPart | null, word: string): boolean {
if (!keybinding) {
return false;
@ -493,22 +451,6 @@ class KeybindingItemMatches {
return this.wordMatchesAltModifier(word);
}
private wordMatchesAltModifier(word: string): boolean {
if (matchesPrefix(this.modifierLabels.ui.altKey, word)) {
return true;
}
if (matchesPrefix(this.modifierLabels.aria.altKey, word)) {
return true;
}
if (matchesPrefix(this.modifierLabels.user.altKey, word)) {
return true;
}
if (matchesPrefix(localize('option', "option"), word)) {
return true;
}
return false;
}
private hasAnyMatch(keybindingMatch: KeybindingMatch): boolean {
return !!keybindingMatch.altKey ||
!!keybindingMatch.ctrlKey ||
@ -574,4 +516,62 @@ class KeybindingItemMatches {
}
return false;
}
private wordMatchesAltModifier(word: string): boolean {
if (strings.equalsIgnoreCase(this.modifierLabels.ui.altKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(this.modifierLabels.aria.altKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(this.modifierLabels.user.altKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(localize('option', "option"), word)) {
return true;
}
return false;
}
private wordMatchesCtrlModifier(word: string): boolean {
if (strings.equalsIgnoreCase(this.modifierLabels.ui.ctrlKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(this.modifierLabels.aria.ctrlKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(this.modifierLabels.user.ctrlKey, word)) {
return true;
}
return false;
}
private wordMatchesMetaModifier(word: string): boolean {
if (strings.equalsIgnoreCase(this.modifierLabels.ui.metaKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(this.modifierLabels.aria.metaKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(this.modifierLabels.user.metaKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(localize('meta', "meta"), word)) {
return true;
}
return false;
}
private wordMatchesShiftModifier(word: string): boolean {
if (strings.equalsIgnoreCase(this.modifierLabels.ui.shiftKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(this.modifierLabels.aria.shiftKey, word)) {
return true;
}
if (strings.equalsIgnoreCase(this.modifierLabels.user.shiftKey, word)) {
return true;
}
return false;
}
}

View File

@ -34,7 +34,7 @@ class AnAction extends Action {
}
}
suite('KeybindingsEditorModel test', () => {
suite('KeybindingsEditorModel', () => {
let instantiationService: TestInstantiationService;
let testObject: KeybindingsEditorModel;
@ -568,6 +568,46 @@ suite('KeybindingsEditorModel test', () => {
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { keyCode: true });
});
test('filter modifiers are not matched when not completely matched (prefix)', async () => {
testObject = instantiationService.createInstance(KeybindingsEditorModel, OperatingSystem.Macintosh);
const term = `alt.${uuid.generateUuid()}`;
const command = `command.${term}`;
const expected = aResolvedKeybindingItem({ command, firstPart: { keyCode: KeyCode.Escape }, isDefault: false });
prepareKeybindingService(expected, aResolvedKeybindingItem({ command: 'some_command', firstPart: { keyCode: KeyCode.Escape, modifiers: { altKey: true } }, isDefault: false }));
await testObject.resolve(new Map<string, string>());
const actual = testObject.fetch(term);
assert.equal(1, actual.length);
assert.equal(command, actual[0].keybindingItem.command);
assert.equal(1, actual[0].commandIdMatches?.length);
});
test('filter modifiers are not matched when not completely matched (includes)', async () => {
testObject = instantiationService.createInstance(KeybindingsEditorModel, OperatingSystem.Macintosh);
const term = `abcaltdef.${uuid.generateUuid()}`;
const command = `command.${term}`;
const expected = aResolvedKeybindingItem({ command, firstPart: { keyCode: KeyCode.Escape }, isDefault: false });
prepareKeybindingService(expected, aResolvedKeybindingItem({ command: 'some_command', firstPart: { keyCode: KeyCode.Escape, modifiers: { altKey: true } }, isDefault: false }));
await testObject.resolve(new Map<string, string>());
const actual = testObject.fetch(term);
assert.equal(1, actual.length);
assert.equal(command, actual[0].keybindingItem.command);
assert.equal(1, actual[0].commandIdMatches?.length);
});
test('filter modifiers are matched with complete term', async () => {
testObject = instantiationService.createInstance(KeybindingsEditorModel, OperatingSystem.Macintosh);
const command = `command.${uuid.generateUuid()}`;
const expected = aResolvedKeybindingItem({ command, firstPart: { keyCode: KeyCode.Escape, modifiers: { altKey: true } }, isDefault: false });
prepareKeybindingService(expected, aResolvedKeybindingItem({ command: 'some_command', firstPart: { keyCode: KeyCode.Escape }, isDefault: false }));
await testObject.resolve(new Map<string, string>());
const actual = testObject.fetch('alt').filter(element => element.keybindingItem.command === command);
assert.equal(1, actual.length);
assert.deepEqual(actual[0].keybindingMatches!.firstPart, { altKey: true });
});
function prepareKeybindingService(...keybindingItems: ResolvedKeybindingItem[]): ResolvedKeybindingItem[] {
instantiationService.stub(IKeybindingService, 'getKeybindings', () => keybindingItems);
instantiationService.stub(IKeybindingService, 'getDefaultKeybindings', () => keybindingItems);

View File

@ -30,7 +30,7 @@ import { ITextModel } from 'vs/editor/common/model';
import { nullExtensionDescription, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { dispose } from 'vs/base/common/lifecycle';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { NullApiDeprecationService } from 'vs/workbench/api/common/extHostApiDeprecationService';
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection';
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';

View File

@ -8,7 +8,7 @@ import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
import { MainThreadCommandsShape } from 'vs/workbench/api/common/extHost.protocol';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { SingleProxyRPCProtocol } from './testRPCProtocol';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { NullLogService } from 'vs/platform/log/common/log';
suite('ExtHostCommands', function () {

View File

@ -10,7 +10,7 @@ import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfigurat
import { MainThreadConfigurationShape, IConfigurationInitData } from 'vs/workbench/api/common/extHost.protocol';
import { ConfigurationModel, ConfigurationModelParser } from 'vs/platform/configuration/common/configurationModels';
import { TestRPCProtocol } from './testRPCProtocol';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { IWorkspaceFolder, WorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { ConfigurationTarget, IConfigurationModel, IConfigurationChange } from 'vs/platform/configuration/common/configuration';
import { NullLogService } from 'vs/platform/log/common/log';

View File

@ -9,7 +9,7 @@ import { DiagnosticCollection, ExtHostDiagnostics } from 'vs/workbench/api/commo
import { Diagnostic, DiagnosticSeverity, Range, DiagnosticRelatedInformation, Location } from 'vs/workbench/api/common/extHostTypes';
import { MainThreadDiagnosticsShape, IMainContext } from 'vs/workbench/api/common/extHost.protocol';
import { IMarkerData, MarkerSeverity } from 'vs/platform/markers/common/markers';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { Emitter, Event } from 'vs/base/common/event';
import { NullLogService } from 'vs/platform/log/common/log';
import type * as vscode from 'vscode';

View File

@ -10,7 +10,7 @@ import { Position } from 'vs/workbench/api/common/extHostTypes';
import { Range } from 'vs/editor/common/core/range';
import { MainThreadDocumentsShape } from 'vs/workbench/api/common/extHost.protocol';
import { IModelChangedEvent } from 'vs/editor/common/model/mirrorTextModel';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
suite('ExtHostDocumentData', () => {

View File

@ -12,7 +12,7 @@ import { ExtHostDocumentSaveParticipant } from 'vs/workbench/api/common/extHostD
import { SingleProxyRPCProtocol } from './testRPCProtocol';
import { SaveReason } from 'vs/workbench/common/editor';
import type * as vscode from 'vscode';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { NullLogService } from 'vs/platform/log/common/log';
import { timeout } from 'vs/base/common/async';
import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';

View File

@ -43,7 +43,7 @@ import { getColors } from 'vs/editor/contrib/colorPicker/color';
import { CancellationToken } from 'vs/base/common/cancellation';
import { nullExtensionDescription as defaultExtension } from 'vs/workbench/services/extensions/common/extensions';
import { provideSelectionRanges } from 'vs/editor/contrib/smartSelect/smartSelect';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { dispose } from 'vs/base/common/lifecycle';
import { withNullAsUndefined } from 'vs/base/common/types';

View File

@ -8,7 +8,7 @@ import { MainThreadMessageService } from 'vs/workbench/api/browser/mainThreadMes
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { INotificationService, INotification, NoOpNotification, INotificationHandle, Severity, IPromptChoice, IPromptOptions, IStatusMessageOptions, NotificationsFilter } from 'vs/platform/notification/common/notification';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { IDisposable, Disposable } from 'vs/base/common/lifecycle';
import * as platform from 'vs/base/common/platform';

View File

@ -9,7 +9,7 @@ import { MainThreadTextEditorsShape, IResolvedTextEditorConfiguration, ITextEdit
import { ExtHostTextEditorOptions, ExtHostTextEditor } from 'vs/workbench/api/common/extHostTextEditor';
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { NullLogService } from 'vs/platform/log/common/log';
suite('ExtHostTextEditor', () => {

View File

@ -6,7 +6,7 @@ import * as assert from 'assert';
import * as extHostTypes from 'vs/workbench/api/common/extHostTypes';
import { MainContext, MainThreadTextEditorsShape, IWorkspaceEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { URI } from 'vs/base/common/uri';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { SingleProxyRPCProtocol, TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
import { ExtHostEditors } from 'vs/workbench/api/common/extHostTextEditors';

View File

@ -14,7 +14,7 @@ import { TestRPCProtocol } from './testRPCProtocol';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { MainThreadCommands } from 'vs/workbench/api/browser/mainThreadCommands';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { TreeItemCollapsibleState, ITreeItem } from 'vs/workbench/common/views';
import { NullLogService } from 'vs/platform/log/common/log';
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';

View File

@ -11,7 +11,7 @@ import { NullLogService } from 'vs/platform/log/common/log';
import { MainThreadWebviews } from 'vs/workbench/api/browser/mainThreadWebview';
import { ExtHostWebviews } from 'vs/workbench/api/common/extHostWebview';
import { EditorViewColumn } from 'vs/workbench/api/common/shared/editor';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { SingleProxyRPCProtocol } from './testRPCProtocol';
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
import { ExtHostDocuments } from 'vs/workbench/api/common/extHostDocuments';

View File

@ -14,7 +14,7 @@ import { MainThreadWorkspace } from 'vs/workbench/api/browser/mainThreadWorkspac
import { IMainContext, IWorkspaceData, MainContext, ITextSearchComplete } from 'vs/workbench/api/common/extHost.protocol';
import { RelativePattern } from 'vs/workbench/api/common/extHostTypes';
import { ExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { TestRPCProtocol } from './testRPCProtocol';
import { ExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';

View File

@ -8,7 +8,7 @@ import { MainThreadCommands } from 'vs/workbench/api/browser/mainThreadCommands'
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
import { SingleProxyRPCProtocol } from './testRPCProtocol';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
suite('MainThreadCommands', function () {

View File

@ -7,7 +7,7 @@ import * as assert from 'assert';
import { URI } from 'vs/base/common/uri';
import { MainThreadDocumentContentProviders } from 'vs/workbench/api/browser/mainThreadDocumentContentProviders';
import { createTextModel } from 'vs/editor/test/common/editorTestUtils';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { IModelService } from 'vs/editor/common/services/modelService';
import { IEditorWorkerService } from 'vs/editor/common/services/editorWorkerService';
import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';

View File

@ -12,7 +12,7 @@ import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ExtHostDocumentsAndEditorsShape, IDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
import { createTestCodeEditor, ITestCodeEditor } from 'vs/editor/test/browser/testCodeEditor';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { TestEditorService, TestEditorGroupsService, TestEnvironmentService } from 'vs/workbench/test/browser/workbenchTestServices';
import { Event } from 'vs/base/common/event';
import { ITextModel } from 'vs/editor/common/model';

View File

@ -11,7 +11,7 @@ import { ModelServiceImpl } from 'vs/editor/common/services/modelServiceImpl';
import { TestCodeEditorService } from 'vs/editor/test/browser/editorTestServices';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
import { ExtHostDocumentsAndEditorsShape, ExtHostContext, ExtHostDocumentsShape, IWorkspaceTextEditDto } from 'vs/workbench/api/common/extHost.protocol';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { Event } from 'vs/base/common/event';
import { MainThreadTextEditors } from 'vs/workbench/api/browser/mainThreadEditors';
import { URI } from 'vs/base/common/uri';

View File

@ -19,7 +19,7 @@ import { TestRPCProtocol } from 'vs/workbench/test/browser/api/testRPCProtocol';
import type * as vscode from 'vscode';
import { NullLogService } from 'vs/platform/log/common/log';
import { URITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
import { mock } from 'vs/workbench/test/browser/api/mock';
import { mock } from 'vs/base/test/common/mock';
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
import { TextSearchManager } from 'vs/workbench/services/search/common/textSearchManager';
import { NativeTextSearchManager } from 'vs/workbench/services/search/node/textSearchManager';