From 5f144928a355139a91812368a20482aa862e3c8e Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Tue, 23 Aug 2016 08:03:56 +0200 Subject: [PATCH] introduce a config model on the workbench side --- .../configuration/common/configuration.ts | 5 +- .../common/configurationRegistry.ts | 10 +- src/vs/platform/configuration/common/model.ts | 108 ++---------------- .../services/configuration/common/model.ts | 93 +++++++++++++++ .../node/configurationService.ts | 3 +- .../configuration/test/common/model.test.ts | 2 +- 6 files changed, 114 insertions(+), 107 deletions(-) create mode 100644 src/vs/workbench/services/configuration/common/model.ts rename src/vs/{platform => workbench/services}/configuration/test/common/model.test.ts (96%) diff --git a/src/vs/platform/configuration/common/configuration.ts b/src/vs/platform/configuration/common/configuration.ts index d04fec071da..3e8ab7da76b 100644 --- a/src/vs/platform/configuration/common/configuration.ts +++ b/src/vs/platform/configuration/common/configuration.ts @@ -3,9 +3,9 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import {TPromise} from 'vs/base/common/winjs.base'; import {createDecorator} from 'vs/platform/instantiation/common/instantiation'; import Event from 'vs/base/common/event'; -import {TPromise} from 'vs/base/common/winjs.base'; export const IConfigurationService = createDecorator('configurationService'); @@ -34,6 +34,9 @@ export interface IConfigurationServiceEvent { config: any; } +/** + * A helper function to get the configuration value with a specific settings path (e.g. config.some.setting) + */ export function getConfigurationValue(config: any, settingPath: string, defaultValue?: T): T { function accessSetting(config: any, path: string[]): any { let current = config; diff --git a/src/vs/platform/configuration/common/configurationRegistry.ts b/src/vs/platform/configuration/common/configurationRegistry.ts index f89789a01dc..375fd019535 100644 --- a/src/vs/platform/configuration/common/configurationRegistry.ts +++ b/src/vs/platform/configuration/common/configurationRegistry.ts @@ -6,11 +6,11 @@ import nls = require('vs/nls'); import Event, {Emitter} from 'vs/base/common/event'; -import { IJSONSchema } from 'vs/base/common/jsonSchema'; -import platform = require('vs/platform/platform'); +import {IJSONSchema} from 'vs/base/common/jsonSchema'; +import {Registry} from 'vs/platform/platform'; import objects = require('vs/base/common/objects'); import {ExtensionsRegistry} from 'vs/platform/extensions/common/extensionsRegistry'; -import JSONContributionRegistry = require('vs/platform/jsonschemas/common/jsonContributionRegistry'); +import {IJSONContributionRegistry, Extensions as JSONExtensions} from 'vs/platform/jsonschemas/common/jsonContributionRegistry'; export const Extensions = { Configuration: 'base.contributions.configuration' @@ -48,7 +48,7 @@ export interface IConfigurationNode { } const schemaId = 'vscode://schemas/settings'; -const contributionRegistry = platform.Registry.as(JSONContributionRegistry.Extensions.JSONContribution); +const contributionRegistry = Registry.as(JSONExtensions.JSONContribution); class ConfigurationRegistry implements IConfigurationRegistry { private configurationContributors: IConfigurationNode[]; @@ -86,7 +86,7 @@ class ConfigurationRegistry implements IConfigurationRegistry { } const configurationRegistry = new ConfigurationRegistry(); -platform.Registry.add(Extensions.Configuration, configurationRegistry); +Registry.add(Extensions.Configuration, configurationRegistry); const configurationExtPoint = ExtensionsRegistry.registerExtensionPoint('configuration', { description: nls.localize('vscode.extension.contributes.configuration', 'Contributes configuration settings.'), diff --git a/src/vs/platform/configuration/common/model.ts b/src/vs/platform/configuration/common/model.ts index 96330816cfa..eeef47420bb 100644 --- a/src/vs/platform/configuration/common/model.ts +++ b/src/vs/platform/configuration/common/model.ts @@ -4,21 +4,11 @@ *--------------------------------------------------------------------------------------------*/ 'use strict'; -import objects = require('vs/base/common/objects'); -import platform = require('vs/platform/platform'); +import {Registry} from 'vs/platform/platform'; import types = require('vs/base/common/types'); -import json = require('vs/base/common/json'); +import {IConfigurationNode, IConfigurationRegistry, Extensions} from 'vs/platform/configuration/common/configurationRegistry'; -import configurationRegistry = require('./configurationRegistry'); - -export const CONFIG_DEFAULT_NAME = 'settings'; - -export interface IConfigFile { - contents: any; - parseError?: any; -} - -function setNode(root: any, key: string, value: any): void { +export function setNode(root: any, key: string, value: any): void { const segments = key.split('.'); const last = segments.pop(); @@ -36,92 +26,14 @@ function setNode(root: any, key: string, value: any): void { } curr = obj; }); - - curr[last] = value; -} - -export function newConfigFile(value: string): IConfigFile { - try { - const root: any = Object.create(null); - const contents = json.parse(value) || {}; - for (let key in contents) { - setNode(root, key, contents[key]); - } - - return { - contents: root - }; - } catch (e) { - return { - contents: {}, - parseError: e - }; - } -} - -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 function consolidate(configMap: { [key: string]: IConfigFile; }): { contents: any; parseErrors: string[]; } { - const finalConfig: any = Object.create(null); - const parseErrors: string[] = []; - const regexp = /\/(team\.)?([^\.]*)*\.json/; - // For each config file in .vscode folder - Object.keys(configMap).forEach((configFileName) => { - const config = objects.clone(configMap[configFileName]); - const matches = regexp.exec(configFileName); - if (!matches || !config) { - return; - } - - // If a file is team.foo.json, it indicates team settings, strip this away - const isTeamSetting = !!matches[1]; - - // Extract the config key from the file name (except for settings.json which is the default) - let configElement: any = finalConfig; - if (matches && matches[2] && matches[2] !== CONFIG_DEFAULT_NAME) { - - // Use the name of the file as top level config section for all settings inside - const configSection = matches[2]; - let element = configElement[configSection]; - if (!element) { - element = Object.create(null); - configElement[configSection] = element; - } - configElement = element; - } - - merge(configElement, config.contents, !isTeamSetting /* user settings overrule team settings */); - if (config.parseError) { - parseErrors.push(configFileName); - } - - }); - - return { - contents: finalConfig, - parseErrors: parseErrors - }; + curr[last] = value; } -// defaults... - -function processDefaultValues(withConfig: (config: configurationRegistry.IConfigurationNode, isTop?: boolean) => boolean): void { - const configurations = (platform.Registry.as(configurationRegistry.Extensions.Configuration)).getConfigurations(); +function processDefaultValues(withConfig: (config: IConfigurationNode, isTop?: boolean) => boolean): void { + const configurations = Registry.as(Extensions.Configuration).getConfigurations(); - const visit = (config: configurationRegistry.IConfigurationNode, level: number) => { + const visit = (config: IConfigurationNode, level: number) => { const handled = withConfig(config, level === 0); if (Array.isArray(config.allOf)) { @@ -151,11 +63,10 @@ function processDefaultValues(withConfig: (config: configurationRegistry.IConfig }); } - export function getDefaultValues(): any { const ret: any = Object.create(null); - const handleConfig = (config: configurationRegistry.IConfigurationNode, isTop: boolean): boolean => { + const handleConfig = (config: IConfigurationNode, isTop: boolean): boolean => { if (config.properties) { Object.keys(config.properties).forEach((key) => { const prop = config.properties[key]; @@ -177,13 +88,12 @@ export function getDefaultValues(): any { return ret; } - export function getDefaultValuesContent(indent: string): string { let lastEntry = -1; const result: string[] = []; result.push('{'); - const handleConfig = (config: configurationRegistry.IConfigurationNode, isTop: boolean): boolean => { + const handleConfig = (config: IConfigurationNode, isTop: boolean): boolean => { let handled = false; if (config.title) { handled = true; diff --git a/src/vs/workbench/services/configuration/common/model.ts b/src/vs/workbench/services/configuration/common/model.ts new file mode 100644 index 00000000000..95ae6d15e20 --- /dev/null +++ b/src/vs/workbench/services/configuration/common/model.ts @@ -0,0 +1,93 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ +'use strict'; + +import objects = require('vs/base/common/objects'); +import types = require('vs/base/common/types'); +import json = require('vs/base/common/json'); +import model = require('vs/platform/configuration/common/model'); + +export const CONFIG_DEFAULT_NAME = 'settings'; + +export interface IConfigFile { + contents: any; + parseError?: any; +} + +export function newConfigFile(value: string): IConfigFile { + try { + const root: any = Object.create(null); + const contents = json.parse(value) || {}; + for (let key in contents) { + model.setNode(root, key, contents[key]); + } + + return { + contents: root + }; + } catch (e) { + return { + contents: {}, + parseError: e + }; + } +} + +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 function consolidate(configMap: { [key: string]: IConfigFile; }): { contents: any; parseErrors: string[]; } { + const finalConfig: any = Object.create(null); + const parseErrors: string[] = []; + const regexp = /\/(team\.)?([^\.]*)*\.json/; + + // For each config file in .vscode folder + Object.keys(configMap).forEach((configFileName) => { + const config = objects.clone(configMap[configFileName]); + const matches = regexp.exec(configFileName); + if (!matches || !config) { + return; + } + + // If a file is team.foo.json, it indicates team settings, strip this away + const isTeamSetting = !!matches[1]; + + // Extract the config key from the file name (except for settings.json which is the default) + let configElement: any = finalConfig; + if (matches && matches[2] && matches[2] !== CONFIG_DEFAULT_NAME) { + + // Use the name of the file as top level config section for all settings inside + const configSection = matches[2]; + let element = configElement[configSection]; + if (!element) { + element = Object.create(null); + configElement[configSection] = element; + } + configElement = element; + } + + merge(configElement, config.contents, !isTeamSetting /* user settings overrule team settings */); + if (config.parseError) { + parseErrors.push(configFileName); + } + + }); + + return { + contents: finalConfig, + parseErrors: parseErrors + }; +} \ No newline at end of file diff --git a/src/vs/workbench/services/configuration/node/configurationService.ts b/src/vs/workbench/services/configuration/node/configurationService.ts index 06a1fb0f58b..20429f270b9 100644 --- a/src/vs/workbench/services/configuration/node/configurationService.ts +++ b/src/vs/workbench/services/configuration/node/configurationService.ts @@ -25,7 +25,8 @@ import {JSONPath} from 'vs/base/common/json'; import {applyEdits} from 'vs/base/common/jsonFormatter'; import {setProperty} from 'vs/base/common/jsonEdit'; import errors = require('vs/base/common/errors'); -import {IConfigFile, consolidate, CONFIG_DEFAULT_NAME, newConfigFile, getDefaultValues} from 'vs/platform/configuration/common/model'; +import {getDefaultValues} from 'vs/platform/configuration/common/model'; +import {IConfigFile, consolidate, CONFIG_DEFAULT_NAME, newConfigFile} from 'vs/workbench/services/configuration/common/model'; import {IConfigurationServiceEvent} from 'vs/platform/configuration/common/configuration'; import {IWorkbenchConfigurationService} from 'vs/workbench/services/configuration/common/configuration'; import {EventType as FileEventType, FileChangeType, FileChangesEvent} from 'vs/platform/files/common/files'; diff --git a/src/vs/platform/configuration/test/common/model.test.ts b/src/vs/workbench/services/configuration/test/common/model.test.ts similarity index 96% rename from src/vs/platform/configuration/test/common/model.test.ts rename to src/vs/workbench/services/configuration/test/common/model.test.ts index d06300d5a28..181e024dd89 100644 --- a/src/vs/platform/configuration/test/common/model.test.ts +++ b/src/vs/workbench/services/configuration/test/common/model.test.ts @@ -5,7 +5,7 @@ 'use strict'; import assert = require('assert'); -import model = require('vs/platform/configuration/common/model'); +import model = require('vs/workbench/services/configuration/common/model'); suite('ConfigurationService - Model', () => { -- GitLab