diff --git a/extensions/git/package.json b/extensions/git/package.json index 058fd6691a7..4395d306bb5 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -1031,7 +1031,7 @@ ], "markdownDescription": "%config.path%", "default": null, - "scope": "application" + "scope": "machine" }, "git.autoRepositoryDetection": { "type": [ diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 89194ce1945..f5516fd5f98 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -83,7 +83,7 @@ ], "default": null, "description": "%typescript.npm%", - "scope": "application" + "scope": "machine" }, "typescript.check.npmIsInstalled": { "type": "boolean", @@ -129,7 +129,7 @@ }, "default": [], "description": "%typescript.tsserver.pluginPaths%", - "scope": "application" + "scope": "machine" }, "typescript.tsserver.trace": { "type": "string", diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index 2f787370ebe..19ca52ec2e4 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -84,6 +84,7 @@ export interface IConfigurationRegistry { export const enum ConfigurationScope { APPLICATION = 1, + MACHINE, WINDOW, RESOURCE, } @@ -116,6 +117,7 @@ export interface IDefaultConfigurationExtension { export const allSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; export const applicationSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; +export const machineSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; export const windowSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; export const resourceSettings: { properties: {}, patternProperties: {} } = { properties: {}, patternProperties: {} }; @@ -186,6 +188,9 @@ class ConfigurationRegistry implements IConfigurationRegistry { case ConfigurationScope.APPLICATION: delete applicationSettings.properties[key]; break; + case ConfigurationScope.MACHINE: + delete machineSettings.properties[key]; + break; case ConfigurationScope.WINDOW: delete windowSettings.properties[key]; break; @@ -334,6 +339,9 @@ class ConfigurationRegistry implements IConfigurationRegistry { case ConfigurationScope.APPLICATION: applicationSettings.properties[key] = properties[key]; break; + case ConfigurationScope.MACHINE: + machineSettings.properties[key] = properties[key]; + break; case ConfigurationScope.WINDOW: windowSettings.properties[key] = properties[key]; break; @@ -371,6 +379,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { delete allSettings.patternProperties[this.overridePropertyPattern]; delete applicationSettings.patternProperties[this.overridePropertyPattern]; + delete machineSettings.patternProperties[this.overridePropertyPattern]; delete windowSettings.patternProperties[this.overridePropertyPattern]; delete resourceSettings.patternProperties[this.overridePropertyPattern]; @@ -378,6 +387,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { allSettings.patternProperties[this.overridePropertyPattern] = patternProperties; applicationSettings.patternProperties[this.overridePropertyPattern] = patternProperties; + machineSettings.patternProperties[this.overridePropertyPattern] = patternProperties; windowSettings.patternProperties[this.overridePropertyPattern] = patternProperties; resourceSettings.patternProperties[this.overridePropertyPattern] = patternProperties; diff --git a/src/vs/workbench/api/common/configurationExtensionPoint.ts b/src/vs/workbench/api/common/configurationExtensionPoint.ts index 1a86479c17c..11459d62aee 100644 --- a/src/vs/workbench/api/common/configurationExtensionPoint.ts +++ b/src/vs/workbench/api/common/configurationExtensionPoint.ts @@ -35,16 +35,17 @@ const configurationEntrySchema: IJSONSchema = { properties: { isExecutable: { type: 'boolean', - deprecationMessage: 'This property is deprecated. Instead use `scope` property and set it to `application` value.' + deprecationMessage: 'This property is deprecated. Instead use `scope` property and set it to `machine` value.' }, scope: { type: 'string', - enum: ['application', 'window', 'resource'], + enum: ['application', 'machine', 'window', 'resource'], default: 'window', enumDescriptions: [ - nls.localize('scope.application.description', "Application specific configuration, which can be configured only in User settings."), - nls.localize('scope.window.description', "Window specific configuration, which can be configured in the User or Workspace settings."), - nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the User, Workspace or Folder settings.") + nls.localize('scope.application.description', "Application specific configuration, which can be configured only in application user settings."), + nls.localize('scope.machine.description', "Machine specific configuration, which can be configured only in user settings."), + nls.localize('scope.window.description', "Window specific configuration, which can be configured in the user or workspace settings."), + nls.localize('scope.resource.description', "Resource specific configuration, which can be configured in the wser, workspace or folder settings.") ], description: nls.localize('scope.description', "Scope in which the configuration is applicable. Available scopes are `window` and `resource`.") }, @@ -210,6 +211,8 @@ function validateProperties(configuration: IConfigurationNode, extension: IExten if (propertyConfiguration.scope) { if (propertyConfiguration.scope.toString() === 'application') { propertyConfiguration.scope = ConfigurationScope.APPLICATION; + } else if (propertyConfiguration.scope.toString() === 'machine') { + propertyConfiguration.scope = ConfigurationScope.MACHINE; } else if (propertyConfiguration.scope.toString() === 'resource') { propertyConfiguration.scope = ConfigurationScope.RESOURCE; } else { diff --git a/src/vs/workbench/services/configuration/browser/configurationService.ts b/src/vs/workbench/services/configuration/browser/configurationService.ts index efbd303489d..379261910a5 100644 --- a/src/vs/workbench/services/configuration/browser/configurationService.ts +++ b/src/vs/workbench/services/configuration/browser/configurationService.ts @@ -18,7 +18,7 @@ import { IConfigurationChangeEvent, ConfigurationTarget, IConfigurationOverrides import { Configuration, WorkspaceConfigurationChangeEvent, AllKeysConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels'; import { FOLDER_CONFIG_FOLDER_NAME, defaultSettingsSchemaId, userSettingsSchemaId, workspaceSettingsSchemaId, folderSettingsSchemaId, IConfigurationCache, IConfigurationFileService, machineSettingsSchemaId } from 'vs/workbench/services/configuration/common/configuration'; import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions, allSettings, windowSettings, resourceSettings, applicationSettings } from 'vs/platform/configuration/common/configurationRegistry'; +import { IConfigurationRegistry, Extensions, allSettings, windowSettings, resourceSettings, applicationSettings, machineSettings } from 'vs/platform/configuration/common/configurationRegistry'; import { IWorkspaceIdentifier, isWorkspaceIdentifier, IStoredWorkspaceFolder, isStoredWorkspaceFolder, IWorkspaceFolderCreationData, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier, IWorkspaceInitializationPayload, isSingleFolderWorkspaceInitializationPayload, ISingleFolderWorkspaceInitializationPayload, IEmptyWorkspaceInitializationPayload, useSlashForPath, getStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ConfigurationEditingService } from 'vs/workbench/services/configuration/common/configurationEditingService'; @@ -503,16 +503,18 @@ export class WorkspaceService extends Disposable implements IConfigurationServic }; const allSettingsSchema: IJSONSchema = { properties: allSettings.properties, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; - const unsupportedApplicationSettings = convertToNotSuggestedProperties(applicationSettings.properties, localize('unsupportedApplicationSetting', "This setting can be applied only in User Settings")); - const workspaceSettingsSchema: IJSONSchema = { properties: { ...unsupportedApplicationSettings, ...windowSettings.properties, ...resourceSettings.properties }, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; + const unsupportedApplicationSettings = convertToNotSuggestedProperties(applicationSettings.properties, localize('unsupportedApplicationSetting', "This setting can be applied only in application user Settings")); + const unsupportedMachineSettings = convertToNotSuggestedProperties(machineSettings.properties, localize('unsupportedMachineSetting', "This setting can be applied only in user Settings")); + const machineSettingsSchema: IJSONSchema = { properties: { ...unsupportedApplicationSettings, ...windowSettings.properties, ...resourceSettings.properties }, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; + const workspaceSettingsSchema: IJSONSchema = { properties: { ...unsupportedApplicationSettings, ...unsupportedMachineSettings, ...windowSettings.properties, ...resourceSettings.properties }, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; jsonRegistry.registerSchema(defaultSettingsSchemaId, allSettingsSchema); jsonRegistry.registerSchema(userSettingsSchemaId, allSettingsSchema); - jsonRegistry.registerSchema(machineSettingsSchemaId, workspaceSettingsSchema); + jsonRegistry.registerSchema(machineSettingsSchemaId, machineSettingsSchema); if (WorkbenchState.WORKSPACE === this.getWorkbenchState()) { const unsupportedWindowSettings = convertToNotSuggestedProperties(windowSettings.properties, localize('unsupportedWindowSetting', "This setting cannot be applied now. It will be applied when you open this folder directly.")); - const folderSettingsSchema: IJSONSchema = { properties: { ...unsupportedApplicationSettings, ...unsupportedWindowSettings, ...resourceSettings.properties }, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; + const folderSettingsSchema: IJSONSchema = { properties: { ...unsupportedApplicationSettings, ...unsupportedMachineSettings, ...unsupportedWindowSettings, ...resourceSettings.properties }, patternProperties: allSettings.patternProperties, additionalProperties: false, errorMessage: 'Unknown configuration setting' }; jsonRegistry.registerSchema(workspaceSettingsSchemaId, workspaceSettingsSchema); jsonRegistry.registerSchema(folderSettingsSchemaId, folderSettingsSchema); } else { diff --git a/src/vs/workbench/services/configuration/common/configuration.ts b/src/vs/workbench/services/configuration/common/configuration.ts index 7c3a06db189..c8ec23ec441 100644 --- a/src/vs/workbench/services/configuration/common/configuration.ts +++ b/src/vs/workbench/services/configuration/common/configuration.ts @@ -20,7 +20,7 @@ export const workspaceSettingsSchemaId = 'vscode://schemas/settings/workspace'; export const folderSettingsSchemaId = 'vscode://schemas/settings/folder'; export const launchSchemaId = 'vscode://schemas/launch'; -export const MACHINE_SCOPES = [ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE]; +export const MACHINE_SCOPES = [ConfigurationScope.MACHINE, ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE]; export const WORKSPACE_SCOPES = [ConfigurationScope.WINDOW, ConfigurationScope.RESOURCE]; export const FOLDER_SCOPES = [ConfigurationScope.RESOURCE]; diff --git a/src/vs/workbench/services/configuration/common/configurationEditingService.ts b/src/vs/workbench/services/configuration/common/configurationEditingService.ts index c299913d7d4..ac6a652040d 100644 --- a/src/vs/workbench/services/configuration/common/configurationEditingService.ts +++ b/src/vs/workbench/services/configuration/common/configurationEditingService.ts @@ -42,6 +42,11 @@ export const enum ConfigurationEditingErrorCode { */ ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION, + /** + * Error when trying to write a machne setting into workspace settings. + */ + ERROR_INVALID_WORKSPACE_CONFIGURATION_MACHINE, + /** * Error when trying to write an invalid folder configuration key to folder settings. */ @@ -284,6 +289,7 @@ export class ConfigurationEditingService { // API constraints case ConfigurationEditingErrorCode.ERROR_UNKNOWN_KEY: return nls.localize('errorUnknownKey', "Unable to write to {0} because {1} is not a registered configuration.", this.stringifyTarget(target), operation.key); case ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION: return nls.localize('errorInvalidWorkspaceConfigurationApplication', "Unable to write {0} to Workspace Settings. This setting can be written only into User settings.", operation.key); + case ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_MACHINE: return nls.localize('errorInvalidWorkspaceConfigurationMachine', "Unable to write {0} to Workspace Settings. This setting can be written only into User settings.", operation.key); case ConfigurationEditingErrorCode.ERROR_INVALID_FOLDER_CONFIGURATION: return nls.localize('errorInvalidFolderConfiguration', "Unable to write to Folder Settings because {0} does not support the folder resource scope.", operation.key); case ConfigurationEditingErrorCode.ERROR_INVALID_USER_TARGET: return nls.localize('errorInvalidUserTarget', "Unable to write to User Settings because {0} does not support for global scope.", operation.key); case ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_TARGET: return nls.localize('errorInvalidWorkspaceTarget', "Unable to write to Workspace Settings because {0} does not support for workspace scope in a multi folder workspace.", operation.key); @@ -424,6 +430,9 @@ export class ConfigurationEditingService { if (configurationProperties[operation.key].scope === ConfigurationScope.APPLICATION) { return this.reject(ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION, target, operation); } + if (configurationProperties[operation.key].scope === ConfigurationScope.MACHINE) { + return this.reject(ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_MACHINE, target, operation); + } } } diff --git a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts index 43d13d5ada3..950b215df35 100644 --- a/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts +++ b/src/vs/workbench/services/configuration/test/common/configurationModels.test.ts @@ -35,6 +35,11 @@ suite('FolderSettingsModelParser', () => { 'type': 'string', 'default': 'isSet', scope: ConfigurationScope.APPLICATION + }, + 'FolderSettingsModelParser.machine': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE } } }); @@ -43,7 +48,7 @@ suite('FolderSettingsModelParser', () => { test('parse all folder settings', () => { const testObject = new ConfigurationModelParser('settings', [ConfigurationScope.RESOURCE, ConfigurationScope.WINDOW]); - testObject.parseContent(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.application': 'executable' })); + testObject.parseContent(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.application': 'application', 'FolderSettingsModelParser.machine': 'executable' })); assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'window': 'window', 'resource': 'resource' } }); }); @@ -51,7 +56,7 @@ suite('FolderSettingsModelParser', () => { test('parse resource folder settings', () => { const testObject = new ConfigurationModelParser('settings', [ConfigurationScope.RESOURCE]); - testObject.parseContent(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.application': 'executable' })); + testObject.parseContent(JSON.stringify({ 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.application': 'application', 'FolderSettingsModelParser.machine': 'executable' })); assert.deepEqual(testObject.configurationModel.contents, { 'FolderSettingsModelParser': { 'resource': 'resource' } }); }); @@ -59,12 +64,12 @@ suite('FolderSettingsModelParser', () => { test('parse overridable resource settings', () => { const testObject = new ConfigurationModelParser('settings', [ConfigurationScope.RESOURCE]); - testObject.parseContent(JSON.stringify({ '[json]': { 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.application': 'executable' } })); + testObject.parseContent(JSON.stringify({ '[json]': { 'FolderSettingsModelParser.window': 'window', 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.application': 'application', 'FolderSettingsModelParser.machine': 'executable' } })); assert.deepEqual(testObject.configurationModel.overrides, [{ 'contents': { 'FolderSettingsModelParser': { 'resource': 'resource' } }, 'identifiers': ['json'] }]); }); - test('reprocess folder settings excludes application setting', () => { + test('reprocess folder settings excludes application and machine setting', () => { const testObject = new ConfigurationModelParser('settings', [ConfigurationScope.RESOURCE, ConfigurationScope.WINDOW]); testObject.parseContent(JSON.stringify({ 'FolderSettingsModelParser.resource': 'resource', 'FolderSettingsModelParser.anotherApplicationSetting': 'executable' })); @@ -80,6 +85,11 @@ suite('FolderSettingsModelParser', () => { 'type': 'string', 'default': 'isSet', scope: ConfigurationScope.APPLICATION + }, + 'FolderSettingsModelParser.anotherMachineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE } } }); diff --git a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts index dee633e4c90..0c3d0a6910d 100644 --- a/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts +++ b/src/vs/workbench/services/configuration/test/electron-browser/configurationService.test.ts @@ -730,6 +730,11 @@ suite('WorkspaceConfigurationService - Folder', () => { 'default': 'isSet', scope: ConfigurationScope.APPLICATION }, + 'configurationService.folder.machineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE + }, 'configurationService.folder.testSetting': { 'type': 'string', 'default': 'isSet', @@ -787,7 +792,7 @@ suite('WorkspaceConfigurationService - Folder', () => { }); test('defaults', () => { - assert.deepEqual(testObject.getValue('configurationService'), { 'folder': { 'applicationSetting': 'isSet', 'testSetting': 'isSet' } }); + assert.deepEqual(testObject.getValue('configurationService'), { 'folder': { 'applicationSetting': 'isSet', 'machineSetting': 'isSet', 'testSetting': 'isSet' } }); }); test('globals override defaults', () => { @@ -843,6 +848,13 @@ suite('WorkspaceConfigurationService - Folder', () => { .then(() => assert.equal(testObject.getValue('configurationService.folder.applicationSetting'), 'userValue')); }); + test('machine settings are not read from workspace', () => { + fs.writeFileSync(globalSettingsFile, '{ "configurationService.folder.machineSetting": "userValue" }'); + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.machineSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.folder.machineSetting'), 'userValue')); + }); + test('get application scope settings are not loaded after defaults are registered', () => { fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.anotherApplicationSetting": "workspaceValue" }'); return testObject.reloadConfiguration() @@ -862,6 +874,25 @@ suite('WorkspaceConfigurationService - Folder', () => { }); }); + test('get machine scope settings are not loaded after defaults are registered', () => { + fs.writeFileSync(path.join(workspaceDir, '.vscode', 'settings.json'), '{ "configurationService.folder.anotherMachineSetting": "workspaceValue" }'); + return testObject.reloadConfiguration() + .then(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.folder.anotherMachineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE + } + } + }); + assert.deepEqual(testObject.keys().workspace, []); + }); + }); + test('reload configuration emits events after global configuraiton changes', () => { fs.writeFileSync(globalSettingsFile, '{ "testworkbench.editor.tabs": true }'); const target = sinon.spy(); @@ -971,6 +1002,11 @@ suite('WorkspaceConfigurationService - Folder', () => { .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION)); }); + test('update machine setting into workspace configuration in a workspace is not supported', () => { + return testObject.updateValue('configurationService.folder.machineSetting', 'workspaceValue', {}, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_MACHINE)); + }); + test('update tasks configuration', () => { return testObject.updateValue('tasks', { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] }, ConfigurationTarget.WORKSPACE) .then(() => assert.deepEqual(testObject.getValue('tasks'), { 'version': '1.0.0', tasks: [{ 'taskName': 'myTask' }] })); @@ -1030,6 +1066,11 @@ suite('WorkspaceConfigurationService-Multiroot', () => { 'default': 'isSet', scope: ConfigurationScope.APPLICATION }, + 'configurationService.workspace.machineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE + }, 'configurationService.workspace.testResourceSetting': { 'type': 'string', 'default': 'isSet', @@ -1095,6 +1136,13 @@ suite('WorkspaceConfigurationService-Multiroot', () => { .then(() => assert.equal(testObject.getValue('configurationService.workspace.applicationSetting'), 'userValue')); }); + test('machine settings are not read from workspace', () => { + fs.writeFileSync(environmentService.appSettingsPath, '{ "configurationService.workspace.machineSetting": "userValue" }'); + return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.machineSetting': 'workspaceValue' } }, true) + .then(() => testObject.reloadConfiguration()) + .then(() => assert.equal(testObject.getValue('configurationService.workspace.machineSetting'), 'userValue')); + }); + test('workspace settings override user settings after defaults are registered ', () => { fs.writeFileSync(environmentService.appSettingsPath, '{ "configurationService.workspace.newSetting": "userValue" }'); return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.newSetting': 'workspaceValue' } }, true) @@ -1121,6 +1169,13 @@ suite('WorkspaceConfigurationService-Multiroot', () => { .then(() => assert.equal(testObject.getValue('configurationService.workspace.applicationSetting'), 'userValue')); }); + test('machine settings are not read from workspace folder', () => { + fs.writeFileSync(environmentService.appSettingsPath, '{ "configurationService.workspace.machineSetting": "userValue" }'); + fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.machineSetting": "workspaceFolderValue" }'); + return testObject.reloadConfiguration() + .then(() => assert.equal(testObject.getValue('configurationService.workspace.machineSetting'), 'userValue')); + }); + test('application settings are not read from workspace folder after defaults are registered', () => { fs.writeFileSync(environmentService.appSettingsPath, '{ "configurationService.workspace.testNewApplicationSetting": "userValue" }'); fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewApplicationSetting": "workspaceFolderValue" }'); @@ -1141,6 +1196,26 @@ suite('WorkspaceConfigurationService-Multiroot', () => { }); }); + test('application settings are not read from workspace folder after defaults are registered', () => { + fs.writeFileSync(environmentService.appSettingsPath, '{ "configurationService.workspace.testNewMachineSetting": "userValue" }'); + fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewMachineSetting": "workspaceFolderValue" }'); + return testObject.reloadConfiguration() + .then(() => { + configurationRegistry.registerConfiguration({ + 'id': '_test', + 'type': 'object', + 'properties': { + 'configurationService.workspace.testNewMachineSetting': { + 'type': 'string', + 'default': 'isSet', + scope: ConfigurationScope.MACHINE + } + } + }); + assert.equal(testObject.getValue('configurationService.workspace.testNewMachineSetting', { resource: workspaceContextService.getWorkspace().folders[0].uri }), 'userValue'); + }); + }); + test('resource setting in folder is read after it is registered later', () => { fs.writeFileSync(workspaceContextService.getWorkspace().folders[0].toResource('.vscode/settings.json').fsPath, '{ "configurationService.workspace.testNewResourceSetting2": "workspaceFolderValue" }'); return jsonEditingServce.write(workspaceContextService.getWorkspace().configuration!, { key: 'settings', value: { 'configurationService.workspace.testNewResourceSetting2': 'workspaceValue' } }, true) @@ -1290,6 +1365,11 @@ suite('WorkspaceConfigurationService-Multiroot', () => { .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_APPLICATION)); }); + test('update machine setting into workspace configuration in a workspace is not supported', () => { + return testObject.updateValue('configurationService.workspace.machineSetting', 'workspaceValue', {}, ConfigurationTarget.WORKSPACE, true) + .then(() => assert.fail('Should not be supported'), (e) => assert.equal(e.code, ConfigurationEditingErrorCode.ERROR_INVALID_WORKSPACE_CONFIGURATION_MACHINE)); + }); + test('update workspace folder configuration', () => { const workspace = workspaceContextService.getWorkspace(); return testObject.updateValue('configurationService.workspace.testResourceSetting', 'workspaceFolderValue', { resource: workspace.folders[0].uri }, ConfigurationTarget.WORKSPACE_FOLDER)