SQL Operations Studio Public Preview 1 (0.23) release source code

This commit is contained in:
Karl Burtram
2017-11-09 14:30:27 -08:00
parent b88ecb8d93
commit 3cdac41339
8829 changed files with 759707 additions and 286 deletions

View File

@@ -0,0 +1,384 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TPromise } from 'vs/base/common/winjs.base';
import * as arrays from 'vs/base/common/arrays';
import * as types from 'vs/base/common/types';
import * as objects from 'vs/base/common/objects';
import URI from 'vs/base/common/uri';
import { StrictResourceMap } from 'vs/base/common/map';
import { Workspace } from 'vs/platform/workspace/common/workspace';
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import Event from 'vs/base/common/event';
export const IConfigurationService = createDecorator<IConfigurationService>('configurationService');
export interface IConfigurationOverrides {
overrideIdentifier?: string;
resource?: URI;
}
export type IConfigurationValues = { [key: string]: IConfigurationValue<any> };
export interface IConfigurationService {
_serviceBrand: any;
getConfigurationData<T>(): IConfigurationData<T>;
/**
* Fetches the appropriate section of the configuration JSON file.
* This will be an object keyed off the section name.
*/
getConfiguration<T>(section?: string, overrides?: IConfigurationOverrides): T;
/**
* Resolves a configuration key to its values in the different scopes
* the setting is defined.
*/
lookup<T>(key: string, overrides?: IConfigurationOverrides): IConfigurationValue<T>;
/**
* Returns the defined keys of configurations in the different scopes
* the key is defined.
*/
keys(overrides?: IConfigurationOverrides): IConfigurationKeys;
/**
* Similar to #getConfiguration() but ensures that the latest configuration
* from disk is fetched.
*/
reloadConfiguration<T>(section?: string): TPromise<T>;
/**
* Event that fires when the configuration changes.
*/
onDidUpdateConfiguration: Event<IConfigurationServiceEvent>;
/**
* Returns the defined values of configurations in the different scopes.
*/
values(): IConfigurationValues;
}
export enum ConfigurationSource {
Default = 1,
User,
Workspace
}
export interface IConfigurationServiceEvent {
/**
* The type of source that triggered this event.
*/
source: ConfigurationSource;
/**
* The part of the configuration contributed by the source of this event.
*/
sourceConfig: any;
}
export interface IConfigurationValue<T> {
value: T;
default: T;
user: T;
workspace: T;
folder: T;
}
export interface IConfigurationKeys {
default: string[];
user: string[];
workspace: string[];
folder: string[];
}
/**
* A helper function to get the configuration value with a specific settings path (e.g. config.some.setting)
*/
export function getConfigurationValue<T>(config: any, settingPath: string, defaultValue?: T): T {
function accessSetting(config: any, path: string[]): any {
let current = config;
for (let i = 0; i < path.length; i++) {
if (typeof current !== 'object' || current === null) {
return undefined;
}
current = current[path[i]];
}
return <T>current;
}
const path = settingPath.split('.');
const result = accessSetting(config, path);
return typeof result === 'undefined' ? defaultValue : result;
}
export function merge(base: any, add: any, overwrite: boolean): void {
Object.keys(add).forEach(key => {
if (key in base) {
if (types.isObject(base[key]) && types.isObject(add[key])) {
merge(base[key], add[key], overwrite);
} else if (overwrite) {
base[key] = add[key];
}
} else {
base[key] = add[key];
}
});
}
export interface IConfiguraionModel<T> {
contents: T;
keys: string[];
overrides: IOverrides<T>[];
}
export interface IOverrides<T> {
contents: T;
identifiers: string[];
}
export class ConfigurationModel<T> implements IConfiguraionModel<T> {
constructor(protected _contents: T = <T>{}, protected _keys: string[] = [], protected _overrides: IOverrides<T>[] = []) {
}
public get contents(): T {
return this._contents;
}
public get overrides(): IOverrides<T>[] {
return this._overrides;
}
public get keys(): string[] {
return this._keys;
}
public getContentsFor<V>(section: string): V {
return objects.clone(this.contents[section]);
}
public override<V>(identifier: string): ConfigurationModel<V> {
const result = new ConfigurationModel<V>();
const contents = objects.clone<any>(this.contents);
if (this._overrides) {
for (const override of this._overrides) {
if (override.identifiers.indexOf(identifier) !== -1) {
merge(contents, override.contents, true);
}
}
}
result._contents = contents;
return result;
}
public merge(other: ConfigurationModel<T>, overwrite: boolean = true): ConfigurationModel<T> {
const mergedModel = new ConfigurationModel<T>();
this.doMerge(mergedModel, this, overwrite);
this.doMerge(mergedModel, other, overwrite);
return mergedModel;
}
protected doMerge(source: ConfigurationModel<T>, target: ConfigurationModel<T>, overwrite: boolean = true) {
merge(source.contents, objects.clone(target.contents), overwrite);
const overrides = objects.clone(source._overrides);
for (const override of target._overrides) {
const [sourceOverride] = overrides.filter(o => arrays.equals(o.identifiers, override.identifiers));
if (sourceOverride) {
merge(sourceOverride.contents, override.contents, overwrite);
} else {
overrides.push(override);
}
}
source._overrides = overrides;
}
}
export interface IConfigurationData<T> {
defaults: IConfiguraionModel<T>;
user: IConfiguraionModel<T>;
workspace: IConfiguraionModel<T>;
folders: { [folder: string]: IConfiguraionModel<T> };
}
export class Configuration<T> {
private _globalConfiguration: ConfigurationModel<T>;
private _workspaceConsolidatedConfiguration: ConfigurationModel<T>;
private _legacyWorkspaceConsolidatedConfiguration: ConfigurationModel<T>;
protected _foldersConsolidatedConfigurations: StrictResourceMap<ConfigurationModel<T>>;
constructor(protected _defaults: ConfigurationModel<T>, protected _user: ConfigurationModel<T>, protected _workspaceConfiguration: ConfigurationModel<T> = new ConfigurationModel<T>(), protected folders: StrictResourceMap<ConfigurationModel<T>> = new StrictResourceMap<ConfigurationModel<T>>(), protected _workspace?: Workspace) {
this.merge();
}
get defaults(): ConfigurationModel<T> {
return this._defaults;
}
get user(): ConfigurationModel<T> {
return this._user;
}
protected merge(): void {
this._globalConfiguration = new ConfigurationModel<T>().merge(this._defaults).merge(this._user);
this._workspaceConsolidatedConfiguration = new ConfigurationModel<T>().merge(this._globalConfiguration).merge(this._workspaceConfiguration);
this._legacyWorkspaceConsolidatedConfiguration = null;
this._foldersConsolidatedConfigurations = new StrictResourceMap<ConfigurationModel<T>>();
for (const folder of this.folders.keys()) {
this.mergeFolder(folder);
}
}
protected mergeFolder(folder: URI) {
this._foldersConsolidatedConfigurations.set(folder, new ConfigurationModel<T>().merge(this._workspaceConsolidatedConfiguration).merge(this.folders.get(folder)));
}
getValue<C>(section: string = '', overrides: IConfigurationOverrides = {}): C {
const configModel = this.getConsolidateConfigurationModel(overrides);
return section ? configModel.getContentsFor<C>(section) : configModel.contents;
}
lookup<C>(key: string, overrides: IConfigurationOverrides = {}): IConfigurationValue<C> {
// make sure to clone the configuration so that the receiver does not tamper with the values
const consolidateConfigurationModel = this.getConsolidateConfigurationModel(overrides);
const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource);
return {
default: objects.clone(getConfigurationValue<C>(overrides.overrideIdentifier ? this._defaults.override(overrides.overrideIdentifier).contents : this._defaults.contents, key)),
user: objects.clone(getConfigurationValue<C>(overrides.overrideIdentifier ? this._user.override(overrides.overrideIdentifier).contents : this._user.contents, key)),
workspace: objects.clone(this._workspace ? getConfigurationValue<C>(overrides.overrideIdentifier ? this._workspaceConfiguration.override(overrides.overrideIdentifier).contents : this._workspaceConfiguration.contents, key) : void 0), //Check on workspace exists or not because _workspaceConfiguration is never null
folder: objects.clone(folderConfigurationModel ? getConfigurationValue<C>(overrides.overrideIdentifier ? folderConfigurationModel.override(overrides.overrideIdentifier).contents : folderConfigurationModel.contents, key) : void 0),
value: objects.clone(getConfigurationValue<C>(consolidateConfigurationModel.contents, key))
};
}
lookupLegacy<C>(key: string): IConfigurationValue<C> {
if (!this._legacyWorkspaceConsolidatedConfiguration) {
this._legacyWorkspaceConsolidatedConfiguration = this._workspace ? new ConfigurationModel<any>().merge(this._workspaceConfiguration).merge(this.folders.get(this._workspace.roots[0])) : null;
}
const consolidateConfigurationModel = this.getConsolidateConfigurationModel({});
return {
default: objects.clone(getConfigurationValue<C>(this._defaults.contents, key)),
user: objects.clone(getConfigurationValue<C>(this._user.contents, key)),
workspace: objects.clone(this._legacyWorkspaceConsolidatedConfiguration ? getConfigurationValue<C>(this._legacyWorkspaceConsolidatedConfiguration.contents, key) : void 0),
folder: void 0,
value: objects.clone(getConfigurationValue<C>(consolidateConfigurationModel.contents, key))
};
}
keys(overrides: IConfigurationOverrides = {}): IConfigurationKeys {
const folderConfigurationModel = this.getFolderConfigurationModelForResource(overrides.resource);
return {
default: this._defaults.keys,
user: this._user.keys,
workspace: this._workspaceConfiguration.keys,
folder: folderConfigurationModel ? folderConfigurationModel.keys : []
};
}
values(): IConfigurationValues {
const result = Object.create(null);
const keyset = this.keys();
const keys = [...keyset.workspace, ...keyset.user, ...keyset.default].sort();
let lastKey: string;
for (const key of keys) {
if (key !== lastKey) {
lastKey = key;
result[key] = this.lookup(key);
}
}
return result;
}
values2(): Map<string, IConfigurationValue<T>> {
const result: Map<string, IConfigurationValue<T>> = new Map<string, IConfigurationValue<T>>();
const keyset = this.keys();
const keys = [...keyset.workspace, ...keyset.user, ...keyset.default].sort();
let lastKey: string;
for (const key of keys) {
if (key !== lastKey) {
lastKey = key;
result.set(key, this.lookup<T>(key));
}
}
return result;
}
private getConsolidateConfigurationModel<C>(overrides: IConfigurationOverrides): ConfigurationModel<any> {
let configurationModel = this.getConsolidatedConfigurationModelForResource(overrides);
return overrides.overrideIdentifier ? configurationModel.override<T>(overrides.overrideIdentifier) : configurationModel;
}
private getConsolidatedConfigurationModelForResource({ resource }: IConfigurationOverrides): ConfigurationModel<any> {
if (!this._workspace) {
return this._globalConfiguration;
}
if (!resource) {
return this._workspaceConsolidatedConfiguration;
}
const root = this._workspace.getRoot(resource);
if (!root) {
return this._workspaceConsolidatedConfiguration;
}
return this._foldersConsolidatedConfigurations.get(root) || this._workspaceConsolidatedConfiguration;
}
private getFolderConfigurationModelForResource(resource: URI): ConfigurationModel<any> {
if (!this._workspace || !resource) {
return null;
}
const root = this._workspace.getRoot(resource);
return root ? this.folders.get(root) : null;
}
public toData(): IConfigurationData<any> {
return {
defaults: {
contents: this._defaults.contents,
overrides: this._defaults.overrides,
keys: this._defaults.keys
},
user: {
contents: this._user.contents,
overrides: this._user.overrides,
keys: this._user.keys
},
workspace: {
contents: this._workspaceConfiguration.contents,
overrides: this._workspaceConfiguration.overrides,
keys: this._workspaceConfiguration.keys
},
folders: this.folders.keys().reduce((result, folder) => {
const { contents, overrides, keys } = this.folders.get(folder);
result[folder.toString()] = { contents, overrides, keys };
return result;
}, Object.create({}))
};
}
public static parse(data: IConfigurationData<any>, workspace: Workspace): Configuration<any> {
const defaultConfiguration = Configuration.parseConfigurationModel(data.defaults);
const userConfiguration = Configuration.parseConfigurationModel(data.user);
const workspaceConfiguration = Configuration.parseConfigurationModel(data.workspace);
const folders: StrictResourceMap<ConfigurationModel<any>> = Object.keys(data.folders).reduce((result, key) => {
result.set(URI.parse(key), Configuration.parseConfigurationModel(data.folders[key]));
return result;
}, new StrictResourceMap<ConfigurationModel<any>>());
return new Configuration<any>(defaultConfiguration, userConfiguration, workspaceConfiguration, folders, workspace);
}
private static parseConfigurationModel(model: IConfiguraionModel<any>): ConfigurationModel<any> {
return new ConfigurationModel(model.contents, model.keys, model.overrides);
}
}

View File

@@ -0,0 +1,313 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import nls = require('vs/nls');
import Event, { Emitter } from 'vs/base/common/event';
import { IJSONSchema } from 'vs/base/common/jsonSchema';
import { Registry } from 'vs/platform/registry/common/platform';
import types = require('vs/base/common/types');
import * as strings from 'vs/base/common/strings';
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
export const Extensions = {
Configuration: 'base.contributions.configuration'
};
export interface IConfigurationRegistry {
/**
* Register a configuration to the registry.
*/
registerConfiguration(configuration: IConfigurationNode): void;
/**
* Register multiple configurations to the registry.
*/
registerConfigurations(configurations: IConfigurationNode[], validate?: boolean): void;
registerDefaultConfigurations(defaultConfigurations: IDefaultConfigurationExtension[]): void;
/**
* Event that fires whenver a configuratio has been
* registered.
*/
onDidRegisterConfiguration: Event<IConfigurationRegistry>;
/**
* Returns all configuration nodes contributed to this registry.
*/
getConfigurations(): IConfigurationNode[];
/**
* Returns all configurations settings of all configuration nodes contributed to this registry.
*/
getConfigurationProperties(): { [qualifiedKey: string]: IConfigurationPropertySchema };
/**
* Register the identifiers for editor configurations
*/
registerOverrideIdentifiers(identifiers: string[]): void;
}
export enum ConfigurationScope {
WINDOW = 1,
RESOURCE
}
export interface IConfigurationPropertySchema extends IJSONSchema {
overridable?: boolean;
isExecutable?: boolean;
scope?: ConfigurationScope;
}
export interface IConfigurationNode {
id?: string;
order?: number;
type?: string | string[];
title?: string;
description?: string;
properties?: { [path: string]: IConfigurationPropertySchema; };
allOf?: IConfigurationNode[];
overridable?: boolean;
scope?: ConfigurationScope;
}
export interface IDefaultConfigurationExtension {
id: string;
name: string;
defaults: { [key: string]: {} };
}
export const schemaId = 'vscode://schemas/settings';
export const editorConfigurationSchemaId = 'vscode://schemas/settings/editor';
export const resourceConfigurationSchemaId = 'vscode://schemas/settings/resource';
const contributionRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
class ConfigurationRegistry implements IConfigurationRegistry {
private configurationContributors: IConfigurationNode[];
private configurationProperties: { [qualifiedKey: string]: IJSONSchema };
private configurationSchema: IJSONSchema;
private editorConfigurationSchema: IJSONSchema;
private resourceConfigurationSchema: IJSONSchema;
private _onDidRegisterConfiguration: Emitter<IConfigurationRegistry>;
private overrideIdentifiers: string[] = [];
private overridePropertyPattern: string;
constructor() {
this.configurationContributors = [];
this.configurationSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown configuration setting' };
this.editorConfigurationSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Unknown editor configuration setting' };
this.resourceConfigurationSchema = { properties: {}, patternProperties: {}, additionalProperties: false, errorMessage: 'Not a resource configuration setting' };
this._onDidRegisterConfiguration = new Emitter<IConfigurationRegistry>();
this.configurationProperties = {};
this.computeOverridePropertyPattern();
contributionRegistry.registerSchema(schemaId, this.configurationSchema);
contributionRegistry.registerSchema(editorConfigurationSchemaId, this.editorConfigurationSchema);
contributionRegistry.registerSchema(resourceConfigurationSchemaId, this.resourceConfigurationSchema);
}
public get onDidRegisterConfiguration() {
return this._onDidRegisterConfiguration.event;
}
public registerConfiguration(configuration: IConfigurationNode, validate: boolean = true): void {
this.registerConfigurations([configuration], validate);
}
public registerConfigurations(configurations: IConfigurationNode[], validate: boolean = true): void {
configurations.forEach(configuration => {
this.validateAndRegisterProperties(configuration, validate); // fills in defaults
this.configurationContributors.push(configuration);
this.registerJSONConfiguration(configuration);
this.updateSchemaForOverrideSettingsConfiguration(configuration);
});
this._onDidRegisterConfiguration.fire(this);
}
public registerOverrideIdentifiers(overrideIdentifiers: string[]): void {
this.overrideIdentifiers.push(...overrideIdentifiers);
this.updateOverridePropertyPatternKey();
}
public registerDefaultConfigurations(defaultConfigurations: IDefaultConfigurationExtension[]): void {
const configurationNode: IConfigurationNode = {
id: 'defaultOverrides',
title: nls.localize('defaultConfigurations.title', "Default Configuration Overrides"),
properties: {}
};
for (const defaultConfiguration of defaultConfigurations) {
for (const key in defaultConfiguration.defaults) {
const defaultValue = defaultConfiguration.defaults[key];
if (OVERRIDE_PROPERTY_PATTERN.test(key) && typeof defaultValue === 'object') {
configurationNode.properties[key] = {
type: 'object',
default: defaultValue,
description: nls.localize('overrideSettings.description', "Configure editor settings to be overridden for {0} language.", key),
$ref: editorConfigurationSchemaId
};
}
}
}
if (Object.keys(configurationNode.properties).length) {
this.registerConfiguration(configurationNode, false);
}
}
private validateAndRegisterProperties(configuration: IConfigurationNode, validate: boolean = true, scope: ConfigurationScope = ConfigurationScope.WINDOW, overridable: boolean = false) {
scope = configuration.scope !== void 0 && configuration.scope !== null ? configuration.scope : scope;
overridable = configuration.overridable || overridable;
let properties = configuration.properties;
if (properties) {
for (let key in properties) {
let message;
if (validate && (message = validateProperty(key))) {
console.warn(message);
delete properties[key];
continue;
}
// fill in default values
let property = properties[key];
let defaultValue = property.default;
if (types.isUndefined(defaultValue)) {
property.default = getDefaultValue(property.type);
}
// Inherit overridable property from parent
if (overridable) {
property.overridable = true;
}
if (property.scope === void 0) {
property.scope = scope;
}
// add to properties map
this.configurationProperties[key] = properties[key];
}
}
let subNodes = configuration.allOf;
if (subNodes) {
for (let node of subNodes) {
this.validateAndRegisterProperties(node, validate, scope, overridable);
}
}
}
validateProperty(property: string): boolean {
return !OVERRIDE_PROPERTY_PATTERN.test(property) && this.getConfigurationProperties()[property] !== void 0;
}
getConfigurations(): IConfigurationNode[] {
return this.configurationContributors;
}
getConfigurationProperties(): { [qualifiedKey: string]: IConfigurationPropertySchema } {
return this.configurationProperties;
}
private registerJSONConfiguration(configuration: IConfigurationNode) {
let configurationSchema = this.configurationSchema;
function register(configuration: IConfigurationNode) {
let properties = configuration.properties;
if (properties) {
for (let key in properties) {
configurationSchema.properties[key] = properties[key];
}
}
let subNodes = configuration.allOf;
if (subNodes) {
subNodes.forEach(register);
}
};
register(configuration);
contributionRegistry.registerSchema(schemaId, configurationSchema);
}
private updateSchemaForOverrideSettingsConfiguration(configuration: IConfigurationNode): void {
if (configuration.id !== SETTINGS_OVERRRIDE_NODE_ID) {
this.update(configuration);
contributionRegistry.registerSchema(editorConfigurationSchemaId, this.editorConfigurationSchema);
contributionRegistry.registerSchema(resourceConfigurationSchemaId, this.resourceConfigurationSchema);
}
}
private updateOverridePropertyPatternKey(): void {
let patternProperties: IJSONSchema = this.configurationSchema.patternProperties[this.overridePropertyPattern];
if (!patternProperties) {
patternProperties = {
type: 'object',
description: nls.localize('overrideSettings.defaultDescription', "Configure editor settings to be overridden for a language."),
errorMessage: 'Unknown Identifier. Use language identifiers',
$ref: editorConfigurationSchemaId
};
}
delete this.configurationSchema.patternProperties[this.overridePropertyPattern];
this.computeOverridePropertyPattern();
this.configurationSchema.patternProperties[this.overridePropertyPattern] = patternProperties;
contributionRegistry.registerSchema(schemaId, this.configurationSchema);
}
private update(configuration: IConfigurationNode): void {
let properties = configuration.properties;
if (properties) {
for (let key in properties) {
if (properties[key].overridable) {
this.editorConfigurationSchema.properties[key] = this.getConfigurationProperties()[key];
}
switch (properties[key].scope) {
case ConfigurationScope.RESOURCE:
this.resourceConfigurationSchema.properties[key] = this.getConfigurationProperties()[key];
break;
}
}
}
let subNodes = configuration.allOf;
if (subNodes) {
subNodes.forEach(subNode => this.update(subNode));
}
}
private computeOverridePropertyPattern(): void {
this.overridePropertyPattern = this.overrideIdentifiers.length ? OVERRIDE_PATTERN_WITH_SUBSTITUTION.replace('${0}', this.overrideIdentifiers.map(identifier => strings.createRegExp(identifier, false).source).join('|')) : OVERRIDE_PROPERTY;
}
}
const SETTINGS_OVERRRIDE_NODE_ID = 'override';
const OVERRIDE_PROPERTY = '\\[.*\\]$';
const OVERRIDE_PATTERN_WITH_SUBSTITUTION = '\\[(${0})\\]$';
export const OVERRIDE_PROPERTY_PATTERN = new RegExp(OVERRIDE_PROPERTY);
function getDefaultValue(type: string | string[]): any {
const t = Array.isArray(type) ? (<string[]>type)[0] : <string>type;
switch (t) {
case 'boolean':
return false;
case 'integer':
case 'number':
return 0;
case 'string':
return '';
case 'array':
return [];
case 'object':
return {};
default:
return null;
}
}
const configurationRegistry = new ConfigurationRegistry();
Registry.add(Extensions.Configuration, configurationRegistry);
export function validateProperty(property: string): string {
if (OVERRIDE_PROPERTY_PATTERN.test(property)) {
return nls.localize('config.property.languageDefault', "Cannot register '{0}'. This matches property pattern '\\\\[.*\\\\]$' for describing language specific editor settings. Use 'configurationDefaults' contribution.", property);
}
if (configurationRegistry.getConfigurationProperties()[property] !== void 0) {
return nls.localize('config.property.duplicate', "Cannot register '{0}'. This property is already registered.", property);
}
return null;
}

