config has value tree and full tree, fixes #15552

This commit is contained in:
Johannes Rieken
2016-11-18 11:23:04 +01:00
parent 14b2e71224
commit e87ab932b6
6 changed files with 114 additions and 123 deletions

View File

@@ -9,48 +9,93 @@ import Event, { Emitter } from 'vs/base/common/event';
import { WorkspaceConfiguration } from 'vscode';
import { ExtHostConfigurationShape, MainThreadConfigurationShape } from './extHost.protocol';
import { ConfigurationTarget } from 'vs/workbench/services/configuration/common/configurationEditing';
import { WorkspaceConfigurationNode, IWorkspaceConfigurationValue } from 'vs/workbench/services/configuration/common/configuration';
import { IWorkspaceConfiguration } from 'vs/workbench/services/configuration/common/configuration';
function lookUp(tree: any, key: string) {
if (key) {
const parts = key.split('.');
let node = tree;
for (let i = 0; node && i < parts.length; i++) {
node = node[parts[i]];
}
return node;
}
}
function insert(tree: any, key: string, value: any) {
const parts = key.split('.');
let node = tree;
let i: number;
let to = parts.length - 1;
for (i = 0; i < to; i++) {
let child = node[parts[i]];
if (child) {
node = child;
} else {
break;
}
}
for (; i < to; i++) {
node = node[parts[i]] = Object.create(null);
}
node[parts[to]] = value;
}
interface UsefulConfiguration {
data: IWorkspaceConfiguration;
valueTree: any;
}
function createUsefulConfiguration(data: IWorkspaceConfiguration): { data: IWorkspaceConfiguration, valueTree: any } {
const valueTree = Object.create(null);
for (let key in data) {
if (Object.prototype.hasOwnProperty.call(data, key)) {
insert(valueTree, key, data[key].value);
}
}
return {
data,
valueTree
};
}
export class ExtHostConfiguration extends ExtHostConfigurationShape {
private _proxy: MainThreadConfigurationShape;
private _config: WorkspaceConfigurationNode;
private _onDidChangeConfiguration = new Emitter<void>();
private _proxy: MainThreadConfigurationShape;
private _configuration: UsefulConfiguration;
constructor(proxy: MainThreadConfigurationShape, config: WorkspaceConfigurationNode) {
constructor(proxy: MainThreadConfigurationShape, data: IWorkspaceConfiguration) {
super();
this._proxy = proxy;
this._config = config;
this._configuration = createUsefulConfiguration(data);
}
get onDidChangeConfiguration(): Event<void> {
return this._onDidChangeConfiguration && this._onDidChangeConfiguration.event;
}
public $acceptConfigurationChanged(config: WorkspaceConfigurationNode) {
this._config = config;
public $acceptConfigurationChanged(data: IWorkspaceConfiguration) {
this._configuration = createUsefulConfiguration(data);
this._onDidChangeConfiguration.fire(undefined);
}
public getConfiguration(section?: string): WorkspaceConfiguration {
const config = section
? ExtHostConfiguration._lookUp(section, this._config)
: this._config;
? lookUp(this._configuration.valueTree, section)
: this._configuration.valueTree;
const result: WorkspaceConfiguration = {
has(key: string): boolean {
return typeof ExtHostConfiguration._lookUp(key, <WorkspaceConfigurationNode>config) !== 'undefined';
return typeof lookUp(config, key) !== 'undefined';
},
get<T>(key: string, defaultValue?: T): any {
let result = ExtHostConfiguration._lookUp(key, <WorkspaceConfigurationNode>config);
get<T>(key: string, defaultValue?: T): T {
let result = lookUp(config, key);
if (typeof result === 'undefined') {
return defaultValue;
} else if (isConfigurationValue(result)) {
return result.value;
} else {
return ExtHostConfiguration._values(result);
result = defaultValue;
}
return result;
},
update: (key: string, value: any, global: boolean = false) => {
key = section ? `${section}.${key}` : key;
@@ -61,65 +106,24 @@ export class ExtHostConfiguration extends ExtHostConfigurationShape {
return this._proxy.$removeConfigurationOption(target, key);
}
},
inspect(key: string) {
let result = ExtHostConfiguration._lookUp(key, <WorkspaceConfigurationNode>config);
if (isConfigurationValue(result)) {
inspect: <T>(key: string): { key: string; defaultValue?: T; globalValue?: T; workspaceValue?: T } => {
key = section ? `${section}.${key}` : key;
const config = this._configuration.data[key];
if (config) {
return {
key: section ? `${section}.${key}` : key,
defaultValue: result.default,
globalValue: result.user,
workspaceValue: result.workspace
key,
defaultValue: config.default,
globalValue: config.user,
workspaceValue: config.workspace
};
}
}
};
if (!isConfigurationValue(config)) {
mixin(result, ExtHostConfiguration._values(config), false);
if (typeof config === 'object') {
mixin(result, config, false);
}
return Object.freeze(result);
}
private static _lookUp(section: string, config: WorkspaceConfigurationNode): WorkspaceConfigurationNode | IWorkspaceConfigurationValue<any> {
if (!section) {
return;
}
let parts = section.split('.');
let node = config;
while (node && parts.length) {
let child = node[parts.shift()];
if (isConfigurationValue(child)) {
return child;
} else {
node = child;
}
}
return node;
}
private static _values(node: WorkspaceConfigurationNode): any {
let target = Object.create(null);
for (let key in node) {
let child = node[key];
if (isConfigurationValue(child)) {
target[key] = child.value;
} else {
target[key] = ExtHostConfiguration._values(child);
}
}
return target;
}
}
function isConfigurationValue(thing: any): thing is IWorkspaceConfigurationValue<any> {
return typeof thing === 'object'
// must have 'value'
&& typeof (<IWorkspaceConfigurationValue<any>>thing).value !== 'undefined'
// and at least one source 'default', 'user', or 'workspace'
&& (typeof (<IWorkspaceConfigurationValue<any>>thing).default !== 'undefined'
|| typeof (<IWorkspaceConfigurationValue<any>>thing).user !== 'undefined'
|| typeof (<IWorkspaceConfigurationValue<any>>thing).workspace !== 'undefined');
}