Implement #36623
This commit is contained in:
parent
178d05621f
commit
a10370cb9f
7 changed files with 81 additions and 17 deletions
|
@ -316,4 +316,9 @@ export function validateProperty(property: string): string {
|
|||
return nls.localize('config.property.duplicate', "Cannot register '{0}'. This property is already registered.", property);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getScopes(keys: string[]): ConfigurationScope[] {
|
||||
const configurationProperties = configurationRegistry.getConfigurationProperties();
|
||||
return keys.map(key => configurationProperties[key].scope);
|
||||
}
|
|
@ -467,7 +467,7 @@ export function createApiFactory(
|
|||
return extHostConfiguration.onDidChangeConfiguration(listener, thisArgs, disposables);
|
||||
},
|
||||
getConfiguration: (section?: string, resource?: vscode.Uri): vscode.WorkspaceConfiguration => {
|
||||
return extHostConfiguration.getConfiguration(section, resource);
|
||||
return extHostConfiguration.getConfiguration(section, resource, extension.id);
|
||||
},
|
||||
registerTextDocumentContentProvider(scheme: string, provider: vscode.TextDocumentContentProvider) {
|
||||
return extHostDocumentContentProviders.registerTextDocumentContentProvider(scheme, provider);
|
||||
|
|
|
@ -49,6 +49,7 @@ import { SerializedError } from 'vs/base/common/errors';
|
|||
import { IRelativePattern } from 'vs/base/common/glob';
|
||||
import { IWorkspaceFolderData } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStat, IFileChange } from 'vs/platform/files/common/files';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
|
||||
export interface IEnvironment {
|
||||
isExtensionDevelopmentDebug: boolean;
|
||||
|
@ -73,10 +74,14 @@ export interface IInitData {
|
|||
environment: IEnvironment;
|
||||
workspace: IWorkspaceData;
|
||||
extensions: IExtensionDescription[];
|
||||
configuration: IConfigurationData;
|
||||
configuration: IConfigurationInitData;
|
||||
telemetryInfo: ITelemetryInfo;
|
||||
}
|
||||
|
||||
export interface IConfigurationInitData extends IConfigurationData {
|
||||
configurationScopes: ConfigurationScope[];
|
||||
}
|
||||
|
||||
export interface IWorkspaceConfigurationChangeEventData {
|
||||
changedConfiguration: IConfigurationModel;
|
||||
changedConfigurationByResource: { [folder: string]: IConfigurationModel };
|
||||
|
|
|
@ -9,12 +9,13 @@ import URI from 'vs/base/common/uri';
|
|||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
import * as vscode from 'vscode';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData } from './extHost.protocol';
|
||||
import { ExtHostConfigurationShape, MainThreadConfigurationShape, IWorkspaceConfigurationChangeEventData, IConfigurationInitData } from './extHost.protocol';
|
||||
import { ConfigurationTarget as ExtHostConfigurationTarget } from './extHostTypes';
|
||||
import { IConfigurationData, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { Configuration, ConfigurationModel, ConfigurationChangeEvent } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { WorkspaceConfigurationChangeEvent } from 'vs/workbench/services/configuration/common/configurationModels';
|
||||
import { StrictResourceMap } from 'vs/base/common/map';
|
||||
import { ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
|
||||
function lookUp(tree: any, key: string) {
|
||||
if (key) {
|
||||
|
@ -40,12 +41,14 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
|||
private readonly _onDidChangeConfiguration = new Emitter<vscode.ConfigurationChangeEvent>();
|
||||
private readonly _proxy: MainThreadConfigurationShape;
|
||||
private readonly _extHostWorkspace: ExtHostWorkspace;
|
||||
private _configurationScopes: Map<string, ConfigurationScope>;
|
||||
private _configuration: Configuration;
|
||||
|
||||
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationData) {
|
||||
constructor(proxy: MainThreadConfigurationShape, extHostWorkspace: ExtHostWorkspace, data: IConfigurationInitData) {
|
||||
this._proxy = proxy;
|
||||
this._extHostWorkspace = extHostWorkspace;
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._readConfigurationScopes(data.configurationScopes);
|
||||
}
|
||||
|
||||
get onDidChangeConfiguration(): Event<vscode.ConfigurationChangeEvent> {
|
||||
|
@ -54,14 +57,18 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
|||
|
||||
$acceptConfigurationChanged(data: IConfigurationData, eventData: IWorkspaceConfigurationChangeEventData) {
|
||||
this._configuration = Configuration.parse(data);
|
||||
this._onDidChangeConfiguration.fire(this.toConfigurationChangeEvent(eventData));
|
||||
this._onDidChangeConfiguration.fire(this._toConfigurationChangeEvent(eventData));
|
||||
}
|
||||
|
||||
getConfiguration(section?: string, resource?: URI): vscode.WorkspaceConfiguration {
|
||||
getConfiguration(section?: string, resource?: URI, extensionId?: string): vscode.WorkspaceConfiguration {
|
||||
const config = section
|
||||
? lookUp(this._configuration.getSection(null, { resource }, this._extHostWorkspace.workspace), section)
|
||||
: this._configuration.getSection(null, { resource }, this._extHostWorkspace.workspace);
|
||||
|
||||
if (section) {
|
||||
this._validateConfigurationAccess(section, resource, extensionId);
|
||||
}
|
||||
|
||||
function parseConfigurationTarget(arg: boolean | ExtHostConfigurationTarget): ConfigurationTarget {
|
||||
if (arg === void 0 || arg === null) {
|
||||
return null;
|
||||
|
@ -81,7 +88,8 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
|||
has(key: string): boolean {
|
||||
return typeof lookUp(config, key) !== 'undefined';
|
||||
},
|
||||
get<T>(key: string, defaultValue?: T): T {
|
||||
get: <T>(key: string, defaultValue?: T) => {
|
||||
this._validateConfigurationAccess(section ? `${section}.${key}` : key, resource, extensionId);
|
||||
let result = lookUp(config, key);
|
||||
if (typeof result === 'undefined') {
|
||||
result = defaultValue;
|
||||
|
@ -90,6 +98,7 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
|||
},
|
||||
update: (key: string, value: any, arg: ExtHostConfigurationTarget | boolean) => {
|
||||
key = section ? `${section}.${key}` : key;
|
||||
this._validateConfigurationAccess(key, resource, extensionId);
|
||||
const target = parseConfigurationTarget(arg);
|
||||
if (value !== void 0) {
|
||||
return this._proxy.$updateConfigurationOption(target, key, value, resource);
|
||||
|
@ -120,7 +129,36 @@ export class ExtHostConfiguration implements ExtHostConfigurationShape {
|
|||
return <vscode.WorkspaceConfiguration>Object.freeze(result);
|
||||
}
|
||||
|
||||
private toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent {
|
||||
private _validateConfigurationAccess(key: string, resource: URI, extensionId: string): void {
|
||||
const scope = this._configurationScopes.get(key);
|
||||
const extensionIdText = extensionId ? `[${extensionId}] ` : '';
|
||||
if (ConfigurationScope.RESOURCE === scope) {
|
||||
if (!resource) {
|
||||
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.`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ConfigurationScope.WINDOW === scope) {
|
||||
if (resource) {
|
||||
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'.`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private _readConfigurationScopes(scopes: ConfigurationScope[]): void {
|
||||
this._configurationScopes = new Map<string, ConfigurationScope>();
|
||||
if (scopes.length) {
|
||||
const defaultKeys = this._configuration.keys(this._extHostWorkspace.workspace).default;
|
||||
if (defaultKeys.length === scopes.length) {
|
||||
for (let i = 0; i < defaultKeys.length; i++) {
|
||||
this._configurationScopes.set(defaultKeys[i], scopes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private _toConfigurationChangeEvent(data: IWorkspaceConfigurationChangeEventData): vscode.ConfigurationChangeEvent {
|
||||
const changedConfiguration = new ConfigurationModel(data.changedConfiguration.contents, data.changedConfiguration.keys, data.changedConfiguration.overrides);
|
||||
const changedConfigurationByResource: StrictResourceMap<ConfigurationModel> = new StrictResourceMap<ConfigurationModel>();
|
||||
for (const key of Object.keys(data.changedConfigurationByResource)) {
|
||||
|
|
|
@ -33,6 +33,7 @@ import { ModelDecorationOptions } from 'vs/editor/common/model/textModelWithDeco
|
|||
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 { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
|
||||
export interface IPreferencesRenderer<T> extends IDisposable {
|
||||
preferencesModel: IPreferencesEditorModel<T>;
|
||||
|
@ -1150,6 +1151,7 @@ class UnsupportedWorkbenchSettingsRenderer extends Disposable {
|
|||
|
||||
constructor(private editor: editorCommon.ICommonCodeEditor, private workspaceSettingsEditorModel: SettingsEditorModel,
|
||||
@IWorkspaceConfigurationService private configurationService: IWorkspaceConfigurationService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService
|
||||
) {
|
||||
super();
|
||||
this._register(this.editor.getModel().onDidChangeContent(() => this.renderingDelayer.trigger(() => this.render())));
|
||||
|
@ -1182,10 +1184,17 @@ class UnsupportedWorkbenchSettingsRenderer extends Disposable {
|
|||
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 change its scope to 'resource' scope or when you open this folder directly."))
|
||||
});
|
||||
|
||||
private createDecoration(range: IRange, model: editorCommon.IModel): editorCommon.IModelDeltaDecoration {
|
||||
return {
|
||||
range,
|
||||
options: UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_
|
||||
options: !this.environmentService.isBuilt || this.environmentService.isExtensionDevelopment ? UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_DEV_MODE : UnsupportedWorkbenchSettingsRenderer._DIM_CONFIGUARATION_
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import { generateRandomPipeName, Protocol } from 'vs/base/parts/ipc/node/ipc.net
|
|||
import { createServer, Server, Socket } from 'net';
|
||||
import Event, { Emitter, debounceEvent, mapEvent, anyEvent } from 'vs/base/common/event';
|
||||
import { fromEventEmitter } from 'vs/base/node/event';
|
||||
import { IInitData, IWorkspaceData } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { IInitData, IWorkspaceData, IConfigurationInitData } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { IExtensionService } from 'vs/platform/extensions/common/extensions';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { ICrashReporterService } from 'vs/workbench/services/crashReporter/common/crashReporterService';
|
||||
|
@ -36,6 +36,7 @@ import { isEqual } from 'vs/base/common/paths';
|
|||
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';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { IRemoteConsoleLog, log, parse } from 'vs/base/node/console';
|
||||
import { getScopes } from 'vs/platform/configuration/common/configurationRegistry';
|
||||
|
||||
export class ExtensionHostProcessWorker {
|
||||
|
||||
|
@ -344,6 +345,7 @@ export class ExtensionHostProcessWorker {
|
|||
|
||||
private _createExtHostInitData(): TPromise<IInitData> {
|
||||
return TPromise.join<any>([this._telemetryService.getTelemetryInfo(), this._extensionService.getExtensions()]).then(([telemetryInfo, extensionDescriptions]) => {
|
||||
const configurationData: IConfigurationInitData = { ...this._configurationService.getConfigurationData(), configurationScopes: [] };
|
||||
const r: IInitData = {
|
||||
parentPid: process.pid,
|
||||
environment: {
|
||||
|
@ -360,7 +362,8 @@ export class ExtensionHostProcessWorker {
|
|||
},
|
||||
workspace: this._contextService.getWorkbenchState() === WorkbenchState.EMPTY ? null : <IWorkspaceData>this._contextService.getWorkspace(),
|
||||
extensions: extensionDescriptions,
|
||||
configuration: this._configurationService.getConfigurationData(),
|
||||
// Send configurations scopes only in development mode.
|
||||
configuration: !this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment ? { ...configurationData, configurationScopes: getScopes(this._configurationService.keys().default) } : configurationData,
|
||||
telemetryInfo
|
||||
};
|
||||
return r;
|
||||
|
|
|
@ -9,7 +9,7 @@ import * as assert from 'assert';
|
|||
import URI from 'vs/base/common/uri';
|
||||
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
|
||||
import { ExtHostConfiguration } from 'vs/workbench/api/node/extHostConfiguration';
|
||||
import { MainThreadConfigurationShape } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { MainThreadConfigurationShape, IConfigurationInitData } from 'vs/workbench/api/node/extHost.protocol';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { ConfigurationModel } from 'vs/platform/configuration/common/configurationModels';
|
||||
import { TestThreadService } from './testThreadService';
|
||||
|
@ -34,12 +34,13 @@ suite('ExtHostConfiguration', function () {
|
|||
return new ExtHostConfiguration(shape, new ExtHostWorkspace(new TestThreadService(), null), createConfigurationData(contents));
|
||||
}
|
||||
|
||||
function createConfigurationData(contents: any) {
|
||||
function createConfigurationData(contents: any): IConfigurationInitData {
|
||||
return {
|
||||
defaults: new ConfigurationModel(contents),
|
||||
user: new ConfigurationModel(contents),
|
||||
workspace: new ConfigurationModel(),
|
||||
folders: Object.create(null)
|
||||
folders: Object.create(null),
|
||||
configurationScopes: []
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -106,7 +107,8 @@ suite('ExtHostConfiguration', function () {
|
|||
}
|
||||
}, ['editor.wordWrap']),
|
||||
workspace: new ConfigurationModel({}, []),
|
||||
folders: Object.create(null)
|
||||
folders: Object.create(null),
|
||||
configurationScopes: []
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -151,7 +153,8 @@ suite('ExtHostConfiguration', function () {
|
|||
}
|
||||
}, ['editor.wordWrap']),
|
||||
workspace,
|
||||
folders
|
||||
folders,
|
||||
configurationScopes: []
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -224,7 +227,8 @@ suite('ExtHostConfiguration', function () {
|
|||
}
|
||||
}, ['editor.wordWrap']),
|
||||
workspace,
|
||||
folders
|
||||
folders,
|
||||
configurationScopes: []
|
||||
}
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue