Skip to content

Commit a10370c

Browse files
committed
Implement #36623
1 parent 178d056 commit a10370c

File tree

7 files changed

+81
-17
lines changed

7 files changed

+81
-17
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,4 +316,9 @@ export function validateProperty(property: string): string {
316316
return nls.localize('config.property.duplicate', "Cannot register '{0}'. This property is already registered.", property);
317317
}
318318
return null;
319+
}
320+
321+
export function getScopes(keys: string[]): ConfigurationScope[] {
322+
const configurationProperties = configurationRegistry.getConfigurationProperties();
323+
return keys.map(key => configurationProperties[key].scope);
319324
}

src/vs/workbench/api/node/extHost.api.impl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ export function createApiFactory(
467467
return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
468468
},
469469
getConfiguration: (section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration => {
470-
return extHostConfiguration.getConfiguration(section, resource);
470+
return extHostConfiguration.getConfiguration(section, resource, extension.id);
471471
},
472472
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
473473
return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider);

src/vs/workbench/api/node/extHost.protocol.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import { SerializedError } from 'vs/base/common/errors';
4949
import { IRelativePattern } from 'vs/base/common/glob';
5050
import { IWorkspaceFolderData } from 'vs/platform/workspace/common/workspace';
5151
import { IStat, IFileChange } from 'vs/platform/files/common/files';
52+
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
5253

