From 6a242516e497b62cca508181395757d2b30c69a3 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 3 Nov 2020 08:56:12 +0100 Subject: [PATCH 01/17] storage - first cut target support (user, machine) --- .../multicursor/test/multicursor.test.ts | 4 +- .../storage/browser/storageService.ts | 32 +-- src/vs/platform/storage/common/storage.ts | 200 ++++++++++++++---- .../platform/storage/node/storageService.ts | 27 +-- .../test/common/storageService.test.ts | 139 ++++++++++++ .../storage/test/node/storageService.test.ts | 69 +----- 6 files changed, 322 insertions(+), 149 deletions(-) create mode 100644 src/vs/platform/storage/test/common/storageService.test.ts diff --git a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts index 8b25ecac5e1..7b0f0f4ed7d 100644 --- a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts @@ -66,12 +66,14 @@ suite('Multicursor selection', () => { get: (key: string) => queryState[key], getBoolean: (key: string) => !!queryState[key], getNumber: (key: string) => undefined!, + store2: (key: string, value: any) => { queryState[key] = value; return Promise.resolve(); }, store: (key: string, value: any) => { queryState[key] = value; return Promise.resolve(); }, remove: (key) => undefined, logStorage: () => undefined, migrate: (toWorkspace) => Promise.resolve(undefined), flush: () => undefined, - isNew: () => true + isNew: () => true, + keys: () => [] } as IStorageService); test('issue #8817: Cursor position changes when you cancel multicursor', () => { diff --git a/src/vs/platform/storage/browser/storageService.ts b/src/vs/platform/storage/browser/storageService.ts index 5fc163c5b2b..32a9c9d595c 100644 --- a/src/vs/platform/storage/browser/storageService.ts +++ b/src/vs/platform/storage/browser/storageService.ts @@ -5,7 +5,7 @@ import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import { Emitter } from 'vs/base/common/event'; -import { IStorageChangeEvent, IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason, logStorage, IS_NEW_KEY } from 'vs/platform/storage/common/storage'; +import { StorageScope, logStorage, IS_NEW_KEY, AbstractStorageService } from 'vs/platform/storage/common/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces'; import { IFileService, FileChangeType } from 'vs/platform/files/common/files'; @@ -16,15 +16,7 @@ import { runWhenIdle, RunOnceScheduler } from 'vs/base/common/async'; import { VSBuffer } from 'vs/base/common/buffer'; import { assertIsDefined, assertAllDefined } from 'vs/base/common/types'; -export class BrowserStorageService extends Disposable implements IStorageService { - - declare readonly _serviceBrand: undefined; - - private readonly _onDidChangeStorage = this._register(new Emitter()); - readonly onDidChangeStorage = this._onDidChangeStorage.event; - - private readonly _onWillSaveState = this._register(new Emitter()); - readonly onWillSaveState = this._onWillSaveState.event; +export class BrowserStorageService extends AbstractStorageService { private globalStorage: IStorage | undefined; private workspaceStorage: IStorage | undefined; @@ -40,6 +32,10 @@ export class BrowserStorageService extends Disposable implements IStorageService private readonly periodicFlushScheduler = this._register(new RunOnceScheduler(() => this.doFlushWhenIdle(), 5000 /* every 5s */)); private runWhenIdleDisposable: IDisposable | undefined = undefined; + get hasPendingUpdate(): boolean { + return (!!this.globalStorageDatabase && this.globalStorageDatabase.hasPendingUpdate) || (!!this.workspaceStorageDatabase && this.workspaceStorageDatabase.hasPendingUpdate); + } + constructor( @IEnvironmentService private readonly environmentService: IEnvironmentService, @IFileService private readonly fileService: IFileService @@ -122,11 +118,11 @@ export class BrowserStorageService extends Disposable implements IStorageService return this.getStorage(scope).getNumber(key, fallbackValue); } - store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope): void { + protected doStore(key: string, value: string | boolean | number | undefined | null, scope: StorageScope): void { this.getStorage(scope).set(key, value); } - remove(key: string, scope: StorageScope): void { + protected doRemove(key: string, scope: StorageScope): void { this.getStorage(scope).delete(key); } @@ -175,14 +171,6 @@ export class BrowserStorageService extends Disposable implements IStorageService }); } - get hasPendingUpdate(): boolean { - return (!!this.globalStorageDatabase && this.globalStorageDatabase.hasPendingUpdate) || (!!this.workspaceStorageDatabase && this.workspaceStorageDatabase.hasPendingUpdate); - } - - flush(): void { - this._onWillSaveState.fire({ reason: WillSaveStateReason.NONE }); - } - close(): void { // We explicitly do not close our DBs because writing data onBeforeUnload() // can result in unexpected results. Namely, it seems that - even though this @@ -195,10 +183,6 @@ export class BrowserStorageService extends Disposable implements IStorageService this.dispose(); } - isNew(scope: StorageScope): boolean { - return this.getBoolean(IS_NEW_KEY, scope) === true; - } - dispose(): void { dispose(this.runWhenIdleDisposable); this.runWhenIdleDisposable = undefined; diff --git a/src/vs/platform/storage/common/storage.ts b/src/vs/platform/storage/common/storage.ts index c740786f473..b74e70fb774 100644 --- a/src/vs/platform/storage/common/storage.ts +++ b/src/vs/platform/storage/common/storage.ts @@ -10,6 +10,7 @@ import { isUndefinedOrNull } from 'vs/base/common/types'; import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces'; export const IS_NEW_KEY = '__$__isNewStorageMarker'; +const TARGET_KEY = '__$__targetStorageMarker'; export const IStorageService = createDecorator('storageService'); @@ -48,45 +49,55 @@ export interface IStorageService { /** * Retrieve an element stored with the given key from storage. Use - * the provided defaultValue if the element is null or undefined. + * the provided `defaultValue` if the element is `null` or `undefined`. * - * The scope argument allows to define the scope of the storage - * operation to either the current workspace only or all workspaces. + * @param scope allows to define the scope of the storage operation + * to either the current workspace only or all workspaces. */ get(key: string, scope: StorageScope, fallbackValue: string): string; get(key: string, scope: StorageScope, fallbackValue?: string): string | undefined; /** * Retrieve an element stored with the given key from storage. Use - * the provided defaultValue if the element is null or undefined. The element - * will be converted to a boolean. + * the provided `defaultValue` if the element is `null` or `undefined`. + * The element will be converted to a `boolean`. * - * The scope argument allows to define the scope of the storage - * operation to either the current workspace only or all workspaces. + * @param scope allows to define the scope of the storage operation + * to either the current workspace only or all workspaces. */ getBoolean(key: string, scope: StorageScope, fallbackValue: boolean): boolean; getBoolean(key: string, scope: StorageScope, fallbackValue?: boolean): boolean | undefined; /** * Retrieve an element stored with the given key from storage. Use - * the provided defaultValue if the element is null or undefined. The element - * will be converted to a number using parseInt with a base of 10. + * the provided `defaultValue` if the element is `null` or `undefined`. + * The element will be converted to a `number` using `parseInt` with a + * base of `10`. * - * The scope argument allows to define the scope of the storage - * operation to either the current workspace only or all workspaces. + * @param scope allows to define the scope of the storage operation + * to either the current workspace only or all workspaces. */ getNumber(key: string, scope: StorageScope, fallbackValue: number): number; getNumber(key: string, scope: StorageScope, fallbackValue?: number): number | undefined; /** - * Store a value under the given key to storage. The value will be converted to a string. - * Storing either undefined or null will remove the entry under the key. - * - * The scope argument allows to define the scope of the storage - * operation to either the current workspace only or all workspaces. + * @deprecated use store2 instead */ store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope): void; + /** + * Store a value under the given key to storage. The value will be + * converted to a `string`. Storing either `undefined` or `null` will + * remove the entry under the key. + * + * @param scope allows to define the scope of the storage operation + * to either the current workspace only or all workspaces. + * + * @param target allows to define the target of the storage operation + * to either the current machine or user. + */ + store2(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): void; + /** * Delete an element stored under the provided key from storage. * @@ -95,6 +106,18 @@ export interface IStorageService { */ remove(key: string, scope: StorageScope): void; + /** + * Returns all the keys used in the storage for the provided `scope` + * and `target`. + * + * @param scope allows to define the scope for the keys + * to either the current workspace only or all workspaces. + * + * @param target allows to define the target for the keys + * to either the current machine or user. + */ + keys(scope: StorageScope, target: StorageTarget): string[]; + /** * Log the contents of the storage to the console. */ @@ -108,7 +131,6 @@ export interface IStorageService { /** * Whether the storage for the given scope was created during this session or * existed before. - * */ isNew(scope: StorageScope): boolean; @@ -133,21 +155,136 @@ export const enum StorageScope { WORKSPACE } +export const enum StorageTarget { + + /** + * The stored data is user specific. + */ + USER, + + /** + * The stored data is machine specific. + */ + MACHINE +} + export interface IStorageChangeEvent { readonly key: string; readonly scope: StorageScope; } -export class InMemoryStorageService extends Disposable implements IStorageService { +export abstract class AbstractStorageService extends Disposable implements IStorageService { declare readonly _serviceBrand: undefined; - private readonly _onDidChangeStorage = this._register(new Emitter()); + protected readonly _onDidChangeStorage = this._register(new Emitter()); readonly onDidChangeStorage = this._onDidChangeStorage.event; protected readonly _onWillSaveState = this._register(new Emitter()); readonly onWillSaveState = this._onWillSaveState.event; + store2(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): void { + + // We remove the key for undefined/null values + if (isUndefinedOrNull(value)) { + this.remove(key, scope); + return; + } + + // Store actual value + this.doStore(key, value, scope); + + // Update key-target map + this.updateKeyTarget(key, scope, target); + } + + store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope): void { + this.store2(key, value, scope, StorageTarget.MACHINE); + } + + remove(key: string, scope: StorageScope): void { + + // Remove actual key + this.doRemove(key, scope); + + // Update key-target map + this.updateKeyTarget(key, scope, undefined); + } + + keys(scope: StorageScope, target: StorageTarget): string[] { + const keys: string[] = []; + for (const [key, keyTarget] of Object.entries(this.getKeyTargets(scope))) { + if (keyTarget === target) { + keys.push(key); + } + } + + return keys; + } + + private getKeyTargets(scope: StorageScope): { [key: string]: StorageTarget } { + const keysRaw = this.get(TARGET_KEY, scope); + if (keysRaw) { + try { + return JSON.parse(keysRaw); + } catch (error) { + // Fail gracefully + } + } + + return Object.create(null); + } + + private updateKeyTarget(key: string, scope: StorageScope, target: StorageTarget | undefined): void { + + // Add + const keyTargets = this.getKeyTargets(scope); + if (typeof target === 'number') { + if (keyTargets[key] !== target) { + keyTargets[key] = target; + this.doStore(TARGET_KEY, JSON.stringify(keyTargets), scope); + } + } + + // Remove + else { + if (typeof keyTargets[key] === 'number') { + delete keyTargets[key]; + this.doStore(TARGET_KEY, JSON.stringify(keyTargets), scope); + } + } + } + + isNew(scope: StorageScope): boolean { + return this.getBoolean(IS_NEW_KEY, scope) === true; + } + + flush(): void { + this._onWillSaveState.fire({ reason: WillSaveStateReason.NONE }); + } + + // --- abstract + + abstract get(key: string, scope: StorageScope, fallbackValue: string): string; + abstract get(key: string, scope: StorageScope, fallbackValue?: string): string | undefined; + + abstract getBoolean(key: string, scope: StorageScope, fallbackValue: boolean): boolean; + abstract getBoolean(key: string, scope: StorageScope, fallbackValue?: boolean): boolean | undefined; + + abstract getNumber(key: string, scope: StorageScope, fallbackValue: number): number; + abstract getNumber(key: string, scope: StorageScope, fallbackValue?: number): number | undefined; + + protected abstract doStore(key: string, value: string | boolean | number, scope: StorageScope): void; + + protected abstract doRemove(key: string, scope: StorageScope): void; + + abstract logStorage(): void; + + abstract migrate(toWorkspace: IWorkspaceInitializationPayload): Promise; +} + +export class InMemoryStorageService extends AbstractStorageService { + private readonly globalCache = new Map(); private readonly workspaceCache = new Map(); @@ -188,12 +325,7 @@ export class InMemoryStorageService extends Disposable implements IStorageServic return parseInt(value, 10); } - store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope): Promise { - - // We remove the key for undefined/null values - if (isUndefinedOrNull(value)) { - return this.remove(key, scope); - } + protected doStore(key: string, value: string | boolean | number, scope: StorageScope): void { // Otherwise, convert to String and store const valueStr = String(value); @@ -201,7 +333,7 @@ export class InMemoryStorageService extends Disposable implements IStorageServic // Return early if value already set const currentValue = this.getCache(scope).get(key); if (currentValue === valueStr) { - return Promise.resolve(); + return; } // Update in cache @@ -209,20 +341,16 @@ export class InMemoryStorageService extends Disposable implements IStorageServic // Events this._onDidChangeStorage.fire({ scope, key }); - - return Promise.resolve(); } - remove(key: string, scope: StorageScope): Promise { + protected doRemove(key: string, scope: StorageScope): void { const wasDeleted = this.getCache(scope).delete(key); if (!wasDeleted) { - return Promise.resolve(); // Return early if value already deleted + return; // Return early if value already deleted } // Events this._onDidChangeStorage.fire({ scope, key }); - - return Promise.resolve(); } logStorage(): void { @@ -233,14 +361,6 @@ export class InMemoryStorageService extends Disposable implements IStorageServic // not supported } - flush(): void { - this._onWillSaveState.fire({ reason: WillSaveStateReason.NONE }); - } - - isNew(): boolean { - return true; // always new when in-memory - } - async close(): Promise { } } diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index f786dd0c502..2da830b8bfd 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -3,10 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; -import { Emitter } from 'vs/base/common/event'; +import { IDisposable, dispose } from 'vs/base/common/lifecycle'; import { ILogService, LogLevel } from 'vs/platform/log/common/log'; -import { IStorageChangeEvent, IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason, logStorage, IS_NEW_KEY } from 'vs/platform/storage/common/storage'; +import { StorageScope, WillSaveStateReason, logStorage, IS_NEW_KEY, AbstractStorageService } from 'vs/platform/storage/common/storage'; import { SQLiteStorageDatabase, ISQLiteStorageDatabaseLoggingOptions } from 'vs/base/parts/storage/node/storage'; import { Storage, IStorageDatabase, IStorage, StorageHint } from 'vs/base/parts/storage/common/storage'; import { mark } from 'vs/base/common/performance'; @@ -17,19 +16,11 @@ import { IWorkspaceInitializationPayload, isWorkspaceIdentifier, isSingleFolderW import { assertIsDefined } from 'vs/base/common/types'; import { RunOnceScheduler, runWhenIdle } from 'vs/base/common/async'; -export class NativeStorageService extends Disposable implements IStorageService { - - declare readonly _serviceBrand: undefined; +export class NativeStorageService extends AbstractStorageService { private static readonly WORKSPACE_STORAGE_NAME = 'state.vscdb'; private static readonly WORKSPACE_META_NAME = 'workspace.json'; - private readonly _onDidChangeStorage = this._register(new Emitter()); - readonly onDidChangeStorage = this._onDidChangeStorage.event; - - private readonly _onWillSaveState = this._register(new Emitter()); - readonly onWillSaveState = this._onWillSaveState.event; - private readonly globalStorage = new Storage(this.globalStorageDatabase); private workspaceStoragePath: string | undefined; @@ -201,11 +192,11 @@ export class NativeStorageService extends Disposable implements IStorageService return this.getStorage(scope).getNumber(key, fallbackValue); } - store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope): void { + protected doStore(key: string, value: string | boolean | number | undefined | null, scope: StorageScope): void { this.getStorage(scope).set(key, value); } - remove(key: string, scope: StorageScope): void { + protected doRemove(key: string, scope: StorageScope): void { this.getStorage(scope).delete(key); } @@ -229,10 +220,6 @@ export class NativeStorageService extends Disposable implements IStorageService }); } - flush(): void { - this._onWillSaveState.fire({ reason: WillSaveStateReason.NONE }); - } - async close(): Promise { // Stop periodic scheduler and idle runner as we now collect state normally @@ -277,8 +264,4 @@ export class NativeStorageService extends Disposable implements IStorageService // Recreate and init workspace storage return this.createWorkspaceStorage(newWorkspaceStoragePath).init(); } - - isNew(scope: StorageScope): boolean { - return this.getBoolean(IS_NEW_KEY, scope) === true; - } } diff --git a/src/vs/platform/storage/test/common/storageService.test.ts b/src/vs/platform/storage/test/common/storageService.test.ts new file mode 100644 index 00000000000..155a13a6d2a --- /dev/null +++ b/src/vs/platform/storage/test/common/storageService.test.ts @@ -0,0 +1,139 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { strictEqual, ok } from 'assert'; +import { StorageScope, InMemoryStorageService, StorageTarget } from 'vs/platform/storage/common/storage'; + +suite('StorageService', function () { + + test('Get Data, Integer, Boolean (global, in-memory)', () => { + storeData(StorageScope.GLOBAL); + }); + + test('Get Data, Integer, Boolean (workspace, in-memory)', () => { + storeData(StorageScope.WORKSPACE); + }); + + function storeData(scope: StorageScope): void { + const storage = new InMemoryStorageService(); + + strictEqual(storage.get('test.get', scope, 'foobar'), 'foobar'); + strictEqual(storage.get('test.get', scope, ''), ''); + strictEqual(storage.getNumber('test.getNumber', scope, 5), 5); + strictEqual(storage.getNumber('test.getNumber', scope, 0), 0); + strictEqual(storage.getBoolean('test.getBoolean', scope, true), true); + strictEqual(storage.getBoolean('test.getBoolean', scope, false), false); + + storage.store('test.get', 'foobar', scope); + strictEqual(storage.get('test.get', scope, (undefined)!), 'foobar'); + + storage.store('test.get', '', scope); + strictEqual(storage.get('test.get', scope, (undefined)!), ''); + + storage.store('test.getNumber', 5, scope); + strictEqual(storage.getNumber('test.getNumber', scope, (undefined)!), 5); + + storage.store('test.getNumber', 0, scope); + strictEqual(storage.getNumber('test.getNumber', scope, (undefined)!), 0); + + storage.store('test.getBoolean', true, scope); + strictEqual(storage.getBoolean('test.getBoolean', scope, (undefined)!), true); + + storage.store('test.getBoolean', false, scope); + strictEqual(storage.getBoolean('test.getBoolean', scope, (undefined)!), false); + + strictEqual(storage.get('test.getDefault', scope, 'getDefault'), 'getDefault'); + strictEqual(storage.getNumber('test.getNumberDefault', scope, 5), 5); + strictEqual(storage.getBoolean('test.getBooleanDefault', scope, true), true); + } + + test('Remove Data (global, in-memory)', () => { + removeData(StorageScope.GLOBAL); + }); + + test('Remove Data (workspace, in-memory)', () => { + removeData(StorageScope.WORKSPACE); + }); + + function removeData(scope: StorageScope): void { + const storage = new InMemoryStorageService(); + + storage.store('test.remove', 'foobar', scope); + strictEqual('foobar', storage.get('test.remove', scope, (undefined)!)); + + storage.remove('test.remove', scope); + ok(!storage.get('test.remove', scope, (undefined)!)); + } + + test('Keys (in-memory)', () => { + const storage = new InMemoryStorageService(); + + // Empty + for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { + for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { + strictEqual(storage.keys(scope, target).length, 0); + } + } + + // Add values + for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { + for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { + storage.store2('test.target1', 'value1', scope, target); + strictEqual(storage.keys(scope, target).length, 1); + + storage.store2('test.target1', 'otherValue1', scope, target); + strictEqual(storage.keys(scope, target).length, 1); + + storage.store2('test.target2', 'value2', scope, target); + storage.store2('test.target3', 'value3', scope, target); + + strictEqual(storage.keys(scope, target).length, 3); + } + } + + // Remove values + for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { + for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { + const keysLength = storage.keys(scope, target).length; + + storage.store2('test.target4', 'value1', scope, target); + strictEqual(storage.keys(scope, target).length, keysLength + 1); + + storage.remove('test.target4', scope); + strictEqual(storage.keys(scope, target).length, keysLength); + } + } + + // Remove all + for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { + for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { + const keys = storage.keys(scope, target); + + for (const key of keys) { + storage.remove(key, scope); + } + + strictEqual(storage.keys(scope, target).length, 0); + } + } + + // Adding undefined or null removes value + for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { + for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { + storage.store2('test.target1', 'value1', scope, target); + strictEqual(storage.keys(scope, target).length, 1); + + storage.store2('test.target1', undefined, scope, target); + strictEqual(storage.keys(scope, target).length, 0); + + storage.store2('test.target1', '', scope, target); + strictEqual(storage.keys(scope, target).length, 1); + + storage.store2('test.target1', null, scope, target); + strictEqual(storage.keys(scope, target).length, 0); + } + } + }); +}); diff --git a/src/vs/platform/storage/test/node/storageService.test.ts b/src/vs/platform/storage/test/node/storageService.test.ts index a87802a84fc..09f8066f64f 100644 --- a/src/vs/platform/storage/test/node/storageService.test.ts +++ b/src/vs/platform/storage/test/node/storageService.test.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { strictEqual, ok, equal } from 'assert'; -import { StorageScope, InMemoryStorageService } from 'vs/platform/storage/common/storage'; +import { equal } from 'assert'; +import { StorageScope } from 'vs/platform/storage/common/storage'; import { NativeStorageService } from 'vs/platform/storage/node/storageService'; import { generateUuid } from 'vs/base/common/uuid'; import { join } from 'vs/base/common/path'; @@ -16,66 +16,7 @@ import { parseArgs, OPTIONS } from 'vs/platform/environment/node/argv'; import { InMemoryStorageDatabase } from 'vs/base/parts/storage/common/storage'; import { URI } from 'vs/base/common/uri'; -suite('StorageService', function () { - - test('Remove Data (global, in-memory)', () => { - removeData(StorageScope.GLOBAL); - }); - - test('Remove Data (workspace, in-memory)', () => { - removeData(StorageScope.WORKSPACE); - }); - - function removeData(scope: StorageScope): void { - const storage = new InMemoryStorageService(); - - storage.store('test.remove', 'foobar', scope); - strictEqual('foobar', storage.get('test.remove', scope, (undefined)!)); - - storage.remove('test.remove', scope); - ok(!storage.get('test.remove', scope, (undefined)!)); - } - - test('Get Data, Integer, Boolean (global, in-memory)', () => { - storeData(StorageScope.GLOBAL); - }); - - test('Get Data, Integer, Boolean (workspace, in-memory)', () => { - storeData(StorageScope.WORKSPACE); - }); - - function storeData(scope: StorageScope): void { - const storage = new InMemoryStorageService(); - - strictEqual(storage.get('test.get', scope, 'foobar'), 'foobar'); - strictEqual(storage.get('test.get', scope, ''), ''); - strictEqual(storage.getNumber('test.getNumber', scope, 5), 5); - strictEqual(storage.getNumber('test.getNumber', scope, 0), 0); - strictEqual(storage.getBoolean('test.getBoolean', scope, true), true); - strictEqual(storage.getBoolean('test.getBoolean', scope, false), false); - - storage.store('test.get', 'foobar', scope); - strictEqual(storage.get('test.get', scope, (undefined)!), 'foobar'); - - storage.store('test.get', '', scope); - strictEqual(storage.get('test.get', scope, (undefined)!), ''); - - storage.store('test.getNumber', 5, scope); - strictEqual(storage.getNumber('test.getNumber', scope, (undefined)!), 5); - - storage.store('test.getNumber', 0, scope); - strictEqual(storage.getNumber('test.getNumber', scope, (undefined)!), 0); - - storage.store('test.getBoolean', true, scope); - strictEqual(storage.getBoolean('test.getBoolean', scope, (undefined)!), true); - - storage.store('test.getBoolean', false, scope); - strictEqual(storage.getBoolean('test.getBoolean', scope, (undefined)!), false); - - strictEqual(storage.get('test.getDefault', scope, 'getDefault'), 'getDefault'); - strictEqual(storage.getNumber('test.getNumberDefault', scope, 5), 5); - strictEqual(storage.getBoolean('test.getBooleanDefault', scope, true), true); - } +suite('NativeStorageService', function () { function uniqueStorageDir(): string { const id = generateUuid(); @@ -115,6 +56,10 @@ suite('StorageService', function () { storage.store('barNumber', 55, StorageScope.WORKSPACE); storage.store('barBoolean', true, StorageScope.GLOBAL); + equal(storage.get('bar', StorageScope.WORKSPACE), 'foo'); + equal(storage.getNumber('barNumber', StorageScope.WORKSPACE), 55); + equal(storage.getBoolean('barBoolean', StorageScope.GLOBAL), true); + await storage.migrate({ id: String(Date.now() + 100) }); equal(storage.get('bar', StorageScope.WORKSPACE), 'foo'); From b64171bd0bde0c19d3c407f56325db1f71cc3473 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 3 Nov 2020 09:54:46 +0100 Subject: [PATCH 02/17] storage - introduce onDidChangeTarget event --- .../multicursor/test/multicursor.test.ts | 1 + src/vs/platform/storage/common/storage.ts | 23 +++++++++++++ .../test/common/storageService.test.ts | 32 +++++++++++++++++-- 3 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts index 7b0f0f4ed7d..249fb5736e7 100644 --- a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts @@ -62,6 +62,7 @@ suite('Multicursor selection', () => { serviceCollection.set(IStorageService, { _serviceBrand: undefined, onDidChangeStorage: Event.None, + onDidChangeTarget: Event.None, onWillSaveState: Event.None, get: (key: string) => queryState[key], getBoolean: (key: string) => !!queryState[key], diff --git a/src/vs/platform/storage/common/storage.ts b/src/vs/platform/storage/common/storage.ts index b74e70fb774..3dbb39c41f5 100644 --- a/src/vs/platform/storage/common/storage.ts +++ b/src/vs/platform/storage/common/storage.ts @@ -32,6 +32,11 @@ export interface IStorageService { */ readonly onDidChangeStorage: Event; + /** + * Emitted whenever target of a storage entry changes. + */ + readonly onDidChangeTarget: Event; + /** * Emitted when the storage is about to persist. This is the right time * to persist data to ensure it is stored before the application shuts @@ -173,6 +178,10 @@ export interface IStorageChangeEvent { readonly scope: StorageScope; } +export interface IStorageTargetChangeEvent { + readonly scope: StorageScope; +} + export abstract class AbstractStorageService extends Disposable implements IStorageService { declare readonly _serviceBrand: undefined; @@ -180,9 +189,23 @@ export abstract class AbstractStorageService extends Disposable implements IStor protected readonly _onDidChangeStorage = this._register(new Emitter()); readonly onDidChangeStorage = this._onDidChangeStorage.event; + protected readonly _onDidChangeTarget = this._register(new Emitter()); + readonly onDidChangeTarget = this._onDidChangeTarget.event; + protected readonly _onWillSaveState = this._register(new Emitter()); readonly onWillSaveState = this._onWillSaveState.event; + constructor() { + super(); + + // Detect changes to `TARGET_KEY` to emit as event + this._register(this.onDidChangeStorage(e => { + if (e.key === TARGET_KEY) { + this._onDidChangeTarget.fire({ scope: e.scope }); + } + })); + } + store2(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): void { // We remove the key for undefined/null values diff --git a/src/vs/platform/storage/test/common/storageService.test.ts b/src/vs/platform/storage/test/common/storageService.test.ts index 155a13a6d2a..1b2049e6242 100644 --- a/src/vs/platform/storage/test/common/storageService.test.ts +++ b/src/vs/platform/storage/test/common/storageService.test.ts @@ -3,8 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { strictEqual, ok } from 'assert'; -import { StorageScope, InMemoryStorageService, StorageTarget } from 'vs/platform/storage/common/storage'; +import { strictEqual, ok, equal } from 'assert'; +import { StorageScope, InMemoryStorageService, StorageTarget, IStorageChangeEvent, IStorageTargetChangeEvent } from 'vs/platform/storage/common/storage'; suite('StorageService', function () { @@ -19,6 +19,9 @@ suite('StorageService', function () { function storeData(scope: StorageScope): void { const storage = new InMemoryStorageService(); + let storageEvents: IStorageChangeEvent[] = []; + storage.onDidChangeStorage(e => storageEvents.push(e)); + strictEqual(storage.get('test.get', scope, 'foobar'), 'foobar'); strictEqual(storage.get('test.get', scope, ''), ''); strictEqual(storage.getNumber('test.getNumber', scope, 5), 5); @@ -28,9 +31,16 @@ suite('StorageService', function () { storage.store('test.get', 'foobar', scope); strictEqual(storage.get('test.get', scope, (undefined)!), 'foobar'); + let storageEvent = storageEvents.find(e => e.key === 'test.get'); + equal(storageEvent?.scope, scope); + equal(storageEvent?.key, 'test.get'); + storageEvents = []; storage.store('test.get', '', scope); strictEqual(storage.get('test.get', scope, (undefined)!), ''); + storageEvent = storageEvents.find(e => e.key === 'test.get'); + equal(storageEvent!.scope, scope); + equal(storageEvent!.key, 'test.get'); storage.store('test.getNumber', 5, scope); strictEqual(storage.getNumber('test.getNumber', scope, (undefined)!), 5); @@ -60,16 +70,25 @@ suite('StorageService', function () { function removeData(scope: StorageScope): void { const storage = new InMemoryStorageService(); + let storageEvents: IStorageChangeEvent[] = []; + storage.onDidChangeStorage(e => storageEvents.push(e)); + storage.store('test.remove', 'foobar', scope); strictEqual('foobar', storage.get('test.remove', scope, (undefined)!)); storage.remove('test.remove', scope); ok(!storage.get('test.remove', scope, (undefined)!)); + let storageEvent = storageEvents.find(e => e.key === 'test.remove'); + equal(storageEvent?.scope, scope); + equal(storageEvent?.key, 'test.remove'); } test('Keys (in-memory)', () => { const storage = new InMemoryStorageService(); + let storageTargetEvent: IStorageTargetChangeEvent | undefined = undefined; + storage.onDidChangeTarget(e => storageTargetEvent = e); + // Empty for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { @@ -80,8 +99,11 @@ suite('StorageService', function () { // Add values for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { + storageTargetEvent = Object.create(null); + storage.store2('test.target1', 'value1', scope, target); strictEqual(storage.keys(scope, target).length, 1); + equal(storageTargetEvent?.scope, scope); storage.store2('test.target1', 'otherValue1', scope, target); strictEqual(storage.keys(scope, target).length, 1); @@ -101,8 +123,11 @@ suite('StorageService', function () { storage.store2('test.target4', 'value1', scope, target); strictEqual(storage.keys(scope, target).length, keysLength + 1); + storageTargetEvent = Object.create(null); + storage.remove('test.target4', scope); strictEqual(storage.keys(scope, target).length, keysLength); + equal(storageTargetEvent?.scope, scope); } } @@ -125,8 +150,11 @@ suite('StorageService', function () { storage.store2('test.target1', 'value1', scope, target); strictEqual(storage.keys(scope, target).length, 1); + storageTargetEvent = Object.create(null); + storage.store2('test.target1', undefined, scope, target); strictEqual(storage.keys(scope, target).length, 0); + equal(storageTargetEvent?.scope, scope); storage.store2('test.target1', '', scope, target); strictEqual(storage.keys(scope, target).length, 1); From 37e16f845b66d37072a21892b803c66295316b3f Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 3 Nov 2020 09:58:38 +0100 Subject: [PATCH 03/17] storage - adopt new API in one place --- src/vs/platform/quickinput/browser/commandsQuickAccess.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts index 18b7dc26e6e..5c6bd8fd0e2 100644 --- a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts @@ -11,7 +11,7 @@ import { DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecyc import { or, matchesPrefix, matchesWords, matchesContiguousSubString } from 'vs/base/common/filters'; import { withNullAsUndefined } from 'vs/base/common/types'; import { LRUCache } from 'vs/base/common/map'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -279,8 +279,8 @@ export class CommandsHistory extends Disposable { const serializedCache: ISerializedCommandHistory = { usesLRU: true, entries: [] }; CommandsHistory.cache.forEach((value, key) => serializedCache.entries.push({ key, value })); - storageService.store(CommandsHistory.PREF_KEY_CACHE, JSON.stringify(serializedCache), StorageScope.GLOBAL); - storageService.store(CommandsHistory.PREF_KEY_COUNTER, CommandsHistory.counter, StorageScope.GLOBAL); + storageService.store2(CommandsHistory.PREF_KEY_CACHE, JSON.stringify(serializedCache), StorageScope.GLOBAL, StorageTarget.USER); + storageService.store2(CommandsHistory.PREF_KEY_COUNTER, CommandsHistory.counter, StorageScope.GLOBAL, StorageTarget.USER); } static getConfiguredCommandHistoryLength(configurationService: IConfigurationService): number { From eeaa42d6509b8735541c60ed8186da97a9db095b Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 3 Nov 2020 11:08:39 +0100 Subject: [PATCH 04/17] storage - let flush return a promise when done --- src/vs/base/parts/storage/common/storage.ts | 32 ++++++++++++++++--- .../parts/storage/test/node/storage.test.ts | 14 ++++++++ .../multicursor/test/multicursor.test.ts | 2 +- .../storage/browser/storageService.ts | 7 ++++ src/vs/platform/storage/common/storage.ts | 20 +++++++++--- .../platform/storage/node/storageService.ts | 7 ++++ 6 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/vs/base/parts/storage/common/storage.ts b/src/vs/base/parts/storage/common/storage.ts index b6602b6a626..8b55819cc54 100644 --- a/src/vs/base/parts/storage/common/storage.ts +++ b/src/vs/base/parts/storage/common/storage.ts @@ -43,9 +43,10 @@ export interface IStorageDatabase { export interface IStorage extends IDisposable { + readonly onDidChangeStorage: Event; + readonly items: Map; readonly size: number; - readonly onDidChangeStorage: Event; init(): Promise; @@ -61,6 +62,8 @@ export interface IStorage extends IDisposable { set(key: string, value: string | boolean | number | undefined | null): Promise; delete(key: string): Promise; + whenFlushed(): Promise; + close(): Promise; } @@ -86,6 +89,8 @@ export class Storage extends Disposable implements IStorage { private pendingDeletes = new Set(); private pendingInserts = new Map(); + private readonly whenFlushedCallbacks: Function[] = []; + constructor( protected readonly database: IStorageDatabase, private readonly options: IStorageOptions = Object.create(null) @@ -273,8 +278,12 @@ export class Storage extends Disposable implements IStorage { await this.database.close(() => this.cache); } + private get hasPending() { + return this.pendingInserts.size > 0 || this.pendingDeletes.size > 0; + } + private flushPending(): Promise { - if (this.pendingInserts.size === 0 && this.pendingDeletes.size === 0) { + if (!this.hasPending) { return Promise.resolve(); // return early if nothing to do } @@ -285,8 +294,23 @@ export class Storage extends Disposable implements IStorage { this.pendingDeletes = new Set(); this.pendingInserts = new Map(); - // Update in storage - return this.database.updateItems(updateRequest); + // Update in storage and release any + // waiters we have once done + return this.database.updateItems(updateRequest).finally(() => { + if (!this.hasPending) { + while (this.whenFlushedCallbacks.length) { + this.whenFlushedCallbacks.pop()?.(); + } + } + }); + } + + whenFlushed(): Promise { + if (!this.hasPending) { + return Promise.resolve(); // return early if nothing to do + } + + return new Promise(resolve => this.whenFlushedCallbacks.push(resolve)); } } diff --git a/src/vs/base/parts/storage/test/node/storage.test.ts b/src/vs/base/parts/storage/test/node/storage.test.ts index 3c3510390d6..e735634c2ec 100644 --- a/src/vs/base/parts/storage/test/node/storage.test.ts +++ b/src/vs/base/parts/storage/test/node/storage.test.ts @@ -45,11 +45,16 @@ suite('Storage Library', function () { changes.add(key); }); + await storage.whenFlushed(); // returns immediately when no pending updates + // Simple updates const set1Promise = storage.set('bar', 'foo'); const set2Promise = storage.set('barNumber', 55); const set3Promise = storage.set('barBoolean', true); + let flushPromiseResolved = false; + storage.whenFlushed().then(() => flushPromiseResolved = true); + equal(storage.get('bar'), 'foo'); equal(storage.getNumber('barNumber'), 55); equal(storage.getBoolean('barBoolean'), true); @@ -62,6 +67,7 @@ suite('Storage Library', function () { let setPromiseResolved = false; await Promise.all([set1Promise, set2Promise, set3Promise]).then(() => setPromiseResolved = true); equal(setPromiseResolved, true); + equal(flushPromiseResolved, true); changes = new Set(); @@ -166,6 +172,9 @@ suite('Storage Library', function () { const set1Promise = storage.set('foo', 'bar'); const set2Promise = storage.set('bar', 'foo'); + let flushPromiseResolved = false; + storage.whenFlushed().then(() => flushPromiseResolved = true); + equal(storage.get('foo'), 'bar'); equal(storage.get('bar'), 'foo'); @@ -175,6 +184,7 @@ suite('Storage Library', function () { await storage.close(); equal(setPromiseResolved, true); + equal(flushPromiseResolved, true); storage = new Storage(new SQLiteStorageDatabase(join(storageDir, 'storage.db'))); await storage.init(); @@ -226,6 +236,9 @@ suite('Storage Library', function () { const set2Promise = storage.set('foo', 'bar2'); const set3Promise = storage.set('foo', 'bar3'); + let flushPromiseResolved = false; + storage.whenFlushed().then(() => flushPromiseResolved = true); + equal(storage.get('foo'), 'bar3'); equal(changes.size, 1); ok(changes.has('foo')); @@ -233,6 +246,7 @@ suite('Storage Library', function () { let setPromiseResolved = false; await Promise.all([set1Promise, set2Promise, set3Promise]).then(() => setPromiseResolved = true); ok(setPromiseResolved); + ok(flushPromiseResolved); changes = new Set(); diff --git a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts index 249fb5736e7..b9b1c5778eb 100644 --- a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts @@ -72,7 +72,7 @@ suite('Multicursor selection', () => { remove: (key) => undefined, logStorage: () => undefined, migrate: (toWorkspace) => Promise.resolve(undefined), - flush: () => undefined, + flush: () => Promise.resolve(undefined), isNew: () => true, keys: () => [] } as IStorageService); diff --git a/src/vs/platform/storage/browser/storageService.ts b/src/vs/platform/storage/browser/storageService.ts index 32a9c9d595c..14d2c01dd0b 100644 --- a/src/vs/platform/storage/browser/storageService.ts +++ b/src/vs/platform/storage/browser/storageService.ts @@ -145,6 +145,13 @@ export class BrowserStorageService extends AbstractStorageService { throw new Error('Migrating storage is currently unsupported in Web'); } + protected async doFlush(): Promise { + await Promise.all([ + this.getStorage(StorageScope.GLOBAL).whenFlushed(), + this.getStorage(StorageScope.WORKSPACE).whenFlushed() + ]); + } + private doFlushWhenIdle(): void { // Dispose any previous idle runner diff --git a/src/vs/platform/storage/common/storage.ts b/src/vs/platform/storage/common/storage.ts index 3dbb39c41f5..40a5de025bd 100644 --- a/src/vs/platform/storage/common/storage.ts +++ b/src/vs/platform/storage/common/storage.ts @@ -141,10 +141,13 @@ export interface IStorageService { /** * Allows to flush state, e.g. in cases where a shutdown is - * imminent. This will send out the onWillSaveState to ask + * imminent. This will send out the `onWillSaveState` to ask * everyone for latest state. + * + * @returns a `Promise` that can be awaited on when all updates + * to the underlying storage have been flushed. */ - flush(): void; + flush(): Promise; } export const enum StorageScope { @@ -282,8 +285,13 @@ export abstract class AbstractStorageService extends Disposable implements IStor return this.getBoolean(IS_NEW_KEY, scope) === true; } - flush(): void { + flush(): Promise { + + // Signal event to collect changes this._onWillSaveState.fire({ reason: WillSaveStateReason.NONE }); + + // Await flush + return this.doFlush(); } // --- abstract @@ -301,9 +309,11 @@ export abstract class AbstractStorageService extends Disposable implements IStor protected abstract doRemove(key: string, scope: StorageScope): void; - abstract logStorage(): void; + protected abstract doFlush(): Promise; abstract migrate(toWorkspace: IWorkspaceInitializationPayload): Promise; + + abstract logStorage(): void; } export class InMemoryStorageService extends AbstractStorageService { @@ -384,6 +394,8 @@ export class InMemoryStorageService extends AbstractStorageService { // not supported } + async doFlush(): Promise { } + async close(): Promise { } } diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index 2da830b8bfd..f4729ad9726 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -204,6 +204,13 @@ export class NativeStorageService extends AbstractStorageService { return assertIsDefined(scope === StorageScope.GLOBAL ? this.globalStorage : this.workspaceStorage); } + protected async doFlush(): Promise { + await Promise.all([ + this.getStorage(StorageScope.GLOBAL).whenFlushed(), + this.getStorage(StorageScope.WORKSPACE).whenFlushed() + ]); + } + private doFlushWhenIdle(): void { // Dispose any previous idle runner From 1f7528568e2578c6e9e6b33d0144d496441b44b2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 4 Nov 2020 09:49:24 +0100 Subject: [PATCH 05/17] storage - add target to change event and cache targets --- .../storage/browser/storageService.ts | 4 +- src/vs/platform/storage/common/storage.ts | 134 +++++++++++++----- .../platform/storage/node/storageService.ts | 10 +- .../test/common/storageService.test.ts | 19 ++- 4 files changed, 123 insertions(+), 44 deletions(-) diff --git a/src/vs/platform/storage/browser/storageService.ts b/src/vs/platform/storage/browser/storageService.ts index 14d2c01dd0b..2d92fcf018a 100644 --- a/src/vs/platform/storage/browser/storageService.ts +++ b/src/vs/platform/storage/browser/storageService.ts @@ -62,13 +62,13 @@ export class BrowserStorageService extends AbstractStorageService { this.workspaceStorageDatabase = this._register(new FileStorageDatabase(this.workspaceStorageFile, false /* do not watch for external changes */, this.fileService)); this.workspaceStorage = this._register(new Storage(this.workspaceStorageDatabase)); - this._register(this.workspaceStorage.onDidChangeStorage(key => this._onDidChangeStorage.fire({ key, scope: StorageScope.WORKSPACE }))); + this._register(this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeStorage(StorageScope.WORKSPACE, key))); // Global Storage this.globalStorageFile = joinPath(stateRoot, 'global.json'); this.globalStorageDatabase = this._register(new FileStorageDatabase(this.globalStorageFile, true /* watch for external changes */, this.fileService)); this.globalStorage = this._register(new Storage(this.globalStorageDatabase)); - this._register(this.globalStorage.onDidChangeStorage(key => this._onDidChangeStorage.fire({ key, scope: StorageScope.GLOBAL }))); + this._register(this.globalStorage.onDidChangeStorage(key => this.emitDidChangeStorage(StorageScope.GLOBAL, key))); // Init both await Promise.all([ diff --git a/src/vs/platform/storage/common/storage.ts b/src/vs/platform/storage/common/storage.ts index 40a5de025bd..007ae0ea6f7 100644 --- a/src/vs/platform/storage/common/storage.ts +++ b/src/vs/platform/storage/common/storage.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; -import { Event, Emitter } from 'vs/base/common/event'; +import { Event, Emitter, PauseableEmitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { isUndefinedOrNull } from 'vs/base/common/types'; import { IWorkspaceInitializationPayload } from 'vs/platform/workspaces/common/workspaces'; @@ -179,34 +179,54 @@ export const enum StorageTarget { export interface IStorageChangeEvent { readonly key: string; readonly scope: StorageScope; + readonly target: StorageTarget | undefined; } export interface IStorageTargetChangeEvent { readonly scope: StorageScope; } +interface IKeyTargets { + [key: string]: StorageTarget +} + export abstract class AbstractStorageService extends Disposable implements IStorageService { declare readonly _serviceBrand: undefined; - protected readonly _onDidChangeStorage = this._register(new Emitter()); + private readonly _onDidChangeStorage = this._register(new PauseableEmitter()); readonly onDidChangeStorage = this._onDidChangeStorage.event; - protected readonly _onDidChangeTarget = this._register(new Emitter()); + private readonly _onDidChangeTarget = this._register(new PauseableEmitter()); readonly onDidChangeTarget = this._onDidChangeTarget.event; - protected readonly _onWillSaveState = this._register(new Emitter()); + private readonly _onWillSaveState = this._register(new Emitter()); readonly onWillSaveState = this._onWillSaveState.event; - constructor() { - super(); + protected emitDidChangeStorage(scope: StorageScope, key: string): void { - // Detect changes to `TARGET_KEY` to emit as event - this._register(this.onDidChangeStorage(e => { - if (e.key === TARGET_KEY) { - this._onDidChangeTarget.fire({ scope: e.scope }); + // Specially handle `TARGET_KEY` + if (key === TARGET_KEY) { + + // Clear our cached version which is now out of date + if (scope === StorageScope.GLOBAL) { + this._globalKeyTargets = undefined; + } else if (scope === StorageScope.WORKSPACE) { + this._workspaceKeyTargets = undefined; } - })); + + // Emit as `didChangeTarget` event + this._onDidChangeTarget.fire({ scope }); + } + + // Emit any other key to outside + else { + this._onDidChangeStorage.fire({ scope, key, target: this.getKeyTargets(scope)[key] }); + } + } + + protected emitWillSaveState(reason: WillSaveStateReason): void { + this._onWillSaveState.fire({ reason }); } store2(key: string, value: string | boolean | number | undefined | null, scope: StorageScope, target: StorageTarget): void { @@ -217,11 +237,15 @@ export abstract class AbstractStorageService extends Disposable implements IStor return; } - // Store actual value - this.doStore(key, value, scope); + // Update our datastructures but send events only after + this.withPausedEmitters(() => { - // Update key-target map - this.updateKeyTarget(key, scope, target); + // Update key-target map + this.updateKeyTarget(key, scope, target); + + // Store actual value + this.doStore(key, value, scope); + }); } store(key: string, value: string | boolean | number | undefined | null, scope: StorageScope): void { @@ -230,11 +254,31 @@ export abstract class AbstractStorageService extends Disposable implements IStor remove(key: string, scope: StorageScope): void { - // Remove actual key - this.doRemove(key, scope); + // Update our datastructures but send events only after + this.withPausedEmitters(() => { - // Update key-target map - this.updateKeyTarget(key, scope, undefined); + // Update key-target map + this.updateKeyTarget(key, scope, undefined); + + // Remove actual key + this.doRemove(key, scope); + }); + } + + private withPausedEmitters(fn: Function): void { + + // Pause emitters + this._onDidChangeStorage.pause(); + this._onDidChangeTarget.pause(); + + try { + fn(); + } finally { + + // Resume emitters + this._onDidChangeStorage.resume(); + this._onDidChangeTarget.resume(); + } } keys(scope: StorageScope, target: StorageTarget): string[] { @@ -248,19 +292,6 @@ export abstract class AbstractStorageService extends Disposable implements IStor return keys; } - private getKeyTargets(scope: StorageScope): { [key: string]: StorageTarget } { - const keysRaw = this.get(TARGET_KEY, scope); - if (keysRaw) { - try { - return JSON.parse(keysRaw); - } catch (error) { - // Fail gracefully - } - } - - return Object.create(null); - } - private updateKeyTarget(key: string, scope: StorageScope, target: StorageTarget | undefined): void { // Add @@ -281,6 +312,41 @@ export abstract class AbstractStorageService extends Disposable implements IStor } } + private _workspaceKeyTargets: IKeyTargets | undefined = undefined; + private get workspaceKeyTargets() { + if (!this._workspaceKeyTargets) { + this._workspaceKeyTargets = this.loadKeyTargets(StorageScope.WORKSPACE); + } + + return this._workspaceKeyTargets; + } + + private _globalKeyTargets: IKeyTargets | undefined = undefined; + private get globalKeyTargets() { + if (!this._globalKeyTargets) { + this._globalKeyTargets = this.loadKeyTargets(StorageScope.GLOBAL); + } + + return this._globalKeyTargets; + } + + private getKeyTargets(scope: StorageScope): IKeyTargets { + return scope === StorageScope.GLOBAL ? this.globalKeyTargets : this.workspaceKeyTargets; + } + + private loadKeyTargets(scope: StorageScope): { [key: string]: StorageTarget } { + const keysRaw = this.get(TARGET_KEY, scope); + if (keysRaw) { + try { + return JSON.parse(keysRaw); + } catch (error) { + // Fail gracefully + } + } + + return Object.create(null); + } + isNew(scope: StorageScope): boolean { return this.getBoolean(IS_NEW_KEY, scope) === true; } @@ -373,7 +439,7 @@ export class InMemoryStorageService extends AbstractStorageService { this.getCache(scope).set(key, valueStr); // Events - this._onDidChangeStorage.fire({ scope, key }); + this.emitDidChangeStorage(scope, key); } protected doRemove(key: string, scope: StorageScope): void { @@ -383,7 +449,7 @@ export class InMemoryStorageService extends AbstractStorageService { } // Events - this._onDidChangeStorage.fire({ scope, key }); + this.emitDidChangeStorage(scope, key); } logStorage(): void { diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index f4729ad9726..d1d2aae6a3c 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -45,11 +45,7 @@ export class NativeStorageService extends AbstractStorageService { private registerListeners(): void { // Global Storage change events - this._register(this.globalStorage.onDidChangeStorage(key => this.handleDidChangeStorage(key, StorageScope.GLOBAL))); - } - - private handleDidChangeStorage(key: string, scope: StorageScope): void { - this._onDidChangeStorage.fire({ key, scope }); + this._register(this.globalStorage.onDidChangeStorage(key => this.emitDidChangeStorage(StorageScope.GLOBAL, key))); } initialize(payload?: IWorkspaceInitializationPayload): Promise { @@ -125,7 +121,7 @@ export class NativeStorageService extends AbstractStorageService { // Create new this.workspaceStoragePath = workspaceStoragePath; this.workspaceStorage = new Storage(new SQLiteStorageDatabase(workspaceStoragePath, { logging: workspaceLoggingOptions }), { hint }); - this.workspaceStorageListener = this.workspaceStorage.onDidChangeStorage(key => this.handleDidChangeStorage(key, StorageScope.WORKSPACE)); + this.workspaceStorageListener = this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeStorage(StorageScope.WORKSPACE, key)); return this.workspaceStorage; } @@ -235,7 +231,7 @@ export class NativeStorageService extends AbstractStorageService { this.runWhenIdleDisposable = undefined; // Signal as event so that clients can still store data - this._onWillSaveState.fire({ reason: WillSaveStateReason.SHUTDOWN }); + this.emitWillSaveState(WillSaveStateReason.SHUTDOWN); // Do it await Promise.all([ diff --git a/src/vs/platform/storage/test/common/storageService.test.ts b/src/vs/platform/storage/test/common/storageService.test.ts index 1b2049e6242..263417ef1de 100644 --- a/src/vs/platform/storage/test/common/storageService.test.ts +++ b/src/vs/platform/storage/test/common/storageService.test.ts @@ -83,12 +83,15 @@ suite('StorageService', function () { equal(storageEvent?.key, 'test.remove'); } - test('Keys (in-memory)', () => { + test('pasero Keys (in-memory)', () => { const storage = new InMemoryStorageService(); let storageTargetEvent: IStorageTargetChangeEvent | undefined = undefined; storage.onDidChangeTarget(e => storageTargetEvent = e); + let storageChangeEvent: IStorageChangeEvent | undefined = undefined; + storage.onDidChangeStorage(e => storageChangeEvent = e); + // Empty for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { @@ -100,13 +103,24 @@ suite('StorageService', function () { for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { storageTargetEvent = Object.create(null); + storageChangeEvent = Object.create(null); storage.store2('test.target1', 'value1', scope, target); strictEqual(storage.keys(scope, target).length, 1); equal(storageTargetEvent?.scope, scope); + equal(storageChangeEvent?.key, 'test.target1'); + equal(storageChangeEvent?.scope, scope); + equal(storageChangeEvent?.target, target); + + storageTargetEvent = undefined; + storageChangeEvent = Object.create(null); storage.store2('test.target1', 'otherValue1', scope, target); strictEqual(storage.keys(scope, target).length, 1); + equal(storageTargetEvent, undefined); + equal(storageChangeEvent?.key, 'test.target1'); + equal(storageChangeEvent?.scope, scope); + equal(storageChangeEvent?.target, target); storage.store2('test.target2', 'value2', scope, target); storage.store2('test.target3', 'value3', scope, target); @@ -124,10 +138,13 @@ suite('StorageService', function () { strictEqual(storage.keys(scope, target).length, keysLength + 1); storageTargetEvent = Object.create(null); + storageChangeEvent = Object.create(null); storage.remove('test.target4', scope); strictEqual(storage.keys(scope, target).length, keysLength); equal(storageTargetEvent?.scope, scope); + equal(storageChangeEvent?.key, 'test.target4'); + equal(storageChangeEvent?.scope, scope); } } From 8b712ee66d3538ccf382df824ce8a6c676e6631b Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 4 Nov 2020 10:38:52 +0100 Subject: [PATCH 06/17] - Use global keys with user scope from storage service to sync - Remove versioning of keys --- .../userDataSync/common/globalStateMerge.ts | 79 +++------- .../userDataSync/common/globalStateSync.ts | 54 +++---- .../userDataSync/common/storageKeys.ts | 15 -- .../userDataSync/common/userDataSyncIpc.ts | 4 +- .../test/common/globalStateMerge.test.ts | 144 +++++------------- .../sandbox.simpleservices.ts | 4 - 6 files changed, 83 insertions(+), 217 deletions(-) diff --git a/src/vs/platform/userDataSync/common/globalStateMerge.ts b/src/vs/platform/userDataSync/common/globalStateMerge.ts index 8af4c4de7de..e8bdcc271dc 100644 --- a/src/vs/platform/userDataSync/common/globalStateMerge.ts +++ b/src/vs/platform/userDataSync/common/globalStateMerge.ts @@ -6,24 +6,22 @@ import * as objects from 'vs/base/common/objects'; import { IStorageValue } from 'vs/platform/userDataSync/common/userDataSync'; import { IStringDictionary } from 'vs/base/common/collections'; -import { IStorageKey } from 'vs/platform/userDataSync/common/storageKeys'; import { ILogService } from 'vs/platform/log/common/log'; export interface IMergeResult { local: { added: IStringDictionary, removed: string[], updated: IStringDictionary }; remote: IStringDictionary | null; - skipped: string[]; } -export function merge(localStorage: IStringDictionary, remoteStorage: IStringDictionary | null, baseStorage: IStringDictionary | null, storageKeys: ReadonlyArray, previouslySkipped: string[], logService: ILogService): IMergeResult { +export function merge(localStorage: IStringDictionary, remoteStorage: IStringDictionary | null, baseStorage: IStringDictionary | null, machineScopedStorageKeys: ReadonlyArray, logService: ILogService): IMergeResult { if (!remoteStorage) { - return { remote: Object.keys(localStorage).length > 0 ? localStorage : null, local: { added: {}, removed: [], updated: {} }, skipped: [] }; + return { remote: Object.keys(localStorage).length > 0 ? localStorage : null, local: { added: {}, removed: [], updated: {} } }; } const localToRemote = compare(localStorage, remoteStorage); if (localToRemote.added.size === 0 && localToRemote.removed.size === 0 && localToRemote.updated.size === 0) { // No changes found between local and remote. - return { remote: null, local: { added: {}, removed: [], updated: {} }, skipped: [] }; + return { remote: null, local: { added: {}, removed: [], updated: {} } }; } const baseToRemote = baseStorage ? compare(baseStorage, remoteStorage) : { added: Object.keys(remoteStorage).reduce((r, k) => { r.add(k); return r; }, new Set()), removed: new Set(), updated: new Set() }; @@ -31,26 +29,19 @@ export function merge(localStorage: IStringDictionary, remoteStor const local: { added: IStringDictionary, removed: string[], updated: IStringDictionary } = { added: {}, removed: [], updated: {} }; const remote: IStringDictionary = objects.deepClone(remoteStorage); - const skipped: string[] = []; // Added in remote for (const key of baseToRemote.added.values()) { const remoteValue = remoteStorage[key]; - const storageKey = storageKeys.filter(storageKey => storageKey.key === key)[0]; - if (!storageKey) { - skipped.push(key); - logService.trace(`GlobalState: Skipped adding ${key} in local storage as it is not registered.`); - continue; - } - if (storageKey.version !== remoteValue.version) { - logService.info(`GlobalState: Skipped adding ${key} in local storage. Local version '${storageKey.version}' and remote version '${remoteValue.version} are not same.`); + if (machineScopedStorageKeys.includes(key)) { + logService.info(`GlobalState: Skipped adding ${key} in local storage because it is declared as machine scoped.`); continue; } const localValue = localStorage[key]; if (localValue && localValue.value === remoteValue.value) { continue; } - if (baseToLocal.added.has(key)) { + if (localValue) { local.updated[key] = remoteValue; } else { local.added[key] = remoteValue; @@ -60,28 +51,25 @@ export function merge(localStorage: IStringDictionary, remoteStor // Updated in Remote for (const key of baseToRemote.updated.values()) { const remoteValue = remoteStorage[key]; - const storageKey = storageKeys.filter(storageKey => storageKey.key === key)[0]; - if (!storageKey) { - skipped.push(key); - logService.trace(`GlobalState: Skipped updating ${key} in local storage as is not registered.`); - continue; - } - if (storageKey.version !== remoteValue.version) { - logService.info(`GlobalState: Skipped updating ${key} in local storage. Local version '${storageKey.version}' and remote version '${remoteValue.version} are not same.`); + if (machineScopedStorageKeys.includes(key)) { + logService.info(`GlobalState: Skipped updating ${key} in local storage because it is declared as machine scoped.`); continue; } const localValue = localStorage[key]; if (localValue && localValue.value === remoteValue.value) { continue; } - local.updated[key] = remoteValue; + if (localValue) { + local.updated[key] = remoteValue; + } else { + local.added[key] = remoteValue; + } } // Removed in remote for (const key of baseToRemote.removed.values()) { - const storageKey = storageKeys.filter(storageKey => storageKey.key === key)[0]; - if (!storageKey) { - logService.trace(`GlobalState: Skipped removing ${key} in local storage. It is not registered to sync.`); + if (machineScopedStorageKeys.includes(key)) { + logService.trace(`GlobalState: Skipped removing ${key} in local storage because it is declared as machine scoped.`); continue; } local.removed.push(key); @@ -89,9 +77,10 @@ export function merge(localStorage: IStringDictionary, remoteStor // Added in local for (const key of baseToLocal.added.values()) { - if (!baseToRemote.added.has(key)) { - remote[key] = localStorage[key]; + if (baseToRemote.added.has(key)) { + continue; } + remote[key] = localStorage[key]; } // Updated in local @@ -99,13 +88,7 @@ export function merge(localStorage: IStringDictionary, remoteStor if (baseToRemote.updated.has(key) || baseToRemote.removed.has(key)) { continue; } - const remoteValue = remote[key]; - const localValue = localStorage[key]; - if (localValue.version < remoteValue.version) { - logService.info(`GlobalState: Skipped updating ${key} in remote storage. Local version '${localValue.version}' and remote version '${remoteValue.version} are not same.`); - continue; - } - remote[key] = localValue; + remote[key] = localStorage[key]; } // Removed in local @@ -114,32 +97,10 @@ export function merge(localStorage: IStringDictionary, remoteStor if (baseToRemote.updated.has(key)) { continue; } - - const storageKey = storageKeys.filter(storageKey => storageKey.key === key)[0]; - // do not remove from remote if storage key is not found - if (!storageKey) { - skipped.push(key); - logService.trace(`GlobalState: Skipped removing ${key} in remote storage. It is not registered to sync.`); - continue; - } - - const remoteValue = remote[key]; - // do not remove from remote if local data version is old - if (storageKey.version < remoteValue.version) { - logService.info(`GlobalState: Skipped updating ${key} in remote storage. Local version '${storageKey.version}' and remote version '${remoteValue.version} are not same.`); - continue; - } - - // add to local if it was skipped before - if (previouslySkipped.indexOf(key) !== -1) { - local.added[key] = remote[key]; - continue; - } - delete remote[key]; } - return { local, remote: areSame(remote, remoteStorage) ? null : remote, skipped }; + return { local, remote: areSame(remote, remoteStorage) ? null : remote }; } function compare(from: IStringDictionary, to: IStringDictionary): { added: Set, removed: Set, updated: Set } { diff --git a/src/vs/platform/userDataSync/common/globalStateSync.ts b/src/vs/platform/userDataSync/common/globalStateSync.ts index c1f4daa7bf5..5a6185c1345 100644 --- a/src/vs/platform/userDataSync/common/globalStateSync.ts +++ b/src/vs/platform/userDataSync/common/globalStateSync.ts @@ -21,9 +21,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { URI } from 'vs/base/common/uri'; import { format } from 'vs/base/common/jsonFormatter'; import { applyEdits } from 'vs/base/common/jsonEdit'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IStorageKeysSyncRegistryService, IStorageKey } from 'vs/platform/userDataSync/common/storageKeys'; -import { equals } from 'vs/base/common/arrays'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { CancellationToken } from 'vs/base/common/cancellation'; const argvStoragePrefx = 'globalState.argv.'; @@ -35,15 +33,19 @@ interface IGlobalStateResourceMergeResult extends IAcceptResult { } export interface IGlobalStateResourcePreview extends IResourcePreview { - readonly skippedStorageKeys: string[]; readonly localUserData: IGlobalState; readonly previewResult: IGlobalStateResourceMergeResult; } -interface ILastSyncUserData extends IRemoteUserData { - skippedStorageKeys: string[] | undefined; -} - +/** + * Synchronises global state that includes + * - Global storage with user scope + * - Locale from argv properties + * + * Global storage is synced without checking version just like other resources (settings, keybindings). + * If there is a change in format of the value of a storage key which requires migration then + * Owner of that key should remove that key from user scope and replace that with new user scoped key. + */ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUserDataSynchroniser { private static readonly GLOBAL_STATE_DATA_URI = URI.from({ scheme: USER_DATA_SYNC_SCHEME, authority: 'globalState', path: `/globalState.json` }); @@ -63,23 +65,22 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs @ITelemetryService telemetryService: ITelemetryService, @IConfigurationService configurationService: IConfigurationService, @IStorageService private readonly storageService: IStorageService, - @IStorageKeysSyncRegistryService private readonly storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, ) { super(SyncResource.GlobalState, fileService, environmentService, storageService, userDataSyncStoreService, userDataSyncBackupStoreService, userDataSyncResourceEnablementService, telemetryService, logService, configurationService); - this._register(this.fileService.watch(this.extUri.dirname(this.environmentService.argvResource))); + this._register(fileService.watch(this.extUri.dirname(this.environmentService.argvResource))); this._register( Event.any( /* Locale change */ - Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.environmentService.argvResource)), - /* Storage change */ - Event.filter(this.storageService.onDidChangeStorage, e => storageKeysSyncRegistryService.storageKeys.some(({ key }) => e.key === key)), - /* Storage key registered */ - this.storageKeysSyncRegistryService.onDidChangeStorageKeys + Event.filter(fileService.onDidFilesChange, e => e.contains(this.environmentService.argvResource)), + /* Global storage with user target has changed */ + Event.filter(storageService.onDidChangeStorage, e => e.scope === StorageScope.GLOBAL && e.target !== undefined ? e.target === StorageTarget.USER : storageService.keys(StorageScope.GLOBAL, StorageTarget.USER).includes(e.key)), + /* Storage key target has changed */ + this.storageService.onDidChangeTarget )((() => this.triggerLocalChange())) ); } - protected async generateSyncPreview(remoteUserData: IRemoteUserData, lastSyncUserData: ILastSyncUserData | null, token: CancellationToken): Promise { + protected async generateSyncPreview(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, token: CancellationToken): Promise { const remoteGlobalState: IGlobalState = remoteUserData.syncData ? JSON.parse(remoteUserData.syncData.content) : null; const lastSyncGlobalState: IGlobalState | null = lastSyncUserData && lastSyncUserData.syncData ? JSON.parse(lastSyncUserData.syncData.content) : null; @@ -91,7 +92,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs this.logService.trace(`${this.syncResourceLogLabel}: Remote ui state does not exist. Synchronizing ui state for the first time.`); } - const { local, remote, skipped } = merge(localGloablState.storage, remoteGlobalState ? remoteGlobalState.storage : null, lastSyncGlobalState ? lastSyncGlobalState.storage : null, this.getSyncStorageKeys(), lastSyncUserData?.skippedStorageKeys || [], this.logService); + const { local, remote } = merge(localGloablState.storage, remoteGlobalState ? remoteGlobalState.storage : null, lastSyncGlobalState ? lastSyncGlobalState.storage : null, this.getIgnoredSyncStorageKeys(), this.logService); const previewResult: IGlobalStateResourceMergeResult = { content: null, local, @@ -101,7 +102,6 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs }; return [{ - skippedStorageKeys: skipped, localResource: this.localResource, localContent: this.format(localGloablState), localUserData: localGloablState, @@ -152,7 +152,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs private async acceptRemote(resourcePreview: IGlobalStateResourcePreview): Promise { if (resourcePreview.remoteContent !== null) { const remoteGlobalState: IGlobalState = JSON.parse(resourcePreview.remoteContent); - const { local, remote } = merge(resourcePreview.localUserData.storage, remoteGlobalState.storage, null, this.getSyncStorageKeys(), resourcePreview.skippedStorageKeys, this.logService); + const { local, remote } = merge(resourcePreview.localUserData.storage, remoteGlobalState.storage, null, this.getIgnoredSyncStorageKeys(), this.logService); return { content: resourcePreview.remoteContent, local, @@ -171,8 +171,8 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs } } - protected async applyResult(remoteUserData: IRemoteUserData, lastSyncUserData: ILastSyncUserData | null, resourcePreviews: [IGlobalStateResourcePreview, IGlobalStateResourceMergeResult][], force: boolean): Promise { - let { localUserData, skippedStorageKeys } = resourcePreviews[0][0]; + protected async applyResult(remoteUserData: IRemoteUserData, lastSyncUserData: IRemoteUserData | null, resourcePreviews: [IGlobalStateResourcePreview, IGlobalStateResourceMergeResult][], force: boolean): Promise { + let { localUserData } = resourcePreviews[0][0]; let { local, remote, localChange, remoteChange } = resourcePreviews[0][1]; if (localChange === Change.None && remoteChange === Change.None) { @@ -195,10 +195,10 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs this.logService.info(`${this.syncResourceLogLabel}: Updated remote ui state`); } - if (lastSyncUserData?.ref !== remoteUserData.ref || !equals(lastSyncUserData.skippedStorageKeys, skippedStorageKeys)) { + if (lastSyncUserData?.ref !== remoteUserData.ref) { // update last sync this.logService.trace(`${this.syncResourceLogLabel}: Updating last synchronized ui state...`); - await this.updateLastSyncUserData(remoteUserData, { skippedStorageKeys }); + await this.updateLastSyncUserData(remoteUserData); this.logService.info(`${this.syncResourceLogLabel}: Updated last synchronized ui state`); } } @@ -267,10 +267,10 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs storage[`${argvStoragePrefx}${argvProperty}`] = { version: 1, value: argvValue[argvProperty] }; } } - for (const { key, version } of this.storageKeysSyncRegistryService.storageKeys) { + for (const key of this.storageService.keys(StorageScope.GLOBAL, StorageTarget.USER)) { const value = this.storageService.get(key, StorageScope.GLOBAL); if (value) { - storage[key] = { version, value }; + storage[key] = { version: 1, value }; } } return { storage }; @@ -336,8 +336,8 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs } } - private getSyncStorageKeys(): IStorageKey[] { - return [...this.storageKeysSyncRegistryService.storageKeys, ...argvProperties.map(argvProprety => ({ key: `${argvStoragePrefx}${argvProprety}`, version: 1 }))]; + private getIgnoredSyncStorageKeys(): string[] { + return this.storageService.keys(StorageScope.GLOBAL, StorageTarget.MACHINE); } } diff --git a/src/vs/platform/userDataSync/common/storageKeys.ts b/src/vs/platform/userDataSync/common/storageKeys.ts index 5ffe0786f05..97757534fcd 100644 --- a/src/vs/platform/userDataSync/common/storageKeys.ts +++ b/src/vs/platform/userDataSync/common/storageKeys.ts @@ -43,16 +43,6 @@ export interface IStorageKeysSyncRegistryService { _serviceBrand: any; - /** - * All registered storage keys - */ - readonly storageKeys: ReadonlyArray; - - /** - * Event that is triggered when storage keys are changed - */ - readonly onDidChangeStorageKeys: Event>; - /** * Register a storage key that has to be synchronized during sync. */ @@ -84,10 +74,6 @@ export abstract class AbstractStorageKeysSyncRegistryService extends Disposable declare readonly _serviceBrand: undefined; protected readonly _storageKeys = new Map(); - get storageKeys(): ReadonlyArray { return [...this._storageKeys.values()]; } - - protected readonly _onDidChangeStorageKeys: Emitter> = this._register(new Emitter>()); - readonly onDidChangeStorageKeys = this._onDidChangeStorageKeys.event; protected readonly _extensionsStorageKeys = new Map(); get extensionsStorageKeys() { @@ -123,7 +109,6 @@ export class StorageKeysSyncRegistryService extends AbstractStorageKeysSyncRegis registerStorageKey(storageKey: IStorageKey): void { if (!this._storageKeys.has(storageKey.key)) { this._storageKeys.set(storageKey.key, storageKey); - this._onDidChangeStorageKeys.fire(this.storageKeys); } } diff --git a/src/vs/platform/userDataSync/common/userDataSyncIpc.ts b/src/vs/platform/userDataSync/common/userDataSyncIpc.ts index c9088b8d7a3..56a4e0a30da 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncIpc.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncIpc.ts @@ -183,7 +183,6 @@ export class StorageKeysSyncRegistryChannel implements IServerChannel { listen(_: unknown, event: string): Event { switch (event) { - case 'onDidChangeStorageKeys': return this.service.onDidChangeStorageKeys; case 'onDidChangeExtensionStorageKeys': return this.service.onDidChangeExtensionStorageKeys; } throw new Error(`Event not found: ${event}`); @@ -191,7 +190,7 @@ export class StorageKeysSyncRegistryChannel implements IServerChannel { call(context: any, command: string, args?: any): Promise { switch (command) { - case '_getInitialData': return Promise.resolve({ storageKeys: this.service.storageKeys, extensionsStorageKeys: this.service.extensionsStorageKeys }); + case '_getInitialData': return Promise.resolve({ storageKeys: [], extensionsStorageKeys: this.service.extensionsStorageKeys }); case 'registerStorageKey': return Promise.resolve(this.service.registerStorageKey(args[0])); case 'registerExtensionStorageKeys': return Promise.resolve(this.service.registerExtensionStorageKeys(args[0], args[1])); } @@ -218,7 +217,6 @@ export class StorageKeysSyncRegistryChannelClient extends AbstractStorageKeysSyn for (const storageKey of storageKeys) { this._storageKeys.set(storageKey.key, storageKey); } - this._onDidChangeStorageKeys.fire(this.storageKeys); } private async updateExtensionsStorageKeys(extensionStorageKeys: ReadonlyArray<[IExtensionIdentifierWithVersion, ReadonlyArray]>): Promise { diff --git a/src/vs/platform/userDataSync/test/common/globalStateMerge.test.ts b/src/vs/platform/userDataSync/test/common/globalStateMerge.test.ts index e89763a4d9a..33aa41f5dd1 100644 --- a/src/vs/platform/userDataSync/test/common/globalStateMerge.test.ts +++ b/src/vs/platform/userDataSync/test/common/globalStateMerge.test.ts @@ -13,7 +13,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, null, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -25,7 +25,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; const remote = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, null, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -37,7 +37,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, null, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -50,7 +50,7 @@ suite('GlobalStateMerge', () => { const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; const base = { 'b': { version: 1, value: 'a' } }; - const actual = merge(local, remote, base, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, base, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -62,7 +62,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, null, [], new NullLogService()); assert.deepEqual(actual.local.added, { 'b': { version: 1, value: 'b' } }); assert.deepEqual(actual.local.updated, {}); @@ -74,7 +74,7 @@ suite('GlobalStateMerge', () => { const local = {}; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, null, [], new NullLogService()); assert.deepEqual(actual.local.added, { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }); assert.deepEqual(actual.local.updated, {}); @@ -86,7 +86,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, local, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, local, [], new NullLogService()); assert.deepEqual(actual.local.added, { 'b': { version: 1, value: 'b' } }); assert.deepEqual(actual.local.updated, {}); @@ -98,7 +98,7 @@ suite('GlobalStateMerge', () => { const local = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; const remote = { 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, local, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, local, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -110,7 +110,7 @@ suite('GlobalStateMerge', () => { const local = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; const remote = {}; - const actual = merge(local, remote, local, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, local, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -122,7 +122,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'a': { version: 1, value: 'b' } }; - const actual = merge(local, remote, local, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, local, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, { 'a': { version: 1, value: 'b' } }); @@ -134,7 +134,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; const remote = { 'a': { version: 1, value: 'd' }, 'c': { version: 1, value: 'c' } }; - const actual = merge(local, remote, local, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, local, [], new NullLogService()); assert.deepEqual(actual.local.added, { 'c': { version: 1, value: 'c' } }); assert.deepEqual(actual.local.updated, { 'a': { version: 1, value: 'd' } }); @@ -146,7 +146,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; const remote = { 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, null, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -158,7 +158,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' }, 'c': { version: 1, value: 'c' } }; const remote = { 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, remote, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, remote, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -170,7 +170,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; - const actual = merge(local, remote, remote, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, remote, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -182,7 +182,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'b' } }; const remote = { 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, remote, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, remote, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -194,7 +194,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'd' }, 'b': { version: 1, value: 'b' } }; const remote = { 'a': { version: 1, value: 'a' }, 'c': { version: 1, value: 'c' } }; - const actual = merge(local, remote, remote, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, remote, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -206,7 +206,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'a': { version: 1, value: 'b' } }; - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, null, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, { 'a': { version: 1, value: 'b' } }); @@ -219,7 +219,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'd' } }; const remote = { 'a': { version: 1, value: 'a' }, 'c': { version: 1, value: 'c' } }; - const actual = merge(local, remote, base, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, base, [], new NullLogService()); assert.deepEqual(actual.local.added, { 'c': { version: 1, value: 'c' } }); assert.deepEqual(actual.local.updated, {}); @@ -232,10 +232,10 @@ suite('GlobalStateMerge', () => { const local = {}; const remote = { 'a': { version: 1, value: 'b' } }; - const actual = merge(local, remote, base, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, base, [], new NullLogService()); - assert.deepEqual(actual.local.added, {}); - assert.deepEqual(actual.local.updated, { 'a': { version: 1, value: 'b' } }); + assert.deepEqual(actual.local.added, { 'a': { version: 1, value: 'b' } }); + assert.deepEqual(actual.local.updated, {}); assert.deepEqual(actual.local.removed, []); assert.deepEqual(actual.remote, null); }); @@ -245,7 +245,7 @@ suite('GlobalStateMerge', () => { const local = { 'a': { version: 1, value: 'd' } }; const remote = { 'a': { version: 1, value: 'b' } }; - const actual = merge(local, remote, base, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }, { key: 'c', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, base, [], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, { 'a': { version: 1, value: 'b' } }); @@ -253,11 +253,11 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when a new entry is added to remote but not a registered key', async () => { + test('merge when a new entry is added to remote but scoped to machine locally', async () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, null, ['b'], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -265,23 +265,11 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when a new entry is added to remote but different version', async () => { - const local = { 'a': { version: 1, value: 'a' } }; - const remote = { 'b': { version: 2, value: 'b' }, 'a': { version: 1, value: 'a' } }; - - const actual = merge(local, remote, null, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); - - assert.deepEqual(actual.local.added, {}); - assert.deepEqual(actual.local.updated, {}); - assert.deepEqual(actual.local.removed, []); - assert.deepEqual(actual.remote, null); - }); - - test('merge when an entry is updated to remote but not a registered key', async () => { + test('merge when an entry is updated to remote but scoped to machine locally', async () => { const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'a': { version: 1, value: 'b' } }; - const actual = merge(local, remote, local, [], [], new NullLogService()); + const actual = merge(local, remote, local, ['a'], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -289,11 +277,12 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when a new entry is updated to remote but different version', async () => { - const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; + test('merge when a local value is removed and iscoped to machine locally', async () => { + const base = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; + const local = { 'a': { version: 1, value: 'a' } }; const remote = { 'b': { version: 2, value: 'b' }, 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, local, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); + const actual = merge(local, remote, base, ['b'], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -301,23 +290,12 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, null); }); - test('merge when a local value is update with lower version', async () => { - const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'c' } }; - const remote = { 'b': { version: 2, value: 'b' }, 'a': { version: 1, value: 'a' } }; + test('merge when local moved forwared by changing a key to machine scope', async () => { + const base = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; + const remote = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; + const local = { 'a': { version: 1, value: 'a' } }; - const actual = merge(local, remote, remote, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); - - assert.deepEqual(actual.local.added, {}); - assert.deepEqual(actual.local.updated, {}); - assert.deepEqual(actual.local.removed, []); - assert.deepEqual(actual.remote, null); - }); - - test('merge when a local value is update with higher version', async () => { - const local = { 'a': { version: 1, value: 'a' }, 'b': { version: 2, value: 'c' } }; - const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; - - const actual = merge(local, remote, remote, [{ key: 'a', version: 1 }, { key: 'b', version: 2 }], [], new NullLogService()); + const actual = merge(local, remote, base, ['b'], new NullLogService()); assert.deepEqual(actual.local.added, {}); assert.deepEqual(actual.local.updated, {}); @@ -325,56 +303,4 @@ suite('GlobalStateMerge', () => { assert.deepEqual(actual.remote, local); }); - test('merge when a local value is removed but not registered', async () => { - const base = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; - const local = { 'a': { version: 1, value: 'a' } }; - const remote = { 'b': { version: 2, value: 'b' }, 'a': { version: 1, value: 'a' } }; - - const actual = merge(local, remote, base, [{ key: 'a', version: 1 }], [], new NullLogService()); - - assert.deepEqual(actual.local.added, {}); - assert.deepEqual(actual.local.updated, {}); - assert.deepEqual(actual.local.removed, []); - assert.deepEqual(actual.remote, null); - }); - - test('merge when a local value is removed with lower version', async () => { - const base = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; - const local = { 'a': { version: 1, value: 'a' } }; - const remote = { 'b': { version: 2, value: 'b' }, 'a': { version: 1, value: 'a' } }; - - const actual = merge(local, remote, base, [{ key: 'a', version: 1 }, { key: 'b', version: 1 }], [], new NullLogService()); - - assert.deepEqual(actual.local.added, {}); - assert.deepEqual(actual.local.updated, {}); - assert.deepEqual(actual.local.removed, []); - assert.deepEqual(actual.remote, null); - }); - - test('merge when a local value is removed with higher version', async () => { - const base = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; - const local = { 'a': { version: 1, value: 'a' } }; - const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; - - const actual = merge(local, remote, base, [{ key: 'a', version: 1 }, { key: 'b', version: 2 }], [], new NullLogService()); - - assert.deepEqual(actual.local.added, {}); - assert.deepEqual(actual.local.updated, {}); - assert.deepEqual(actual.local.removed, []); - assert.deepEqual(actual.remote, local); - }); - - test('merge when a local value is not yet registered', async () => { - const base = { 'a': { version: 1, value: 'a' }, 'b': { version: 1, value: 'b' } }; - const local = { 'a': { version: 1, value: 'a' } }; - const remote = { 'b': { version: 1, value: 'b' }, 'a': { version: 1, value: 'a' } }; - - const actual = merge(local, remote, base, [{ key: 'a', version: 1 }], [], new NullLogService()); - - assert.deepEqual(actual.local.added, {}); - assert.deepEqual(actual.local.updated, {}); - assert.deepEqual(actual.local.removed, []); - assert.deepEqual(actual.remote, null); - }); - }); diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index 4c430390100..f15968db003 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -677,10 +677,6 @@ class SimpleStorageKeysSyncRegistryService implements IStorageKeysSyncRegistrySe declare readonly _serviceBrand: undefined; - onDidChangeStorageKeys = Event.None; - - storageKeys = []; - registerStorageKey(): void { } onDidChangeExtensionStorageKeys = Event.None; From c49bc9b1cb4bdacfd06ec0a72f80dbbed0fbcebb Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 4 Nov 2020 10:57:31 +0100 Subject: [PATCH 07/17] fix tests --- .../test/common/globalStateSync.test.ts | 39 ++++++++----------- 1 file changed, 16 insertions(+), 23 deletions(-) diff --git a/src/vs/platform/userDataSync/test/common/globalStateSync.test.ts b/src/vs/platform/userDataSync/test/common/globalStateSync.test.ts index 2d5594c01d7..e6eb8819f09 100644 --- a/src/vs/platform/userDataSync/test/common/globalStateSync.test.ts +++ b/src/vs/platform/userDataSync/test/common/globalStateSync.test.ts @@ -10,10 +10,9 @@ import { DisposableStore, toDisposable } from 'vs/base/common/lifecycle'; import { UserDataSyncService } from 'vs/platform/userDataSync/common/userDataSyncService'; import { IFileService } from 'vs/platform/files/common/files'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { GlobalStateSynchroniser } from 'vs/platform/userDataSync/common/globalStateSync'; import { VSBuffer } from 'vs/base/common/buffer'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; suite('GlobalStateSync', () => { @@ -28,17 +27,11 @@ suite('GlobalStateSync', () => { setup(async () => { testClient = disposableStore.add(new UserDataSyncClient(server)); await testClient.setUp(true); - let storageKeysSyncRegistryService = testClient.instantiationService.get(IStorageKeysSyncRegistryService); - storageKeysSyncRegistryService.registerStorageKey({ key: 'a', version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: 'b', version: 1 }); testObject = (testClient.instantiationService.get(IUserDataSyncService) as UserDataSyncService).getSynchroniser(SyncResource.GlobalState) as GlobalStateSynchroniser; disposableStore.add(toDisposable(() => testClient.instantiationService.get(IUserDataSyncStoreService).clear())); client2 = disposableStore.add(new UserDataSyncClient(server)); await client2.setUp(true); - storageKeysSyncRegistryService = client2.instantiationService.get(IStorageKeysSyncRegistryService); - storageKeysSyncRegistryService.registerStorageKey({ key: 'a', version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: 'b', version: 1 }); }); teardown(() => disposableStore.clear()); @@ -72,7 +65,7 @@ suite('GlobalStateSync', () => { test('when global state is created after first sync', async () => { await testObject.sync(await testClient.manifest()); - updateStorage('a', 'value1', testClient); + updateUserStorage('a', 'value1', testClient); let lastSyncUserData = await testObject.getLastSyncUserData(); const manifest = await testClient.manifest(); @@ -91,7 +84,7 @@ suite('GlobalStateSync', () => { }); test('first time sync - outgoing to server (no state)', async () => { - updateStorage('a', 'value1', testClient); + updateUserStorage('a', 'value1', testClient); await updateLocale(testClient); await testObject.sync(await testClient.manifest()); @@ -105,7 +98,7 @@ suite('GlobalStateSync', () => { }); test('first time sync - incoming from server (no state)', async () => { - updateStorage('a', 'value1', client2); + updateUserStorage('a', 'value1', client2); await updateLocale(client2); await client2.sync(); @@ -118,10 +111,10 @@ suite('GlobalStateSync', () => { }); test('first time sync when storage exists', async () => { - updateStorage('a', 'value1', client2); + updateUserStorage('a', 'value1', client2); await client2.sync(); - updateStorage('b', 'value2', testClient); + updateUserStorage('b', 'value2', testClient); await testObject.sync(await testClient.manifest()); assert.equal(testObject.status, SyncStatus.Idle); assert.deepEqual(testObject.conflicts, []); @@ -136,10 +129,10 @@ suite('GlobalStateSync', () => { }); test('first time sync when storage exists - has conflicts', async () => { - updateStorage('a', 'value1', client2); + updateUserStorage('a', 'value1', client2); await client2.sync(); - updateStorage('a', 'value2', client2); + updateUserStorage('a', 'value2', client2); await testObject.sync(await testClient.manifest()); assert.equal(testObject.status, SyncStatus.Idle); @@ -154,10 +147,10 @@ suite('GlobalStateSync', () => { }); test('sync adding a storage value', async () => { - updateStorage('a', 'value1', testClient); + updateUserStorage('a', 'value1', testClient); await testObject.sync(await testClient.manifest()); - updateStorage('b', 'value2', testClient); + updateUserStorage('b', 'value2', testClient); await testObject.sync(await testClient.manifest()); assert.equal(testObject.status, SyncStatus.Idle); assert.deepEqual(testObject.conflicts, []); @@ -172,10 +165,10 @@ suite('GlobalStateSync', () => { }); test('sync updating a storage value', async () => { - updateStorage('a', 'value1', testClient); + updateUserStorage('a', 'value1', testClient); await testObject.sync(await testClient.manifest()); - updateStorage('a', 'value2', testClient); + updateUserStorage('a', 'value2', testClient); await testObject.sync(await testClient.manifest()); assert.equal(testObject.status, SyncStatus.Idle); assert.deepEqual(testObject.conflicts, []); @@ -189,8 +182,8 @@ suite('GlobalStateSync', () => { }); test('sync removing a storage value', async () => { - updateStorage('a', 'value1', testClient); - updateStorage('b', 'value2', testClient); + updateUserStorage('a', 'value1', testClient); + updateUserStorage('b', 'value2', testClient); await testObject.sync(await testClient.manifest()); removeStorage('b', testClient); @@ -218,9 +211,9 @@ suite('GlobalStateSync', () => { await fileService.writeFile(environmentService.argvResource, VSBuffer.fromString(JSON.stringify({ 'locale': 'en' }))); } - function updateStorage(key: string, value: string, client: UserDataSyncClient): void { + function updateUserStorage(key: string, value: string, client: UserDataSyncClient): void { const storageService = client.instantiationService.get(IStorageService); - storageService.store(key, value, StorageScope.GLOBAL); + storageService.store2(key, value, StorageScope.GLOBAL, StorageTarget.USER); } function removeStorage(key: string, client: UserDataSyncClient): void { From 59bfe65e18985f07e53fb89e9f1aa9b8e46ae27f Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 4 Nov 2020 11:04:04 +0100 Subject: [PATCH 08/17] store synced state in user scope --- src/vs/platform/userDataSync/common/globalStateSync.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/vs/platform/userDataSync/common/globalStateSync.ts b/src/vs/platform/userDataSync/common/globalStateSync.ts index 5a6185c1345..552e0b99ded 100644 --- a/src/vs/platform/userDataSync/common/globalStateSync.ts +++ b/src/vs/platform/userDataSync/common/globalStateSync.ts @@ -317,7 +317,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs if (updatedStorageKeys.length) { this.logService.trace(`${this.syncResourceLogLabel}: Updating global state...`); for (const key of Object.keys(updatedStorage)) { - this.storageService.store(key, updatedStorage[key], StorageScope.GLOBAL); + this.storageService.store2(key, updatedStorage[key], StorageScope.GLOBAL, StorageTarget.USER); } this.logService.info(`${this.syncResourceLogLabel}: Updated global state`, Object.keys(updatedStorage)); } @@ -385,7 +385,7 @@ export class GlobalStateInitializer extends AbstractInitializer { if (Object.keys(storage).length) { for (const key of Object.keys(storage)) { - this.storageService.store(key, storage[key], StorageScope.GLOBAL); + this.storageService.store2(key, storage[key], StorageScope.GLOBAL, StorageTarget.USER); } } } From 0feb41eed09a5481ad626332fbc971d5834031db Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 4 Nov 2020 12:04:53 +0100 Subject: [PATCH 09/17] test machine storage is not synced --- .../userDataSync/test/common/globalStateSync.test.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/vs/platform/userDataSync/test/common/globalStateSync.test.ts b/src/vs/platform/userDataSync/test/common/globalStateSync.test.ts index e6eb8819f09..53263d2e77a 100644 --- a/src/vs/platform/userDataSync/test/common/globalStateSync.test.ts +++ b/src/vs/platform/userDataSync/test/common/globalStateSync.test.ts @@ -85,6 +85,7 @@ suite('GlobalStateSync', () => { test('first time sync - outgoing to server (no state)', async () => { updateUserStorage('a', 'value1', testClient); + updateMachineStorage('b', 'value1', testClient); await updateLocale(testClient); await testObject.sync(await testClient.manifest()); @@ -216,6 +217,11 @@ suite('GlobalStateSync', () => { storageService.store2(key, value, StorageScope.GLOBAL, StorageTarget.USER); } + function updateMachineStorage(key: string, value: string, client: UserDataSyncClient): void { + const storageService = client.instantiationService.get(IStorageService); + storageService.store2(key, value, StorageScope.GLOBAL, StorageTarget.MACHINE); + } + function removeStorage(key: string, client: UserDataSyncClient): void { const storageService = client.instantiationService.get(IStorageService); storageService.remove(key, StorageScope.GLOBAL); From dfb74a6c97d3704b7af03c4336314bbf8ba758b2 Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 4 Nov 2020 14:52:06 +0100 Subject: [PATCH 10/17] some comments and more tests --- src/vs/platform/storage/common/storage.ts | 27 ++++++++++++++++--- .../test/common/storageService.test.ts | 14 ++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/src/vs/platform/storage/common/storage.ts b/src/vs/platform/storage/common/storage.ts index 007ae0ea6f7..fd6d7d5fd44 100644 --- a/src/vs/platform/storage/common/storage.ts +++ b/src/vs/platform/storage/common/storage.ts @@ -115,6 +115,10 @@ export interface IStorageService { * Returns all the keys used in the storage for the provided `scope` * and `target`. * + * Note: this will NOT return all keys stored in the storage layer. + * Some keys may not have an associated `StorageTarget` and thus + * will be excluded from the results. + * * @param scope allows to define the scope for the keys * to either the current workspace only or all workspaces. * @@ -166,7 +170,7 @@ export const enum StorageScope { export const enum StorageTarget { /** - * The stored data is user specific. + * The stored data is user specific and applies across machines. */ USER, @@ -177,8 +181,23 @@ export const enum StorageTarget { } export interface IStorageChangeEvent { - readonly key: string; + + /** + * The scope for the storage entry that changed + * or was removed. + */ readonly scope: StorageScope; + + /** + * The `key` of the storage entry that was changed + * or was removed. + */ + readonly key: string; + + /** + * The `target` can be `undefined` if a key is being + * removed. + */ readonly target: StorageTarget | undefined; } @@ -313,7 +332,7 @@ export abstract class AbstractStorageService extends Disposable implements IStor } private _workspaceKeyTargets: IKeyTargets | undefined = undefined; - private get workspaceKeyTargets() { + private get workspaceKeyTargets(): IKeyTargets { if (!this._workspaceKeyTargets) { this._workspaceKeyTargets = this.loadKeyTargets(StorageScope.WORKSPACE); } @@ -322,7 +341,7 @@ export abstract class AbstractStorageService extends Disposable implements IStor } private _globalKeyTargets: IKeyTargets | undefined = undefined; - private get globalKeyTargets() { + private get globalKeyTargets(): IKeyTargets { if (!this._globalKeyTargets) { this._globalKeyTargets = this.loadKeyTargets(StorageScope.GLOBAL); } diff --git a/src/vs/platform/storage/test/common/storageService.test.ts b/src/vs/platform/storage/test/common/storageService.test.ts index 263417ef1de..fef7361494e 100644 --- a/src/vs/platform/storage/test/common/storageService.test.ts +++ b/src/vs/platform/storage/test/common/storageService.test.ts @@ -180,5 +180,19 @@ suite('StorageService', function () { strictEqual(storage.keys(scope, target).length, 0); } } + + // Target change + storageTargetEvent = undefined; + storage.store2('test.target5', 'value1', StorageScope.GLOBAL, StorageTarget.MACHINE); + ok(storageTargetEvent); + storageTargetEvent = undefined; + storage.store2('test.target5', 'value1', StorageScope.GLOBAL, StorageTarget.USER); + ok(storageTargetEvent); + storageTargetEvent = undefined; + storage.store2('test.target5', 'value1', StorageScope.GLOBAL, StorageTarget.MACHINE); + ok(storageTargetEvent); + storageTargetEvent = undefined; + storage.store2('test.target5', 'value1', StorageScope.GLOBAL, StorageTarget.MACHINE); + ok(!storageTargetEvent); // no change in target }); }); From 194c7ea2371f55574604d9874806eb0f6e1d11ee Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 4 Nov 2020 14:55:43 +0100 Subject: [PATCH 11/17] test name --- src/vs/platform/storage/test/common/storageService.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/vs/platform/storage/test/common/storageService.test.ts b/src/vs/platform/storage/test/common/storageService.test.ts index fef7361494e..eaf4a4a6606 100644 --- a/src/vs/platform/storage/test/common/storageService.test.ts +++ b/src/vs/platform/storage/test/common/storageService.test.ts @@ -83,7 +83,7 @@ suite('StorageService', function () { equal(storageEvent?.key, 'test.remove'); } - test('pasero Keys (in-memory)', () => { + test('Keys (in-memory)', () => { const storage = new InMemoryStorageService(); let storageTargetEvent: IStorageTargetChangeEvent | undefined = undefined; From a66589991595ad31e1e8299fc2dea4cdf3bf116c Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 4 Nov 2020 15:03:55 +0100 Subject: [PATCH 12/17] fix compile and tests --- .../services/editor/test/browser/editorsObserver.test.ts | 6 +++--- src/vs/workbench/test/common/workbenchTestServices.ts | 8 +++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts index bd08a0b369a..5f927c5571c 100644 --- a/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorsObserver.test.ts @@ -298,7 +298,7 @@ suite('EditorsObserver', function () { assert.equal(observer.hasEditor(input2.resource), true); assert.equal(observer.hasEditor(input3.resource), true); - storage._onWillSaveState.fire({ reason: WillSaveStateReason.SHUTDOWN }); + storage.emitWillSaveState(WillSaveStateReason.SHUTDOWN); const restoredObserver = new EditorsObserver(part, storage); await part.whenRestored; @@ -350,7 +350,7 @@ suite('EditorsObserver', function () { assert.equal(observer.hasEditor(input2.resource), true); assert.equal(observer.hasEditor(input3.resource), true); - storage._onWillSaveState.fire({ reason: WillSaveStateReason.SHUTDOWN }); + storage.emitWillSaveState(WillSaveStateReason.SHUTDOWN); const restoredObserver = new EditorsObserver(part, storage); await part.whenRestored; @@ -390,7 +390,7 @@ suite('EditorsObserver', function () { assert.equal(currentEditorsMRU[0].editor, input1); assert.equal(observer.hasEditor(input1.resource), true); - storage._onWillSaveState.fire({ reason: WillSaveStateReason.SHUTDOWN }); + storage.emitWillSaveState(WillSaveStateReason.SHUTDOWN); const restoredObserver = new EditorsObserver(part, storage); await part.whenRestored; diff --git a/src/vs/workbench/test/common/workbenchTestServices.ts b/src/vs/workbench/test/common/workbenchTestServices.ts index 61ca309fd35..08210ef22ab 100644 --- a/src/vs/workbench/test/common/workbenchTestServices.ts +++ b/src/vs/workbench/test/common/workbenchTestServices.ts @@ -13,7 +13,7 @@ import { TestWorkspace } from 'vs/platform/workspace/test/common/testWorkspace'; import { IWorkspaceIdentifier, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces'; import { ITextResourcePropertiesService } from 'vs/editor/common/services/textResourceConfigurationService'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; -import { InMemoryStorageService, IWillSaveStateEvent } from 'vs/platform/storage/common/storage'; +import { InMemoryStorageService, WillSaveStateReason } from 'vs/platform/storage/common/storage'; import { WorkingCopyService, IWorkingCopy, IWorkingCopyBackup, WorkingCopyCapabilities } from 'vs/workbench/services/workingCopy/common/workingCopyService'; import { NullExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IWorkingCopyFileService, IWorkingCopyFileOperationParticipant, WorkingCopyFileEvent } from 'vs/workbench/services/workingCopy/common/workingCopyFileService'; @@ -121,8 +121,10 @@ export class TestContextService implements IWorkspaceContextService { } export class TestStorageService extends InMemoryStorageService { - readonly _onWillSaveState = this._register(new Emitter()); - readonly onWillSaveState = this._onWillSaveState.event; + + emitWillSaveState(reason: WillSaveStateReason): void { + super.emitWillSaveState(reason); + } } export class TestWorkingCopyService extends WorkingCopyService { } From e6b53ff8da7dd1063963f2be53a0fee8e38c3337 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 4 Nov 2020 15:19:02 +0100 Subject: [PATCH 13/17] adopt using new storage service to sync storage --- src/vs/editor/contrib/find/findController.ts | 4 +- src/vs/editor/contrib/find/findWidget.ts | 7 +--- .../quickinput/browser/commandsQuickAccess.ts | 6 --- .../userDataSync/common/storageKeys.ts | 21 +---------- .../userDataSync/common/userDataSyncIpc.ts | 22 ++--------- .../api/browser/mainThreadAuthentication.ts | 17 +++------ src/vs/workbench/browser/layout.ts | 6 +-- .../parts/activitybar/activitybarActions.ts | 4 +- .../parts/activitybar/activitybarPart.ts | 14 ++----- .../browser/parts/panel/panelPart.ts | 7 +--- .../browser/parts/statusbar/statusbarPart.ts | 8 +--- .../browser/largeFileOptimizations.ts | 8 +--- ...ensionRecommendationNotificationService.ts | 7 +--- .../editors/textFileSaveErrorHandler.ts | 9 +---- .../browser/localizations.contribution.ts | 11 ++---- .../preferences/browser/settingsEditor2.ts | 8 +--- .../browser/languageSurveys.contribution.ts | 37 +++++++------------ .../surveys/browser/nps.contribution.ts | 28 +++++--------- .../terminal/browser/terminalConfigHelper.ts | 5 --- .../test/browser/terminalConfigHelper.test.ts | 35 +++++++++--------- .../contrib/update/browser/update.ts | 5 --- .../contrib/url/browser/trustedDomains.ts | 7 ++-- .../trustedDomainsFileSystemProvider.ts | 14 +++---- .../browser/telemetryOptOut.ts | 10 ++--- .../electron-sandbox/telemetryOptOut.ts | 4 +- .../extensionIgnoredRecommendationsService.ts | 7 +--- .../common/notificationService.ts | 6 +-- .../themes/browser/workbenchThemeService.ts | 5 --- .../services/themes/common/colorThemeData.ts | 5 ++- .../views/browser/viewDescriptorService.ts | 10 ++--- .../views/common/viewContainerModel.ts | 7 +--- .../workspaces/browser/workspacesService.ts | 9 +---- 32 files changed, 106 insertions(+), 247 deletions(-) diff --git a/src/vs/editor/contrib/find/findController.ts b/src/vs/editor/contrib/find/findController.ts index 841bd9fe9e8..c5850601299 100644 --- a/src/vs/editor/contrib/find/findController.ts +++ b/src/vs/editor/contrib/find/findController.ts @@ -26,7 +26,6 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag import { IThemeService } from 'vs/platform/theme/common/themeService'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { EditorOption } from 'vs/editor/common/config/editorOptions'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; const SEARCH_STRING_MAX_LENGTH = 524288; @@ -411,7 +410,6 @@ export class FindController extends CommonFindController implements IFindControl @IThemeService private readonly _themeService: IThemeService, @INotificationService private readonly _notificationService: INotificationService, @IStorageService _storageService: IStorageService, - @IStorageKeysSyncRegistryService private readonly _storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @IClipboardService clipboardService: IClipboardService, ) { super(editor, _contextKeyService, _storageService, clipboardService); @@ -468,7 +466,7 @@ export class FindController extends CommonFindController implements IFindControl } private _createFindWidget() { - this._widget = this._register(new FindWidget(this._editor, this, this._state, this._contextViewService, this._keybindingService, this._contextKeyService, this._themeService, this._storageService, this._notificationService, this._storageKeysSyncRegistryService)); + this._widget = this._register(new FindWidget(this._editor, this, this._state, this._contextViewService, this._keybindingService, this._contextKeyService, this._themeService, this._storageService, this._notificationService)); this._findOptionsWidget = this._register(new FindOptionsWidget(this._editor, this._state, this._keybindingService, this._themeService)); } } diff --git a/src/vs/editor/contrib/find/findWidget.ts b/src/vs/editor/contrib/find/findWidget.ts index 21fbb0060e0..5566fb24392 100644 --- a/src/vs/editor/contrib/find/findWidget.ts +++ b/src/vs/editor/contrib/find/findWidget.ts @@ -34,9 +34,8 @@ import { contrastBorder, editorFindMatch, editorFindMatchBorder, editorFindMatch import { IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { ContextScopedFindInput, ContextScopedReplaceInput } from 'vs/platform/browser/contextScopedHistoryWidget'; import { AccessibilitySupport } from 'vs/platform/accessibility/common/accessibility'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { Codicon, registerIcon } from 'vs/base/common/codicons'; const findSelectionIcon = registerIcon('find-selection', Codicon.selection); @@ -164,7 +163,6 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL themeService: IThemeService, storageService: IStorageService, notificationService: INotificationService, - storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); this._codeEditor = codeEditor; @@ -176,7 +174,6 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL this._storageService = storageService; this._notificationService = notificationService; - storageKeysSyncRegistryService.registerStorageKey({ key: ctrlEnterReplaceAllWarningPromptedKey, version: 1 }); this._ctrlEnterReplaceAllWarningPrompted = !!storageService.getBoolean(ctrlEnterReplaceAllWarningPromptedKey, StorageScope.GLOBAL); this._isVisible = false; @@ -880,7 +877,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IVerticalSashL ); this._ctrlEnterReplaceAllWarningPrompted = true; - this._storageService.store(ctrlEnterReplaceAllWarningPromptedKey, true, StorageScope.GLOBAL); + this._storageService.store2(ctrlEnterReplaceAllWarningPromptedKey, true, StorageScope.GLOBAL, StorageTarget.USER); } diff --git a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts index 5c6bd8fd0e2..f3aea416d65 100644 --- a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts @@ -21,7 +21,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { INotificationService } from 'vs/platform/notification/common/notification'; import { toErrorMessage } from 'vs/base/common/errorMessage'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; export interface ICommandQuickPick extends IPickerQuickAccessItem { commandId: string; @@ -204,14 +203,9 @@ export class CommandsHistory extends Disposable { constructor( @IStorageService private readonly storageService: IStorageService, @IConfigurationService private readonly configurationService: IConfigurationService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); - // opt-in to syncing - storageKeysSyncRegistryService.registerStorageKey({ key: CommandsHistory.PREF_KEY_CACHE, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: CommandsHistory.PREF_KEY_COUNTER, version: 1 }); - this.updateConfiguration(); this.load(); diff --git a/src/vs/platform/userDataSync/common/storageKeys.ts b/src/vs/platform/userDataSync/common/storageKeys.ts index 97757534fcd..73161fac6f2 100644 --- a/src/vs/platform/userDataSync/common/storageKeys.ts +++ b/src/vs/platform/userDataSync/common/storageKeys.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Event, Emitter } from 'vs/base/common/event'; -import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; +import { Disposable } from 'vs/base/common/lifecycle'; import { IExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagement'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; @@ -43,11 +43,6 @@ export interface IStorageKeysSyncRegistryService { _serviceBrand: any; - /** - * Register a storage key that has to be synchronized during sync. - */ - registerStorageKey(key: IStorageKey): void; - /** * All registered extensions storage keys */ @@ -73,8 +68,6 @@ export abstract class AbstractStorageKeysSyncRegistryService extends Disposable declare readonly _serviceBrand: undefined; - protected readonly _storageKeys = new Map(); - protected readonly _extensionsStorageKeys = new Map(); get extensionsStorageKeys() { const result: [IExtensionIdWithVersion, ReadonlyArray][] = []; @@ -84,11 +77,6 @@ export abstract class AbstractStorageKeysSyncRegistryService extends Disposable protected readonly _onDidChangeExtensionStorageKeys = this._register(new Emitter<[IExtensionIdWithVersion, ReadonlyArray]>()); readonly onDidChangeExtensionStorageKeys = this._onDidChangeExtensionStorageKeys.event; - constructor() { - super(); - this._register(toDisposable(() => this._storageKeys.clear())); - } - getExtensioStorageKeys(extension: IExtensionIdWithVersion): ReadonlyArray | undefined { return this._extensionsStorageKeys.get(ExtensionIdWithVersion.toKey(extension)); } @@ -98,7 +86,6 @@ export abstract class AbstractStorageKeysSyncRegistryService extends Disposable this._onDidChangeExtensionStorageKeys.fire([extension, keys]); } - abstract registerStorageKey(key: IStorageKey): void; abstract registerExtensionStorageKeys(extension: IExtensionIdWithVersion, keys: string[]): void; } @@ -106,12 +93,6 @@ export class StorageKeysSyncRegistryService extends AbstractStorageKeysSyncRegis _serviceBrand: any; - registerStorageKey(storageKey: IStorageKey): void { - if (!this._storageKeys.has(storageKey.key)) { - this._storageKeys.set(storageKey.key, storageKey); - } - } - registerExtensionStorageKeys(extension: IExtensionIdWithVersion, keys: string[]): void { this.updateExtensionStorageKeys(extension, keys); } diff --git a/src/vs/platform/userDataSync/common/userDataSyncIpc.ts b/src/vs/platform/userDataSync/common/userDataSyncIpc.ts index 56a4e0a30da..4e2d06b1e3f 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncIpc.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncIpc.ts @@ -9,7 +9,7 @@ import { IUserDataSyncService, IUserDataSyncUtilService, IUserDataAutoSyncServic import { URI } from 'vs/base/common/uri'; import { IStringDictionary } from 'vs/base/common/collections'; import { FormattingOptions } from 'vs/base/common/jsonFormatter'; -import { IStorageKeysSyncRegistryService, IStorageKey, IExtensionIdWithVersion, AbstractStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; +import { IStorageKeysSyncRegistryService, IExtensionIdWithVersion, AbstractStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { ILogService } from 'vs/platform/log/common/log'; import { IUserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines'; import { IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/userDataSyncAccount'; @@ -175,7 +175,7 @@ export class UserDataSyncUtilServiceClient implements IUserDataSyncUtilService { } -type StorageKeysSyncRegistryServiceInitData = { storageKeys: ReadonlyArray, extensionsStorageKeys: ReadonlyArray<[IExtensionIdWithVersion, ReadonlyArray]> }; +type StorageKeysSyncRegistryServiceInitData = { extensionsStorageKeys: ReadonlyArray<[IExtensionIdWithVersion, ReadonlyArray]> }; export class StorageKeysSyncRegistryChannel implements IServerChannel { @@ -190,8 +190,7 @@ export class StorageKeysSyncRegistryChannel implements IServerChannel { call(context: any, command: string, args?: any): Promise { switch (command) { - case '_getInitialData': return Promise.resolve({ storageKeys: [], extensionsStorageKeys: this.service.extensionsStorageKeys }); - case 'registerStorageKey': return Promise.resolve(this.service.registerStorageKey(args[0])); + case '_getInitialData': return Promise.resolve({ extensionsStorageKeys: this.service.extensionsStorageKeys }); case 'registerExtensionStorageKeys': return Promise.resolve(this.service.registerExtensionStorageKeys(args[0], args[1])); } throw new Error('Invalid call'); @@ -204,31 +203,18 @@ export class StorageKeysSyncRegistryChannelClient extends AbstractStorageKeysSyn constructor(private readonly channel: IChannel) { super(); - this.channel.call('_getInitialData').then(({ storageKeys, extensionsStorageKeys }) => { - this.updateStorageKeys(storageKeys); + this.channel.call('_getInitialData').then(({ extensionsStorageKeys }) => { this.updateExtensionsStorageKeys(extensionsStorageKeys); - this._register(this.channel.listen>('onDidChangeStorageKeys')(storageKeys => this.updateStorageKeys(storageKeys))); this._register(this.channel.listen<[IExtensionIdentifierWithVersion, string[]]>('onDidChangeExtensionStorageKeys')(e => this.updateExtensionStorageKeys(e[0], e[1]))); }); } - private async updateStorageKeys(storageKeys: ReadonlyArray): Promise { - this._storageKeys.clear(); - for (const storageKey of storageKeys) { - this._storageKeys.set(storageKey.key, storageKey); - } - } - private async updateExtensionsStorageKeys(extensionStorageKeys: ReadonlyArray<[IExtensionIdentifierWithVersion, ReadonlyArray]>): Promise { for (const [extension, keys] of extensionStorageKeys) { this.updateExtensionStorageKeys(extension, [...keys]); } } - registerStorageKey(storageKey: IStorageKey): void { - this.channel.call('registerStorageKey', [storageKey]); - } - registerExtensionStorageKeys(extension: IExtensionIdentifierWithVersion, keys: string[]): void { this.channel.call('registerExtensionStorageKeys', [extension, keys]); } diff --git a/src/vs/workbench/api/browser/mainThreadAuthentication.ts b/src/vs/workbench/api/browser/mainThreadAuthentication.ts index 02240e28b7e..2510b2e89de 100644 --- a/src/vs/workbench/api/browser/mainThreadAuthentication.ts +++ b/src/vs/workbench/api/browser/mainThreadAuthentication.ts @@ -10,11 +10,10 @@ import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { IAuthenticationService, AllowedExtension, readAllowedExtensions, getAuthenticationProviderActivationEvent } from 'vs/workbench/services/authentication/browser/authenticationService'; import { ExtHostAuthenticationShape, ExtHostContext, IExtHostContext, MainContext, MainThreadAuthenticationShape } from '../common/extHost.protocol'; import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import Severity from 'vs/base/common/severity'; import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { fromNow } from 'vs/base/common/date'; import { ActivationKind, IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -83,7 +82,6 @@ export class MainThreadAuthenticationProvider extends Disposable { public readonly label: string, public readonly supportsMultipleAccounts: boolean, private readonly notificationService: INotificationService, - private readonly storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, private readonly storageService: IStorageService, private readonly quickInputService: IQuickInputService, private readonly dialogService: IDialogService @@ -122,7 +120,7 @@ export class MainThreadAuthenticationProvider extends Disposable { quickPick.onDidAccept(() => { const updatedAllowedList = quickPick.selectedItems.map(item => item.extension); - this.storageService.store(`${this.id}-${accountName}`, JSON.stringify(updatedAllowedList), StorageScope.GLOBAL); + this.storageService.store2(`${this.id}-${accountName}`, JSON.stringify(updatedAllowedList), StorageScope.GLOBAL, StorageTarget.USER); quickPick.dispose(); }); @@ -153,8 +151,6 @@ export class MainThreadAuthenticationProvider extends Disposable { } else { this._accounts.set(session.account.label, [session.id]); } - - this.storageKeysSyncRegistryService.registerStorageKey({ key: `${this.id}-${session.account.label}`, version: 1 }); } async signOut(accountName: string): Promise { @@ -220,7 +216,6 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu @IDialogService private readonly dialogService: IDialogService, @IStorageService private readonly storageService: IStorageService, @INotificationService private readonly notificationService: INotificationService, - @IStorageKeysSyncRegistryService private readonly storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @IRemoteAgentService private readonly remoteAgentService: IRemoteAgentService, @IQuickInputService private readonly quickInputService: IQuickInputService, @IExtensionService private readonly extensionService: IExtensionService, @@ -259,7 +254,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu } async $registerAuthenticationProvider(id: string, label: string, supportsMultipleAccounts: boolean): Promise { - const provider = new MainThreadAuthenticationProvider(this._proxy, id, label, supportsMultipleAccounts, this.notificationService, this.storageKeysSyncRegistryService, this.storageService, this.quickInputService, this.dialogService); + const provider = new MainThreadAuthenticationProvider(this._proxy, id, label, supportsMultipleAccounts, this.notificationService, this.storageService, this.quickInputService, this.dialogService); await provider.initialize(); this.authenticationService.registerAuthenticationProvider(id, provider); } @@ -383,7 +378,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu const allowList = readAllowedExtensions(this.storageService, providerId, accountName); if (!allowList.find(allowed => allowed.id === extensionId)) { allowList.push({ id: extensionId, name: extensionName }); - this.storageService.store(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL); + this.storageService.store2(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL, StorageTarget.USER); } this.storageService.store(`${extensionName}-${providerId}`, session.id, StorageScope.GLOBAL); @@ -435,7 +430,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu if (allow) { addAccountUsage(this.storageService, providerId, accountName, extensionId, extensionName); allowList.push({ id: extensionId, name: extensionName }); - this.storageService.store(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL); + this.storageService.store2(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL, StorageTarget.USER); } return allow; @@ -458,7 +453,7 @@ export class MainThreadAuthentication extends Disposable implements MainThreadAu const allowList = readAllowedExtensions(this.storageService, providerId, accountName); if (!allowList.find(allowed => allowed.id === extensionId)) { allowList.push({ id: extensionId, name: extensionName }); - this.storageService.store(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL); + this.storageService.store2(`${providerId}-${accountName}`, JSON.stringify(allowList), StorageScope.GLOBAL, StorageTarget.USER); } this.storageService.store(`${extensionName}-${providerId}`, sessionId, StorageScope.GLOBAL); diff --git a/src/vs/workbench/browser/layout.ts b/src/vs/workbench/browser/layout.ts index 13f62c49247..82a2c2b6821 100644 --- a/src/vs/workbench/browser/layout.ts +++ b/src/vs/workbench/browser/layout.ts @@ -16,7 +16,7 @@ import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart'; import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel'; import { Position, Parts, PanelOpensMaximizedOptions, IWorkbenchLayoutService, positionFromString, positionToString, panelOpensMaximizedFromString } from 'vs/workbench/services/layout/browser/layoutService'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; -import { IStorageService, StorageScope, WillSaveStateReason } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget, WillSaveStateReason } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; @@ -670,7 +670,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } if (sidebarState.length) { - storageService.store(ActivitybarPart.PINNED_VIEW_CONTAINERS, JSON.stringify(sidebarState), StorageScope.GLOBAL); + storageService.store2(ActivitybarPart.PINNED_VIEW_CONTAINERS, JSON.stringify(sidebarState), StorageScope.GLOBAL, StorageTarget.USER); } } } @@ -740,7 +740,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi } if (panelState.length) { - storageService.store(PanelPart.PINNED_PANELS, JSON.stringify(panelState), StorageScope.GLOBAL); + storageService.store2(PanelPart.PINNED_PANELS, JSON.stringify(panelState), StorageScope.GLOBAL, StorageTarget.USER); } } } diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts index fe59893c389..a57a9957fc1 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts @@ -32,7 +32,7 @@ import { getCurrentAuthenticationSessionInfo, IAuthenticationService } from 'vs/ import { AuthenticationSession } from 'vs/editor/common/modes'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IProductService } from 'vs/platform/product/common/productService'; import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview'; @@ -235,7 +235,7 @@ export class AccountsActionViewItem extends ActivityActionViewItem { } menus.push(new Action('hide', nls.localize('hide', "Hide"), undefined, true, _ => { - this.storageService.store(ACCOUNTS_VISIBILITY_PREFERENCE_KEY, false, StorageScope.GLOBAL); + this.storageService.store2(ACCOUNTS_VISIBILITY_PREFERENCE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); return Promise.resolve(); })); diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 592027dbfd0..822cbcbfc45 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -19,7 +19,7 @@ import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar'; import { Dimension, createCSSRule, asCSSUrl, addDisposableListener, EventType } from 'vs/base/browser/dom'; -import { IStorageService, StorageScope, IStorageChangeEvent } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { URI, UriComponents } from 'vs/base/common/uri'; import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity } from 'vs/workbench/browser/parts/compositeBarActions'; @@ -34,7 +34,6 @@ import { CustomMenubarControl } from 'vs/workbench/browser/parts/titlebar/menuba import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { getMenuBarVisibility } from 'vs/platform/windows/common/windows'; import { isWeb } from 'vs/base/common/platform'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { Before2D } from 'vs/workbench/browser/dnd'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; import { Action, Separator } from 'vs/base/common/actions'; @@ -125,14 +124,9 @@ export class ActivitybarPart extends Part implements IActivityBarService { @IContextKeyService private readonly contextKeyService: IContextKeyService, @IConfigurationService private readonly configurationService: IConfigurationService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(Parts.ACTIVITYBAR_PART, { hasTitle: false }, themeService, storageService, layoutService); - storageKeysSyncRegistryService.registerStorageKey({ key: ActivitybarPart.PINNED_VIEW_CONTAINERS, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: ActivitybarPart.HOME_BAR_VISIBILITY_PREFERENCE, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: ACCOUNTS_VISIBILITY_PREFERENCE_KEY, version: 1 }); - this.migrateFromOldCachedViewContainersValue(); for (const cachedViewContainer of this.cachedViewContainers) { @@ -971,7 +965,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } private setStoredPinnedViewContainersValue(value: string): void { - this.storageService.store(ActivitybarPart.PINNED_VIEW_CONTAINERS, value, StorageScope.GLOBAL); + this.storageService.store2(ActivitybarPart.PINNED_VIEW_CONTAINERS, value, StorageScope.GLOBAL, StorageTarget.USER); } private getPlaceholderViewContainers(): IPlaceholderViewContainer[] { @@ -1011,7 +1005,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } private set homeBarVisibilityPreference(value: boolean) { - this.storageService.store(ActivitybarPart.HOME_BAR_VISIBILITY_PREFERENCE, value, StorageScope.GLOBAL); + this.storageService.store2(ActivitybarPart.HOME_BAR_VISIBILITY_PREFERENCE, value, StorageScope.GLOBAL, StorageTarget.USER); } private get accountsVisibilityPreference(): boolean { @@ -1019,7 +1013,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { } private set accountsVisibilityPreference(value: boolean) { - this.storageService.store(ACCOUNTS_VISIBILITY_PREFERENCE_KEY, value, StorageScope.GLOBAL); + this.storageService.store2(ACCOUNTS_VISIBILITY_PREFERENCE_KEY, value, StorageScope.GLOBAL, StorageTarget.USER); } private migrateFromOldCachedViewContainersValue(): void { diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 8212bf29007..2a8d7b4f7b6 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -13,7 +13,7 @@ import { CompositePart, ICompositeTitleLabel } from 'vs/workbench/browser/parts/ import { Panel, PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService'; import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService'; -import { IStorageService, StorageScope, IStorageChangeEvent } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -37,7 +37,6 @@ import { ViewContainer, IViewDescriptorService, IViewContainerModel, ViewContain import { MenuId } from 'vs/platform/actions/common/actions'; import { ViewMenuActions, ViewContainerMenuActions } from 'vs/workbench/browser/parts/views/viewMenuActions'; import { IPaneComposite } from 'vs/workbench/common/panecomposite'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { Before2D, CompositeDragAndDropObserver, ICompositeDragAndDrop, toggleDropEffect } from 'vs/workbench/browser/dnd'; import { IActivity } from 'vs/workbench/common/activity'; @@ -118,7 +117,6 @@ export class PanelPart extends CompositePart implements IPanelService { @IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService, @IContextKeyService private readonly contextKeyService: IContextKeyService, @IExtensionService private readonly extensionService: IExtensionService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super( notificationService, @@ -140,7 +138,6 @@ export class PanelPart extends CompositePart implements IPanelService { ); this.panelRegistry = Registry.as(PanelExtensions.Panels); - storageKeysSyncRegistryService.registerStorageKey({ key: PanelPart.PINNED_PANELS, version: 1 }); this.dndHandler = new CompositeDragAndDrop(this.viewDescriptorService, ViewContainerLocation.Panel, (id: string, focus?: boolean) => (this.openPanel(id, focus) as Promise).then(panel => panel || null), @@ -760,7 +757,7 @@ export class PanelPart extends CompositePart implements IPanelService { } private setStoredCachedViewletsValue(value: string): void { - this.storageService.store(PanelPart.PINNED_PANELS, value, StorageScope.GLOBAL); + this.storageService.store2(PanelPart.PINNED_PANELS, value, StorageScope.GLOBAL, StorageTarget.USER); } private getPlaceholderViewContainers(): IPlaceholderViewContainer[] { diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index e88b369b390..6181ede82d8 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -23,7 +23,7 @@ import { isThemeColor } from 'vs/editor/common/editorCommon'; import { Color } from 'vs/base/common/color'; import { EventHelper, createStyleSheet, addDisposableListener, EventType, hide, show, isAncestor, appendChildren } from 'vs/base/browser/dom'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IStorageService, StorageScope, IStorageChangeEvent } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { coalesce } from 'vs/base/common/arrays'; @@ -32,7 +32,6 @@ import { ToggleStatusbarVisibilityAction } from 'vs/workbench/browser/actions/la import { assertIsDefined } from 'vs/base/common/types'; import { Emitter } from 'vs/base/common/event'; import { Command } from 'vs/editor/common/modes'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; import { KeyCode } from 'vs/base/common/keyCodes'; import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry'; @@ -275,7 +274,7 @@ class StatusbarViewModel extends Disposable { private saveState(): void { if (this.hidden.size > 0) { - this.storageService.store(StatusbarViewModel.HIDDEN_ENTRIES_KEY, JSON.stringify(Array.from(this.hidden.values())), StorageScope.GLOBAL); + this.storageService.store2(StatusbarViewModel.HIDDEN_ENTRIES_KEY, JSON.stringify(Array.from(this.hidden.values())), StorageScope.GLOBAL, StorageTarget.USER); } else { this.storageService.remove(StatusbarViewModel.HIDDEN_ENTRIES_KEY, StorageScope.GLOBAL); } @@ -405,12 +404,9 @@ export class StatusbarPart extends Part implements IStatusbarService { @IWorkbenchLayoutService layoutService: IWorkbenchLayoutService, @IContextMenuService private contextMenuService: IContextMenuService, @IContextKeyService private readonly contextKeyService: IContextKeyService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, ) { super(Parts.STATUSBAR_PART, { hasTitle: false }, themeService, storageService, layoutService); - storageKeysSyncRegistryService.registerStorageKey({ key: StatusbarViewModel.HIDDEN_ENTRIES_KEY, version: 1 }); - this.registerListeners(); } diff --git a/src/vs/workbench/contrib/codeEditor/browser/largeFileOptimizations.ts b/src/vs/workbench/contrib/codeEditor/browser/largeFileOptimizations.ts index 8268057aff8..f7a7ea98dfb 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/largeFileOptimizations.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/largeFileOptimizations.ts @@ -11,7 +11,6 @@ import { registerEditorContribution } from 'vs/editor/browser/editorExtensions'; import { IEditorContribution } from 'vs/editor/common/editorCommon'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; /** * Shows a message when opening a large file which has been memory optimized (and features disabled). @@ -24,14 +23,9 @@ export class LargeFileOptimizationsWarner extends Disposable implements IEditorC private readonly _editor: ICodeEditor, @INotificationService private readonly _notificationService: INotificationService, @IConfigurationService private readonly _configurationService: IConfigurationService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); - // opt-in to syncing - const neverShowAgainId = 'editor.contrib.largeFileOptimizationsWarner'; - storageKeysSyncRegistryService.registerStorageKey({ key: neverShowAgainId, version: 1 }); - this._register(this._editor.onDidChangeModel((e) => { const model = this._editor.getModel(); if (!model) { @@ -61,7 +55,7 @@ export class LargeFileOptimizationsWarner extends Disposable implements IEditorC }); } } - ], { neverShowAgain: { id: neverShowAgainId } }); + ], { neverShowAgain: { id: 'editor.contrib.largeFileOptimizationsWarner' } }); } })); } diff --git a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts index f6aa5db5a7d..f1bb6e280e5 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionRecommendationNotificationService.ts @@ -16,9 +16,8 @@ import { areSameExtensions } from 'vs/platform/extensionManagement/common/extens import { IExtensionRecommendationNotificationService, RecommendationsNotificationResult, RecommendationSource } from 'vs/platform/extensionRecommendations/common/extensionRecommendations'; import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation'; import { INotificationHandle, INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { IUserDataAutoSyncEnablementService, IUserDataSyncResourceEnablementService, SyncResource } from 'vs/platform/userDataSync/common/userDataSync'; import { SearchExtensionsAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; import { IExtension, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions'; @@ -142,12 +141,10 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec @IWorkbenchExtensioManagementService private readonly extensionManagementService: IWorkbenchExtensioManagementService, @IWorkbenchExtensionEnablementService private readonly extensionEnablementService: IWorkbenchExtensionEnablementService, @IExtensionIgnoredRecommendationsService private readonly extensionIgnoredRecommendationsService: IExtensionIgnoredRecommendationsService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @IUserDataAutoSyncEnablementService private readonly userDataAutoSyncEnablementService: IUserDataAutoSyncEnablementService, @IUserDataSyncResourceEnablementService private readonly userDataSyncResourceEnablementService: IUserDataSyncResourceEnablementService, @optional(ITASExperimentService) tasExperimentService: ITASExperimentService, ) { - storageKeysSyncRegistryService.registerStorageKey({ key: ignoreImportantExtensionRecommendationStorageKey, version: 1 }); this.tasExperimentService = tasExperimentService; } @@ -423,7 +420,7 @@ export class ExtensionRecommendationNotificationService implements IExtensionRec const importantRecommendationsIgnoreList = [...this.ignoredRecommendations]; if (!importantRecommendationsIgnoreList.includes(id.toLowerCase())) { importantRecommendationsIgnoreList.push(id.toLowerCase()); - this.storageService.store(ignoreImportantExtensionRecommendationStorageKey, JSON.stringify(importantRecommendationsIgnoreList), StorageScope.GLOBAL); + this.storageService.store2(ignoreImportantExtensionRecommendationStorageKey, JSON.stringify(importantRecommendationsIgnoreList), StorageScope.GLOBAL, StorageTarget.USER); } } diff --git a/src/vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler.ts b/src/vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler.ts index 424d01cdffd..1776ec0bddc 100644 --- a/src/vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler.ts +++ b/src/vs/workbench/contrib/files/browser/editors/textFileSaveErrorHandler.ts @@ -23,7 +23,7 @@ import { FileEditorInput } from 'vs/workbench/contrib/files/common/editors/fileE import { SAVE_FILE_COMMAND_ID, REVERT_FILE_COMMAND_ID, SAVE_FILE_AS_COMMAND_ID, SAVE_FILE_AS_LABEL } from 'vs/workbench/contrib/files/browser/fileCommands'; import { INotificationService, INotificationHandle, INotificationActions, Severity } from 'vs/platform/notification/common/notification'; import { IOpenerService } from 'vs/platform/opener/common/opener'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ExecuteCommandAction } from 'vs/platform/actions/common/actions'; import { IProductService } from 'vs/platform/product/common/productService'; import { Event } from 'vs/base/common/event'; @@ -32,7 +32,6 @@ import { isWindows } from 'vs/base/common/platform'; import { Schemas } from 'vs/base/common/network'; import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences'; import { SaveReason } from 'vs/workbench/common/editor'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; export const CONFLICT_RESOLUTION_CONTEXT = 'saveConflictResolutionContext'; export const CONFLICT_RESOLUTION_SCHEME = 'conflictResolution'; @@ -56,13 +55,9 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa @ITextModelService textModelService: ITextModelService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IStorageService private readonly storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); - // opt-in to syncing - storageKeysSyncRegistryService.registerStorageKey({ key: LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, version: 1 }); - const provider = this._register(instantiationService.createInstance(TextFileContentProvider)); this._register(textModelService.registerTextModelContentProvider(CONFLICT_RESOLUTION_SCHEME, provider)); @@ -225,7 +220,7 @@ class DoNotShowResolveConflictLearnMoreAction extends Action { } async run(notification: IDisposable): Promise { - this.storageService.store(LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, true, StorageScope.GLOBAL); + this.storageService.store2(LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, true, StorageScope.GLOBAL, StorageTarget.USER); // Hide notification notification.dispose(); diff --git a/src/vs/workbench/contrib/localizations/browser/localizations.contribution.ts b/src/vs/workbench/contrib/localizations/browser/localizations.contribution.ts index 446ad446f07..06063d9da1b 100644 --- a/src/vs/workbench/contrib/localizations/browser/localizations.contribution.ts +++ b/src/vs/workbench/contrib/localizations/browser/localizations.contribution.ts @@ -19,13 +19,12 @@ import Severity from 'vs/base/common/severity'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IHostService } from 'vs/workbench/services/host/browser/host'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet'; import { VIEWLET_ID as EXTENSIONS_VIEWLET_ID, IExtensionsViewPaneContainer } from 'vs/workbench/contrib/extensions/common/extensions'; import { minimumTranslatedStrings } from 'vs/workbench/contrib/localizations/browser/minimalTranslations'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; // Register action to configure locale and related settings const registry = Registry.as(Extensions.WorkbenchActions); @@ -44,12 +43,9 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo @IExtensionGalleryService private readonly galleryService: IExtensionGalleryService, @IViewletService private readonly viewletService: IViewletService, @ITelemetryService private readonly telemetryService: ITelemetryService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); - storageKeysSyncRegistryService.registerStorageKey({ key: LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: 'langugage.update.donotask', version: 1 }); this.checkAndInstall(); this._register(this.extensionManagementService.onDidInstallExtension(e => this.onDidInstallExtension(e))); } @@ -172,10 +168,11 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo isSecondary: true, run: () => { languagePackSuggestionIgnoreList.push(language); - this.storageService.store( + this.storageService.store2( LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY, JSON.stringify(languagePackSuggestionIgnoreList), - StorageScope.GLOBAL + StorageScope.GLOBAL, + StorageTarget.USER ); logUserReaction('neverShowAgain'); } diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 941cd7b5b7c..44e4f805406 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -31,12 +31,11 @@ import { IEditorModel } from 'vs/platform/editor/common/editor'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { badgeBackground, badgeForeground, contrastBorder, editorForeground } from 'vs/platform/theme/common/colorRegistry'; import { attachButtonStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; import { IThemeService } from 'vs/platform/theme/common/themeService'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { IUserDataAutoSyncEnablementService, IUserDataSyncService, SyncStatus } from 'vs/platform/userDataSync/common/userDataSync'; import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane'; import { IEditorMemento, IEditorOpenContext, IEditorPane } from 'vs/workbench/common/editor'; @@ -173,7 +172,6 @@ export class SettingsEditor2 extends EditorPane { @IStorageService private readonly storageService: IStorageService, @INotificationService private readonly notificationService: INotificationService, @IEditorGroupsService protected editorGroupService: IEditorGroupsService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @IUserDataSyncWorkbenchService private readonly userDataSyncWorkbenchService: IUserDataSyncWorkbenchService, @IUserDataAutoSyncEnablementService private readonly userDataAutoSyncEnablementService: IUserDataAutoSyncEnablementService ) { @@ -202,8 +200,6 @@ export class SettingsEditor2 extends EditorPane { this.onConfigUpdate(e.affectedKeys); } })); - - storageKeysSyncRegistryService.registerStorageKey({ key: SETTINGS_AUTOSAVE_NOTIFIED_KEY, version: 1 }); } get minimumWidth(): number { return 375; } @@ -737,7 +733,7 @@ export class SettingsEditor2 extends EditorPane { private notifyNoSaveNeeded() { if (!this.storageService.getBoolean(SETTINGS_AUTOSAVE_NOTIFIED_KEY, StorageScope.GLOBAL, false)) { - this.storageService.store(SETTINGS_AUTOSAVE_NOTIFIED_KEY, true, StorageScope.GLOBAL); + this.storageService.store2(SETTINGS_AUTOSAVE_NOTIFIED_KEY, true, StorageScope.GLOBAL, StorageTarget.USER); this.notificationService.info(localize('settingsNoSaveNeeded', "Your changes are automatically saved as you edit.")); } } diff --git a/src/vs/workbench/contrib/surveys/browser/languageSurveys.contribution.ts b/src/vs/workbench/contrib/surveys/browser/languageSurveys.contribution.ts index 273f4cc82a7..df1a050ad1e 100644 --- a/src/vs/workbench/contrib/surveys/browser/languageSurveys.contribution.ts +++ b/src/vs/workbench/contrib/surveys/browser/languageSurveys.contribution.ts @@ -9,8 +9,7 @@ import { IModelService } from 'vs/editor/common/services/modelService'; import { IWorkbenchContributionsRegistry, IWorkbenchContribution, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { Registry } from 'vs/platform/registry/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ISurveyData, IProductService } from 'vs/platform/product/common/productService'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { Severity, INotificationService } from 'vs/platform/notification/common/notification'; @@ -26,7 +25,6 @@ class LanguageSurvey extends Disposable { constructor( data: ISurveyData, storageService: IStorageService, - storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, notificationService: INotificationService, telemetryService: ITelemetryService, modelService: IModelService, @@ -43,14 +41,6 @@ class LanguageSurvey extends Disposable { const EDITED_LANGUAGE_COUNT_KEY = `${data.surveyId}.editedCount`; const EDITED_LANGUAGE_DATE_KEY = `${data.surveyId}.editedDate`; - // opt-in to syncing - storageKeysSyncRegistryService.registerStorageKey({ key: SESSION_COUNT_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: LAST_SESSION_DATE_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: SKIP_VERSION_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: IS_CANDIDATE_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: EDITED_LANGUAGE_COUNT_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: EDITED_LANGUAGE_DATE_KEY, version: 1 }); - const skipVersion = storageService.get(SKIP_VERSION_KEY, StorageScope.GLOBAL, ''); if (skipVersion) { return; @@ -65,8 +55,8 @@ class LanguageSurvey extends Disposable { models.forEach(m => { if (m.getMode() === data.languageId && date !== storageService.get(EDITED_LANGUAGE_DATE_KEY, StorageScope.GLOBAL)) { const editedCount = storageService.getNumber(EDITED_LANGUAGE_COUNT_KEY, StorageScope.GLOBAL, 0) + 1; - storageService.store(EDITED_LANGUAGE_COUNT_KEY, editedCount, StorageScope.GLOBAL); - storageService.store(EDITED_LANGUAGE_DATE_KEY, date, StorageScope.GLOBAL); + storageService.store2(EDITED_LANGUAGE_COUNT_KEY, editedCount, StorageScope.GLOBAL, StorageTarget.USER); + storageService.store2(EDITED_LANGUAGE_DATE_KEY, date, StorageScope.GLOBAL, StorageTarget.USER); } }); }, 250)); @@ -80,8 +70,8 @@ class LanguageSurvey extends Disposable { } const sessionCount = storageService.getNumber(SESSION_COUNT_KEY, StorageScope.GLOBAL, 0) + 1; - storageService.store(LAST_SESSION_DATE_KEY, date, StorageScope.GLOBAL); - storageService.store(SESSION_COUNT_KEY, sessionCount, StorageScope.GLOBAL); + storageService.store2(LAST_SESSION_DATE_KEY, date, StorageScope.GLOBAL, StorageTarget.USER); + storageService.store2(SESSION_COUNT_KEY, sessionCount, StorageScope.GLOBAL, StorageTarget.USER); if (sessionCount < 9) { return; @@ -94,10 +84,10 @@ class LanguageSurvey extends Disposable { const isCandidate = storageService.getBoolean(IS_CANDIDATE_KEY, StorageScope.GLOBAL, false) || Math.random() < data.userProbability; - storageService.store(IS_CANDIDATE_KEY, isCandidate, StorageScope.GLOBAL); + storageService.store2(IS_CANDIDATE_KEY, isCandidate, StorageScope.GLOBAL, StorageTarget.USER); if (!isCandidate) { - storageService.store(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL); + storageService.store2(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL, StorageTarget.USER); return; } @@ -113,23 +103,23 @@ class LanguageSurvey extends Disposable { telemetryService.publicLog(`${data.surveyId}.survey/takeShortSurvey`); telemetryService.getTelemetryInfo().then(info => { openerService.open(URI.parse(`${data.surveyUrl}?o=${encodeURIComponent(platform)}&v=${encodeURIComponent(productService.version)}&m=${encodeURIComponent(info.machineId)}`)); - storageService.store(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); - storageService.store(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL); + storageService.store2(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); + storageService.store2(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL, StorageTarget.USER); }); } }, { label: nls.localize('remindLater', "Remind Me later"), run: () => { telemetryService.publicLog(`${data.surveyId}.survey/remindMeLater`); - storageService.store(SESSION_COUNT_KEY, sessionCount - 3, StorageScope.GLOBAL); + storageService.store2(SESSION_COUNT_KEY, sessionCount - 3, StorageScope.GLOBAL, StorageTarget.USER); } }, { label: nls.localize('neverAgain', "Don't Show Again"), isSecondary: true, run: () => { telemetryService.publicLog(`${data.surveyId}.survey/dontShowAgain`); - storageService.store(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); - storageService.store(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL); + storageService.store2(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); + storageService.store2(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL, StorageTarget.USER); } }], { sticky: true } @@ -141,7 +131,6 @@ class LanguageSurveysContribution implements IWorkbenchContribution { constructor( @IStorageService storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @INotificationService notificationService: INotificationService, @ITelemetryService telemetryService: ITelemetryService, @IModelService modelService: IModelService, @@ -155,7 +144,7 @@ class LanguageSurveysContribution implements IWorkbenchContribution { productService.surveys .filter(surveyData => surveyData.surveyId && surveyData.editCount && surveyData.languageId && surveyData.surveyUrl && surveyData.userProbability) - .map(surveyData => new LanguageSurvey(surveyData, storageService, storageKeysSyncRegistryService, notificationService, telemetryService, modelService, textFileService, openerService, productService)); + .map(surveyData => new LanguageSurvey(surveyData, storageService, notificationService, telemetryService, modelService, textFileService, openerService, productService)); } } diff --git a/src/vs/workbench/contrib/surveys/browser/nps.contribution.ts b/src/vs/workbench/contrib/surveys/browser/nps.contribution.ts index 7f8e32d2842..16de633cb34 100644 --- a/src/vs/workbench/contrib/surveys/browser/nps.contribution.ts +++ b/src/vs/workbench/contrib/surveys/browser/nps.contribution.ts @@ -8,8 +8,7 @@ import { language } from 'vs/base/common/platform'; import { IWorkbenchContributionsRegistry, IWorkbenchContribution, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { Registry } from 'vs/platform/registry/common/platform'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IProductService } from 'vs/platform/product/common/productService'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; import { Severity, INotificationService } from 'vs/platform/notification/common/notification'; @@ -27,7 +26,6 @@ class NPSContribution implements IWorkbenchContribution { constructor( @IStorageService storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @INotificationService notificationService: INotificationService, @ITelemetryService telemetryService: ITelemetryService, @IOpenerService openerService: IOpenerService, @@ -37,12 +35,6 @@ class NPSContribution implements IWorkbenchContribution { return; } - // opt-in to syncing - storageKeysSyncRegistryService.registerStorageKey({ key: SESSION_COUNT_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: LAST_SESSION_DATE_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: SKIP_VERSION_KEY, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: IS_CANDIDATE_KEY, version: 1 }); - const skipVersion = storageService.get(SKIP_VERSION_KEY, StorageScope.GLOBAL, ''); if (skipVersion) { return; @@ -56,8 +48,8 @@ class NPSContribution implements IWorkbenchContribution { } const sessionCount = (storageService.getNumber(SESSION_COUNT_KEY, StorageScope.GLOBAL, 0) || 0) + 1; - storageService.store(LAST_SESSION_DATE_KEY, date, StorageScope.GLOBAL); - storageService.store(SESSION_COUNT_KEY, sessionCount, StorageScope.GLOBAL); + storageService.store2(LAST_SESSION_DATE_KEY, date, StorageScope.GLOBAL, StorageTarget.USER); + storageService.store2(SESSION_COUNT_KEY, sessionCount, StorageScope.GLOBAL, StorageTarget.USER); if (sessionCount < 9) { return; @@ -66,10 +58,10 @@ class NPSContribution implements IWorkbenchContribution { const isCandidate = storageService.getBoolean(IS_CANDIDATE_KEY, StorageScope.GLOBAL, false) || Math.random() < PROBABILITY; - storageService.store(IS_CANDIDATE_KEY, isCandidate, StorageScope.GLOBAL); + storageService.store2(IS_CANDIDATE_KEY, isCandidate, StorageScope.GLOBAL, StorageTarget.USER); if (!isCandidate) { - storageService.store(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL); + storageService.store2(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL, StorageTarget.USER); return; } @@ -81,18 +73,18 @@ class NPSContribution implements IWorkbenchContribution { run: () => { telemetryService.getTelemetryInfo().then(info => { openerService.open(URI.parse(`${productService.npsSurveyUrl}?o=${encodeURIComponent(platform)}&v=${encodeURIComponent(productService.version)}&m=${encodeURIComponent(info.machineId)}`)); - storageService.store(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); - storageService.store(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL); + storageService.store2(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); + storageService.store2(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL, StorageTarget.USER); }); } }, { label: nls.localize('remindLater', "Remind Me later"), - run: () => storageService.store(SESSION_COUNT_KEY, sessionCount - 3, StorageScope.GLOBAL) + run: () => storageService.store2(SESSION_COUNT_KEY, sessionCount - 3, StorageScope.GLOBAL, StorageTarget.USER) }, { label: nls.localize('neverAgain', "Don't Show Again"), run: () => { - storageService.store(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL); - storageService.store(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL); + storageService.store2(IS_CANDIDATE_KEY, false, StorageScope.GLOBAL, StorageTarget.USER); + storageService.store2(SKIP_VERSION_KEY, productService.version, StorageScope.GLOBAL, StorageTarget.USER); } }], { sticky: true } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts index 6dc11347198..6d0941e55c6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts @@ -20,7 +20,6 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions'; import { IProductService } from 'vs/platform/product/common/productService'; import { XTermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; const MINIMUM_FONT_SIZE = 6; const MAXIMUM_FONT_SIZE = 25; @@ -51,7 +50,6 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { @ITelemetryService private readonly telemetryService: ITelemetryService, @IInstantiationService private readonly instantiationService: IInstantiationService, @IProductService private readonly productService: IProductService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { this._updateConfig(); this._configurationService.onDidChangeConfiguration(e => { @@ -59,9 +57,6 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { this._updateConfig(); } }); - - // opt-in to syncing - storageKeysSyncRegistryService.registerStorageKey({ key: 'terminalConfigHelper/launchRecommendationsIgnore', version: 1 }); } public setLinuxDistro(linuxDistro: LinuxDistro) { diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalConfigHelper.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalConfigHelper.test.ts index eed4382af0a..d8263b55864 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalConfigHelper.test.ts @@ -8,7 +8,6 @@ import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/term import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; -import { StorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; suite('Workbench - TerminalConfigHelper', () => { let fixture: HTMLElement; @@ -30,7 +29,7 @@ suite('Workbench - TerminalConfigHelper', () => { const configurationService = new TestConfigurationService(); configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); - const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.setLinuxDistro(LinuxDistro.Fedora); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set'); @@ -40,7 +39,7 @@ suite('Workbench - TerminalConfigHelper', () => { const configurationService = new TestConfigurationService(); configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); - const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.setLinuxDistro(LinuxDistro.Ubuntu); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set'); @@ -50,7 +49,7 @@ suite('Workbench - TerminalConfigHelper', () => { const configurationService = new TestConfigurationService(); configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); - const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontFamily, 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set'); }); @@ -68,7 +67,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 10 } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize'); @@ -81,12 +80,12 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 0 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.setLinuxDistro(LinuxDistro.Ubuntu); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 8, 'The minimum terminal font size (with adjustment) should be used when terminal.integrated.fontSize less than it'); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it'); @@ -99,7 +98,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 1500 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, 25, 'The maximum terminal font size should be used when terminal.integrated.fontSize more than it'); @@ -112,12 +111,12 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: null } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.setLinuxDistro(LinuxDistro.Ubuntu); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize + 2, 'The default editor font size (with adjustment) should be used when terminal.integrated.fontSize is not set'); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set'); }); @@ -135,7 +134,7 @@ suite('Workbench - TerminalConfigHelper', () => { lineHeight: 2 } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight'); @@ -149,7 +148,7 @@ suite('Workbench - TerminalConfigHelper', () => { lineHeight: 0 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.getFont().lineHeight, 1, 'editor.lineHeight should be 1 when terminal.integrated.lineHeight not set'); }); @@ -162,7 +161,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), true, 'monospace is monospaced'); }); @@ -174,7 +173,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontFamily: 'sans-serif' } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced'); }); @@ -186,7 +185,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontFamily: 'serif' } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), false, 'serif is not monospaced'); }); @@ -202,7 +201,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), true, 'monospace is monospaced'); }); @@ -218,7 +217,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced'); }); @@ -234,7 +233,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!, new StorageKeysSyncRegistryService()); + let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.equal(configHelper.configFontIsMonospace(), false, 'serif is not monospaced'); }); diff --git a/src/vs/workbench/contrib/update/browser/update.ts b/src/vs/workbench/contrib/update/browser/update.ts index f4101c7f4bf..14c3f0fb077 100644 --- a/src/vs/workbench/contrib/update/browser/update.ts +++ b/src/vs/workbench/contrib/update/browser/update.ts @@ -28,7 +28,6 @@ import { ShowCurrentReleaseNotesActionId, CheckForVSCodeUpdateActionId } from 'v import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IProductService } from 'vs/platform/product/common/productService'; import product from 'vs/platform/product/common/product'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; export const CONTEXT_UPDATE_STATE = new RawContextKey('updateState', StateType.Idle); @@ -185,15 +184,11 @@ export class UpdateContribution extends Disposable implements IWorkbenchContribu @IContextKeyService private readonly contextKeyService: IContextKeyService, @IProductService private readonly productService: IProductService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); this.state = updateService.state; this.updateStateContextKey = CONTEXT_UPDATE_STATE.bindTo(this.contextKeyService); - // opt-in to syncing - storageKeysSyncRegistryService.registerStorageKey({ key: 'neverShowAgain:update/win32-fast-updates', version: 1 }); - this._register(updateService.onStateChange(this.onUpdateStateChange, this)); this.onUpdateStateChange(this.updateService.state); diff --git a/src/vs/workbench/contrib/url/browser/trustedDomains.ts b/src/vs/workbench/contrib/url/browser/trustedDomains.ts index 351cdf63ebd..d688b6b5817 100644 --- a/src/vs/workbench/contrib/url/browser/trustedDomains.ts +++ b/src/vs/workbench/contrib/url/browser/trustedDomains.ts @@ -8,7 +8,7 @@ import { localize } from 'vs/nls'; import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'; import { IProductService } from 'vs/platform/product/common/productService'; import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; @@ -127,10 +127,11 @@ export async function configureOpenerTrustedDomainsHandler( const itemToTrust = pickedResult.toTrust; if (trustedDomains.indexOf(itemToTrust) === -1) { storageService.remove(TRUSTED_DOMAINS_CONTENT_STORAGE_KEY, StorageScope.GLOBAL); - storageService.store( + storageService.store2( TRUSTED_DOMAINS_STORAGE_KEY, JSON.stringify([...trustedDomains, itemToTrust]), - StorageScope.GLOBAL + StorageScope.GLOBAL, + StorageTarget.USER ); return [...trustedDomains, itemToTrust]; diff --git a/src/vs/workbench/contrib/url/browser/trustedDomainsFileSystemProvider.ts b/src/vs/workbench/contrib/url/browser/trustedDomainsFileSystemProvider.ts index a04a706c8b1..c2e9353a3c4 100644 --- a/src/vs/workbench/contrib/url/browser/trustedDomainsFileSystemProvider.ts +++ b/src/vs/workbench/contrib/url/browser/trustedDomainsFileSystemProvider.ts @@ -8,11 +8,10 @@ import { parse } from 'vs/base/common/json'; import { IDisposable } from 'vs/base/common/lifecycle'; import { URI } from 'vs/base/common/uri'; import { FileDeleteOptions, FileOverwriteOptions, FileSystemProviderCapabilities, FileType, FileWriteOptions, IFileService, IStat, IWatchOptions, IFileSystemProviderWithFileReadWriteCapability } from 'vs/platform/files/common/files'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; import { VSBuffer } from 'vs/base/common/buffer'; import { readTrustedDomains, TRUSTED_DOMAINS_CONTENT_STORAGE_KEY, TRUSTED_DOMAINS_STORAGE_KEY } from 'vs/workbench/contrib/url/browser/trustedDomains'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { assertIsDefined } from 'vs/base/common/types'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -97,12 +96,8 @@ export class TrustedDomainsFileSystemProvider implements IFileSystemProviderWith @IFileService private readonly fileService: IFileService, @IStorageService private readonly storageService: IStorageService, @IInstantiationService private readonly instantiationService: IInstantiationService, - @IStorageKeysSyncRegistryService private readonly storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, ) { this.fileService.registerProvider(TRUSTED_DOMAINS_SCHEMA, this); - - this.storageKeysSyncRegistryService.registerStorageKey({ key: TRUSTED_DOMAINS_STORAGE_KEY, version: 1 }); - this.storageKeysSyncRegistryService.registerStorageKey({ key: TRUSTED_DOMAINS_CONTENT_STORAGE_KEY, version: 1 }); } stat(resource: URI): Promise { @@ -134,11 +129,12 @@ export class TrustedDomainsFileSystemProvider implements IFileSystemProviderWith const trustedDomainsContent = VSBuffer.wrap(content).toString(); const trustedDomains = parse(trustedDomainsContent); - this.storageService.store(TRUSTED_DOMAINS_CONTENT_STORAGE_KEY, trustedDomainsContent, StorageScope.GLOBAL); - this.storageService.store( + this.storageService.store2(TRUSTED_DOMAINS_CONTENT_STORAGE_KEY, trustedDomainsContent, StorageScope.GLOBAL, StorageTarget.USER); + this.storageService.store2( TRUSTED_DOMAINS_STORAGE_KEY, JSON.stringify(trustedDomains) || '', - StorageScope.GLOBAL + StorageScope.GLOBAL, + StorageTarget.USER ); } catch (err) { } diff --git a/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts index 6b2fa23f33b..bc5699b1556 100644 --- a/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/browser/telemetryOptOut.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; @@ -19,7 +19,6 @@ import { IProductService } from 'vs/platform/product/common/productService'; import { IHostService } from 'vs/workbench/services/host/browser/host'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution { @@ -28,7 +27,6 @@ export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution constructor( @IStorageService private readonly storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @IOpenerService private readonly openerService: IOpenerService, @INotificationService private readonly notificationService: INotificationService, @IHostService private readonly hostService: IHostService, @@ -40,7 +38,6 @@ export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution @IEnvironmentService private readonly environmentService: IEnvironmentService, @IJSONEditingService private readonly jsonEditingService: IJSONEditingService ) { - storageKeysSyncRegistryService.registerStorageKey({ key: AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, version: 1 }); } protected async handleTelemetryOptOut(): Promise { @@ -53,7 +50,7 @@ export abstract class AbstractTelemetryOptOut implements IWorkbenchContribution return; // return early if meanwhile another window opened (we only show the opt-out once) } - this.storageService.store(AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, true, StorageScope.GLOBAL); + this.storageService.store2(AbstractTelemetryOptOut.TELEMETRY_OPT_OUT_SHOWN, true, StorageScope.GLOBAL, StorageTarget.USER); this.privacyUrl = this.productService.privacyStatementUrl || this.productService.telemetryOptOutUrl; @@ -165,7 +162,6 @@ export class BrowserTelemetryOptOut extends AbstractTelemetryOptOut { constructor( @IStorageService storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @IOpenerService openerService: IOpenerService, @INotificationService notificationService: INotificationService, @IHostService hostService: IHostService, @@ -177,7 +173,7 @@ export class BrowserTelemetryOptOut extends AbstractTelemetryOptOut { @IEnvironmentService environmentService: IEnvironmentService, @IJSONEditingService jsonEditingService: IJSONEditingService ) { - super(storageService, storageKeysSyncRegistryService, openerService, notificationService, hostService, telemetryService, experimentService, configurationService, galleryService, productService, environmentService, jsonEditingService); + super(storageService, openerService, notificationService, hostService, telemetryService, experimentService, configurationService, galleryService, productService, environmentService, jsonEditingService); this.handleTelemetryOptOut(); } diff --git a/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.ts b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.ts index 60c4fcfa34c..81b28a10849 100644 --- a/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.ts +++ b/src/vs/workbench/contrib/welcome/telemetryOptOut/electron-sandbox/telemetryOptOut.ts @@ -16,13 +16,11 @@ import { AbstractTelemetryOptOut } from 'vs/workbench/contrib/welcome/telemetryO import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; export class NativeTelemetryOptOut extends AbstractTelemetryOptOut { constructor( @IStorageService storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, @IOpenerService openerService: IOpenerService, @INotificationService notificationService: INotificationService, @IHostService hostService: IHostService, @@ -35,7 +33,7 @@ export class NativeTelemetryOptOut extends AbstractTelemetryOptOut { @IJSONEditingService jsonEditingService: IJSONEditingService, @INativeHostService private readonly nativeHostService: INativeHostService ) { - super(storageService, storageKeysSyncRegistryService, openerService, notificationService, hostService, telemetryService, experimentService, configurationService, galleryService, productService, environmentService, jsonEditingService); + super(storageService, openerService, notificationService, hostService, telemetryService, experimentService, configurationService, galleryService, productService, environmentService, jsonEditingService); this.handleTelemetryOptOut(); } diff --git a/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.ts b/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.ts index 3655af5bea3..2f5ed993573 100644 --- a/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.ts +++ b/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.ts @@ -7,8 +7,7 @@ import { distinct } from 'vs/base/common/arrays'; import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IStorageService, IStorageChangeEvent, StorageScope } from 'vs/platform/storage/common/storage'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; +import { IStorageService, IStorageChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionIgnoredRecommendationsService, IgnoredRecommendationChangeNotification } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations'; import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; @@ -35,10 +34,8 @@ export class ExtensionIgnoredRecommendationsService extends Disposable implement constructor( @IWorkpsaceExtensionsConfigService private readonly workpsaceExtensionsConfigService: IWorkpsaceExtensionsConfigService, @IStorageService private readonly storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, ) { super(); - storageKeysSyncRegistryService.registerStorageKey({ key: ignoredRecommendationsStorageKey, version: 1 }); this._globalIgnoredRecommendations = this.getCachedIgnoredRecommendations(); this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); @@ -106,7 +103,7 @@ export class ExtensionIgnoredRecommendationsService extends Disposable implement } private setStoredIgnoredRecommendationsValue(value: string): void { - this.storageService.store(ignoredRecommendationsStorageKey, value, StorageScope.GLOBAL); + this.storageService.store2(ignoredRecommendationsStorageKey, value, StorageScope.GLOBAL, StorageTarget.USER); } } diff --git a/src/vs/workbench/services/notification/common/notificationService.ts b/src/vs/workbench/services/notification/common/notificationService.ts index b49ea4a665e..50a6a8b2095 100644 --- a/src/vs/workbench/services/notification/common/notificationService.ts +++ b/src/vs/workbench/services/notification/common/notificationService.ts @@ -10,7 +10,7 @@ import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecyc import { Event } from 'vs/base/common/event'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IAction, Action } from 'vs/base/common/actions'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; export class NotificationService extends Disposable implements INotificationService { @@ -83,7 +83,7 @@ export class NotificationService extends Disposable implements INotificationServ handle.close(); // Remember choice - this.storageService.store(id, true, scope); + this.storageService.store2(id, true, scope, StorageTarget.USER); return Promise.resolve(); })); @@ -127,7 +127,7 @@ export class NotificationService extends Disposable implements INotificationServ const neverShowAgainChoice = { label: nls.localize('neverShowAgain', "Don't Show Again"), - run: () => this.storageService.store(id, true, scope), + run: () => this.storageService.store2(id, true, scope, StorageTarget.USER), isSecondary: options.neverShowAgain.isSecondary }; diff --git a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts index 32459f57524..cde9e21cf7e 100644 --- a/src/vs/workbench/services/themes/browser/workbenchThemeService.ts +++ b/src/vs/workbench/services/themes/browser/workbenchThemeService.ts @@ -38,7 +38,6 @@ import { ColorScheme } from 'vs/platform/theme/common/theme'; import { IHostColorSchemeService } from 'vs/workbench/services/themes/common/hostColorSchemeService'; import { CodiconStyles } from 'vs/base/browser/ui/codicons/codiconStyles'; import { RunOnceScheduler } from 'vs/base/common/async'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; // implementation @@ -109,11 +108,7 @@ export class WorkbenchThemeService implements IWorkbenchThemeService { @IWorkbenchLayoutService readonly layoutService: IWorkbenchLayoutService, @ILogService private readonly logService: ILogService, @IHostColorSchemeService private readonly hostColorService: IHostColorSchemeService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { - // roam persisted color theme colors. Don't enable for icons as they contain references to fonts and images. - storageKeysSyncRegistryService.registerStorageKey({ key: ColorThemeData.STORAGE_KEY, version: 1 }); - this.container = layoutService.container; this.settings = new ThemeConfiguration(configurationService); diff --git a/src/vs/workbench/services/themes/common/colorThemeData.ts b/src/vs/workbench/services/themes/common/colorThemeData.ts index 5fd6f38e201..d5336c831ad 100644 --- a/src/vs/workbench/services/themes/common/colorThemeData.ts +++ b/src/vs/workbench/services/themes/common/colorThemeData.ts @@ -21,7 +21,7 @@ import { TokenStyle, SemanticTokenRule, ProbeScope, getTokenClassificationRegist import { MatcherWithPriority, Matcher, createMatchers } from 'vs/workbench/services/themes/common/textMateScopeMatcher'; import { IExtensionResourceLoaderService } from 'vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader'; import { CharCode } from 'vs/base/common/charCode'; -import { StorageScope, IStorageService } from 'vs/platform/storage/common/storage'; +import { StorageScope, IStorageService, StorageTarget } from 'vs/platform/storage/common/storage'; import { ThemeConfiguration } from 'vs/workbench/services/themes/common/themeConfiguration'; import { ColorScheme } from 'vs/platform/theme/common/theme'; @@ -523,7 +523,8 @@ export class ColorThemeData implements IWorkbenchColorTheme { watch: this.watch }); - storageService.store(ColorThemeData.STORAGE_KEY, value, StorageScope.GLOBAL); + // roam persisted color theme colors. Don't enable for icons as they contain references to fonts and images. + storageService.store2(ColorThemeData.STORAGE_KEY, value, StorageScope.GLOBAL, StorageTarget.USER); } get baseTheme(): string { diff --git a/src/vs/workbench/services/views/browser/viewDescriptorService.ts b/src/vs/workbench/services/views/browser/viewDescriptorService.ts index a734c4aada5..f2d88b5a8e1 100644 --- a/src/vs/workbench/services/views/browser/viewDescriptorService.ts +++ b/src/vs/workbench/services/views/browser/viewDescriptorService.ts @@ -5,7 +5,7 @@ import { ViewContainerLocation, IViewDescriptorService, ViewContainer, IViewsRegistry, IViewContainersRegistry, IViewDescriptor, Extensions as ViewExtensions, ViewVisibilityState } from 'vs/workbench/common/views'; import { IContextKey, RawContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IStorageService, StorageScope, IStorageChangeEvent } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { Registry } from 'vs/platform/registry/common/platform'; import { toDisposable, DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle'; @@ -13,7 +13,6 @@ import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneCont import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Event, Emitter } from 'vs/base/common/event'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { generateUuid } from 'vs/base/common/uuid'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -98,12 +97,9 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor @IStorageService private readonly storageService: IStorageService, @IExtensionService private readonly extensionService: IExtensionService, @ITelemetryService private readonly telemetryService: ITelemetryService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService, ) { super(); - storageKeysSyncRegistryService.registerStorageKey({ key: ViewDescriptorService.CACHED_VIEW_POSITIONS, version: 1 }); - storageKeysSyncRegistryService.registerStorageKey({ key: ViewDescriptorService.CACHED_VIEW_CONTAINER_LOCATIONS, version: 1 }); this.viewContainerModels = new Map(); this.activeViewContextKeys = new Map>(); this.movableViewContextKeys = new Map>(); @@ -600,7 +596,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor } private setStoredCachedViewPositionsValue(value: string): void { - this.storageService.store(ViewDescriptorService.CACHED_VIEW_POSITIONS, value, StorageScope.GLOBAL); + this.storageService.store2(ViewDescriptorService.CACHED_VIEW_POSITIONS, value, StorageScope.GLOBAL, StorageTarget.USER); } private getStoredCachedViewContainerLocationsValue(): string { @@ -608,7 +604,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor } private setStoredCachedViewContainerLocationsValue(value: string): void { - this.storageService.store(ViewDescriptorService.CACHED_VIEW_CONTAINER_LOCATIONS, value, StorageScope.GLOBAL); + this.storageService.store2(ViewDescriptorService.CACHED_VIEW_CONTAINER_LOCATIONS, value, StorageScope.GLOBAL, StorageTarget.USER); } private saveViewPositionsToCache(): void { diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index 4450c639156..ded4501ff9b 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -5,11 +5,10 @@ import { ViewContainer, IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions, IViewContainerModel, IAddedViewDescriptorRef, IViewDescriptorRef, IAddedViewDescriptorState } from 'vs/workbench/common/views'; import { IContextKeyService, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; -import { IStorageService, StorageScope, IStorageChangeEvent } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; import { Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; import { move } from 'vs/base/common/arrays'; @@ -84,13 +83,11 @@ class ViewDescriptorsState extends Disposable { constructor( viewContainerStorageId: string, @IStorageService private readonly storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); this.globalViewsStateStorageId = getViewsStateStorageId(viewContainerStorageId); this.workspaceViewsStateStorageId = viewContainerStorageId; - storageKeysSyncRegistryService.registerStorageKey({ key: this.globalViewsStateStorageId, version: 1 }); this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); this.state = this.initialize(); @@ -270,7 +267,7 @@ class ViewDescriptorsState extends Disposable { } private setStoredGlobalViewsStatesValue(value: string): void { - this.storageService.store(this.globalViewsStateStorageId, value, StorageScope.GLOBAL); + this.storageService.store2(this.globalViewsStateStorageId, value, StorageScope.GLOBAL, StorageTarget.USER); } } diff --git a/src/vs/workbench/services/workspaces/browser/workspacesService.ts b/src/vs/workbench/services/workspaces/browser/workspacesService.ts index faf2abf6388..19985b8bc17 100644 --- a/src/vs/workbench/services/workspaces/browser/workspacesService.ts +++ b/src/vs/workbench/services/workspaces/browser/workspacesService.ts @@ -7,7 +7,7 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IWorkspacesService, IWorkspaceFolderCreationData, IWorkspaceIdentifier, IEnterWorkspaceResult, IRecentlyOpened, restoreRecentlyOpened, IRecent, isRecentFile, isRecentFolder, toStoreData, IStoredWorkspaceFolder, getStoredWorkspaceFolder, WORKSPACE_EXTENSION, IStoredWorkspace } from 'vs/platform/workspaces/common/workspaces'; import { URI } from 'vs/base/common/uri'; import { Emitter } from 'vs/base/common/event'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { ILogService } from 'vs/platform/log/common/log'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -16,7 +16,6 @@ import { IFileService, FileOperationError, FileOperationResult } from 'vs/platfo import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { joinPath } from 'vs/base/common/resources'; import { VSBuffer } from 'vs/base/common/buffer'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; export class BrowserWorkspacesService extends Disposable implements IWorkspacesService { @@ -33,13 +32,9 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS @ILogService private readonly logService: ILogService, @IFileService private readonly fileService: IFileService, @IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService, - @IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService ) { super(); - // opt-in to syncing - storageKeysSyncRegistryService.registerStorageKey({ key: BrowserWorkspacesService.RECENTLY_OPENED_KEY, version: 1 }); - // Opening a workspace should push it as most // recently used to the workspaces history this.addWorkspaceToRecentlyOpened(); @@ -116,7 +111,7 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS } private async saveRecentlyOpened(data: IRecentlyOpened): Promise { - return this.storageService.store(BrowserWorkspacesService.RECENTLY_OPENED_KEY, JSON.stringify(toStoreData(data)), StorageScope.GLOBAL); + return this.storageService.store2(BrowserWorkspacesService.RECENTLY_OPENED_KEY, JSON.stringify(toStoreData(data)), StorageScope.GLOBAL, StorageTarget.USER); } async clearRecentlyOpened(): Promise { From d562ace3357f70c5a0247982843679ac29772bfb Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Wed, 4 Nov 2020 15:33:33 +0100 Subject: [PATCH 14/17] adopt to new storage api --- .../workbench/contrib/snippets/browser/snippetsService.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/vs/workbench/contrib/snippets/browser/snippetsService.ts b/src/vs/workbench/contrib/snippets/browser/snippetsService.ts index 634bc709998..dc8e7027fb1 100644 --- a/src/vs/workbench/contrib/snippets/browser/snippetsService.ts +++ b/src/vs/workbench/contrib/snippets/browser/snippetsService.ts @@ -26,9 +26,8 @@ import { languagesExtPoint } from 'vs/workbench/services/mode/common/workbenchMo import { SnippetCompletionProvider } from './snippetCompletionProvider'; import { IExtensionResourceLoaderService } from 'vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader'; import { ResourceMap } from 'vs/base/common/map'; -import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { isStringArray } from 'vs/base/common/types'; -import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; namespace snippetExt { @@ -136,11 +135,8 @@ class SnippetEnablement { constructor( @IStorageService private readonly _storageService: IStorageService, - @IStorageKeysSyncRegistryService storageKeysSyncService: IStorageKeysSyncRegistryService, ) { - storageKeysSyncService.registerStorageKey({ key: SnippetEnablement._key, version: 1 }); - const raw = _storageService.get(SnippetEnablement._key, StorageScope.GLOBAL, ''); let data: string[] | undefined; try { @@ -164,7 +160,7 @@ class SnippetEnablement { changed = true; } if (changed) { - this._storageService.store(SnippetEnablement._key, JSON.stringify(Array.from(this._ignored)), StorageScope.GLOBAL); + this._storageService.store2(SnippetEnablement._key, JSON.stringify(Array.from(this._ignored)), StorageScope.GLOBAL, StorageTarget.USER); } } } From ea14fc2c2f9317374b288905151f1826422baf83 Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 Nov 2020 15:03:06 +0100 Subject: [PATCH 15/17] add command to reset suggest widget sizes --- .../contrib/suggest/suggestController.ts | 21 +++++++++++++++++++ .../editor/contrib/suggest/suggestWidget.ts | 8 +++++++ 2 files changed, 29 insertions(+) diff --git a/src/vs/editor/contrib/suggest/suggestController.ts b/src/vs/editor/contrib/suggest/suggestController.ts index 8bd4d44079e..887064414ba 100644 --- a/src/vs/editor/contrib/suggest/suggestController.ts +++ b/src/vs/editor/contrib/suggest/suggestController.ts @@ -584,6 +584,10 @@ export class SuggestController implements IEditorContribution { toggleSuggestionFocus(): void { this.widget.value.toggleDetailsFocus(); } + + resetWidgetSize(): void { + this.widget.value.resetPersistedSize(); + } } export class TriggerSuggestAction extends EditorAction { @@ -875,3 +879,20 @@ registerEditorCommand(new SuggestCommand({ primary: KeyMod.Shift | KeyCode.Tab } })); + + +registerEditorAction(class extends EditorAction { + + constructor() { + super({ + id: 'editor.action.resetSuggestSize', + label: nls.localize('suggest.reset.label', "Reset Suggest Widget Size"), + alias: 'Reset Suggest Widget Size', + precondition: undefined + }); + } + + run(_accessor: ServicesAccessor, editor: ICodeEditor): void { + SuggestController.get(editor).resetWidgetSize(); + } +}); diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index 91f1f9d60ed..ba2f5133459 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -84,6 +84,10 @@ class PersistedWidgetSize { store(size: dom.Dimension) { this._service.store(this._key, JSON.stringify(size), StorageScope.GLOBAL); } + + reset(): void { + this._service.remove(this._key, StorageScope.GLOBAL); + } } export class SuggestWidget implements IDisposable { @@ -677,6 +681,10 @@ export class SuggestWidget implements IDisposable { } } + resetPersistedSize(): void { + this._persistedSize.reset(); + } + hideWidget(): void { this._loadingTimeout?.dispose(); this._setState(State.Hidden); From e216a598d3e02401f26459fb63a4f1b6365ec4ec Mon Sep 17 00:00:00 2001 From: Johannes Rieken Date: Wed, 4 Nov 2020 15:22:35 +0100 Subject: [PATCH 16/17] don't presist little size changes --- src/vs/editor/contrib/suggest/suggestWidget.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/vs/editor/contrib/suggest/suggestWidget.ts b/src/vs/editor/contrib/suggest/suggestWidget.ts index ba2f5133459..488c8f80c53 100644 --- a/src/vs/editor/contrib/suggest/suggestWidget.ts +++ b/src/vs/editor/contrib/suggest/suggestWidget.ts @@ -152,11 +152,13 @@ export class SuggestWidget implements IDisposable { this._persistedSize = new PersistedWidgetSize(_storageService, editor); let persistedSize: dom.Dimension | undefined; + let currentSize: dom.Dimension | undefined; let persistHeight = false; let persistWidth = false; this._disposables.add(this.element.onDidWillResize(() => { this._contentWidget.lockPreference(); persistedSize = this._persistedSize.restore(); + currentSize = this.element.size; })); this._disposables.add(this.element.onDidResize(e => { @@ -165,14 +167,15 @@ export class SuggestWidget implements IDisposable { persistHeight = persistHeight || !!e.north || !!e.south; persistWidth = persistWidth || !!e.east || !!e.west; if (e.done) { - - // only store width or height value that have changed + // only store width or height value that have changed and also + // only store changes that are above a certain threshold + const threshold = Math.floor(this.getLayoutInfo().itemHeight / 3); let { width, height } = this.element.size; - if (persistedSize) { - if (!persistHeight) { + if (persistedSize && currentSize) { + if (!persistHeight || Math.abs(currentSize.height - height) > threshold) { height = persistedSize.height; } - if (!persistWidth) { + if (!persistWidth || Math.abs(currentSize.width - width) > threshold) { width = persistedSize.width; } } @@ -181,6 +184,7 @@ export class SuggestWidget implements IDisposable { // reset working state this._contentWidget.unlockPreference(); persistedSize = undefined; + currentSize = undefined; persistHeight = false; persistWidth = false; } From 163bd1dcb34d43a401b67e929c24c0c752385dff Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Wed, 4 Nov 2020 15:36:27 +0100 Subject: [PATCH 17/17] storage - rename storage change event --- .../multicursor/test/multicursor.test.ts | 2 +- .../common/extensionEnablementService.ts | 6 +- .../storage/browser/storageService.ts | 4 +- src/vs/platform/storage/common/storage.ts | 20 +++---- .../platform/storage/node/storageService.ts | 4 +- .../test/common/storageService.test.ts | 56 +++++++++---------- .../userDataSync/common/extensionsSync.ts | 2 +- .../userDataSync/common/globalStateSync.ts | 2 +- .../common/userDataAutoSyncService.ts | 6 +- .../userDataSyncResourceEnablementService.ts | 6 +- .../api/browser/mainThreadStorage.ts | 2 +- .../parts/activitybar/activitybarPart.ts | 6 +- .../browser/parts/panel/panelPart.ts | 6 +- .../browser/parts/statusbar/statusbarPart.ts | 6 +- .../extensionIgnoredRecommendationsService.ts | 6 +- .../browser/userDataSyncWorkbenchService.ts | 6 +- .../views/browser/viewDescriptorService.ts | 6 +- .../views/common/viewContainerModel.ts | 6 +- .../workspaces/browser/workspacesService.ts | 2 +- 19 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts index b9b1c5778eb..56ec69d45eb 100644 --- a/src/vs/editor/contrib/multicursor/test/multicursor.test.ts +++ b/src/vs/editor/contrib/multicursor/test/multicursor.test.ts @@ -61,7 +61,7 @@ suite('Multicursor selection', () => { let serviceCollection = new ServiceCollection(); serviceCollection.set(IStorageService, { _serviceBrand: undefined, - onDidChangeStorage: Event.None, + onDidChangeValue: Event.None, onDidChangeTarget: Event.None, onWillSaveState: Event.None, get: (key: string) => queryState[key], diff --git a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts index 096d43f6048..990e670c8df 100644 --- a/src/vs/platform/extensionManagement/common/extensionEnablementService.ts +++ b/src/vs/platform/extensionManagement/common/extensionEnablementService.ts @@ -7,7 +7,7 @@ import { Event, Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { IExtensionIdentifier, IGlobalExtensionEnablementService, DISABLED_EXTENSIONS_STORAGE_PATH } from 'vs/platform/extensionManagement/common/extensionManagement'; import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; -import { IStorageService, StorageScope, IStorageChangeEvent } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageValueChangeEvent } from 'vs/platform/storage/common/storage'; import { isUndefinedOrNull } from 'vs/base/common/types'; export class GlobalExtensionEnablementService extends Disposable implements IGlobalExtensionEnablementService { @@ -96,7 +96,7 @@ export class StorageManager extends Disposable { constructor(private storageService: IStorageService) { super(); - this._register(storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); + this._register(storageService.onDidChangeValue(e => this.onDidStorageChange(e))); } get(key: string, scope: StorageScope): IExtensionIdentifier[] { @@ -127,7 +127,7 @@ export class StorageManager extends Disposable { } } - private onDidStorageChange(storageChangeEvent: IStorageChangeEvent): void { + private onDidStorageChange(storageChangeEvent: IStorageValueChangeEvent): void { if (storageChangeEvent.scope === StorageScope.GLOBAL) { if (!isUndefinedOrNull(this.storage[storageChangeEvent.key])) { const newValue = this._get(storageChangeEvent.key, storageChangeEvent.scope); diff --git a/src/vs/platform/storage/browser/storageService.ts b/src/vs/platform/storage/browser/storageService.ts index 2d92fcf018a..c667dd88f88 100644 --- a/src/vs/platform/storage/browser/storageService.ts +++ b/src/vs/platform/storage/browser/storageService.ts @@ -62,13 +62,13 @@ export class BrowserStorageService extends AbstractStorageService { this.workspaceStorageDatabase = this._register(new FileStorageDatabase(this.workspaceStorageFile, false /* do not watch for external changes */, this.fileService)); this.workspaceStorage = this._register(new Storage(this.workspaceStorageDatabase)); - this._register(this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeStorage(StorageScope.WORKSPACE, key))); + this._register(this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.WORKSPACE, key))); // Global Storage this.globalStorageFile = joinPath(stateRoot, 'global.json'); this.globalStorageDatabase = this._register(new FileStorageDatabase(this.globalStorageFile, true /* watch for external changes */, this.fileService)); this.globalStorage = this._register(new Storage(this.globalStorageDatabase)); - this._register(this.globalStorage.onDidChangeStorage(key => this.emitDidChangeStorage(StorageScope.GLOBAL, key))); + this._register(this.globalStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.GLOBAL, key))); // Init both await Promise.all([ diff --git a/src/vs/platform/storage/common/storage.ts b/src/vs/platform/storage/common/storage.ts index fd6d7d5fd44..5b515af5759 100644 --- a/src/vs/platform/storage/common/storage.ts +++ b/src/vs/platform/storage/common/storage.ts @@ -30,7 +30,7 @@ export interface IStorageService { /** * Emitted whenever data is updated or deleted. */ - readonly onDidChangeStorage: Event; + readonly onDidChangeValue: Event; /** * Emitted whenever target of a storage entry changes. @@ -180,7 +180,7 @@ export const enum StorageTarget { MACHINE } -export interface IStorageChangeEvent { +export interface IStorageValueChangeEvent { /** * The scope for the storage entry that changed @@ -213,8 +213,8 @@ export abstract class AbstractStorageService extends Disposable implements IStor declare readonly _serviceBrand: undefined; - private readonly _onDidChangeStorage = this._register(new PauseableEmitter()); - readonly onDidChangeStorage = this._onDidChangeStorage.event; + private readonly _onDidChangeValue = this._register(new PauseableEmitter()); + readonly onDidChangeValue = this._onDidChangeValue.event; private readonly _onDidChangeTarget = this._register(new PauseableEmitter()); readonly onDidChangeTarget = this._onDidChangeTarget.event; @@ -222,7 +222,7 @@ export abstract class AbstractStorageService extends Disposable implements IStor private readonly _onWillSaveState = this._register(new Emitter()); readonly onWillSaveState = this._onWillSaveState.event; - protected emitDidChangeStorage(scope: StorageScope, key: string): void { + protected emitDidChangeValue(scope: StorageScope, key: string): void { // Specially handle `TARGET_KEY` if (key === TARGET_KEY) { @@ -240,7 +240,7 @@ export abstract class AbstractStorageService extends Disposable implements IStor // Emit any other key to outside else { - this._onDidChangeStorage.fire({ scope, key, target: this.getKeyTargets(scope)[key] }); + this._onDidChangeValue.fire({ scope, key, target: this.getKeyTargets(scope)[key] }); } } @@ -287,7 +287,7 @@ export abstract class AbstractStorageService extends Disposable implements IStor private withPausedEmitters(fn: Function): void { // Pause emitters - this._onDidChangeStorage.pause(); + this._onDidChangeValue.pause(); this._onDidChangeTarget.pause(); try { @@ -295,7 +295,7 @@ export abstract class AbstractStorageService extends Disposable implements IStor } finally { // Resume emitters - this._onDidChangeStorage.resume(); + this._onDidChangeValue.resume(); this._onDidChangeTarget.resume(); } } @@ -458,7 +458,7 @@ export class InMemoryStorageService extends AbstractStorageService { this.getCache(scope).set(key, valueStr); // Events - this.emitDidChangeStorage(scope, key); + this.emitDidChangeValue(scope, key); } protected doRemove(key: string, scope: StorageScope): void { @@ -468,7 +468,7 @@ export class InMemoryStorageService extends AbstractStorageService { } // Events - this.emitDidChangeStorage(scope, key); + this.emitDidChangeValue(scope, key); } logStorage(): void { diff --git a/src/vs/platform/storage/node/storageService.ts b/src/vs/platform/storage/node/storageService.ts index d1d2aae6a3c..11049a8f969 100644 --- a/src/vs/platform/storage/node/storageService.ts +++ b/src/vs/platform/storage/node/storageService.ts @@ -45,7 +45,7 @@ export class NativeStorageService extends AbstractStorageService { private registerListeners(): void { // Global Storage change events - this._register(this.globalStorage.onDidChangeStorage(key => this.emitDidChangeStorage(StorageScope.GLOBAL, key))); + this._register(this.globalStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.GLOBAL, key))); } initialize(payload?: IWorkspaceInitializationPayload): Promise { @@ -121,7 +121,7 @@ export class NativeStorageService extends AbstractStorageService { // Create new this.workspaceStoragePath = workspaceStoragePath; this.workspaceStorage = new Storage(new SQLiteStorageDatabase(workspaceStoragePath, { logging: workspaceLoggingOptions }), { hint }); - this.workspaceStorageListener = this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeStorage(StorageScope.WORKSPACE, key)); + this.workspaceStorageListener = this.workspaceStorage.onDidChangeStorage(key => this.emitDidChangeValue(StorageScope.WORKSPACE, key)); return this.workspaceStorage; } diff --git a/src/vs/platform/storage/test/common/storageService.test.ts b/src/vs/platform/storage/test/common/storageService.test.ts index eaf4a4a6606..6d22dd224a5 100644 --- a/src/vs/platform/storage/test/common/storageService.test.ts +++ b/src/vs/platform/storage/test/common/storageService.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { strictEqual, ok, equal } from 'assert'; -import { StorageScope, InMemoryStorageService, StorageTarget, IStorageChangeEvent, IStorageTargetChangeEvent } from 'vs/platform/storage/common/storage'; +import { StorageScope, InMemoryStorageService, StorageTarget, IStorageValueChangeEvent, IStorageTargetChangeEvent } from 'vs/platform/storage/common/storage'; suite('StorageService', function () { @@ -19,8 +19,8 @@ suite('StorageService', function () { function storeData(scope: StorageScope): void { const storage = new InMemoryStorageService(); - let storageEvents: IStorageChangeEvent[] = []; - storage.onDidChangeStorage(e => storageEvents.push(e)); + let storageValueChangeEvents: IStorageValueChangeEvent[] = []; + storage.onDidChangeValue(e => storageValueChangeEvents.push(e)); strictEqual(storage.get('test.get', scope, 'foobar'), 'foobar'); strictEqual(storage.get('test.get', scope, ''), ''); @@ -31,16 +31,16 @@ suite('StorageService', function () { storage.store('test.get', 'foobar', scope); strictEqual(storage.get('test.get', scope, (undefined)!), 'foobar'); - let storageEvent = storageEvents.find(e => e.key === 'test.get'); - equal(storageEvent?.scope, scope); - equal(storageEvent?.key, 'test.get'); - storageEvents = []; + let storageValueChangeEvent = storageValueChangeEvents.find(e => e.key === 'test.get'); + equal(storageValueChangeEvent?.scope, scope); + equal(storageValueChangeEvent?.key, 'test.get'); + storageValueChangeEvents = []; storage.store('test.get', '', scope); strictEqual(storage.get('test.get', scope, (undefined)!), ''); - storageEvent = storageEvents.find(e => e.key === 'test.get'); - equal(storageEvent!.scope, scope); - equal(storageEvent!.key, 'test.get'); + storageValueChangeEvent = storageValueChangeEvents.find(e => e.key === 'test.get'); + equal(storageValueChangeEvent!.scope, scope); + equal(storageValueChangeEvent!.key, 'test.get'); storage.store('test.getNumber', 5, scope); strictEqual(storage.getNumber('test.getNumber', scope, (undefined)!), 5); @@ -70,17 +70,17 @@ suite('StorageService', function () { function removeData(scope: StorageScope): void { const storage = new InMemoryStorageService(); - let storageEvents: IStorageChangeEvent[] = []; - storage.onDidChangeStorage(e => storageEvents.push(e)); + let storageValueChangeEvents: IStorageValueChangeEvent[] = []; + storage.onDidChangeValue(e => storageValueChangeEvents.push(e)); storage.store('test.remove', 'foobar', scope); strictEqual('foobar', storage.get('test.remove', scope, (undefined)!)); storage.remove('test.remove', scope); ok(!storage.get('test.remove', scope, (undefined)!)); - let storageEvent = storageEvents.find(e => e.key === 'test.remove'); - equal(storageEvent?.scope, scope); - equal(storageEvent?.key, 'test.remove'); + let storageValueChangeEvent = storageValueChangeEvents.find(e => e.key === 'test.remove'); + equal(storageValueChangeEvent?.scope, scope); + equal(storageValueChangeEvent?.key, 'test.remove'); } test('Keys (in-memory)', () => { @@ -89,8 +89,8 @@ suite('StorageService', function () { let storageTargetEvent: IStorageTargetChangeEvent | undefined = undefined; storage.onDidChangeTarget(e => storageTargetEvent = e); - let storageChangeEvent: IStorageChangeEvent | undefined = undefined; - storage.onDidChangeStorage(e => storageChangeEvent = e); + let storageValueChangeEvent: IStorageValueChangeEvent | undefined = undefined; + storage.onDidChangeValue(e => storageValueChangeEvent = e); // Empty for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { @@ -103,24 +103,24 @@ suite('StorageService', function () { for (const scope of [StorageScope.WORKSPACE, StorageScope.GLOBAL]) { for (const target of [StorageTarget.MACHINE, StorageTarget.USER]) { storageTargetEvent = Object.create(null); - storageChangeEvent = Object.create(null); + storageValueChangeEvent = Object.create(null); storage.store2('test.target1', 'value1', scope, target); strictEqual(storage.keys(scope, target).length, 1); equal(storageTargetEvent?.scope, scope); - equal(storageChangeEvent?.key, 'test.target1'); - equal(storageChangeEvent?.scope, scope); - equal(storageChangeEvent?.target, target); + equal(storageValueChangeEvent?.key, 'test.target1'); + equal(storageValueChangeEvent?.scope, scope); + equal(storageValueChangeEvent?.target, target); storageTargetEvent = undefined; - storageChangeEvent = Object.create(null); + storageValueChangeEvent = Object.create(null); storage.store2('test.target1', 'otherValue1', scope, target); strictEqual(storage.keys(scope, target).length, 1); equal(storageTargetEvent, undefined); - equal(storageChangeEvent?.key, 'test.target1'); - equal(storageChangeEvent?.scope, scope); - equal(storageChangeEvent?.target, target); + equal(storageValueChangeEvent?.key, 'test.target1'); + equal(storageValueChangeEvent?.scope, scope); + equal(storageValueChangeEvent?.target, target); storage.store2('test.target2', 'value2', scope, target); storage.store2('test.target3', 'value3', scope, target); @@ -138,13 +138,13 @@ suite('StorageService', function () { strictEqual(storage.keys(scope, target).length, keysLength + 1); storageTargetEvent = Object.create(null); - storageChangeEvent = Object.create(null); + storageValueChangeEvent = Object.create(null); storage.remove('test.target4', scope); strictEqual(storage.keys(scope, target).length, keysLength); equal(storageTargetEvent?.scope, scope); - equal(storageChangeEvent?.key, 'test.target4'); - equal(storageChangeEvent?.scope, scope); + equal(storageValueChangeEvent?.key, 'test.target4'); + equal(storageValueChangeEvent?.scope, scope); } } diff --git a/src/vs/platform/userDataSync/common/extensionsSync.ts b/src/vs/platform/userDataSync/common/extensionsSync.ts index 60d21a3ee86..fd74504f55f 100644 --- a/src/vs/platform/userDataSync/common/extensionsSync.ts +++ b/src/vs/platform/userDataSync/common/extensionsSync.ts @@ -115,7 +115,7 @@ export class ExtensionsSynchroniser extends AbstractSynchroniser implements IUse Event.filter(this.extensionManagementService.onDidUninstallExtension, (e => !e.error)), this.extensionEnablementService.onDidChangeEnablement, this.storageKeysSyncRegistryService.onDidChangeExtensionStorageKeys, - Event.filter(this.storageService.onDidChangeStorage, e => e.scope === StorageScope.GLOBAL + Event.filter(this.storageService.onDidChangeValue, e => e.scope === StorageScope.GLOBAL && this.storageKeysSyncRegistryService.extensionsStorageKeys.some(([extensionIdentifier]) => areSameExtensions(extensionIdentifier, { id: e.key })))), () => undefined, 500)(() => this.triggerLocalChange())); } diff --git a/src/vs/platform/userDataSync/common/globalStateSync.ts b/src/vs/platform/userDataSync/common/globalStateSync.ts index 552e0b99ded..1f0cf98be86 100644 --- a/src/vs/platform/userDataSync/common/globalStateSync.ts +++ b/src/vs/platform/userDataSync/common/globalStateSync.ts @@ -73,7 +73,7 @@ export class GlobalStateSynchroniser extends AbstractSynchroniser implements IUs /* Locale change */ Event.filter(fileService.onDidFilesChange, e => e.contains(this.environmentService.argvResource)), /* Global storage with user target has changed */ - Event.filter(storageService.onDidChangeStorage, e => e.scope === StorageScope.GLOBAL && e.target !== undefined ? e.target === StorageTarget.USER : storageService.keys(StorageScope.GLOBAL, StorageTarget.USER).includes(e.key)), + Event.filter(storageService.onDidChangeValue, e => e.scope === StorageScope.GLOBAL && e.target !== undefined ? e.target === StorageTarget.USER : storageService.keys(StorageScope.GLOBAL, StorageTarget.USER).includes(e.key)), /* Storage key target has changed */ this.storageService.onDidChangeTarget )((() => this.triggerLocalChange())) diff --git a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts index 9af5f8f70ac..175566d511c 100644 --- a/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts +++ b/src/vs/platform/userDataSync/common/userDataAutoSyncService.ts @@ -11,7 +11,7 @@ import { IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/use import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { isPromiseCanceledError } from 'vs/base/common/errors'; import { CancellationToken } from 'vs/base/common/cancellation'; -import { IStorageService, StorageScope, IStorageChangeEvent } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageValueChangeEvent } from 'vs/platform/storage/common/storage'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; import { IUserDataSyncMachinesService } from 'vs/platform/userDataSync/common/userDataSyncMachines'; import { localize } from 'vs/nls'; @@ -55,7 +55,7 @@ export class UserDataAutoSyncEnablementService extends Disposable implements _IU @IUserDataSyncStoreManagementService private readonly userDataSyncStoreManagementService: IUserDataSyncStoreManagementService, ) { super(); - this._register(storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); + this._register(storageService.onDidChangeValue(e => this.onDidStorageChange(e))); } isEnabled(defaultEnablement?: boolean): boolean { @@ -76,7 +76,7 @@ export class UserDataAutoSyncEnablementService extends Disposable implements _IU this.storageService.store(enablementKey, enabled, StorageScope.GLOBAL); } - private onDidStorageChange(storageChangeEvent: IStorageChangeEvent): void { + private onDidStorageChange(storageChangeEvent: IStorageValueChangeEvent): void { if (storageChangeEvent.scope !== StorageScope.GLOBAL) { return; } diff --git a/src/vs/platform/userDataSync/common/userDataSyncResourceEnablementService.ts b/src/vs/platform/userDataSync/common/userDataSyncResourceEnablementService.ts index a59c4c51fd4..d5feb4fd146 100644 --- a/src/vs/platform/userDataSync/common/userDataSyncResourceEnablementService.ts +++ b/src/vs/platform/userDataSync/common/userDataSyncResourceEnablementService.ts @@ -6,7 +6,7 @@ import { IUserDataSyncResourceEnablementService, ALL_SYNC_RESOURCES, SyncResource } from 'vs/platform/userDataSync/common/userDataSync'; import { Disposable } from 'vs/base/common/lifecycle'; import { Emitter, Event } from 'vs/base/common/event'; -import { IStorageService, IStorageChangeEvent, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, IStorageValueChangeEvent, StorageScope } from 'vs/platform/storage/common/storage'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; type SyncEnablementClassification = { @@ -28,7 +28,7 @@ export class UserDataSyncResourceEnablementService extends Disposable implements @ITelemetryService private readonly telemetryService: ITelemetryService, ) { super(); - this._register(storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); + this._register(storageService.onDidChangeValue(e => this.onDidStorageChange(e))); } isResourceEnabled(resource: SyncResource): boolean { @@ -43,7 +43,7 @@ export class UserDataSyncResourceEnablementService extends Disposable implements } } - private onDidStorageChange(storageChangeEvent: IStorageChangeEvent): void { + private onDidStorageChange(storageChangeEvent: IStorageValueChangeEvent): void { if (storageChangeEvent.scope === StorageScope.GLOBAL) { const resourceKey = ALL_SYNC_RESOURCES.filter(resourceKey => getEnablementKey(resourceKey) === storageChangeEvent.key)[0]; if (resourceKey) { diff --git a/src/vs/workbench/api/browser/mainThreadStorage.ts b/src/vs/workbench/api/browser/mainThreadStorage.ts index 57abf0e86a5..987ca0788e1 100644 --- a/src/vs/workbench/api/browser/mainThreadStorage.ts +++ b/src/vs/workbench/api/browser/mainThreadStorage.ts @@ -27,7 +27,7 @@ export class MainThreadStorage implements MainThreadStorageShape { this._storageKeysSyncRegistryService = storageKeysSyncRegistryService; this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostStorage); - this._storageListener = this._storageService.onDidChangeStorage(e => { + this._storageListener = this._storageService.onDidChangeValue(e => { const shared = e.scope === StorageScope.GLOBAL; if (shared && this._sharedStorageKeysToWatch.has(e.key)) { try { diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 822cbcbfc45..66f4e39409f 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -19,7 +19,7 @@ import { ACTIVITY_BAR_BACKGROUND, ACTIVITY_BAR_BORDER, ACTIVITY_BAR_FOREGROUND, import { contrastBorder } from 'vs/platform/theme/common/colorRegistry'; import { CompositeBar, ICompositeBarItem, CompositeDragAndDrop } from 'vs/workbench/browser/parts/compositeBar'; import { Dimension, createCSSRule, asCSSUrl, addDisposableListener, EventType } from 'vs/base/browser/dom'; -import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { URI, UriComponents } from 'vs/base/common/uri'; import { ToggleCompositePinnedAction, ICompositeBarColors, ActivityAction, ICompositeActivity } from 'vs/workbench/browser/parts/compositeBarActions'; @@ -247,7 +247,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { disposables.clear(); this.onDidRegisterExtensions(); this.compositeBar.onDidChange(() => this.saveCachedViewContainers(), this, disposables); - this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables); + this.storageService.onDidChangeValue(e => this.onDidStorageValueChange(e), this, disposables); })); // Register for configuration changes @@ -835,7 +835,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { return this.viewDescriptorService.getViewContainersByLocation(this.location); } - private onDidStorageChange(e: IStorageChangeEvent): void { + private onDidStorageValueChange(e: IStorageValueChangeEvent): void { if (e.key === ActivitybarPart.PINNED_VIEW_CONTAINERS && e.scope === StorageScope.GLOBAL && this.pinnedViewContainersValue !== this.getStoredPinnedViewContainersValue() /* This checks if current window changed the value or not */) { this._pinnedViewContainersValue = undefined; diff --git a/src/vs/workbench/browser/parts/panel/panelPart.ts b/src/vs/workbench/browser/parts/panel/panelPart.ts index 2a8d7b4f7b6..b63b79614ef 100644 --- a/src/vs/workbench/browser/parts/panel/panelPart.ts +++ b/src/vs/workbench/browser/parts/panel/panelPart.ts @@ -13,7 +13,7 @@ import { CompositePart, ICompositeTitleLabel } from 'vs/workbench/browser/parts/ import { Panel, PanelRegistry, Extensions as PanelExtensions, PanelDescriptor } from 'vs/workbench/browser/panel'; import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService'; import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService'; -import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -335,7 +335,7 @@ export class PanelPart extends CompositePart implements IPanelService { disposables.clear(); this.onDidRegisterExtensions(); this.compositeBar.onDidChange(() => this.saveCachedPanels(), this, disposables); - this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e), this, disposables); + this.storageService.onDidChangeValue(e => this.onDidStorageValueChange(e), this, disposables); })); } @@ -667,7 +667,7 @@ export class PanelPart extends CompositePart implements IPanelService { return this.toolBar.getItemsWidth(); } - private onDidStorageChange(e: IStorageChangeEvent): void { + private onDidStorageValueChange(e: IStorageValueChangeEvent): void { if (e.key === PanelPart.PINNED_PANELS && e.scope === StorageScope.GLOBAL && this.cachedPanelsValue !== this.getStoredCachedPanelsValue() /* This checks if current window changed the value or not */) { this._cachedPanelsValue = undefined; diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 6181ede82d8..cdee7f68103 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -23,7 +23,7 @@ import { isThemeColor } from 'vs/editor/common/editorCommon'; import { Color } from 'vs/base/common/color'; import { EventHelper, createStyleSheet, addDisposableListener, EventType, hide, show, isAncestor, appendChildren } from 'vs/base/browser/dom'; import { INotificationService } from 'vs/platform/notification/common/notification'; -import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { coalesce } from 'vs/base/common/arrays'; @@ -101,10 +101,10 @@ class StatusbarViewModel extends Disposable { } private registerListeners(): void { - this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); + this._register(this.storageService.onDidChangeValue(e => this.onDidStorageValueChange(e))); } - private onDidStorageChange(event: IStorageChangeEvent): void { + private onDidStorageValueChange(event: IStorageValueChangeEvent): void { if (event.key === StatusbarViewModel.HIDDEN_ENTRIES_KEY && event.scope === StorageScope.GLOBAL) { // Keep current hidden entries diff --git a/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.ts b/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.ts index 2f5ed993573..f77128e3dfc 100644 --- a/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.ts +++ b/src/vs/workbench/services/extensionRecommendations/common/extensionIgnoredRecommendationsService.ts @@ -7,7 +7,7 @@ import { distinct } from 'vs/base/common/arrays'; import { Emitter } from 'vs/base/common/event'; import { Disposable } from 'vs/base/common/lifecycle'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IStorageService, IStorageChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionIgnoredRecommendationsService, IgnoredRecommendationChangeNotification } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations'; import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig'; @@ -37,7 +37,7 @@ export class ExtensionIgnoredRecommendationsService extends Disposable implement ) { super(); this._globalIgnoredRecommendations = this.getCachedIgnoredRecommendations(); - this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); + this._register(this.storageService.onDidChangeValue(e => this.onDidStorageChange(e))); this.initIgnoredWorkspaceRecommendations(); } @@ -69,7 +69,7 @@ export class ExtensionIgnoredRecommendationsService extends Disposable implement return ignoredRecommendations.map(e => e.toLowerCase()); } - private onDidStorageChange(e: IStorageChangeEvent): void { + private onDidStorageChange(e: IStorageValueChangeEvent): void { if (e.key === ignoredRecommendationsStorageKey && e.scope === StorageScope.GLOBAL && this.ignoredRecommendationsValue !== this.getStoredIgnoredRecommendationsValue() /* This checks if current window changed the value or not */) { this._ignoredRecommendationsValue = undefined; diff --git a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts index 03eb9098b0f..53cd8dcd1d8 100644 --- a/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts +++ b/src/vs/workbench/services/userDataSync/browser/userDataSyncWorkbenchService.ts @@ -14,7 +14,7 @@ import { flatten, equals } from 'vs/base/common/arrays'; import { getCurrentAuthenticationSessionInfo, IAuthenticationService } from 'vs/workbench/services/authentication/browser/authenticationService'; import { IUserDataSyncAccountService } from 'vs/platform/userDataSync/common/userDataSyncAccount'; import { IQuickInputService, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput'; -import { IStorageService, IStorageChangeEvent, StorageScope } from 'vs/platform/storage/common/storage'; +import { IStorageService, IStorageValueChangeEvent, StorageScope } from 'vs/platform/storage/common/storage'; import { ILogService } from 'vs/platform/log/common/log'; import { IProductService } from 'vs/platform/product/common/productService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; @@ -175,7 +175,7 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat (() => this.update())); this._register(Event.filter(this.authenticationService.onDidChangeSessions, e => this.isSupportedAuthenticationProviderId(e.providerId))(({ event }) => this.onDidChangeSessions(event))); - this._register(this.storageService.onDidChangeStorage(e => this.onDidChangeStorage(e))); + this._register(this.storageService.onDidChangeValue(e => this.onDidChangeStorage(e))); this._register(Event.filter(this.userDataSyncAccountService.onTokenFailed, isSuccessive => isSuccessive)(() => this.onDidSuccessiveAuthFailures())); } @@ -584,7 +584,7 @@ export class UserDataSyncWorkbenchService extends Disposable implements IUserDat this.update(); } - private onDidChangeStorage(e: IStorageChangeEvent): void { + private onDidChangeStorage(e: IStorageValueChangeEvent): void { if (e.key === UserDataSyncWorkbenchService.CACHED_SESSION_STORAGE_KEY && e.scope === StorageScope.GLOBAL && this.currentSessionId !== this.getStoredCachedSessionId() /* This checks if current window changed the value or not */) { this._cachedCurrentSessionId = null; diff --git a/src/vs/workbench/services/views/browser/viewDescriptorService.ts b/src/vs/workbench/services/views/browser/viewDescriptorService.ts index f2d88b5a8e1..7087fc31c27 100644 --- a/src/vs/workbench/services/views/browser/viewDescriptorService.ts +++ b/src/vs/workbench/services/views/browser/viewDescriptorService.ts @@ -5,7 +5,7 @@ import { ViewContainerLocation, IViewDescriptorService, ViewContainer, IViewsRegistry, IViewContainersRegistry, IViewDescriptor, Extensions as ViewExtensions, ViewVisibilityState } from 'vs/workbench/common/views'; import { IContextKey, RawContextKey, IContextKeyService, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { Registry } from 'vs/platform/registry/common/platform'; import { toDisposable, DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle'; @@ -135,7 +135,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor this.viewContainerModels.clear(); })); - this._register(this.storageService.onDidChangeStorage((e) => { this.onDidStorageChange(e); })); + this._register(this.storageService.onDidChangeValue((e) => { this.onDidStorageChange(e); })); this._register(this.extensionService.onDidRegisterExtensions(() => this.onDidRegisterExtensions())); } @@ -501,7 +501,7 @@ export class ViewDescriptorService extends Disposable implements IViewDescriptor return new Map(JSON.parse(this.cachedViewContainerLocationsValue)); } - private onDidStorageChange(e: IStorageChangeEvent): void { + private onDidStorageChange(e: IStorageValueChangeEvent): void { if (e.key === ViewDescriptorService.CACHED_VIEW_POSITIONS && e.scope === StorageScope.GLOBAL && this.cachedViewPositionsValue !== this.getStoredCachedViewPositionsValue() /* This checks if current window changed the value or not */) { this._cachedViewPositionsValue = this.getStoredCachedViewPositionsValue(); diff --git a/src/vs/workbench/services/views/common/viewContainerModel.ts b/src/vs/workbench/services/views/common/viewContainerModel.ts index ded4501ff9b..1f8686f0c74 100644 --- a/src/vs/workbench/services/views/common/viewContainerModel.ts +++ b/src/vs/workbench/services/views/common/viewContainerModel.ts @@ -5,7 +5,7 @@ import { ViewContainer, IViewsRegistry, IViewDescriptor, Extensions as ViewExtensions, IViewContainerModel, IAddedViewDescriptorRef, IViewDescriptorRef, IAddedViewDescriptorState } from 'vs/workbench/common/views'; import { IContextKeyService, IReadableSet } from 'vs/platform/contextkey/common/contextkey'; -import { IStorageService, StorageScope, IStorageChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IStorageService, StorageScope, IStorageValueChangeEvent, StorageTarget } from 'vs/platform/storage/common/storage'; import { Registry } from 'vs/platform/registry/common/platform'; import { Disposable } from 'vs/base/common/lifecycle'; import { Event, Emitter } from 'vs/base/common/event'; @@ -88,7 +88,7 @@ class ViewDescriptorsState extends Disposable { this.globalViewsStateStorageId = getViewsStateStorageId(viewContainerStorageId); this.workspaceViewsStateStorageId = viewContainerStorageId; - this._register(this.storageService.onDidChangeStorage(e => this.onDidStorageChange(e))); + this._register(this.storageService.onDidChangeValue(e => this.onDidStorageChange(e))); this.state = this.initialize(); } @@ -140,7 +140,7 @@ class ViewDescriptorsState extends Disposable { this.setStoredGlobalState(storedGlobalState); } - private onDidStorageChange(e: IStorageChangeEvent): void { + private onDidStorageChange(e: IStorageValueChangeEvent): void { if (e.key === this.globalViewsStateStorageId && e.scope === StorageScope.GLOBAL && this.globalViewsStatesValue !== this.getStoredGlobalViewsStatesValue() /* This checks if current window changed the value or not */) { this._globalViewsStatesValue = undefined; diff --git a/src/vs/workbench/services/workspaces/browser/workspacesService.ts b/src/vs/workbench/services/workspaces/browser/workspacesService.ts index 19985b8bc17..46b9066688e 100644 --- a/src/vs/workbench/services/workspaces/browser/workspacesService.ts +++ b/src/vs/workbench/services/workspaces/browser/workspacesService.ts @@ -43,7 +43,7 @@ export class BrowserWorkspacesService extends Disposable implements IWorkspacesS } private registerListeners(): void { - this._register(this.storageService.onDidChangeStorage(event => { + this._register(this.storageService.onDidChangeValue(event => { if (event.key === BrowserWorkspacesService.RECENTLY_OPENED_KEY && event.scope === StorageScope.GLOBAL) { this._onRecentlyOpenedChange.fire(); }