From 997eb0e56854cedf3e387af8ff8d6ceeed320838 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 30 Oct 2017 13:43:42 +0100 Subject: [PATCH] Fix #33439 --- .../browser/preferencesRenderers.ts | 157 ++++++++---------- .../preferences/browser/preferencesService.ts | 11 +- ...supportedWorkspaceSettings.contribution.ts | 3 + .../common/configurationModels.ts | 86 ++++++---- .../configuration/node/configuration.ts | 6 +- .../node/configurationService.ts | 56 ++++--- 6 files changed, 170 insertions(+), 149 deletions(-) diff --git a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts index e900dfd9d1b22..2bcc9ac743ae2 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts @@ -32,7 +32,7 @@ import { ICursorPositionChangedEvent } from 'vs/editor/common/controller/cursorE import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDecorations'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; import { MarkdownString } from 'vs/base/common/htmlContent'; -import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration'; +import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IEnvironmentService } from 'vs/platform/environment/common/environment'; export interface IPreferencesRenderer extends IDisposable { @@ -175,7 +175,7 @@ export class UserSettingsRenderer extends Disposable implements IPreferencesRend export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer { - private untrustedSettingRenderer: UnsupportedWorkspaceSettingsRenderer; + private unsupportedSettingsRenderer: UnsupportedSettingsRenderer; private workspaceConfigurationRenderer: WorkspaceConfigurationRenderer; constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel, @@ -187,7 +187,7 @@ export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements I @IInstantiationService instantiationService: IInstantiationService ) { super(editor, preferencesModel, preferencesService, telemetryService, textFileService, configurationService, messageService, instantiationService); - this.untrustedSettingRenderer = this._register(instantiationService.createInstance(UnsupportedWorkspaceSettingsRenderer, editor, preferencesModel)); + this.unsupportedSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedSettingsRenderer, editor, preferencesModel)); this.workspaceConfigurationRenderer = this._register(instantiationService.createInstance(WorkspaceConfigurationRenderer, editor, preferencesModel)); } @@ -197,14 +197,14 @@ export class WorkspaceSettingsRenderer extends UserSettingsRenderer implements I public render(): void { super.render(); - this.untrustedSettingRenderer.render(); + this.unsupportedSettingsRenderer.render(); this.workspaceConfigurationRenderer.render(); } } export class FolderSettingsRenderer extends UserSettingsRenderer implements IPreferencesRenderer { - private unsupportedWorkbenchSettingsRenderer: UnsupportedWorkbenchSettingsRenderer; + private unsupportedSettingsRenderer: UnsupportedSettingsRenderer; constructor(editor: ICodeEditor, preferencesModel: SettingsEditorModel, @IPreferencesService preferencesService: IPreferencesService, @@ -215,7 +215,7 @@ export class FolderSettingsRenderer extends UserSettingsRenderer implements IPre @IInstantiationService instantiationService: IInstantiationService ) { super(editor, preferencesModel, preferencesService, telemetryService, textFileService, configurationService, messageService, instantiationService); - this.unsupportedWorkbenchSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedWorkbenchSettingsRenderer, editor, preferencesModel)); + this.unsupportedSettingsRenderer = this._register(instantiationService.createInstance(UnsupportedSettingsRenderer, editor, preferencesModel)); } protected createHeader(): void { @@ -224,7 +224,7 @@ export class FolderSettingsRenderer extends UserSettingsRenderer implements IPre public render(): void { super.render(); - this.unsupportedWorkbenchSettingsRenderer.render(); + this.unsupportedSettingsRenderer.render(); } } @@ -1088,69 +1088,16 @@ class SettingHighlighter extends Disposable { } } -class UnsupportedWorkspaceSettingsRenderer extends Disposable { - - constructor(private editor: editorCommon.ICommonCodeEditor, private workspaceSettingsEditorModel: SettingsEditorModel, - @IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService, - @IMarkerService private markerService: IMarkerService - ) { - super(); - this._register(this.configurationService.onDidChangeConfiguration(e => this.onDidConfigurationChange(e))); - } - - private getMarkerMessage(settingKey: string): string { - switch (settingKey) { - case 'php.validate.executablePath': - return nls.localize('unsupportedPHPExecutablePathSetting', "This setting must be a User Setting. To configure PHP for the workspace, open a PHP file and click on 'PHP Path' in the status bar."); - default: - return nls.localize('unsupportedWorkspaceSetting', "This setting must be a User Setting."); - } - } - - public render(): void { - const unsupportedWorkspaceKeys = this.configurationService.getUnsupportedWorkspaceKeys(); - if (unsupportedWorkspaceKeys.length) { - const markerData: IMarkerData[] = []; - for (const unsupportedKey of unsupportedWorkspaceKeys) { - const setting = this.workspaceSettingsEditorModel.getPreference(unsupportedKey); - if (setting) { - markerData.push({ - severity: Severity.Warning, - startLineNumber: setting.keyRange.startLineNumber, - startColumn: setting.keyRange.startColumn, - endLineNumber: setting.keyRange.endLineNumber, - endColumn: setting.keyRange.endColumn, - message: this.getMarkerMessage(unsupportedKey) - }); - } - } - if (markerData.length) { - this.markerService.changeOne('preferencesEditor', this.workspaceSettingsEditorModel.uri, markerData); - } else { - this.markerService.remove('preferencesEditor', [this.workspaceSettingsEditorModel.uri]); - } - } - } - - private onDidConfigurationChange(event: IConfigurationChangeEvent): void { - if (event.source === ConfigurationTarget.DEFAULT || event.source === ConfigurationTarget.WORKSPACE || event.source === ConfigurationTarget.WORKSPACE_FOLDER) { - this.render(); - } - } - - public dispose(): void { - this.markerService.remove('preferencesEditor', [this.workspaceSettingsEditorModel.uri]); - super.dispose(); - } -} - -class UnsupportedWorkbenchSettingsRenderer extends Disposable { +class UnsupportedSettingsRenderer extends Disposable { private decorationIds: string[] = []; private renderingDelayer: Delayer = new Delayer(200); - constructor(private editor: editorCommon.ICommonCodeEditor, private workspaceSettingsEditorModel: SettingsEditorModel, + constructor( + private editor: editorCommon.ICommonCodeEditor, + private settingsEditorModel: SettingsEditorModel, @IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService, + @IMarkerService private markerService: IMarkerService, @IEnvironmentService private environmentService: IEnvironmentService ) { super(); @@ -1158,47 +1105,65 @@ class UnsupportedWorkbenchSettingsRenderer extends Disposable { } public render(): void { - const ranges: IRange[] = []; const configurationRegistry = Registry.as(ConfigurationExtensions.Configuration).getConfigurationProperties(); - for (const settingsGroup of this.workspaceSettingsEditorModel.settingsGroups) { + const ranges: IRange[] = []; + const markerData: IMarkerData[] = []; + for (const settingsGroup of this.settingsEditorModel.settingsGroups) { for (const section of settingsGroup.sections) { for (const setting of section.settings) { - if (configurationRegistry[setting.key] && configurationRegistry[setting.key].scope === ConfigurationScope.WINDOW) { - ranges.push({ - startLineNumber: setting.keyRange.startLineNumber, - startColumn: setting.keyRange.startColumn - 1, - endLineNumber: setting.valueRange.endLineNumber, - endColumn: setting.valueRange.endColumn - }); + if (this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE || this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) { + // Show warnings for executable settings + if (configurationRegistry[setting.key] && configurationRegistry[setting.key].isExecutable) { + markerData.push({ + severity: Severity.Warning, + startLineNumber: setting.keyRange.startLineNumber, + startColumn: setting.keyRange.startColumn, + endLineNumber: setting.keyRange.endLineNumber, + endColumn: setting.keyRange.endColumn, + message: this.getMarkerMessage(setting.key) + }); + } + } + if (this.settingsEditorModel.configurationTarget === ConfigurationTarget.WORKSPACE_FOLDER) { + // Dim and show information for window settings + if (configurationRegistry[setting.key] && configurationRegistry[setting.key].scope === ConfigurationScope.WINDOW) { + ranges.push({ + startLineNumber: setting.keyRange.startLineNumber, + startColumn: setting.keyRange.startColumn - 1, + endLineNumber: setting.valueRange.endLineNumber, + endColumn: setting.valueRange.endColumn + }); + } } } } } + if (markerData.length) { + this.markerService.changeOne('preferencesEditor', this.settingsEditorModel.uri, markerData); + } else { + this.markerService.remove('preferencesEditor', [this.settingsEditorModel.uri]); + } this.editor.changeDecorations(changeAccessor => this.decorationIds = changeAccessor.deltaDecorations(this.decorationIds, ranges.map(range => this.createDecoration(range, this.editor.getModel())))); } - private static _DIM_CONFIGUARATION_ = ModelDecorationOptions.register({ - stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - inlineClassName: 'dim-configuration', - beforeContentClassName: 'unsupportedWorkbenhSettingInfo', - hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSetting', "This setting cannot be applied now. It will be applied when you open this folder directly.")) - }); - - private static _DIM_CONFIGUARATION_DEV_MODE = ModelDecorationOptions.register({ - stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, - inlineClassName: 'dim-configuration', - beforeContentClassName: 'unsupportedWorkbenhSettingInfo', - hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSettingDevMode', "This setting cannot be applied now. It will be applied if you define it's scope as 'resource' while registering, or when you open this folder directly.")) - }); - private createDecoration(range: IRange, model: editorCommon.IModel): editorCommon.IModelDeltaDecoration { return { range, - options: !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment ? UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_DEV_MODE : UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_ + options: !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment ? UnsupportedSettingsRenderer._DIM_CONFIGUARATION_DEV_MODE : UnsupportedSettingsRenderer._DIM_CONFIGUARATION_ }; } + private getMarkerMessage(settingKey: string): string { + switch (settingKey) { + case 'php.validate.executablePath': + return nls.localize('unsupportedPHPExecutablePathSetting', "This setting must be a User Setting. To configure PHP for the workspace, open a PHP file and click on 'PHP Path' in the status bar."); + default: + return nls.localize('unsupportedWorkspaceSetting', "This setting must be a User Setting."); + } + } + public dispose(): void { + this.markerService.remove('preferencesEditor', [this.settingsEditorModel.uri]); if (this.decorationIds) { this.decorationIds = this.editor.changeDecorations(changeAccessor => { return changeAccessor.deltaDecorations(this.decorationIds, []); @@ -1206,6 +1171,20 @@ class UnsupportedWorkbenchSettingsRenderer extends Disposable { } super.dispose(); } + + private static _DIM_CONFIGUARATION_ = ModelDecorationOptions.register({ + stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + inlineClassName: 'dim-configuration', + beforeContentClassName: 'unsupportedWorkbenhSettingInfo', + hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSetting', "This setting cannot be applied now. It will be applied when you open this folder directly.")) + }); + + private static _DIM_CONFIGUARATION_DEV_MODE = ModelDecorationOptions.register({ + stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges, + inlineClassName: 'dim-configuration', + beforeContentClassName: 'unsupportedWorkbenhSettingInfo', + hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSettingDevMode', "This setting cannot be applied now. It will be applied if you define it's scope as 'resource' while registering, or when you open this folder directly.")) + }); } class WorkspaceConfigurationRenderer extends Disposable { diff --git a/src/vs/workbench/parts/preferences/browser/preferencesService.ts b/src/vs/workbench/parts/preferences/browser/preferencesService.ts index 17fbf389edb9f..41ada932bde04 100644 --- a/src/vs/workbench/parts/preferences/browser/preferencesService.ts +++ b/src/vs/workbench/parts/preferences/browser/preferencesService.ts @@ -40,6 +40,7 @@ import { IJSONEditingService } from 'vs/workbench/services/configuration/common/ import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { ConfigurationTarget } from 'vs/platform/configuration/common/configuration'; import { IModeService } from 'vs/editor/common/services/modeService'; +import { parse } from 'vs/base/common/json'; const emptyEditableSettingsContent = '{\n}'; @@ -327,9 +328,13 @@ export class PreferencesService extends Disposable implements IPreferencesServic private createSettingsIfNotExists(target: ConfigurationTarget, resource: URI): TPromise { if (this.contextService.getWorkbenchState() === WorkbenchState.WORKSPACE && target === ConfigurationTarget.WORKSPACE) { - if (!this.configurationService.keys().workspace.length) { - return this.jsonEditingService.write(resource, { key: 'settings', value: {} }, true).then(null, () => { }); - } + return this.fileService.resolveContent(this.contextService.getWorkspace().configuration) + .then(content => { + if (Object.keys(parse(content.value)).indexOf('settings') === -1) { + return this.jsonEditingService.write(resource, { key: 'settings', value: {} }, true).then(null, () => { }); + } + return null; + }); } return this.createIfNotExists(resource, emptyEditableSettingsContent).then(() => { }); } diff --git a/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts b/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts index a008c9c954fa1..86ba85f8e0b71 100644 --- a/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts +++ b/src/vs/workbench/parts/trust/electron-browser/unsupportedWorkspaceSettings.contribution.ts @@ -17,6 +17,7 @@ import { IPreferencesService } from 'vs/workbench/parts/preferences/common/prefe import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage'; +import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace'; @@ -28,6 +29,7 @@ class UnsupportedWorkspaceSettingsContribution implements IWorkbenchContribution constructor( @ILifecycleService lifecycleService: ILifecycleService, + @IWorkspaceContextService workspaceContextService: IWorkspaceContextService, @IWorkspaceConfigurationService private workspaceConfigurationService: IWorkspaceConfigurationService, @IPreferencesService private preferencesService: IPreferencesService, @IMessageService private messageService: IMessageService, @@ -36,6 +38,7 @@ class UnsupportedWorkspaceSettingsContribution implements IWorkbenchContribution ) { lifecycleService.onShutdown(this.dispose, this); this.toDispose.push(this.workspaceConfigurationService.onDidChangeConfiguration(e => this.checkWorkspaceSettings())); + this.toDispose.push(workspaceContextService.onDidChangeWorkspaceFolders(e => this.checkWorkspaceSettings())); } getId(): string { diff --git a/src/vs/workbench/services/configuration/common/configurationModels.ts b/src/vs/workbench/services/configuration/common/configurationModels.ts index a222048cf4c32..be16b2d69c6de 100644 --- a/src/vs/workbench/services/configuration/common/configurationModels.ts +++ b/src/vs/workbench/services/configuration/common/configurationModels.ts @@ -20,13 +20,12 @@ export class WorkspaceConfigurationModel extends CustomConfigurationModel { private _raw: any; private _folders: IStoredWorkspaceFolder[]; - private _worksapaceSettings: ConfigurationModel; - private _workspaceConfiguration: ConfigurationModel; + private _worksapaceSettings: WorkspaceSettingsModel; public update(content: string): void { super.update(content); - this._worksapaceSettings = new ConfigurationModel(this._worksapaceSettings.contents, this._worksapaceSettings.keys, this.overrides); - this._workspaceConfiguration = this.consolidate(); + this._folders = (this._raw['folders'] || []) as IStoredWorkspaceFolder[]; + this._worksapaceSettings = new WorkspaceSettingsModel(this._raw['settings'] || {}); } get folders(): IStoredWorkspaceFolder[] { @@ -34,26 +33,41 @@ export class WorkspaceConfigurationModel extends CustomConfigurationModel { } get workspaceConfiguration(): ConfigurationModel { - return this._workspaceConfiguration; + return this._worksapaceSettings || new WorkspaceSettingsModel({}); + } + + get workspaceSettingsModel(): WorkspaceSettingsModel { + return this._worksapaceSettings || new WorkspaceSettingsModel({}); } protected processRaw(raw: any): void { this._raw = raw; + super.processRaw(raw); + } - this._folders = (this._raw['folders'] || []) as IStoredWorkspaceFolder[]; - this._worksapaceSettings = this.parseConfigurationModel('settings'); - super.processRaw(raw); +} + +export class WorkspaceSettingsModel extends ConfigurationModel { + + private _raw: any; + private _unsupportedKeys: string[]; + + constructor(raw: any) { + super(); + this._raw = raw; + this.update(); } - private parseConfigurationModel(section: string): ConfigurationModel { - const rawSection = this._raw[section] || {}; - const contents = toValuesTree(rawSection, message => console.error(`Conflict in section '${section}' of workspace configuration file ${message}`)); - return new ConfigurationModel(contents, Object.keys(rawSection)); + public get unsupportedKeys(): string[] { + return this._unsupportedKeys || []; } - private consolidate(): ConfigurationModel { - return this._worksapaceSettings; + update(): void { + const { unsupportedKeys, contents } = processWorkspaceSettings(this._raw); + this._unsupportedKeys = unsupportedKeys; + this._contents = toValuesTree(contents, message => console.error(`Conflict in workspace settings file: ${message}`)); + this._keys = Object.keys(contents); } } @@ -73,6 +87,28 @@ export class ScopedConfigurationModel extends CustomConfigurationModel { } +function processWorkspaceSettings(content: any): { unsupportedKeys: string[], contents: any } { + const isNotExecutable = (key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): boolean => { + const propertySchema = configurationProperties[key]; + if (!propertySchema) { + return true; // Unknown propertis are ignored from checks + } + return !propertySchema.isExecutable; + }; + + const unsupportedKeys = []; + const contents = {}; + const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties(); + for (let key in content) { + if (isNotExecutable(key, configurationProperties)) { + contents[key] = content[key]; + } else { + unsupportedKeys.push(key); + } + } + return { contents, unsupportedKeys }; +} + export class FolderSettingsModel extends CustomConfigurationModel { private _raw: any; @@ -80,17 +116,9 @@ export class FolderSettingsModel extends CustomConfigurationModel { protected processRaw(raw: any): void { this._raw = raw; - const processedRaw = {}; - this._unsupportedKeys = []; - const configurationProperties = Registry.as(Extensions.Configuration).getConfigurationProperties(); - for (let key in raw) { - if (this.isNotExecutable(key, configurationProperties)) { - processedRaw[key] = raw[key]; - } else { - this._unsupportedKeys.push(key); - } - } - return super.processRaw(processedRaw); + const { unsupportedKeys, contents } = processWorkspaceSettings(raw); + this._unsupportedKeys = unsupportedKeys; + return super.processRaw(contents); } public reprocess(): void { @@ -101,14 +129,6 @@ export class FolderSettingsModel extends CustomConfigurationModel { return this._unsupportedKeys || []; } - private isNotExecutable(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): boolean { - const propertySchema = configurationProperties[key]; - if (!propertySchema) { - return true; // Unknown propertis are ignored from checks - } - return !propertySchema.isExecutable; - } - public createWorkspaceConfigurationModel(): ConfigurationModel { return this.createScopedConfigurationModel(ConfigurationScope.WINDOW); } diff --git a/src/vs/workbench/services/configuration/node/configuration.ts b/src/vs/workbench/services/configuration/node/configuration.ts index f19c00527111d..3692195001fd9 100644 --- a/src/vs/workbench/services/configuration/node/configuration.ts +++ b/src/vs/workbench/services/configuration/node/configuration.ts @@ -16,7 +16,7 @@ import { FileChangeType, FileChangesEvent } from 'vs/platform/files/common/files import { isLinux } from 'vs/base/common/platform'; import { ConfigWatcher } from 'vs/base/node/config'; import { CustomConfigurationModel, ConfigurationModel } from 'vs/platform/configuration/common/configurationModels'; -import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels'; +import { WorkspaceConfigurationModel, ScopedConfigurationModel, FolderConfigurationModel, FolderSettingsModel, WorkspaceSettingsModel } from 'vs/workbench/services/configuration/common/configurationModels'; import { WORKSPACE_STANDALONE_CONFIGURATIONS, WORKSPACE_CONFIG_DEFAULT_PATH, TASKS_CONFIGURATION_KEY, LAUNCH_CONFIGURATION_KEY } from 'vs/workbench/services/configuration/common/configuration'; import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry'; import { IStoredWorkspace, IStoredWorkspaceFolder } from 'vs/platform/workspaces/common/workspaces'; @@ -127,6 +127,10 @@ export class WorkspaceConfiguration extends Disposable { return this.workspaceConfigurationModel.workspaceConfiguration; } + getWorkspaceSettings(): WorkspaceSettingsModel { + return this.workspaceConfigurationModel.workspaceSettingsModel; + } + private listenToWatcher() { this._workspaceConfigurationWatcherDisposables.push(this._workspaceConfigurationWatcher); this._workspaceConfigurationWatcher.onDidUpdateConfiguration(() => this._onDidUpdateConfiguration.fire(), this, this._workspaceConfigurationWatcherDisposables); diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 2304834b4c338..101e2cabfc095 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -39,6 +39,7 @@ import { WorkspaceConfiguration, FolderConfiguration } from 'vs/workbench/servic import { JSONEditingService } from 'vs/workbench/services/configuration/node/jsonEditingService'; import { Schemas } from 'vs/base/common/network'; import { massageFolderPathForWorkspace } from 'vs/platform/workspaces/node/workspaces'; +import { distinct } from 'vs/base/common/arrays'; export class WorkspaceService extends Disposable implements IWorkspaceConfigurationService, IWorkspaceContextService { @@ -278,13 +279,16 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat } getUnsupportedWorkspaceKeys(): string[] { - return this.getWorkbenchState() === WorkbenchState.FOLDER ? this._configuration.getFolderConfigurationModel(this.workspace.folders[0].uri).workspaceSettingsConfig.unsupportedKeys : []; + const unsupportedWorkspaceKeys = [...this.workspaceConfiguration.getWorkspaceSettings().unsupportedKeys]; + for (const folder of this.workspace.folders) { + unsupportedWorkspaceKeys.push(...this._configuration.getFolderConfigurationModel(folder.uri).workspaceSettingsConfig.unsupportedKeys); + } + return distinct(unsupportedWorkspaceKeys); } initialize(arg: IWorkspaceIdentifier | ISingleFolderWorkspaceIdentifier | IWindowConfiguration): TPromise { return this.createWorkspace(arg) - .then(workspace => this.setWorkspace(workspace)) - .then(() => this.initializeConfiguration()); + .then(workspace => this.updateWorkspaceAndInitializeConfiguration(workspace)); } setInstantiationService(instantiationService: IInstantiationService): void { @@ -341,32 +345,37 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat return TPromise.as(new Workspace(id)); } - private setWorkspace(workspace: Workspace): void { - if (!this.workspace) { - this.workspace = workspace; - return; - } + private updateWorkspaceAndInitializeConfiguration(workspace: Workspace): TPromise { + let folderChanges: IWorkspaceFoldersChangeEvent; + if (this.workspace) { + const currentState = this.getWorkbenchState(); + const currentWorkspacePath = this.workspace.configuration ? this.workspace.configuration.fsPath : void 0; + const currentFolders = this.workspace.folders; - const currentState = this.getWorkbenchState(); - const currentWorkspacePath = this.workspace.configuration ? this.workspace.configuration.fsPath : void 0; - const currentFolders = this.workspace.folders; + this.workspace.update(workspace); - this.workspace.update(workspace); + const newState = this.getWorkbenchState(); + if (newState !== currentState) { + this._onDidChangeWorkbenchState.fire(newState); + } - const newState = this.getWorkbenchState(); - if (newState !== currentState) { - this._onDidChangeWorkbenchState.fire(newState); - } + const newWorkspacePath = this.workspace.configuration ? this.workspace.configuration.fsPath : void 0; + if (newWorkspacePath !== currentWorkspacePath || newState !== currentState) { + this._onDidChangeWorkspaceName.fire(); + } - const newWorkspacePath = this.workspace.configuration ? this.workspace.configuration.fsPath : void 0; - if (newWorkspacePath !== currentWorkspacePath || newState !== currentState) { - this._onDidChangeWorkspaceName.fire(); - } + folderChanges = this.compareFolders(currentFolders, this.workspace.folders); - const changes = this.compareFolders(currentFolders, this.workspace.folders); - if (changes.added.length || changes.removed.length || changes.changed.length) { - this._onDidChangeWorkspaceFolders.fire(changes); + } else { + this.workspace = workspace; } + + return this.initializeConfiguration().then(() => { + // Trigger folders change after configuration initialization so that configuration is up to date. + if (folderChanges && (folderChanges.added.length || folderChanges.removed.length || folderChanges.changed.length)) { + this._onDidChangeWorkspaceFolders.fire(folderChanges); + } + }); } private compareFolders(currentFolders: IWorkspaceFolder[], newFolders: IWorkspaceFolder[]): IWorkspaceFoldersChangeEvent { @@ -457,6 +466,7 @@ export class WorkspaceService extends Disposable implements IWorkspaceConfigurat private onBaseConfigurationChanged(e: IConfigurationChangeEvent): void { if (this.workspace && this._configuration) { if (e.source === ConfigurationTarget.DEFAULT) { + this.workspaceConfiguration.getWorkspaceSettings().update(); this.workspace.folders.forEach(folder => this._configuration.getFolderConfigurationModel(folder.uri).update()); this._configuration.updateDefaultConfiguration(this.baseConfigurationService.configuration.defaults); this.triggerConfigurationChange(new ConfigurationChangeEvent().change(e.affectedKeys), e.source);