5354
export interface IEnvironment {
5455
isExtensionDevelopmentDebug: boolean;
@@ -73,10 +74,14 @@ export interface IInitData {
7374
environment: IEnvironment;
7475
workspace: IWorkspaceData;
7576
extensions: IExtensionDescription[];
76-
configuration: IConfigurationData;
77+
configuration: IConfigurationInitData;
7778
telemetryInfo: ITelemetryInfo;
7879
}
7980

81+
export interface IConfigurationInitData extends IConfigurationData {
82+
configurationScopes: ConfigurationScope[];
83+
}
84+
8085
export interface IWorkspaceConfigurationChangeEventData {
8186
changedConfiguration: IConfigurationModel;
8287
changedConfigurationByResource: { [folder: string]: IConfigurationModel };

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

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,13 @@ import URI from 'vs/base/common/uri';
99
import Event, { Emitter } from 'vs/base/common/event';
1010
import * as vscode from 'vscode';
1111
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
12-
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData } from './extHost.protocol';
12+
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from './extHost.protocol';
1313
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
1414
import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
1515
import { Configuration, ConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
1616
import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
1717
import { StrictResourceMap } from 'vs/base/common/map';
18+
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
1819

1920
function lookUp(tree: any, key: string) {
2021
if (key) {
@@ -40,12 +41,14 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
4041
private readonly _onDidChangeConfiguration = new Emitter<vscode.ConfigurationChangeEvent>();
4142
private readonly _proxy: MainThreadConfigurationShape;
4243
private readonly _extHostWorkspace: ExtHostWorkspace;
44+
private _configurationScopes: Map<string, ConfigurationScope>;
4345
private _configuration: Configuration;
4446

45-
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationData) {
47+
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) {
4648
this._proxy = proxy;
4749
this._extHostWorkspace = extHostWorkspace;
4850
this._configuration = Configuration.parse(data);
51+
this._readConfigurationScopes(data.configurationScopes);
4952
}
5053

5154
get onDidChangeConfiguration(): Event<vscode.ConfigurationChangeEvent> {
@@ -54,14 +57,18 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
5457

5558
$acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) {
5659
this._configuration = Configuration.parse(data);
57-
this._onDidChangeConfiguration.fire(this.toConfigurationChangeEvent(eventData));
60+
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData));
5861
}
5962

60-
getConfiguration(section?: string, resource?: URI): vscode.WorkspaceConfiguration {
63+
getConfiguration(section?: string, resource?: URI, extensionId?: string): vscode.WorkspaceConfiguration {
6164
const config = section
6265
? lookUp(this._configuration.getSection(null, { resource }, this._extHostWorkspace.workspace), section)
6366
: this._configuration.getSection(null, { resource }, this._extHostWorkspace.workspace);
6467

68+
if (section) {
69+
this._validateConfigurationAccess(section, resource, extensionId);
70+
}
71+
6572
function parseConfigurationTarget(arg: boolean | ExtHostConfigurationTarget): ConfigurationTarget {
6673
if (arg === void 0 || arg === null) {
6774
return null;
@@ -81,7 +88,8 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
8188
has(key: string): boolean {
8289
return typeof lookUp(config, key) !== 'undefined';
8390
},
84-
get<T>(key: string, defaultValue?: T): T {
91+
get: <T>(key: string, defaultValue?: T) => {
92+
this._validateConfigurationAccess(section ? `${section}.${key}` : key, resource, extensionId);
8593
let result = lookUp(config, key);
8694
if (typeof result === 'undefined') {
8795
result = defaultValue;
@@ -90,6 +98,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
9098
},
9199
update: (key: string, value: any, arg: ExtHostConfigurationTarget | boolean) => {
92100
key = section ? `${section}.${key}` : key;
101+
this._validateConfigurationAccess(key, resource, extensionId);
93102
const target = parseConfigurationTarget(arg);
94103
if (value !== void 0) {
95104
return this._proxy.$updateConfigurationOption(target, key, value, resource);
@@ -120,7 +129,36 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
120129
return <vscode.WorkspaceConfiguration>Object.freeze(result);
121130
}
122131

123-
private toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent {
132+
private _validateConfigurationAccess(key: string, resource: URI, extensionId: string): void {
133+
const scope = this._configurationScopes.get(key);
134+
const extensionIdText = extensionId ? `[${extensionId}] ` : '';
135+
if (ConfigurationScope.RESOURCE === scope) {
136+
if (!resource) {
137+
console.warn(`${extensionIdText}Accessing a resource scoped configuration without providing a resource is not expected. To get the effective value for '${key}', provide the resource for which the value is needed. If you would like to look up all values, use 'inspect' method instead.`);
138+
}
139+
return;
140+
}
141+
if (ConfigurationScope.WINDOW === scope) {
142+
if (resource) {
143+
console.warn(`${extensionIdText}Accessing a window scoped configuration for a resource is not expected. To associate '${key}' to a resource, define its scope to 'resource' in configuration contributions in 'package.json'.`);
144+
}
145+
return;
146+
}
147+
}
148+
149+
private _readConfigurationScopes(scopes: ConfigurationScope[]): void {
150+
this._configurationScopes = new Map<string, ConfigurationScope>();
151+
if (scopes.length) {
152+
const defaultKeys = this._configuration.keys(this._extHostWorkspace.workspace).default;
153+
if (defaultKeys.length === scopes.length) {
154+
for (let i = 0; i < defaultKeys.length; i++) {
155+
this._configurationScopes.set(defaultKeys[i], scopes[i]);
156+
}
157+
}
158+
}
159+
}
160+
161+
private _toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent {
124162
const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides);
125163
const changedConfigurationByResource: StrictResourceMap<ConfigurationModel> = new StrictResourceMap<ConfigurationModel>();
126164
for (const key of Object.keys(data.changedConfigurationByResource)) {

src/vs/workbench/parts/preferences/browser/preferencesRenderers.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDeco
3333
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
3434
import { MarkdownString } from 'vs/base/common/htmlContent';
3535
import { overrideIdentifierFromKey, IConfigurationService, ConfigurationTarget, IConfigurationChangeEvent } from 'vs/platform/configuration/common/configuration';
36+
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
3637

3738
export interface IPreferencesRenderer<T> extends IDisposable {
3839
preferencesModel: IPreferencesEditorModel<T>;
@@ -1150,6 +1151,7 @@ class UnsupportedWorkbenchSettingsRenderer extends Disposable {
11501151

11511152
constructor(private editor: editorCommon.ICommonCodeEditor, private workspaceSettingsEditorModel: SettingsEditorModel,
11521153
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
1154+
@IEnvironmentService private environmentService: IEnvironmentService
11531155
) {
11541156
super();
11551157
this._register(this.editor.getModel().onDidChangeContent(() => this.renderingDelayer.trigger(() => this.render())));
@@ -1182,10 +1184,17 @@ class UnsupportedWorkbenchSettingsRenderer extends Disposable {
11821184
hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSetting', "This setting cannot be applied now. It will be applied when you open this folder directly."))
11831185
});
11841186

1187+
private static _DIM_CONFIGUARATION_DEV_MODE = ModelDecorationOptions.register({
1188+
stickiness: editorCommon.TrackedRangeStickiness.NeverGrowsWhenTypingAtEdges,
1189+
inlineClassName: 'dim-configuration',
1190+
beforeContentClassName: 'unsupportedWorkbenhSettingInfo',
1191+
hoverMessage: new MarkdownString().appendText(nls.localize('unsupportedWorkbenchSettingDevMode', "This setting cannot be applied now. It will be applied if you change its scope to 'resource' scope or when you open this folder directly."))
1192+
});
1193+
11851194
private createDecoration(range: IRange, model: editorCommon.IModel): editorCommon.IModelDeltaDecoration {
11861195
return {
11871196
range,
1188-
options: UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_
1197+
options: !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment ? UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_DEV_MODE : UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_
11891198
};
11901199
}
11911200

src/vs/workbench/services/extensions/electron-browser/extensionHost.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import { generateRandomPipeName, Protocol } from 'vs/base/parts/ipc/node/ipc.net
2727
import { createServer, Server, Socket } from 'net';
2828
import Event, { Emitter, debounceEvent, mapEvent, anyEvent } from 'vs/base/common/event';
2929
import { fromEventEmitter } from 'vs/base/node/event';
30-
import { IInitData, IWorkspaceData } from 'vs/workbench/api/node/extHost.protocol';
30+
import { IInitData, IWorkspaceData, IConfigurationInitData } from 'vs/workbench/api/node/extHost.protocol';
3131
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
3232
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
3333
import { ICrashReporterService } from 'vs/workbench/services/crashReporter/common/crashReporterService';
@@ -36,6 +36,7 @@ import { isEqual } from 'vs/base/common/paths';
3636
import { EXTENSION_CLOSE_EXTHOST_BROADCAST_CHANNEL, EXTENSION_RELOAD_BROADCAST_CHANNEL, EXTENSION_ATTACH_BROADCAST_CHANNEL, EXTENSION_LOG_BROADCAST_CHANNEL, EXTENSION_TERMINATE_BROADCAST_CHANNEL } from 'vs/platform/extensions/common/extensionHost';
3737
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
3838
import { IRemoteConsoleLog, log, parse } from 'vs/base/node/console';
39+
import { getScopes } from 'vs/platform/configuration/common/configurationRegistry';
3940

4041
export class ExtensionHostProcessWorker {
4142

@@ -344,6 +345,7 @@ export class ExtensionHostProcessWorker {
344345

345346
private _createExtHostInitData(): TPromise<IInitData> {
346347
return TPromise.join<any>([this._telemetryService.getTelemetryInfo(), this._extensionService.getExtensions()]).then(([telemetryInfo, extensionDescriptions]) => {
348+
const configurationData: IConfigurationInitData = { ...this._configurationService.getConfigurationData(), configurationScopes: [] };
347349
const r: IInitData = {
348350
parentPid: process.pid,
349351
environment: {
@@ -360,7 +362,8 @@ export class ExtensionHostProcessWorker {
360362
},
361363
workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : <IWorkspaceData>this._contextService.getWorkspace(),
362364
extensions: extensionDescriptions,
363-
configuration: this._configurationService.getConfigurationData(),
365+
// Send configurations scopes only in development mode.
366+
configuration: !this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment ? { ...configurationData, configurationScopes: getScopes(this._configurationService.keys().default) } : configurationData,
364367
telemetryInfo
365368
};
366369
return r;

src/vs/workbench/test/electron-browser/api/extHostConfiguration.test.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as assert from 'assert';
99
import URI from 'vs/base/common/uri';
1010
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
1111
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
12-
import { MainThreadConfigurationShape } from 'vs/workbench/api/node/extHost.protocol';
12+
import { MainThreadConfigurationShape, IConfigurationInitData } from 'vs/workbench/api/node/extHost.protocol';
1313
import { TPromise } from 'vs/base/common/winjs.base';
1414
import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
1515
import { TestThreadService } from './testThreadService';
@@ -34,12 +34,13 @@ suite('ExtHostConfiguration', function () {
3434
return new ExtHostConfiguration(shape, new ExtHostWorkspace(new TestThreadService(), null), createConfigurationData(contents));
3535
}
3636

37-
function createConfigurationData(contents: any) {
37+
function createConfigurationData(contents: any): IConfigurationInitData {
3838
return {
3939
defaults: new ConfigurationModel(contents),
4040
user: new ConfigurationModel(contents),
4141
workspace: new ConfigurationModel(),
42-
folders: Object.create(null)
42+
folders: Object.create(null),
43+
configurationScopes: []
4344
};
4445
}
4546

@@ -106,7 +107,8 @@ suite('ExtHostConfiguration', function () {
106107
}
107108
}, ['editor.wordWrap']),
108109
workspace: new ConfigurationModel({}, []),
109-
folders: Object.create(null)
110+
folders: Object.create(null),
111+
configurationScopes: []
110112
}
111113
);
112114

@@ -151,7 +153,8 @@ suite('ExtHostConfiguration', function () {
151153
}
152154
}, ['editor.wordWrap']),
153155
workspace,
154-
folders
156+
folders,
157+
configurationScopes: []
155158
}
156159
);
157160

@@ -224,7 +227,8 @@ suite('ExtHostConfiguration', function () {
224227
}
225228
}, ['editor.wordWrap']),
226229
workspace,
227-
folders
230+
folders,
231+
configurationScopes: []
228232
}
229233
);
230234

0 commit comments

Comments
 (0)