diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index b1d5160d44e..ef59a9672d0 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -5399,7 +5399,7 @@ declare module 'vscode' { /** * An event that is emitted when the [configuration](#WorkspaceConfiguration) changed. */ - export const onDidChangeConfiguration: Event; + export const onDidChangeConfiguration: Event; /** * Register a task provider. @@ -5411,6 +5411,21 @@ declare module 'vscode' { export function registerTaskProvider(type: string, provider: TaskProvider): Disposable; } + /** + * An event describing the change in Configuration + */ + export interface ConfigurationChangeEvent { + + /** + * Returns `true` if the given section for the given resource (if provided) has affected. + * + * @param section Configuration name, supports _dotted_ names. + * @param resource A resource Uri. + * @return `true` if the given section for the given resource (if provided) has affected. + */ + affectsConfiguration(section: string, resource?: Uri): boolean; + } + /** * Namespace for participating in language-specific editor [features](https://code.visualstudio.com/docs/editor/editingevolved), * like IntelliSense, code actions, diagnostics etc. diff --git a/src/vs/workbench/api/node/extHostConfiguration.ts b/src/vs/workbench/api/node/extHostConfiguration.ts index f7b42446d55..69a4cc1fdfb 100644 --- a/src/vs/workbench/api/node/extHostConfiguration.ts +++ b/src/vs/workbench/api/node/extHostConfiguration.ts @@ -37,7 +37,7 @@ type ConfigurationInspect = { export class ExtHostConfiguration implements ExtHostConfigurationShape { - private readonly _onDidChangeConfiguration = new Emitter(); + private readonly _onDidChangeConfiguration = new Emitter(); private readonly _proxy: MainThreadConfigurationShape; private readonly _extHostWorkspace: ExtHostWorkspace; private _configuration: Configuration; @@ -48,13 +48,13 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { this._configuration = Configuration.parse(data); } - get onDidChangeConfiguration(): Event { + get onDidChangeConfiguration(): Event { return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event; } $acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) { this._configuration = Configuration.parse(data); - this._onDidChangeConfiguration.fire(undefined); + this._onDidChangeConfiguration.fire(this.toConfigurationChangeEvent(eventData)); } getConfiguration(section?: string, resource?: URI): vscode.WorkspaceConfiguration { @@ -120,7 +120,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { return Object.freeze(result); } - protected toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): WorkspaceConfigurationChangeEvent { + private toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent { const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides); const changedConfigurationByResource: StrictResourceMap = new StrictResourceMap(); for (const key of Object.keys(data.changedConfigurationByResource)) { @@ -128,7 +128,9 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape { const model = data.changedConfigurationByResource[key]; changedConfigurationByResource.set(resource, new ConfigurationModel(model.contents, model.keys, model.overrides)); } - const event = new ConfigurationChangeEvent(changedConfiguration, changedConfigurationByResource); - return new WorkspaceConfigurationChangeEvent(event, this._extHostWorkspace.workspace); + const event = new WorkspaceConfigurationChangeEvent(new ConfigurationChangeEvent(changedConfiguration, changedConfigurationByResource), this._extHostWorkspace.workspace); + return Object.freeze({ + affectsConfiguration: (section: string, resource?: URI) => event.affectsConfiguration(section, resource) + }); } } diff --git a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts index 098ad1ccde8..1d750b6730c 100644 --- a/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts +++ b/src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts @@ -31,12 +31,16 @@ suite('ExtHostConfiguration', function () { if (!shape) { shape = new class extends mock() { }; } - return new ExtHostConfiguration(shape, new ExtHostWorkspace(new TestThreadService(), null), { + return new ExtHostConfiguration(shape, new ExtHostWorkspace(new TestThreadService(), null), createConfigurationData(contents)); + } + + function createConfigurationData(contents: any) { + return { defaults: new ConfigurationModel(contents), user: new ConfigurationModel(contents), workspace: new ConfigurationModel(), folders: Object.create(null) - }); + }; } test('getConfiguration fails regression test 1.7.1 -> 1.8 #15552', function () { @@ -404,6 +408,74 @@ suite('ExtHostConfiguration', function () { .then(() => assert.ok(false), err => { /* expecting rejection */ }); }); + test('configuration change event', (done) => { + + const workspaceFolder = aWorkspaceFolder(URI.file('folder1'), 0); + const testObject = new ExtHostConfiguration( + new class extends mock() { }, + new ExtHostWorkspace(new TestThreadService(), { + 'id': 'foo', + 'folders': [workspaceFolder], + 'name': 'foo' + }), + createConfigurationData({ + 'farboo': { + 'config': false, + 'updatedconfig': false + } + }) + ); + + const newConfigData = createConfigurationData({ + 'farboo': { + 'config': false, + 'updatedconfig': true, + 'newConfig': true, + } + }); + const changedConfigurationByResource = Object.create({}); + changedConfigurationByResource[workspaceFolder.uri.toString()] = new ConfigurationModel({ + 'farboo': { + 'newConfig': true, + } + }, ['farboo.newConfig']); + const configEventData = { + changedConfiguration: new ConfigurationModel({ + 'farboo': { + 'updatedConfig': true, + } + }, ['farboo.updatedConfig']), + changedConfigurationByResource + }; + testObject.onDidChangeConfiguration(e => { + + assert.deepEqual(testObject.getConfiguration().get('farboo'), { + 'config': false, + 'updatedconfig': true, + 'newConfig': true, + }); + + assert.ok(e.affectsConfiguration('farboo')); + assert.ok(e.affectsConfiguration('farboo', workspaceFolder.uri)); + assert.ok(e.affectsConfiguration('farboo', URI.file('any'))); + + assert.ok(e.affectsConfiguration('farboo.updatedConfig')); + assert.ok(e.affectsConfiguration('farboo.updatedConfig', workspaceFolder.uri)); + assert.ok(e.affectsConfiguration('farboo.updatedConfig', URI.file('any'))); + + assert.ok(e.affectsConfiguration('farboo.newConfig')); + assert.ok(e.affectsConfiguration('farboo.newConfig', workspaceFolder.uri)); + assert.ok(!e.affectsConfiguration('farboo.newConfig', URI.file('any'))); + + assert.ok(!e.affectsConfiguration('farboo.config')); + assert.ok(!e.affectsConfiguration('farboo.config', workspaceFolder.uri)); + assert.ok(!e.affectsConfiguration('farboo.config', URI.file('any'))); + done(); + }); + + testObject.$acceptConfigurationChanged(newConfigData, configEventData); + }); + function aWorkspaceFolder(uri: URI, index: number, name: string = ''): IWorkspaceFolder { return new WorkspaceFolder({ uri, name, index }); }