Skip to content

Commit bed2921

Browse files
committed
Support remote user configuration
1 parent 75bf16e commit bed2921

19 files changed

Lines changed: 389 additions & 75 deletions

File tree

src/vs/platform/configuration/common/configuration.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export interface IConfigurationOverrides {
2929

3030
export const enum ConfigurationTarget {
3131
USER = 1,
32+
USER_LOCAL,
33+
USER_REMOTE,
3234
WORKSPACE,
3335
WORKSPACE_FOLDER,
3436
DEFAULT,
@@ -37,6 +39,8 @@ export const enum ConfigurationTarget {
3739
export function ConfigurationTargetToString(configurationTarget: ConfigurationTarget) {
3840
switch (configurationTarget) {
3941
case ConfigurationTarget.USER: return 'USER';
42+
case ConfigurationTarget.USER_LOCAL: return 'USER_LOCAL';
43+
case ConfigurationTarget.USER_REMOTE: return 'USER_REMOTE';
4044
case ConfigurationTarget.WORKSPACE: return 'WORKSPACE';
4145
case ConfigurationTarget.WORKSPACE_FOLDER: return 'WORKSPACE_FOLDER';
4246
case ConfigurationTarget.DEFAULT: return 'DEFAULT';
@@ -88,6 +92,8 @@ export interface IConfigurationService {
8892
inspect<T>(key: string, overrides?: IConfigurationOverrides): {
8993
default: T,
9094
user: T,
95+
userLocal?: T,
96+
userRemote?: T,
9197
workspace?: T,
9298
workspaceFolder?: T,
9399
memory?: T,

src/vs/platform/configuration/common/configurationModels.ts

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export class ConfigurationModel implements IConfigurationModel {
3636
return this.checkAndFreeze(this._keys);
3737
}
3838

39+
isEmpty(): boolean {
40+
return this._keys.length === 0 || Object.keys(this._contents).length === 0 || this._overrides.length === 0;
41+
}
42+
3943
getValue<V>(section: string | undefined): V {
4044
return section ? getConfigurationValue<any>(this.contents, section) : this.contents;
4145
}
@@ -283,7 +287,8 @@ export class Configuration {
283287

284288
constructor(
285289
private _defaultConfiguration: ConfigurationModel,
286-
private _userConfiguration: ConfigurationModel,
290+
private _localUserConfiguration: ConfigurationModel,
291+
private _remoteUserConfiguration: ConfigurationModel = new ConfigurationModel(),
287292
private _workspaceConfiguration: ConfigurationModel = new ConfigurationModel(),
288293
private _folderConfigurations: ResourceMap<ConfigurationModel> = new ResourceMap<ConfigurationModel>(),
289294
private _memoryConfiguration: ConfigurationModel = new ConfigurationModel(),
@@ -322,6 +327,8 @@ export class Configuration {
322327
inspect<C>(key: string, overrides: IConfigurationOverrides, workspace: Workspace | undefined): {
323328
default: C,
324329
user: C,
330+
userLocal?: C,
331+
userRemote?: C,
325332
workspace?: C,
326333
workspaceFolder?: C
327334
memory?: C
@@ -332,7 +339,9 @@ export class Configuration {
332339
const memoryConfigurationModel = overrides.resource ? this._memoryConfigurationByResource.get(overrides.resource) || this._memoryConfiguration : this._memoryConfiguration;
333340
return {
334341
default: overrides.overrideIdentifier ? this._defaultConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._defaultConfiguration.freeze().getValue(key),
335-
user: overrides.overrideIdentifier ? this._userConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._userConfiguration.freeze().getValue(key),
342+
user: overrides.overrideIdentifier ? this.userConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.userConfiguration.freeze().getValue(key),
343+
userLocal: overrides.overrideIdentifier ? this.localUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.localUserConfiguration.freeze().getValue(key),
344+
userRemote: overrides.overrideIdentifier ? this.remoteUserConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this.remoteUserConfiguration.freeze().getValue(key),
336345
workspace: workspace ? overrides.overrideIdentifier ? this._workspaceConfiguration.freeze().override(overrides.overrideIdentifier).getValue(key) : this._workspaceConfiguration.freeze().getValue(key) : undefined, //Check on workspace exists or not because _workspaceConfiguration is never null
337346
workspaceFolder: folderConfigurationModel ? overrides.overrideIdentifier ? folderConfigurationModel.freeze().override(overrides.overrideIdentifier).getValue(key) : folderConfigurationModel.freeze().getValue(key) : undefined,
338347
memory: overrides.overrideIdentifier ? memoryConfigurationModel.override(overrides.overrideIdentifier).getValue(key) : memoryConfigurationModel.getValue(key),
@@ -349,7 +358,7 @@ export class Configuration {
349358
const folderConfigurationModel = this.getFolderConfigurationModelForResource(undefined, workspace);
350359
return {
351360
default: this._defaultConfiguration.freeze().keys,
352-
user: this._userConfiguration.freeze().keys,
361+
user: this.userConfiguration.freeze().keys,
353362
workspace: this._workspaceConfiguration.freeze().keys,
354363
workspaceFolder: folderConfigurationModel ? folderConfigurationModel.freeze().keys : []
355364
};
@@ -361,8 +370,16 @@ export class Configuration {
361370
this._foldersConsolidatedConfigurations.clear();
362371
}
363372

364-
updateUserConfiguration(userConfiguration: ConfigurationModel): void {
365-
this._userConfiguration = userConfiguration;
373+
updateLocalUserConfiguration(localUserConfiguration: ConfigurationModel): void {
374+
this._localUserConfiguration = localUserConfiguration;
375+
this._userConfiguration = null;
376+
this._workspaceConsolidatedConfiguration = null;
377+
this._foldersConsolidatedConfigurations.clear();
378+
}
379+
380+
updateRemoteUserConfiguration(remoteUserConfiguration: ConfigurationModel): void {
381+
this._remoteUserConfiguration = remoteUserConfiguration;
382+
this._userConfiguration = null;
366383
this._workspaceConsolidatedConfiguration = null;
367384
this._foldersConsolidatedConfigurations.clear();
368385
}
@@ -379,23 +396,38 @@ export class Configuration {
379396
}
380397

381398
deleteFolderConfiguration(resource: URI): void {
382-
this.folders.delete(resource);
399+
this.folderConfigurations.delete(resource);
383400
this._foldersConsolidatedConfigurations.delete(resource);
384401
}
385402

386403
get defaults(): ConfigurationModel {
387404
return this._defaultConfiguration;
388405
}
389406

390-
get user(): ConfigurationModel {
407+
private _userConfiguration: ConfigurationModel | null;
408+
get userConfiguration(): ConfigurationModel {
409+
if (!this._userConfiguration) {
410+
this._userConfiguration = this._remoteUserConfiguration.isEmpty() ? this._localUserConfiguration : this._localUserConfiguration.merge(this._remoteUserConfiguration);
411+
if (this._freeze) {
412+
this._userConfiguration.freeze();
413+
}
414+
}
391415
return this._userConfiguration;
392416
}
393417

394-
get workspace(): ConfigurationModel {
418+
get localUserConfiguration(): ConfigurationModel {
419+
return this._localUserConfiguration;
420+
}
421+
422+
get remoteUserConfiguration(): ConfigurationModel {
423+
return this._remoteUserConfiguration;
424+
}
425+
426+
get workspaceConfiguration(): ConfigurationModel {
395427
return this._workspaceConfiguration;
396428
}
397429

398-
protected get folders(): ResourceMap<ConfigurationModel> {
430+
protected get folderConfigurations(): ResourceMap<ConfigurationModel> {
399431
return this._folderConfigurations;
400432
}
401433

@@ -423,7 +455,7 @@ export class Configuration {
423455

424456
private getWorkspaceConsolidatedConfiguration(): ConfigurationModel {
425457
if (!this._workspaceConsolidatedConfiguration) {
426-
this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this._userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
458+
this._workspaceConsolidatedConfiguration = this._defaultConfiguration.merge(this.userConfiguration, this._workspaceConfiguration, this._memoryConfiguration);
427459
if (this._freeze) {
428460
this._workspaceConfiguration = this._workspaceConfiguration.freeze();
429461
}
@@ -467,9 +499,9 @@ export class Configuration {
467499
keys: this._defaultConfiguration.keys
468500
},
469501
user: {
470-
contents: this._userConfiguration.contents,
471-
overrides: this._userConfiguration.overrides,
472-
keys: this._userConfiguration.keys
502+
contents: this.userConfiguration.contents,
503+
overrides: this.userConfiguration.overrides,
504+
keys: this.userConfiguration.keys
473505
},
474506
workspace: {
475507
contents: this._workspaceConfiguration.contents,
@@ -497,8 +529,8 @@ export class Configuration {
497529
};
498530
addKeys(keys.user);
499531
addKeys(keys.workspace);
500-
for (const resource of this.folders.keys()) {
501-
addKeys(this.folders.get(resource)!.keys);
532+
for (const resource of this.folderConfigurations.keys()) {
533+
addKeys(this.folderConfigurations.get(resource)!.keys);
502534
}
503535
return all;
504536
}

src/vs/platform/configuration/node/configurationService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
9191
}
9292

9393
private onDidChangeUserConfiguration(userConfigurationModel: ConfigurationModel): void {
94-
const { added, updated, removed } = compare(this._configuration.user, userConfigurationModel);
94+
const { added, updated, removed } = compare(this._configuration.localUserConfiguration, userConfigurationModel);
9595
const changedKeys = [...added, ...updated, ...removed];
9696
if (changedKeys.length) {
97-
this._configuration.updateUserConfiguration(userConfigurationModel);
97+
this._configuration.updateLocalUserConfiguration(userConfigurationModel);
9898
this.trigger(changedKeys, ConfigurationTarget.USER);
9999
}
100100
}
@@ -113,7 +113,7 @@ export class ConfigurationService extends Disposable implements IConfigurationSe
113113
case ConfigurationTarget.DEFAULT:
114114
return this._configuration.defaults.contents;
115115
case ConfigurationTarget.USER:
116-
return this._configuration.user.contents;
116+
return this._configuration.localUserConfiguration.contents;
117117
}
118118
return {};
119119
}

src/vs/platform/configuration/test/common/testConfigurationService.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ export class TestConfigurationService implements IConfigurationService {
5656
public inspect<T>(key: string, overrides?: IConfigurationOverrides): {
5757
default: T,
5858
user: T,
59+
userLocal?: T,
60+
userRemote?: T,
5961
workspace?: T,
6062
workspaceFolder?: T
6163
value: T,

src/vs/workbench/api/node/extHostConfiguration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ export class ExtHostConfigProvider {
263263
result.set(URI.parse(key), ExtHostConfigProvider.parseConfigurationModel(data.folders[key]));
264264
return result;
265265
}, new ResourceMap<ConfigurationModel>());
266-
return new Configuration(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false);
266+
return new Configuration(defaultConfiguration, userConfiguration, new ConfigurationModel(), workspaceConfiguration, folders, new ConfigurationModel(), new ResourceMap<ConfigurationModel>(), false);
267267
}
268268

269269
private static parseConfigurationModel(model: IConfigurationModel): ConfigurationModel {

src/vs/workbench/browser/contextkeys.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/c
99
import { InputFocusedContext } from 'vs/platform/contextkey/common/contextkeys';
1010
import { IWindowConfiguration, IWindowService } from 'vs/platform/windows/common/windows';
1111
import { ActiveEditorContext, EditorsVisibleContext, TextCompareEditorVisibleContext, TextCompareEditorActiveContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, TEXT_DIFF_EDITOR_ID, SplitEditorsVertically, InEditorZenModeContext } from 'vs/workbench/common/editor';
12-
import { IsMacContext, IsLinuxContext, IsWindowsContext, HasMacNativeTabsContext, IsDevelopmentContext, SupportsWorkspacesContext, SupportsOpenFileFolderContext, WorkbenchStateContext, WorkspaceFolderCountContext } from 'vs/workbench/common/contextkeys';
12+
import { IsMacContext, IsLinuxContext, IsWindowsContext, HasMacNativeTabsContext, IsDevelopmentContext, SupportsWorkspacesContext, SupportsOpenFileFolderContext, WorkbenchStateContext, WorkspaceFolderCountContext, IsRemoteContext } from 'vs/workbench/common/contextkeys';
1313
import { trackFocus, addDisposableListener, EventType } from 'vs/base/browser/dom';
1414
import { preferredSideBySideGroupDirection, GroupDirection, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
1515
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
@@ -90,6 +90,8 @@ export class WorkbenchContextKeysHandler extends Disposable {
9090
IsLinuxContext.bindTo(this.contextKeyService);
9191
IsWindowsContext.bindTo(this.contextKeyService);
9292

93+
IsRemoteContext.bindTo(this.contextKeyService).set(!!this.windowService.getConfiguration().remoteAuthority);
94+
9395
// macOS Native Tabs
9496
const windowConfig = this.configurationService.getValue<IWindowConfiguration>();
9597
HasMacNativeTabsContext.bindTo(this.contextKeyService).set(windowConfig && windowConfig.window && windowConfig.window.nativeTabs);

src/vs/workbench/common/contextkeys.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { isMacintosh, isLinux, isWindows } from 'vs/base/common/platform';
99
export const IsMacContext = new RawContextKey<boolean>('isMac', isMacintosh);
1010
export const IsLinuxContext = new RawContextKey<boolean>('isLinux', isLinux);
1111
export const IsWindowsContext = new RawContextKey<boolean>('isWindows', isWindows);
12+
export const IsRemoteContext = new RawContextKey<boolean>('isRemote', false);
1213

1314
export const HasMacNativeTabsContext = new RawContextKey<boolean>('hasMacNativeTabs', false);
1415

src/vs/workbench/contrib/preferences/browser/preferencesActions.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,24 @@ export class OpenGlobalSettingsAction extends Action {
8888
}
8989
}
9090

91+
export class OpenRemoteSettingsAction extends Action {
92+
93+
static readonly ID = 'workbench.action.openRemoteSettings';
94+
static readonly LABEL = nls.localize('openRemoteSettings', "Open User Settings (Remote)");
95+
96+
constructor(
97+
id: string,
98+
label: string,
99+
@IPreferencesService private readonly preferencesService: IPreferencesService,
100+
) {
101+
super(id, label);
102+
}
103+
104+
run(event?: any): Promise<any> {
105+
return this.preferencesService.openRemoteSettings();
106+
}
107+
}
108+
91109
export class OpenGlobalKeybindingsAction extends Action {
92110

93111
static readonly ID = 'workbench.action.openGlobalKeybindings';

src/vs/workbench/contrib/preferences/electron-browser/preferences.contribution.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import * as nls from 'vs/nls';
1313
import { MenuId, MenuRegistry, SyncActionDescriptor } from 'vs/platform/actions/common/actions';
1414
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
1515
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
16-
import { WorkbenchStateContext } from 'vs/workbench/common/contextkeys';
16+
import { WorkbenchStateContext, IsRemoteContext } from 'vs/workbench/common/contextkeys';
1717
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
1818
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
1919
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
@@ -28,7 +28,7 @@ import { Extensions as WorkbenchExtensions, IWorkbenchContribution, IWorkbenchCo
2828
import { EditorInput, Extensions as EditorInputExtensions, IEditorInputFactory, IEditorInputFactoryRegistry } from 'vs/workbench/common/editor';
2929
import { ResourceContextKey } from 'vs/workbench/common/resources';
3030
import { KeybindingsEditor } from 'vs/workbench/contrib/preferences/browser/keybindingsEditor';
31-
import { ConfigureLanguageBasedSettingsAction, OpenDefaultKeybindingsFileAction, OpenFolderSettingsAction, OpenGlobalKeybindingsAction, OpenGlobalKeybindingsFileAction, OpenGlobalSettingsAction, OpenRawDefaultSettingsAction, OpenSettings2Action, OpenSettingsJsonAction, OpenWorkspaceSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND, OPEN_FOLDER_SETTINGS_LABEL } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
31+
import { ConfigureLanguageBasedSettingsAction, OpenDefaultKeybindingsFileAction, OpenFolderSettingsAction, OpenGlobalKeybindingsAction, OpenGlobalKeybindingsFileAction, OpenGlobalSettingsAction, OpenRawDefaultSettingsAction, OpenSettings2Action, OpenSettingsJsonAction, OpenWorkspaceSettingsAction, OPEN_FOLDER_SETTINGS_COMMAND, OPEN_FOLDER_SETTINGS_LABEL, OpenRemoteSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
3232
import { PreferencesEditor } from 'vs/workbench/contrib/preferences/browser/preferencesEditor';
3333
import { CONTEXT_KEYBINDINGS_EDITOR, CONTEXT_KEYBINDINGS_SEARCH_FOCUS, CONTEXT_KEYBINDING_FOCUS, CONTEXT_SETTINGS_EDITOR, CONTEXT_SETTINGS_JSON_EDITOR, CONTEXT_SETTINGS_SEARCH_FOCUS, CONTEXT_TOC_ROW_FOCUS, IKeybindingsEditor, IPreferencesSearchService, KEYBINDINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, KEYBINDINGS_EDITOR_COMMAND_COPY, KEYBINDINGS_EDITOR_COMMAND_COPY_COMMAND, KEYBINDINGS_EDITOR_COMMAND_DEFINE, KEYBINDINGS_EDITOR_COMMAND_FOCUS_KEYBINDINGS, KEYBINDINGS_EDITOR_COMMAND_RECORD_SEARCH_KEYS, KEYBINDINGS_EDITOR_COMMAND_REMOVE, KEYBINDINGS_EDITOR_COMMAND_RESET, KEYBINDINGS_EDITOR_COMMAND_SEARCH, KEYBINDINGS_EDITOR_COMMAND_SHOW_SIMILAR, KEYBINDINGS_EDITOR_COMMAND_SORTBY_PRECEDENCE, KEYBINDINGS_EDITOR_SHOW_DEFAULT_KEYBINDINGS, KEYBINDINGS_EDITOR_SHOW_USER_KEYBINDINGS, MODIFIED_SETTING_TAG, SETTINGS_EDITOR_COMMAND_CLEAR_SEARCH_RESULTS, SETTINGS_EDITOR_COMMAND_EDIT_FOCUSED_SETTING, SETTINGS_EDITOR_COMMAND_FILTER_MODIFIED, SETTINGS_EDITOR_COMMAND_FILTER_ONLINE, SETTINGS_EDITOR_COMMAND_FOCUS_FILE, SETTINGS_EDITOR_COMMAND_FOCUS_NEXT_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_PREVIOUS_SETTING, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_FROM_SEARCH, SETTINGS_EDITOR_COMMAND_FOCUS_SETTINGS_LIST, SETTINGS_EDITOR_COMMAND_SEARCH, SETTINGS_EDITOR_COMMAND_SHOW_CONTEXT_MENU, SETTINGS_EDITOR_COMMAND_SWITCH_TO_JSON, SETTINGS_COMMAND_OPEN_SETTINGS, KEYBINDINGS_EDITOR_COMMAND_DEFINE_WHEN } from 'vs/workbench/contrib/preferences/common/preferences';
3434
import { PreferencesContribution } from 'vs/workbench/contrib/preferences/common/preferencesContribution';
@@ -553,6 +553,18 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
553553
group: '1_keyboard_preferences_actions'
554554
});
555555

556+
CommandsRegistry.registerCommand(OpenRemoteSettingsAction.ID, serviceAccessor => {
557+
serviceAccessor.get(IInstantiationService).createInstance(OpenRemoteSettingsAction, OpenRemoteSettingsAction.ID, OpenRemoteSettingsAction.LABEL).run();
558+
});
559+
MenuRegistry.appendMenuItem(MenuId.CommandPalette, {
560+
command: {
561+
id: OpenRemoteSettingsAction.ID,
562+
title: { value: OpenRemoteSettingsAction.LABEL, original: 'Preferences: Open Remote Settings' },
563+
category: nls.localize('preferencesCategory', "Preferences")
564+
},
565+
when: IsRemoteContext
566+
});
567+
556568
abstract class SettingsCommand extends Command {
557569

558570
protected getPreferencesEditor(accessor: ServicesAccessor): PreferencesEditor | SettingsEditor2 | null {

0 commit comments

Comments
 (0)