View File

@@ -0,0 +1,202 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { Registry } from 'vs/platform/registry/common/platform';
import * as json from 'vs/base/common/json';
import { IConfigurationRegistry, Extensions, OVERRIDE_PROPERTY_PATTERN } from 'vs/platform/configuration/common/configurationRegistry';
import { ConfigurationModel, IOverrides } from 'vs/platform/configuration/common/configuration';
export function getDefaultValues(): any {
const valueTreeRoot: any = Object.create(null);
const properties = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
for (let key in properties) {
let value = properties[key].default;
addToValueTree(valueTreeRoot, key, value, message => console.error(`Conflict in default settings: ${message}`));
}
return valueTreeRoot;
}
export function toValuesTree(properties: { [qualifiedKey: string]: any }, conflictReporter: (message: string) => void): any {
const root = Object.create(null);
for (let key in properties) {
addToValueTree(root, key, properties[key], conflictReporter);
}
return root;
}
function addToValueTree(settingsTreeRoot: any, key: string, value: any, conflictReporter: (message: string) => void): void {
const segments = key.split('.');
const last = segments.pop();
let curr = settingsTreeRoot;
for (let i = 0; i < segments.length; i++) {
let s = segments[i];
let obj = curr[s];
switch (typeof obj) {
case 'undefined':
obj = curr[s] = Object.create(null);
break;
case 'object':
break;
default:
conflictReporter(`Ignoring ${key} as ${segments.slice(0, i + 1).join('.')} is ${JSON.stringify(obj)}`);
return;
}
curr = obj;
};
if (typeof curr === 'object') {
curr[last] = value; // workaround https://github.com/Microsoft/vscode/issues/13606
} else {
conflictReporter(`Ignoring ${key} as ${segments.join('.')} is ${JSON.stringify(curr)}`);
}
}
export function getConfigurationKeys(): string[] {
const properties = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
return Object.keys(properties);
}
export class DefaultConfigurationModel<T> extends ConfigurationModel<T> {
constructor() {
super(getDefaultValues());
this._keys = getConfigurationKeys();
this._overrides = Object.keys(this._contents)
.filter(key => OVERRIDE_PROPERTY_PATTERN.test(key))
.map(key => {
return <IOverrides<any>>{
identifiers: [overrideIdentifierFromKey(key).trim()],
contents: toValuesTree(this._contents[key], message => console.error(`Conflict in default settings file: ${message}`))
};
});
}
public get keys(): string[] {
return this._keys;
}
}
interface Overrides<T> extends IOverrides<T> {
raw: any;
}
export class CustomConfigurationModel<T> extends ConfigurationModel<T> {
protected _parseErrors: any[] = [];
constructor(content: string = '', private name: string = '') {
super();
if (content) {
this.update(content);
}
}
public get errors(): any[] {
return this._parseErrors;
}
public update(content: string): void {
let parsed: T = <T>{};
let overrides: Overrides<T>[] = [];
let currentProperty: string = null;
let currentParent: any = [];
let previousParents: any[] = [];
let parseErrors: json.ParseError[] = [];
function onValue(value: any) {
if (Array.isArray(currentParent)) {
(<any[]>currentParent).push(value);
} else if (currentProperty) {
currentParent[currentProperty] = value;
}
if (OVERRIDE_PROPERTY_PATTERN.test(currentProperty)) {
onOverrideSettingsValue(currentProperty, value);
}
}
function onOverrideSettingsValue(property: string, value: any): void {
overrides.push({
identifiers: [overrideIdentifierFromKey(property).trim()],
raw: value,
contents: null
});
}
let visitor: json.JSONVisitor = {
onObjectBegin: () => {
let object = {};
onValue(object);
previousParents.push(currentParent);
currentParent = object;
currentProperty = null;
},
onObjectProperty: (name: string) => {
currentProperty = name;
},
onObjectEnd: () => {
currentParent = previousParents.pop();
},
onArrayBegin: () => {
let array = [];
onValue(array);
previousParents.push(currentParent);
currentParent = array;
currentProperty = null;
},
onArrayEnd: () => {
currentParent = previousParents.pop();
},
onLiteralValue: onValue,
onError: (error: json.ParseErrorCode) => {
parseErrors.push({ error: error });
}
};
if (content) {
try {
json.visit(content, visitor);
parsed = currentParent[0] || {};
} catch (e) {
console.error(`Error while parsing settings file ${this.name}: ${e}`);
this._parseErrors = [e];
}
}
this.processRaw(parsed);
const configurationProperties = Registry.as<IConfigurationRegistry>(Extensions.Configuration).getConfigurationProperties();
this._overrides = overrides.map<IOverrides<T>>(override => {
// Filter unknown and non-overridable properties
const raw = {};
for (const key in override.raw) {
if (configurationProperties[key] && configurationProperties[key].overridable) {
raw[key] = override.raw[key];
}
}
return {
identifiers: override.identifiers,
contents: <T>toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`))
};
});
}
protected processRaw(raw: T): void {
this._contents = toValuesTree(raw, message => console.error(`Conflict in settings file ${this.name}: ${message}`));
this._keys = Object.keys(raw);
}
}
export function overrideIdentifierFromKey(key: string): string {
return key.substring(1, key.length - 1);
}
export function keyFromOverrideIdentifier(overrideIdentifier: string): string {
return `[${overrideIdentifier}]`;
}

View File

@@ -0,0 +1,100 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TPromise } from 'vs/base/common/winjs.base';
import { ConfigWatcher } from 'vs/base/node/config';
import { Registry } from 'vs/platform/registry/common/platform';
import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry';
import { IDisposable, toDisposable, Disposable } from 'vs/base/common/lifecycle';
import { ConfigurationSource, IConfigurationService, IConfigurationServiceEvent, IConfigurationValue, IConfigurationKeys, ConfigurationModel, IConfigurationOverrides, Configuration, IConfigurationValues, IConfigurationData } from 'vs/platform/configuration/common/configuration';
import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/model';
import Event, { Emitter } from 'vs/base/common/event';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { onUnexpectedError } from 'vs/base/common/errors';
export class ConfigurationService<T> extends Disposable implements IConfigurationService, IDisposable {
_serviceBrand: any;
private _configuration: Configuration<T>;
private userConfigModelWatcher: ConfigWatcher<ConfigurationModel<T>>;
private _onDidUpdateConfiguration: Emitter<IConfigurationServiceEvent> = this._register(new Emitter<IConfigurationServiceEvent>());
public readonly onDidUpdateConfiguration: Event<IConfigurationServiceEvent> = this._onDidUpdateConfiguration.event;
constructor(
@IEnvironmentService environmentService: IEnvironmentService
) {
super();
this.userConfigModelWatcher = new ConfigWatcher(environmentService.appSettingsPath, {
changeBufferDelay: 300, onError: error => onUnexpectedError(error), defaultConfig: new CustomConfigurationModel<T>(null, environmentService.appSettingsPath), parse: (content: string, parseErrors: any[]) => {
const userConfigModel = new CustomConfigurationModel<T>(content, environmentService.appSettingsPath);
parseErrors = [...userConfigModel.errors];
return userConfigModel;
}
});
this._register(toDisposable(() => this.userConfigModelWatcher.dispose()));
// Listeners
this._register(this.userConfigModelWatcher.onDidUpdateConfiguration(() => this.onConfigurationChange(ConfigurationSource.User)));
this._register(Registry.as<IConfigurationRegistry>(Extensions.Configuration).onDidRegisterConfiguration(() => this.onConfigurationChange(ConfigurationSource.Default)));
}
public configuration(): Configuration<any> {
return this._configuration || (this._configuration = this.consolidateConfigurations());
}
private onConfigurationChange(source: ConfigurationSource): void {
this.reset(); // reset our caches
const cache = this.configuration();
this._onDidUpdateConfiguration.fire({
source,
sourceConfig: source === ConfigurationSource.Default ? cache.defaults.contents : cache.user.contents
});
}
public reloadConfiguration<C>(section?: string): TPromise<C> {
return new TPromise<C>(c => {
this.userConfigModelWatcher.reload(() => {
this.reset(); // reset our caches
c(this.getConfiguration<C>(section));
});
});
}
public getConfiguration<C>(section?: string, options?: IConfigurationOverrides): C {
return this.configuration().getValue<C>(section, options);
}
public lookup<C>(key: string, overrides?: IConfigurationOverrides): IConfigurationValue<C> {
return this.configuration().lookup<C>(key, overrides);
}
public keys(overrides?: IConfigurationOverrides): IConfigurationKeys {
return this.configuration().keys(overrides);
}
public values<V>(): IConfigurationValues {
return this._configuration.values();
}
public getConfigurationData<T2>(): IConfigurationData<T2> {
return this.configuration().toData();
}
private reset(): void {
this._configuration = this.consolidateConfigurations();
}
private consolidateConfigurations(): Configuration<T> {
const defaults = new DefaultConfigurationModel<T>();
const user = this.userConfigModelWatcher.getConfig();
return new Configuration(defaults, user);
}
}

View File

@@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { ConfigurationModel, merge } from 'vs/platform/configuration/common/configuration';
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
suite('Configuration', () => {
suiteSetup(() => {
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({
'id': 'a',
'order': 1,
'title': 'a',
'type': 'object',
'properties': {
'a': {
'description': 'a',
'type': 'boolean',
'default': true,
'overridable': true
}
}
});
});
test('simple merge', () => {
let base = { 'a': 1, 'b': 2 };
merge(base, { 'a': 3, 'c': 4 }, true);
assert.deepEqual(base, { 'a': 3, 'b': 2, 'c': 4 });
base = { 'a': 1, 'b': 2 };
merge(base, { 'a': 3, 'c': 4 }, false);
assert.deepEqual(base, { 'a': 1, 'b': 2, 'c': 4 });
});
test('Recursive merge', () => {
const base = { 'a': { 'b': 1 } };
merge(base, { 'a': { 'b': 2 } }, true);
assert.deepEqual(base, { 'a': { 'b': 2 } });
});
test('simple merge using configuration', () => {
let base = new ConfigurationModel<any>({ 'a': 1, 'b': 2 });
let add = new ConfigurationModel<any>({ 'a': 3, 'c': 4 });
let result = base.merge(add);
assert.deepEqual(result.contents, { 'a': 3, 'b': 2, 'c': 4 });
});
test('Recursive merge using config models', () => {
let base = new ConfigurationModel({ 'a': { 'b': 1 } });
let add = new ConfigurationModel({ 'a': { 'b': 2 } });
let result = base.merge(add);
assert.deepEqual(result.contents, { 'a': { 'b': 2 } });
});
test('Test contents while getting an existing property', () => {
let testObject = new ConfigurationModel({ 'a': 1 });
assert.deepEqual(testObject.getContentsFor('a'), 1);
testObject = new ConfigurationModel<any>({ 'a': { 'b': 1 } });
assert.deepEqual(testObject.getContentsFor('a'), { 'b': 1 });
});
test('Test contents are undefined for non existing properties', () => {
const testObject = new ConfigurationModel({ awesome: true });
assert.deepEqual(testObject.getContentsFor('unknownproperty'), undefined);
});
test('Test override gives all content merged with overrides', () => {
const testObject = new ConfigurationModel<any>({ 'a': 1, 'c': 1 }, [], [{ identifiers: ['b'], contents: { 'a': 2 } }]);
assert.deepEqual(testObject.override('b').contents, { 'a': 2, 'c': 1 });
});
});

View File

@@ -0,0 +1,148 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import { CustomConfigurationModel, DefaultConfigurationModel } from 'vs/platform/configuration/common/model';
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry';
import { Registry } from 'vs/platform/registry/common/platform';
suite('Configuration', () => {
suiteSetup(() => {
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({
'id': 'a',
'order': 1,
'title': 'a',
'type': 'object',
'properties': {
'a': {
'description': 'a',
'type': 'boolean',
'default': true,
'overridable': true
}
}
});
});
test('simple merge using models', () => {
let base = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 }));
let add = new CustomConfigurationModel(JSON.stringify({ 'a': 3, 'c': 4 }));
let result = base.merge(add);
assert.deepEqual(result.contents, { 'a': 3, 'b': 2, 'c': 4 });
});
test('simple merge with an undefined contents', () => {
let base = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 }));
let add = new CustomConfigurationModel(null);
let result = base.merge(add);
assert.deepEqual(result.contents, { 'a': 1, 'b': 2 });
base = new CustomConfigurationModel(null);
add = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'b': 2 }));
result = base.merge(add);
assert.deepEqual(result.contents, { 'a': 1, 'b': 2 });
base = new CustomConfigurationModel(null);
add = new CustomConfigurationModel(null);
result = base.merge(add);
assert.deepEqual(result.contents, {});
});
test('Recursive merge using config models', () => {
let base = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 1 } }));
let add = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 2 } }));
let result = base.merge(add);
assert.deepEqual(result.contents, { 'a': { 'b': 2 } });
});
test('Test contents while getting an existing property', () => {
let testObject = new CustomConfigurationModel(JSON.stringify({ 'a': 1 }));
assert.deepEqual(testObject.getContentsFor('a'), 1);
testObject = new CustomConfigurationModel(JSON.stringify({ 'a': { 'b': 1 } }));
assert.deepEqual(testObject.getContentsFor('a'), { 'b': 1 });
});
test('Test contents are undefined for non existing properties', () => {
const testObject = new CustomConfigurationModel(JSON.stringify({
awesome: true
}));
assert.deepEqual(testObject.getContentsFor('unknownproperty'), undefined);
});
test('Test contents are undefined for undefined config', () => {
const testObject = new CustomConfigurationModel(null);
assert.deepEqual(testObject.getContentsFor('unknownproperty'), undefined);
});
test('Test configWithOverrides gives all content merged with overrides', () => {
const testObject = new CustomConfigurationModel(JSON.stringify({ 'a': 1, 'c': 1, '[b]': { 'a': 2 } }));
assert.deepEqual(testObject.override('b').contents, { 'a': 2, 'c': 1, '[b]': { 'a': 2 } });
});
test('Test configWithOverrides gives empty contents', () => {
const testObject = new CustomConfigurationModel(null);
assert.deepEqual(testObject.override('b').contents, {});
});
test('Test update with empty data', () => {
const testObject = new CustomConfigurationModel();
testObject.update('');
assert.deepEqual(testObject.contents, {});
assert.deepEqual(testObject.keys, []);
testObject.update(null);
assert.deepEqual(testObject.contents, {});
assert.deepEqual(testObject.keys, []);
testObject.update(undefined);
assert.deepEqual(testObject.contents, {});
assert.deepEqual(testObject.keys, []);
});
test('Test registering the same property again', () => {
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({
'id': 'a',
'order': 1,
'title': 'a',
'type': 'object',
'properties': {
'a': {
'description': 'a',
'type': 'boolean',
'default': false,
}
}
});
assert.equal(true, new DefaultConfigurationModel().getContentsFor('a'));
});
test('Test registering the language property', () => {
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({
'id': '[a]',
'order': 1,
'title': 'a',
'type': 'object',
'properties': {
'[a]': {
'description': 'a',
'type': 'boolean',
'default': false,
}
}
});
assert.equal(undefined, new DefaultConfigurationModel().getContentsFor('[a]'));
});
});

View File

@@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import { TrieMap } from 'vs/base/common/map';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { EventEmitter } from 'vs/base/common/eventEmitter';
import { getConfigurationKeys } from 'vs/platform/configuration/common/model';
import { IConfigurationOverrides, IConfigurationService, getConfigurationValue, IConfigurationValue, IConfigurationKeys, IConfigurationValues, IConfigurationData, Configuration, ConfigurationModel } from 'vs/platform/configuration/common/configuration';
export class TestConfigurationService extends EventEmitter implements IConfigurationService {
public _serviceBrand: any;
private configuration = Object.create(null);
private configurationByRoot: TrieMap<any> = new TrieMap<any>();
public reloadConfiguration<T>(section?: string): TPromise<T> {
return TPromise.as(this.getConfiguration());
}
public getConfiguration(section?: string, overrides?: IConfigurationOverrides): any {
if (overrides && overrides.resource) {
const configForResource = this.configurationByRoot.findSubstr(overrides.resource.fsPath);
return configForResource || this.configuration;
}
return this.configuration;
}
public getConfigurationData(): IConfigurationData<any> {
return new Configuration(new ConfigurationModel(), new ConfigurationModel(this.configuration)).toData();
}
public setUserConfiguration(key: any, value: any, root?: URI): Thenable<void> {
if (root) {
const configForRoot = this.configurationByRoot.lookUp(root.fsPath) || Object.create(null);
configForRoot[key] = value;
this.configurationByRoot.insert(root.fsPath, configForRoot);
} else {
this.configuration[key] = value;
}
return TPromise.as(null);
}
public onDidUpdateConfiguration() {
return { dispose() { } };
}
public lookup<C>(key: string, overrides?: IConfigurationOverrides): IConfigurationValue<C> {
const config = this.getConfiguration(undefined, overrides);
return {
value: getConfigurationValue<C>(config, key),
default: getConfigurationValue<C>(config, key),
user: getConfigurationValue<C>(config, key),
workspace: null,
folder: null
};
}
public keys(): IConfigurationKeys {
return {
default: getConfigurationKeys(),
user: Object.keys(this.configuration),
workspace: [],
folder: []
};
}
public values(): IConfigurationValues {
return {};
}
}

View File

@@ -0,0 +1,264 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import assert = require('assert');
import os = require('os');
import path = require('path');
import fs = require('fs');
import { Registry } from 'vs/platform/registry/common/platform';
import { ConfigurationService } from 'vs/platform/configuration/node/configurationService';
import { ParsedArgs } from 'vs/platform/environment/common/environment';
import { parseArgs } from 'vs/platform/environment/node/argv';
import { EnvironmentService } from 'vs/platform/environment/node/environmentService';
import extfs = require('vs/base/node/extfs');
import uuid = require('vs/base/common/uuid');
import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'vs/platform/configuration/common/configurationRegistry';
class SettingsTestEnvironmentService extends EnvironmentService {
constructor(args: ParsedArgs, _execPath: string, private customAppSettingsHome) {
super(args, _execPath);
}
get appSettingsPath(): string { return this.customAppSettingsHome; }
}
suite('ConfigurationService - Node', () => {
function testFile(callback: (path: string, cleanUp: (callback: () => void) => void) => void): void {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'config', id);
const testFile = path.join(newDir, 'config.json');
extfs.mkdirp(newDir, 493, (error) => {
callback(testFile, (callback) => extfs.del(parentDir, os.tmpdir(), () => { }, callback));
});
}
test('simple', (done: () => void) => {
testFile((testFile, cleanUp) => {
fs.writeFileSync(testFile, '{ "foo": "bar" }');
const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile));
const config = service.getConfiguration<{ foo: string }>();
assert.ok(config);
assert.equal(config.foo, 'bar');
service.dispose();
cleanUp(done);
});
});
test('config gets flattened', (done: () => void) => {
testFile((testFile, cleanUp) => {
fs.writeFileSync(testFile, '{ "testworkbench.editor.tabs": true }');
const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile));
const config = service.getConfiguration<{ testworkbench: { editor: { tabs: boolean } } }>();
assert.ok(config);
assert.ok(config.testworkbench);
assert.ok(config.testworkbench.editor);
assert.equal(config.testworkbench.editor.tabs, true);
service.dispose();
cleanUp(done);
});
});
test('error case does not explode', (done: () => void) => {
testFile((testFile, cleanUp) => {
fs.writeFileSync(testFile, ',,,,');
const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile));
const config = service.getConfiguration<{ foo: string }>();
assert.ok(config);
service.dispose();
cleanUp(done);
});
});
test('missing file does not explode', () => {
const id = uuid.generateUuid();
const parentDir = path.join(os.tmpdir(), 'vsctests', id);
const newDir = path.join(parentDir, 'config', id);
const testFile = path.join(newDir, 'config.json');
const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile));
const config = service.getConfiguration<{ foo: string }>();
assert.ok(config);
service.dispose();
});
test('reloadConfiguration', (done: () => void) => {
testFile((testFile, cleanUp) => {
fs.writeFileSync(testFile, '{ "foo": "bar" }');
const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile));
let config = service.getConfiguration<{ foo: string }>();
assert.ok(config);
assert.equal(config.foo, 'bar');
fs.writeFileSync(testFile, '{ "foo": "changed" }');
// still outdated
config = service.getConfiguration<{ foo: string }>();
assert.ok(config);
assert.equal(config.foo, 'bar');
// force a reload to get latest
service.reloadConfiguration<{ foo: string }>().then(config => {
assert.ok(config);
assert.equal(config.foo, 'changed');
service.dispose();
cleanUp(done);
});
});
});
test('model defaults', (done: () => void) => {
interface ITestSetting {
configuration: {
service: {
testSetting: string;
}
};
}
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
'id': '_test',
'type': 'object',
'properties': {
'configuration.service.testSetting': {
'type': 'string',
'default': 'isSet'
}
}
});
let serviceWithoutFile = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, '__testFile'));
let setting = serviceWithoutFile.getConfiguration<ITestSetting>();
assert.ok(setting);
assert.equal(setting.configuration.service.testSetting, 'isSet');
testFile((testFile, cleanUp) => {
fs.writeFileSync(testFile, '{ "testworkbench.editor.tabs": true }');
const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile));
let setting = service.getConfiguration<ITestSetting>();
assert.ok(setting);
assert.equal(setting.configuration.service.testSetting, 'isSet');
fs.writeFileSync(testFile, '{ "configuration.service.testSetting": "isChanged" }');
service.reloadConfiguration().then(() => {
let setting = service.getConfiguration<ITestSetting>();
assert.ok(setting);
assert.equal(setting.configuration.service.testSetting, 'isChanged');
service.dispose();
serviceWithoutFile.dispose();
cleanUp(done);
});
});
});
test('lookup', (done: () => void) => {
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
'id': '_test',
'type': 'object',
'properties': {
'lookup.service.testSetting': {
'type': 'string',
'default': 'isSet'
}
}
});
testFile((testFile, cleanUp) => {
const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile));
let res = service.lookup('something.missing');
assert.strictEqual(res.value, void 0);
assert.strictEqual(res.default, void 0);
assert.strictEqual(res.user, void 0);
res = service.lookup('lookup.service.testSetting');
assert.strictEqual(res.default, 'isSet');
assert.strictEqual(res.value, 'isSet');
assert.strictEqual(res.user, void 0);
fs.writeFileSync(testFile, '{ "lookup.service.testSetting": "bar" }');
return service.reloadConfiguration().then(() => {
res = service.lookup('lookup.service.testSetting');
assert.strictEqual(res.default, 'isSet');
assert.strictEqual(res.user, 'bar');
assert.strictEqual(res.value, 'bar');
service.dispose();
cleanUp(done);
});
});
});
test('lookup with null', (done: () => void) => {
const configurationRegistry = <IConfigurationRegistry>Registry.as(ConfigurationExtensions.Configuration);
configurationRegistry.registerConfiguration({
'id': '_testNull',
'type': 'object',
'properties': {
'lookup.service.testNullSetting': {
'type': 'null',
}
}
});
testFile((testFile, cleanUp) => {
const service = new ConfigurationService(new SettingsTestEnvironmentService(parseArgs(process.argv), process.execPath, testFile));
let res = service.lookup('lookup.service.testNullSetting');
assert.strictEqual(res.default, null);
assert.strictEqual(res.value, null);
assert.strictEqual(res.user, void 0);
fs.writeFileSync(testFile, '{ "lookup.service.testNullSetting": null }');
return service.reloadConfiguration().then(() => {
res = service.lookup('lookup.service.testNullSetting');
assert.strictEqual(res.default, null);
assert.strictEqual(res.value, null);
assert.strictEqual(res.user, null);
service.dispose();
cleanUp(done);
});
});
});
});