Merge branch 'master' into ben/electron-sandbox
This commit is contained in:
commit
76590a7764
|
@ -207,6 +207,7 @@
|
|||
"vs/nls",
|
||||
"**/vs/base/common/**",
|
||||
"**/vs/base/parts/*/common/**",
|
||||
"**/vs/base/test/common/**",
|
||||
"**/vs/platform/*/common/**",
|
||||
"**/vs/platform/*/test/common/**"
|
||||
]
|
||||
|
|
211
src/vs/platform/undoRedo/test/common/undoRedoService.test.ts
Normal file
211
src/vs/platform/undoRedo/test/common/undoRedoService.test.ts
Normal 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);
|
||||
|
||||
});
|
||||
});
|
|
@ -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...`);
|
||||
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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)}`);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1276,9 +1276,6 @@ export class TerminalTaskSystem implements ITaskSystem {
|
|||
}
|
||||
}
|
||||
|
||||
if (basename === 'cmd' && platform === Platform.Platform.Windows && commandQuoted && argQuoted) {
|
||||
commandLine = '"' + commandLine + '"';
|
||||
}
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
|
|
|
@ -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: {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 () {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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 () {
|
||||
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
|
Loading…
Reference in a new issue